Sunday, April 20, 2014

Bit more soldering

Soldered three more pillars yesterday, and did another eight tonight. On average it takes around 11 minutes to solder one pillar. Not bad. Only 2 mistakes in the last batch: one LED was inserted into the jig incorrectly (or I marked the wrong lead) and one bad solder joint.

Here's the result of my labor so far:
24 done, 40 more to go.

Thursday, April 17, 2014

Stackable!

Received a bunch of spacers today (HTS-310) and they fit the cathode boards perfectly.
The whole construction feels pretty solid, very little flex. That's a good thing, since putting in the cables requires quite a bit of force. Speaking of cables, that's one more extra time consuming job...

Not much time spent on the cube lately. I'll probably be able to find a couple of free hours this weekend (yay for second Easter day). I did spend some time on some other stuf.

Thursday, April 03, 2014

Cathode board works!

And we have a video!
Pretty neat! I found a bug in my bit angle modulation code which caused some weird things. After I fixed that everything worked like a charm.
My setup is like this:
  • An Arduino Nano on the left side of the breadboard, this microcontroller has a bit of animation code and it streams the resulting led states (on or off for each LED) to the cathode board. It does this roughly 12.000 times per second, creating a very smooth image. It's important to note that it is streaming the data for a full 8x8x8 RGB cube, but only one row of the top level is is shown (since that's the last byte that is streamed). On other words, the same smoothness can be achieved when the complete cube is connected. It's also interesting to note that this code is capable of streaming 100 "frames" per second and has loads of cpu power left.
  • The Arduino is connected to my cathode control board using a ribbon cable. Each of the five wires in the cable is connected directly to one of the pins of the shift register on the cathode board for full control. There's a three wire power cable as well; one wire for logic power supply, one for logic ground and a separate one for LED ground. Finally there's an eight wire ribbon cable connected to the cathodes of the LEDs on the breadboard.
  • The 8 LEDs on the right side of the breadboard have their anodes connected directly to 5V. The green cathodes go to the cathode control board which contains a series resistor for each LED. The other end of each resistor is connected to the collector of a transistor. The emitter of each transistor is connected to the LED ground pin on the board, and the base goes through a series resistor to an output pin of the shift register. If the output pin goes high, then current can flow through the transistor and the LED goes on. If the output pin is low then current is blocked and the LED goes off.
Next up: two more boards for full RGB control :)

Testing the cathode board

Quick update, more will follow.
I've been a bit busy with some other stuff lately, I had to make 35 buzzer games (like this one) for a group of kids, so I spent most of my free time last week putting a bunch of leds, resistors, battery holders and piezo buzzers together. The rest of my time went to miscellaneous stuff like housekeeping and filling in my tax forms. Last night I finally had some time to get back to the cube...

I need some way to test if my cathode boards work after I solder all parts on them, so I populated a breadboard with 8 LEDs and wired them to the cathode board and an Arduino. The Arduino runs pretty much the same code as the cube will eventually in terms of refresh rate and how the cathode board is controlled. It took some time before I had everything working somewhat correctly, always double check your connections and don't mix up the MOSI and MISO pins...

But in the end, it works! One LED didn't light up, I didn't solder the transistor for that one correctly, easy fix. I'm still tweaking the code a bit, there's a bug somewhere that stops the brightness from functioning properly. I don't have any photos or videos at the moment, I'll shoot them after I fix that bug.

One thing that I overlooked is how bright a 0603 LED can be. I have a small power indicator LED on the board and that thing is just blindingly bright. I've already replaced the 150 Ohm series resistor with a 1K Ohm, but it's still too bright. I'll try a 10K tonight; all it needs to do is provide a visual indication, not light up the living room...

Sunday, March 23, 2014

Soldering tiny things

Some people make soldering look so easy. It's not. Not for me. I made a bit of a mess of my practice board, but at least it helped me get the hang of it a bit. 0805 sized components are pretty small, 0603 is just tiny! It's pretty difficult to get them straight on the board. SOT-23 is just as awful. SO-16 was doable fortunately, I'd hate to have that one messed up. But I'm going to stay away from TQFP for now, I made a terrible mess out of those.

The first board I finished turned out okay, nothing to be terribly proud of. 

Also did a bit of practicing with my new cable crimp tool, the first couple of cables are pretty horrible, but the last few went pretty well. 

Saturday, March 22, 2014

Cathode boards arrived!

Today I received the cathode boards that I had ordered from OSH Park about two weeks ago. That's a lot faster then I thought it would be. Nice!
They came in a matching purple bubble envelope, the people at OSH Park seem to be really fond of purple :) They even threw in a sticker, awesome! I'll put it somewhere on the base of the cube I think, probably on the inside next to the boards ;)

The boards themselves look pretty much like how I thought they would be. The gold finish looks really nice. But I also noticed that the silkscreen isn't positioned as accurate as I thought it would be.
Here's the worst one, you can clearly see the silkscreen around the mounting holes being off center. At some points the silkscreen has been printed on the pads. Not that it matters that much, the biggest mistake is on my account. I have via's running through a bunch of pads. That's not going to make soldering any easier. I'm going to fix that before I order any more boards. I'm also going to have to do something about the component references, they're pretty much impossible to read for the smaller components because they either overlap with the footprint, or are clipped by the pads.
This one turned out really nice! I still have to trim the tabs; nothing a side cutter and a file can't fix. And I must say, it's really cool to hold something in your hands you designed yourself :)

I've also received a smd soldering practice board this week. I'll give that one a go before I start populating these boards :)

Thursday, March 20, 2014

That's more like it!

So I'm done with bending leads on those LEDs, in multiple ways... I've done about 500 now and am calling it quits. I'll bend the rest when I need them.

It's finally soldering time again! Six done tonight in a bit over an hour. Average soldering time for one pillar is now about twelve minutes instead of twenty. Not having to bend those leads before putting them in the jig really makes it go a lot smoother. Anyway, 13 down, 51 more to go...

Soldering also seems to go faster, I think I'm getting the hang of it :)

Tuesday, March 18, 2014

Moar LEDs!

Phew! 400 done, just a bit over 100 to go until I have 512 perfectly shaped LEDs. That's one bag and a dozen :)

Sunday, March 16, 2014

Bending LEDs

Another weekend well spent :)

I've soldered three more pillars and straightened around fifty wires. I've also started bending the leads on all LEDs, a really boring job, but doing this beforehand will make the soldering go much faster. As it turns out, bending one LED costs about as much time as soldering one. And the more I can do in batch, the better!

Here's what I started with: around 600 LEDs
And the result after an evening on the couch, watching TV while bending leads.
200 done, 400 to go :)

I've marked the green cathode with a marker on each LED, that lead will have point up when the LED is inserted into the jig. It's pretty easy to spot the correct lead by just looking into the package, but more on that later.

All leads are at a 90 degree angle of each other and the LED sits perfectly flat on a flat surface (my hand isn't flat obviously).  It takes about 30 to 40 seconds to bend the leads on one LED, I could've done this faster but I'm a bit of a perfectionist, and I was watching TV :) It costs about 1 hour per 100 LEDs, but hopefully it'll save some time when soldering.

The great thing about this project is that it's easy to spend anywhere from 15 minutes to a few hours on it; you can just grab a box with all the tools/parts, do some work, and put it away when you're done or out of time. Cleaning up and getting started only takes a minute or two.

In other news, the PCBs I've ordered have been shipped last Friday! They'll probably arrive somewhere next week, but at least before the end of the month :)

Update 17-03: and a few more LEDs done, halfway there!

Tuesday, March 11, 2014

Cutting and stripping the time away

2.5 hours well spent. I've cut and stripped about 150 wires. I guess I still have a few wires left to cut and strip, but I'm not going to count them right now. I guess I'll find out when I run out of wires :)

I also just learned that the order for my boards have been sent to the fab. It's expected to arrive at OSH Park in about a week, not bad :)

Theory: shift registers, and the test jig code explained!

Ahh... Shift registers. The heart of most LED cubes.

So, what is a shift register and what does it do? Basically it's a serial input, parallel output IC; you send a stream of ones and zeroes to it on one pin and this makes a bunch of output pins go high or low. Usually you have two more pins: a clock pin and a latch pin. The clock pin is used to tell the shift register when to read a new bit on its input pin. The latch pin is used to tell it when to make the read bits appear on the output pins.

In my cube I use the 74HC595 shift register which is an 8 bit shift register. It simply means that it has 8 outputs. You can find these for almost a dime a dozen on eBay. If you need the smaller SMD type, search for 74HC595D.
The 595 (as I'll refer to it from now on) has two internal registers: the shift register and the storage register. We'll start at the beginning - the input pin - and work our way down to the output pins.

When you want to send data to the 595 you start by setting the DS pin (Serial Data Input) high or low, depending on whether you want to write a one or zero. Then you make the SHCP pin (Shift Register Clock Input) go from low to high to low again. The shift register will update whenever that pin goes from low to high. It will store whatever value is at DS and put it in bit 0 of the shift register. All the other bits of the register are shifted to the next one. So bit 1 will get the old value of bit 0, bit 2 the old value of bit 1, etc etc. The cool thing about this is that the old value of bit 7 will appear at a pin called Q7S. If you connect this pin to the DS pin of a second 595, and also connect the SHCP pins of both 595s, then bit 7 of the first 595 will be shifted to bit 0 of the second 595. You can chain a whole bunch of registers like this, effectively forming one large shift register.

Great, now that you've shifted 8 bits into the 595, you'll want to have them appear at the output pins. To do this you pull the STCP (Storage Register Clock Input, otherwise known as Latch) pin from low to high to low again. Whenever this pin goes from low to high all values from the shift register will be copied to the storage register.
This storage register is connected to the output pins, so any value in it will appear on the output pins. But only if the OE (Output Enable) pin is pulled low. If OE is high all output pins will be low.

One thing that's important to know is that when both the STCP and SHCP pins go high simultaneously, the shift will take place after the contents of the shift register have been copied to the storage register. This means that when you have STCP and SHCP connected to eachother, and you shift in a bit, that this bit will not appear on the output directly (since the content of the shift register has been copied to the output register before the new bit was shifted in).

Let's have another look at my pillar testing code. For this I have connected STCP and SHCP to the same pin on the controller (B4) and DS to B3. OE has been connected to ground.


1:  /*  
2:   * TinyPillarTester.c  
3:   *  
4:   * Created: 6-3-2014 21:48:11  
5:   * Author: Daniel  
6:   */   
7:    
8:    
9:  #include <avr/io.h>  
10:  #include <avr/interrupt.h>  
11:    
12:  int main(void)  
13:  {  
14:      PORTB = 7;  
15:      DDRB = _BV(DDB0) | _BV(DDB1) | _BV(DDB2) | _BV(DDB3) | _BV(DDB4);  
16:    
17:      TCNT0 = 0;  
18:      TIMSK0 = (1 << OCIE0A); // interrupt on compare match  
19:      TCCR0A = _BV(WGM01);  
20:      TCCR0B = _BV(CS01); // F_CPU / 8  
21:      OCR0A = 250;  
22:      asm("sei");  
23:    while(1)  
24:    {  
25:        // do nothing!  
26:        asm("sleep");  
27:    }  
28:  }  
29:    
30:  uint8_t cathodeCounter = 4;  
31:  uint8_t anodeCounter = 0;  
32:    
33:  ISR(TIM0_COMPA_vect, ISR_NAKED)  
34:  {  
35:      uint8_t sreg = SREG;  
36:      static uint8_t counter = 0;  
37:      ++counter;  
38:      if ( counter >= 75 )  
39:      {  
40:          counter = 0;  
41:          ++anodeCounter;  
42:          if ( anodeCounter == 8 )  
43:          {  
44:              anodeCounter = 0;  
45:              PORTB |= _BV(3);  
46:          }  
47:          else if ( anodeCounter == 1 )  
48:          {  
49:              PORTB |= cathodeCounter;  
50:              cathodeCounter <<= 1;  
51:              if ( cathodeCounter >= 8 )  
52:              {  
53:                  cathodeCounter = 1;  
54:              }  
55:              PORTB &= ~cathodeCounter;  
56:              PORTB &= ~_BV(3);  
57:          }  
58:          PORTB |= _BV(4);  
59:          PORTB &= ~_BV(4);  
60:      }  
61:      SREG = sreg;  
62:      asm("reti");  
63:  }  
64: 

Let's go through this line by line.

12:  int main(void)  
13:  {  
14:      PORTB = 7;  
15:      DDRB = _BV(DDB0) | _BV(DDB1) | _BV(DDB2) | _BV(DDB3) | _BV(DDB4);  
Line 14: Pins B0,B1 and B2 are set high, since they are connected to the cathodes of the LEDs this will make the LEDs go off. B3 (DS) and B4 (SHCP, STCP) are set low.
Line 15: All pins are configured as output pins (except B5, which is the reset pin)

17:      TCNT0 = 0;  
18:      TIMSK0 = (1 << OCIE0A); // interrupt on compare match  
19:      TCCR0A = _BV(WGM01);  
20:      TCCR0B = _BV(CS01); // F_CPU / 8  
21:      OCR0A = 250;  
Line 17-21: Timer initialization, it's set to generate an interrupt on compare match. The value to match is 250. The counter will reset when the match occurs (line 19) and its speed is 1/8th of the cpu speed (line 20).

22:      asm("sei");  
23:    while(1)  
24:    {  
25:        // do nothing!  
26:        asm("sleep");  
27:    }  
Line 22: Inline assembler, the "sei" command will enable interrupts
Line 23 - 27: Do nothing. The "sleep" command puts the cpu in idle state until there's an interrupt. This also reduces power consumption from 3 mA to 0.5 mA.

33:  ISR(TIM0_COMPA_vect, ISR_NAKED)  
34:  {  
35:      uint8_t sreg = SREG;  
Line 33: Start of interrupt handler for timer0 compare match. ISR_NAKED means the compiler won't put any code at the start and end specific to handling interrupts. One of the things you need do do is store the SREG register and restore it at the end, as you can see on line 35
Let's skip some stuff

61:      SREG = sreg;  
62:      asm("reti");  
63:  }  
64: 
Line 61: Restore SREG, not really necessary since we don't have any code in our main loop. But hey, it's good practice.
Line 62: Return from interrupt. Required special command if you exit an interrupt handler.

36:      static uint8_t counter = 0;  
37:      ++counter;  
38:      if ( counter >= 75 )  
39:      {  
40:          counter = 0;  
Line 36-40: The timer is configured to generate 600 interrupts per second, I only need 8, so this slows it down a bit :)

41:          ++anodeCounter;  
42:          if ( anodeCounter == 8 )  
43:          {  
44:              anodeCounter = 0;  
45:              PORTB |= _BV(3);  
46:          }  
Line 41: A counter to run through all the anodes. When it reaches 8, I reset it to 0. I also set B3 (DS) high (line 45).
47:          else if ( anodeCounter == 1 )  
48:          {
56:              PORTB &= ~_BV(3);  
57:          }  
Line 47: On the first interrupt (or the first one after the anode counter has been reset) I set B3 low again (line 56). It'll stay that way until the counter reaches 8 again. So it's high for 1 update, and low for 7.

58:          PORTB |= _BV(4);  
59:          PORTB &= ~_BV(4);  
Line 58: Set B4 (SHCP and STCP) high, this will cause the contents of the shift register to be copied to the storage register, and then shift a new bit from DS into the shift register.
Line 59: Set B4 low again.

And that's pretty much it. This clocks one bit to the shift register every 8th of a second, one one and seven zeroes. So one pin will be high and the others low, and the high pin will shift to the next every 8th of a second.

Now there's just a small piece of code left:
49:              PORTB |= cathodeCounter;  
50:              cathodeCounter <<= 1;  
51:              if ( cathodeCounter >= 8 )  
52:              {  
53:                  cathodeCounter = 1;  
54:              }  
55:              PORTB &= ~cathodeCounter;  
Line 49-55: This handles switching between red green and blue (cathodes). The cathodeCounter variable is a bit mask, only one bit will be set, which corresponds to one of the output pins B0, B1 or B2. I first apply this mask to the pins, which makes the current active pin go high (line 49) turning the LED off. Then I shift the variable left one bit to move to the next pin (line 50). If it goes past the last pin (line 51) I reset it back to the first pin (line 53). Finally I negate the mask and apply it, setting the new active pin low (line 55) turning the LED on.

The reason this piece of code sits inside the anodeCounter == 1 block is because the actual output of the 595 lags one clock cycle behind the content of the shift register. If I had put this code in the anodeCounter == 8 block then the jig would switch colors while the last LED was on. Since we don't want that, we have to wait one more cycle.

That's it! I hope this gives a better understanding of the 595 and the test jig :)

Sunday, March 09, 2014

4 down, 60 to go!

This project is going to take some time... I've just finished the fourth pillar and did some timing. I first cut, stripped and straightened 24 wires (for eight columns). This took about an hour, 7.5 minute per pillar. Then I started building pillars.
  • Bend the legs on eight LEDs
  • Trim the leads on the LEDs
  • Insert them in the jig
  • Insert the wires
  • Solder the LEDs
  • Trim the leads on the LEDs further
  • Cut the wires
  • Take the pillar out of the jig
  • Test it using the test jig
That took well over half an hour for the first pillar, 30 minutes flat for the second, and 20 minutes for the third. I did things slightly different for the last pillar. Instead of trimming the leads after bending them I just inserted the LEDs in the jig. I start by slightly pressing the top wire down on the jig and trim the top leads (green) before soldering them. Then I solder the top leads. After that I trim the remaining leads (red and blue). I then slightly bend the leads so they (almost) touch the wires. This makes soldering a bit easier, and you don't risk damaging the solder joint when trimming the leads.

All in all it takes about half an hour to create one pillar. I must admit I'm not that experienced when it comes to soldering, so I might be able to shave a few minutes off on that. It also helps to do things in batches and minimize switching between tools; I've first cut 24 wires, then stripped them and finally straightened them, instead of performing 3 steps on 1 wire after another.

Anyway, at this speed it's going to take about a month to finish all the pillars if I spend one hour a day. Damn...

Saturday, March 08, 2014

You've got mail!

The mailman doesn't seem to be liking me much lately, annoying bubble envelopes every couple of days, and often multiple on the same day. Having delivered mail myself for a few years I can relate to that, but nevertheless it makes me happy when I hear big things fall on the doormat :D
Today's "harvest": 200 LEDs, 5000 91 Ohm resistors, 5000 150 Ohm resistors.

Also visible on the photo are some wires I stripped and straightened. A colleague of mine gave me a golden tip on how to straighten those wires easily, but that's worth its own post and instructional video ;)

Friday, March 07, 2014

Cathode Board ordered!

I decided to go ahead and order a few cathode boards from OSH Park. It's the first time I've ordered a PCB I designed so I'm pretty excited about this. I've ordered six for now, for a total cost of $14.40, just to see if the design is actually going to work or not. Six of these boards is what I need to build a 4x4x4 cube as a proof-of-concept. If they work I can recycle them for the 8x8x8 cube.
OSH Park gives you a rendered preview of what the board is going to look like, pretty neat. Here's the bottom
 And the top:
And now we wait. The boards have been assigned to a panel, once the panel is full it will be manufactured. I believe it takes about 12 days for the board to be shipped, and then another 2 weeks or so before it actually arrives in the mail. So I guess I'll receive them somewhere early April.

Thursday, March 06, 2014

Debugging the pillar test jig

When the cause of a problem is not immediately often it is often good practice to first check for the most obvious mistakes, isolate a few small portions and check if they work and then work your way up, combining the parts you've checked. This approach works pretty well in debugging software and I use it a lot.

I should've used it here as well.

As I wrote in my previous post, only the bottom LED in my pillar would light up properly when I inserted it in the jig. What I also noticed is that this is also when I put the serial data line high (for the other 7 points in the cycle it's low). I also noticed that the serial data pin on the shift register is right next to output pin 0, to which the bottom LED is connected. It's obvious to expect a bad soldering job (if you're familiar with my soldering) so I wanted to rule that out first.
What I did was modify the code a bit, so will put the data line high after 4 cycles as well. This would give me 2 lit LEDs in the loop and would give me a chance to see if only the bottom LED would light up brightly or not. That wasn't the case; both LEDs would light up brightly whenever the serial data pin went high.
Next up was measuring voltages and current on the bright and dim LEDs, this confirmed that the dim LEDs got less volts across them than the bright ones, but it still didn't explain why.
I slowed down the code a bit (one update per two seconds) and started to notice something odd: the shift register would reset after a brightly lit LED would go off. Expecting something more fundamentally to be wrong I ripped all of the jumper wires out of the protoboard and pulled the shift register IC out of its socket. Then I started checking all connections on the protoboard.

I should've started with that really.

I forgot to connect the power supply of the shift register to the power supply of the ATtiny. There was a wire going there and it was soldered to the board, but on the bottom I never connected the wire to the VCC pin... Doh!
I also forgot to solder the pull up resistor on the reset line to 5V and the ceramic capacitor was floating as well. What a mess. I'm a bit puzzled as to why the LEDs would even light up in the first place, probably the shift register got some current through its input pins just enough to keep running. Anyway, I hooked everthing up and it works like a charm now!


Here's the Arduino code. Yes, it's messy and more complicated than it should be since I'm not using any Arduino functions. This way I can simply copy/paste it to AVR studio so it can run on the ATtiny (apart from the timer prescaler setting and counters).I'm using PORTB since that's what the ATtiny13 also has. Arduino pins 8-10 should connect to cathodes R, G and B.Pin 11 should connect to DS and pin 12 to SHCP and STCP.


1:  void setup()  
2:  {  
3:      PORTB = 7; // pull cathode pins high, no current will flow
4:      DDRB = _BV(DDB0) | _BV(DDB1) | _BV(DDB2) | _BV(DDB3) | _BV(DDB4);  
5:      // initialize timer
6:      TCNT0 = 0;  
7:      TIMSK0 = (1 << OCIE0A); // interrupt on compare match  
8:      TCCR0A = _BV(WGM01);  
9:      TCCR0B = _BV(CS02); // F_CPU / 256
10:      OCR0A = 250;  
11:      asm("sei");  // enable interrupts
12:  }  
13:    
14:  uint8_t cathodeCounter = 4;  
15:  uint8_t anodeCounter = 0;  
16:    
17:  void loop()  
18:  {  
19:      // do nothing!  
20:      asm("sleep");  
21:  }  
22:    
23:  ISR(TIMER0_COMPA_vect, ISR_NAKED)  
24:  {  
25:      uint8_t sreg = SREG;  
26:      static uint8_t counter = 0;  
27:      ++counter;  
28:      if ( counter >= 20 )  
29:      {  
30:          counter = 0;  
31:          ++anodeCounter;  
32:          if ( anodeCounter == 8 )  
33:          {  
34:              PORTB |= _BV(3);  
35:              anodeCounter = 0;  
36:          }  
37:          else if ( anodeCounter == 1 )  
38:          {  
39:              PORTB |= cathodeCounter;  
40:              cathodeCounter <<= 1;  
41:              if ( cathodeCounter >= 8 )  
42:              {  
43:                  cathodeCounter = 1;  
44:              }  
45:              PORTB &= ~cathodeCounter;  
46:              PORTB &= ~_BV(3);  
47:          }  
48:          PORTB |= _BV(4);   
49:          PORTB &= ~_BV(4);  
50:      }  
51:      SREG = sreg;  
52:      asm("reti");  // return from interrupt
53:  }
Here is the board with the ATtiny installed. The jumper wires are there to supply power from USB. The second protoboard in the background is my home made programming socket for the ATtiny. It's just a DIP 8 socket with all pins available on female headers. There's a 10 pin male header connected to the necessary ISCP pins so I can just simply connect a flat cable to the USB programmer (shown on the left).
Now all that's left to do is fix the board to the jig and add a power connector, or maybe a 7805 voltage regulator so I can power it from a battery or other external source and make the whole thing more portable :)
As for the ATtiny code:
1:  /*  
2:   * TinyPillarTester.c  
3:   *  
4:   * Created: 6-3-2014 21:48:11  
5:   * Author: Daniel  
6:   */   
7:    
8:    
9:  #include <avr/io.h>  
10:  #include <avr/interrupt.h>  
11:    
12:  int main(void)  
13:  {  
14:      PORTB = 7;  
15:      DDRB = _BV(DDB0) | _BV(DDB1) | _BV(DDB2) | _BV(DDB3) | _BV(DDB4);  
16:    
17:      TCNT0 = 0;  
18:      TIMSK0 = (1 << OCIE0A); // interrupt on compare match  
19:      TCCR0A = _BV(WGM01);  
20:      TCCR0B = _BV(CS01); // F_CPU / 8  
21:      OCR0A = 250;  
22:      asm("sei");  
23:    while(1)  
24:    {  
25:        // do nothing!  
26:        asm("sleep");  
27:    }  
28:  }  
29:    
30:  uint8_t cathodeCounter = 4;  
31:  uint8_t anodeCounter = 0;  
32:    
33:  ISR(TIM0_COMPA_vect, ISR_NAKED)  
34:  {  
35:      uint8_t sreg = SREG;  
36:      static uint8_t counter = 0;  
37:      ++counter;  
38:      if ( counter >= 75 )  
39:      {  
40:          counter = 0;  
41:          ++anodeCounter;  
42:          if ( anodeCounter == 8 )  
43:          {  
44:              PORTB |= _BV(3);  
45:              anodeCounter = 0;  
46:          }  
47:          else if ( anodeCounter == 1 )  
48:          {  
49:              PORTB |= cathodeCounter;  
50:              cathodeCounter <<= 1;  
51:              if ( cathodeCounter >= 8 )  
52:              {  
53:                  cathodeCounter = 1;  
54:              }  
55:              PORTB &= ~cathodeCounter;  
56:              PORTB &= ~_BV(3);  
57:          }  
58:          PORTB |= _BV(4);  
59:          PORTB &= ~_BV(4);  
60:      }  
61:      SREG = sreg;  
62:      asm("reti");  
63:  }  
64:    
Notice how similar it is to the Arduino code. The name of the interrupt handler is a bit different, and I've chosen different values for the timer prescaler and counter, and the setup and loop functions are combined in one main function. This code uses 208 bytes (20%) of ROM and 4 bytes (6%) of SRAM. Even the ATtiny13A is a bit overkill for something like this :)

Anyway, that's it for today, I'm always glad when something is working by the time I decide to call it a day :)

Wednesday, March 05, 2014

Pillar testing jig v1.1

I didn't like my initial version of the pillar testing jig much; it's too much work putting on 11 connectors and I'd have to use quite a bit of force to get the connector on, risking some bent leads. So I came up with the following contraption:
I can just clamp the anode leads between the two pieces of wood. There are connectors running through the top piece into the wires. And on the bottom side they touch the anode leads.
And when the pillar is clamped in it'll look like this:
It's just a few pieces of wire going through the wood, bent 90 degrees. But it works fairly well. As long as I press down on it all leads make contact, just gravity isn't enough. But hey, it only takes a couple of seconds to see if all LED leads are connected or not.
Unfortunately there's not demonstration video yet. I still have a small glitch somewhere in my protoboard which causes the bottom LED to light up brighter than the rest. To be more precise; when the DS line on the shift register goes high, the LED connected to Q0 lights up bright. And the other ones are just dim whenever they turn on.
 Great, I hate debugging hardware... :)

The ATtiny still needs to be installed, but I want to fix the brightness issue first. I also need some different connectors for the cathodes, these Dupont connectors simply aren't suitable for this kind of work.

Tuesday, March 04, 2014

Theory

In this post I want to take some time to explain the schematics. I want this to be as accessible as possible, so we'll start at the very beginning.

Connecting an LED

LEDs arent' like ordinary light bulbs. You cannot (read: should not) connect an LED directly to a battery. The reason for this is that an LED has a very low internal resistance, so you'll effectively be shorting the battery. Sure, it will work if the voltage is right, but you risk damaging the LED. They're also picky about the voltage, so you'll want to provide an LED with just the right voltage.

To accomplish this we put a resistor in series with the LED. To get the right resistor value you need a couple of parameters: the forward voltage of the LED (VF), the input voltage (VI), and the forward current (IF). The forward voltage of an LED depends on its color. Red usually means 2.4V, Green and Blue 3.4V. The input voltage of my cube is 5V. The forward current of an LED is typically 20mA (0.02A). Check your datasheets for your specific LEDs to verify this.
Now we need our input voltage VI to drop to VF, so that's VI - VF Volts. Then we simply apply Ohm's law (I = U/R, or R = U/I) and we get R = (VI - VF) / IF. So for a red LED that's (5 - 2.4) / 0.02 = 130 Ohm. For green and blue it's (5 - 3.4) / 0.02 = 80 Ohm.

Let's wire up a red LED to 5V. 130 Ohm resistors aren't that common, so we'll use the next best thing: 150 Ohm. Remember, LEDs are Light Emitting Diodes, so they'll only let current flow from one lead to the other, specifically from the anode (long lead) to the cathode (short lead, and the side where there's a flat spot).

That was simple enough, now let's try something more interesting.

Connecting an RGB LED

Multicolor LEDs come in two configurations: common Anode and common Cathode. They are basically multiple LEDs in one package with either the anode or cathode lead shared between all LEDs.
Does it matter which one you use? Not really, as long as you know what type you're using/ordering. This also has consequences for where you place the series resistor. You shouldn't connect your resistor to the common lead of your LED, unless you have a bi-color LED where both LEDs have the same forward voltage, or you're using the highest resistor value.

For the rest of this post we'll be using common anode LEDs, since that's what I'm going to put in my cube.

Connecting it is easy, just hook 5V to the common anode, a few resistors to each cathode and the other end of the resistor to ground.

Controlling an RGB LED

So we've got our RGB LED burning, but now we want to control it. We want to be able to turn each color on and off. So we grab our Arduino (or other microcontroller) and hook our LED up. Instead of connecting the resistors to ground, we connect each resistor to a I/O pin of the microcontroller. With an AVR, like the Atmega328 that's on an Arduino Uno/Nano, we can set the pin to OUTPUT mode (low impedance), and by writing a digital LOW we connect the pin to ground (it sinks current), and the LED will turn on. By writing a digital HIGH we connect the pin to 5V (it sources current) and the LED will turn off (since both the anode and cathode are connected to 5V, no current will flow).

While this works fine for one RGB LED, and even for two or three, any more will start to become a problem. Remember how an LED has a forward current of 020mA? If you turn all three colors of an RGB LED on that becomes 60mA. If you connect 4 RGB LEDs and turn them all on you'll be putting 240mA through the microcontroller. Now google the datasheet for the Atmega328 and have a look at chapter 29. Electrical Characteristics, section 1 Absolute Maximum Ratings. It says: DC Current Vcc and GND pins: 200mA. Whoops, we possibly just killed our Arduino. Also note how the DC Current per I/O pin is just 40mA, so don't even think about connecting more than one LED to a pin.

So we'll need to come up with some way to reduce the amount of current going through our microcontroller. Fortunately, there's this thing called a transistor. With just a tiny amount of current you can control a much larger amount of current. A transistor has three leads: Base, Collector and Emitter. The base lead is used to control the amount of current flowing between the collector and emitter. There are two types of transistors: NPN and PNP. In an NPN transistor, a small current entering the base is amplified to produce a large collector and emitter current. (http://en.wikipedia.org/wiki/Bipolar_junction_transistor#NPN)

A PNP transistor works the other way around. When you pull the base low (connect to ground) a larger current will flow from the emitter to the collector (notice how the flow of current between the emitter and collector is reversed compared to a NPN transistor).

We'll be using a NPN transistor. We need a transistor that has a maximum collector current of at least 20mA. Then there's this thing called the gain. This figure indicates how much more current there is going to flow through the collector and emitter, compared to how much flows through the base and emitter. Basically it's your amplification. We need at least 20mA, but we don't want to use that much to control it. So let's use a gain of 10, this way we only need 2mA to control 20mA.

If you have a look at the datasheet of the 2N3904 you can find the following figures:
Collector Current : 200mA
DC current gain (at 1mA IC (input current)) : 70
That's well within specs.

The required base current will be 20mA / 70 = 0.3mA. Now we need to find a resistor to give us at least 0.3mA. First we have another look at the datasheet, we need to find the base-emitter saturation voltage, which happens to be between 0.65 and 0.85V, so 0.75 average. Enter Ohm's law again. (5V - 0.75V) / 0.0003A = 14166 Ohm. So a 10K resistor will do the trick, this will give us (5V - 0.75V) / 10000 = 0.4mA. A lower resistor like 1K will work as well, but it'll increase the power consumption, add extra heat, shorten the life of our components, etc. Don't even think about directly connecting your I/O pin to the transistor base lead since you'll effectively be shorting it to ground and kill your micro controller. If you want to read a bit more, click here.


That's it for now, next time I'll explain the anode driver and shift registers :)

Monday, March 03, 2014

Pillar testing jig

After soldering a pillar of LEDs you'll want to test it to make sure you didn't make any mistakes. It's much easier to fix mistakes at this point than fixing them when the cube's fully assembled. So here's a little setup I came up with to make testing easier:

It's an ATtiny13 connected to an 74HC595 shift register. The outputs of the shift register are connected to the anodes of the pillar. The cathodes of the pillar are connected to pins PB0-2 of the ATtiny and have a few series resistors. By configuring the pins as output pins we can sink some current when we write them low, turning the LEDs on. When we write a high to the pins we source current and the LEDs go off. So with the shift register we can control which LED should be on, and with the input pins we can select the color.
Normally you'd use some transistors instead of connecting the LEDs to the pins/register directly because the ATtiny nor the shift register will be able to handle the current of all LEDs going on simultaneously (3 x 8 x 20mA = 480 mA), but we'll program the ATtiny to only turn on one LED at a time so we can get away with this setup.

Both the storage and shift clock of the shift register are connected to PB4, this causes data that is shifted into the register to appear almost directly on the output pin, which is fine for this setup. The output enable is connected to ground so we'll have continuous output. The reset pins of both ICs are connected to +5V through a 10K pull-up resistor. The DS pin of the 595 is connected to PB3, the Q7S pin is left floating since we're not using it, which seems to be common practice. There's a 100nF ceramic cap added as a bypass for the ICs, and a power connector of course.
And for kicks, here's a dirty PCB:
For my test jig I'm not going to put those LEDs on the board, instead I'll have a three terminal connector near the resistors to connect the cathode wires of the pillar to. And an eight terminal connector for the anodes.

As you can see, I used Fritzing for this quick prototype. It just works a bit faster and the breadboard view is handy for this situation. If you want to download the Fritzing project, click here.

As for the programming: that's easy:
  • Setup
    • DDRB should be set as input for PB5 (reset) and output for PB0-4
    • PORTB should be set high for PB0, PB1 and PB2 so they don't sink any current. 
    • define an eight bit anode counter variable, initialize it with 1.
    • define a cathode counter variable, initialize it with 1.
  • Main loop
    • Start setting PORTB to 7, so we set PB0-2 high
    • Shift the anode counter variable out on PB3 while toggling PB4.
    • Set PB3 low and toggle PB4 twice to shift out a zero, because the 595's output is lagging behind one cycle.
    • Shift the anode counter variable left by one.
    • Toggle one of the output pins by writing the cathode counter variable to PINB.
    • Shift the anode counter variable left one position.
    • If the result is zero, set it to one. Shift the cathode counter variable left one position as well.
    • If the result is eight, set it to one.
    • Add a delay for 1/8th of a second.
It's probably easier to put everything in an interrupt handler and leave the main loop empty. All we need to do is set a timer. Factory default for an ATtiny13 is 9.6MHz (depends a lot on ambient temperature and supply voltage), If we set the timer prescaler to 64 we'll have the timer running at 150,000Hz. If we then set the timer to generate an interrupt every 250 timer ticks we get an interrupt frequency of 600Hz. If we execute our code every 75th interrupt we'll get exactly 8Hz, perfect!
One thing I can't remember correctly is whether or not the system clock prescaler is active by default. If so then it's set to 8, reducing the system clock to 1.2MHz. We can tackle this by changing the timer prescaler to 8, so we'll still have our 150,000Hz timer clock. Easy!

Here's a video of the setup without using the cathode shifting.
And here is the setup on a protoboard, connected to the pillar. Still no cathode shifting and driven by an Arduino; I've stuck some jumper wires into the DIP socket for the ATtiny to connect the Arduino.

I'm not too happy with the custom cable I made. It's a bit too much work to stick those connectors in and I risk bending the anode legs. I think I'll create a wooden jig with some contacts, to place the pillar in.

Sunday, March 02, 2014

Jig: Mk. 2

Sunday afternoon, a perfect moment to spend some time in the man cave :)

I decided to build another jig, since the first one is, well... crap. The main reason for that are my lack of skills. Fortunately there are plenty of tools to compensate for it, and my old man has a shed full of 'em :)

Starting with a nice jig to compensate for my horrible skills with a saw (it even says "no skills required" on the box, perfect!)
 Finally, 90 degree angles! I decided to make the columns in the jig 10mm deep, that will leave 15mm of space left for putting the LEDs in. I want the columns to be about 14mm wide, so there will be around 11mm of space between the LED pillars when they're installed. Unfortunately the wood is 22mm thick. Sawing that off would be a pain in the behind, so enter tool nr 2:
Yes, it's an electric planer. At the highest setting it turns 2mm of wood into a large pile of dust. So after using it four times I end up with a 14mm wood instead of 22, and a work bench covered in wood particles. Nice.
Back to the hand saw, 8 columns of 10mm done. Time to put some holes in them.
Since they're 14 mm wide, I've drawn a line 7mm from the top, and a vertical line right in the center. For the drilling, enter tool nr 3:
It's my trusty Dremel in the Dremel Workstation. Perfect for drilling some perfectly vertical holes.
Spot on, right through the center! That's just a 3mm drill, but the hole needs to be 5mm. I enlarged the holes using my cordless drill. The existing hole will guide the larger drill, so the hole remains in the center.
Then it's simply a matter of drawing a few lines on the base plate. The lines are spaced 25mm apart and there are two lines crossing them to mark the sides of the colums. Those are 14mm apart and 15mm from the edge.
Add glue, apply pressure. This is the fast drying type, takes about 15 minutes to cure. Tightening and loosening the clamps needs to be done carefully. Add the center clamp first, then the outer ones. Don't tighten them completely right away, but tighten each one a bit and move to the next. Removal is done in reverse order (center one last).

In the mean time, I created a small jig for bending the LED's legs.
Simply insert the LED, bend the legs, and press another piece of wood on top. Easy! The front and back plate are done as well:
The outer holes are 14mm apart, the center hole is 7mm above the outer holes.
After the glue has dried, it's time to drill a couple of holes from the bottom into the colums. Again, I used the Dremel for this to make sure the holes are perfectly vertical and spot on down the center of the colums.
Let's put in some screws. It's important to put a load of pressure on the columns so they won't start to rotate when you put the screws in. Clamping the whole thing down seems to work pretty well. The front and back plate had the same treatment.
And after about 3.5 hours it's done! Let's put in some LEDs!
 Nice! Works like a charm, now let's cut the three wires so we can pull the pillar out of the jig.
No problems there, plenty of room!
That's usable, may need a bit of bending, but not bad!
And it works!
Compared with the one from the first jig (at front). The space between the LEDs and the cathode wires has become a lot smaller (20mm to 14mm) and the distance between the LEDs has been reduced from 30mm to 25, awesome.

The next step is rigging up a framework to test a pillar. I'll probably just use one shift register to turn on each anode sequentially while sourcing one of the cathodes. After cycling through all anodes it'll move to the next cathode. So it'll first light up all reds, then all greens, then all blues and then all reds again, all in a matter of a few seconds.Guess I'll wire up an AtTiny on a protoboard to make it a semi permanent setup, I just need to get my hands on a dozen alligator clips :)

Saturday, March 01, 2014

Some PCB tweaking

Digging through some datasheets I discovered that I had the MR pin (Master Reset) of the 74HC595 shift registers tied to 5V, so I wouldn't be able to reset it from a microcontroller. I fixed it by widening the data connector to 5 pins and connecting the extra column to MR. I also realized the footprint on the design doesn't match the package of the chips I've ordered; the footprint should've been slightly narrower.

On the cathode board there was no room for the extra pins, so I had to move the power indicator LED to the other side of the board, It's now located near the power connector. I've also added a bunch vias in various places that are connected to GND. This helps the ground fill occupy a larger part of the board. I've also rerouted a couple of traces to make things prettier :)

On the anode board there was a bit more room for the extra pin, but connecting the extra pin took a bit more work. On the anode board the pins are pretty much right next to the pins on the IC. On the cathode board the traces have to cross each other.
One of my colleagues noticed the 100 Ohm resistor between the MOSFETs drain and GND. Ohm's law tells us that a 100 Ohm resistor at 5 Volts will have 0.05 Ampères running through it (I = U/R). It also tells us that there will be 0.25 Watt to handle (P = U^2/R). That doesn't sound like much, but an ordinary 0603 sized resistor is only rated at 1/8th or 1/10th Watt. I don't want to add through hole resistors, so I ordered a bunch of 2512 sized resistors, they're rated at 1 Watt (and easier to find than 1210s). There's plenty of space on the board for the increased footprint, so no problem there. I may be moving the caps to the other side of the board so the MOSFETs have more room for heat dissipation (and electrolytic caps don't like heat much).

Thursday, February 27, 2014

Shopping

Buying electronics on eBay; my favorite way to kill time :)
It's amazing how little you pay for hundreds of components, most of the time it's less than what you'd pay for shipping alone if you'd buy it from some European supplier like Conrad or Elfa. Sure, I have to wait a week or two for the items to arrive, but who cares? Here's a small selection of items that have arrived in the past week:
6 meter of rainbow flat cable, 100 meter 22AWG wire, 100 8P dupont connector housings, 10 electrolytic capacitors, 50 ceramic smd caps, 200 sot-23 transistors, 200 RGB LEDs and 5000 1K ohm 0603 resistors.

Some people ask me if I'm afraid to get ripped off. The answer is no, not really. I've done nearly 100 transactions in the last couple of years, only 1 never arrived, and I blame that on the mail :) None of the items on the photo above have cost me more than $20, so even if an item never arrives, I never lose a significant amount of money. I'd be more bummed by having to wait two more weeks :)

I have a few favorite sellers which I'll pick if the difference isn't too big. They are, in no particular order:
Ele-parts
G&C supermarket
Tayda2009

But most of the time, I'll just try to find the cheapest ;)

Creating a jig


Probably the most important tool when constructing the cube is the jig. It hold the wires and LEDs in place when you solder them, making life a whole lot easier. This jig is used to create a pillar of LEDs; 8 LEDs stacked on top of each other with all their cathodes connected.
I've bought a piece of wood, about 44 mm wide and 20 mm thick, and cut it into pieces. I've cut off eight pieces of 20 mm to hold the LEDs, and two pieces of 80mm to go on each end. The bottom part is about 250 mm. In the 8 "columns" I've drilled 5mm holes, 1 cm from the top. The distance between the hole and the edges of the columns determines the distance of the wires to the LED.
I've drilled three 3 mm holes on both ends to hold the wires. The position of these holes should match the top and sides of the columns, so the wires will touch the columns.

This was just a prototype I made to figure out the what works and what doesn't. I recommend taking your time for designing and constructing the jig, as it will eventually determine the quality of your cube.

Plan your cube; think about how large you want it to be. I'm going for a 1 inch spacing between all LEDs. This means that the front of a jig column should be one inch away from the front of the next and previous  jig column. The width of the columns shouldn't exceed 20mm, this leaves just 5 mm of space between the pillars of LEDs. As you can see, the design of the jig determines the dimensions of the cube. And make SURE you keep plenty of room between the bottom LED and the end of the jig, you'll need this extra wire to install the pillar.

Things that went wrong:
  • I'm not that great with wood, I used a hand saw and a portable electric drill. The result is far from perfect. Next time I'll use an electric jig saw for cutting and my Dremel workstation to drill straight holes.
  • Use glue. The columns rotate a bit, so next time I'll glue them first, then drill holes from the bottom before screwing them in place. This should keep them perfectly in place.
  • Make the columns thinner. The space between the columns is a bit too small to comfortably put the LEDs in and out; they tend to get stuck.
  • Make the columns narrower. Right now I'm creating pillars that are 20 mm wide, I think I'm going with 12 or 15 mm instead, so I'll have more space between the pillars.
 Here's the result of my first test with the jig:
 Not too shabby. I had to put quite a bit of force on it to get it out of the jig so it's a bit bent. A few more lessons learned:
  • Make sure you have plenty of clearance between the columns, one of the LEDs got stuck.
  • Make sure you bend the legs of all LEDs equally, or they might push the wire away making it difficult to solder other LEDs. I'm probably going to create a jig for bending the legs as well.
  • Place the LEDs before you place the wires, it's much easier that way.
  • When done, cut the wires at the top of the pillar first, then pull the pillar back so the LEDs are freed, then cut the wires at the bottom of the pillar on the outside of the jig, this gives you another extra cm of wire.
  • Straightening the wire is done by inserting them into the jig, tie their ends together and rotate the bunch. This will put tension on the wires and that will make them nice and straight. Don't put too much tension on them or they will break!
And a few things to keep in mind:
  • Test your LEDs before you put them in the jig, make sure they work and that the brightness is the same as the others; you really don't want to replace a LED when your cube is already constructed.
  • You can use a wire stripper to strip the wire, but I like to use a snap off knife. Just place the wire on a surface, place the knife on the wire and hold it almost parallel to the wire, then gently pull the wire along the knife and half of the insulation will be stripped away in one go. You can peel the other half off easily.
  • The wire I got is pre-tinned, and it looks great! Much better than bare copper in my opinion.
  • You can straighten the wires a bit before inserting them in the jig. Use two pliers to grab both ends of the wire, then tug on them gently a couple of times. Don't do this too hard or too often because the ends will suffer from metal fatigue and break.
  • WASH YOUR HANDS! You're not going to get lead poisoning from breathing fumes, only lung cancer. But the lead does get on your hands, so make sure you wash your hands thoroughly before you eat, drink, rub your eyes, scratch your <insert bodypart>, etc. Also clean your working surface and don't put food on it.
  • Don't breath the fumes, it's not exactly healthy. Using a small 12V computer fan is enough to blow most of the fumes away from you. Keep your mancave/shed/living room well ventilated.
That's it for now, once I'll have my final jig done I'll add another post on this subject.

Designing some PCBs

Having decided that I didn't want a big mess of wires and several square feet of prototype boards, I set out to design a PCB to accommodate all the circuitry. Initial drafts were made using Fritzing, a very accessible open source program.
I wanted to have one shift register with eight transistors and all required resistors on one small board, so I could control 8 cathodes. The design had to be small and stackable; you should be able to put multiple boards on top of each other easily.

Designing a PCB is surprisingly easy. All you need to do is create the schematic in the schematic view by placing all components and drawing wires between the connectors.

 Then you go to the PCB view and set all the right footprints for the components (components may come in various forms, like through hole or surface mount, check the datasheets of your components). After that it's simply a matter of placing the components on the PCB in a logical way. The software will draw lines between pads that need to be connected to each other (so called rats nests) and all you need to do is draw traces between unconnected pads, making sure they don't cross and aren't too close to each other. The software will check for the most obvious design faults.
The above pcb is about 5 by 2 cm (2 by 0.8 inch) and can control the cathodes of 8 LEDs. Check out the result in 3D (made with KiCad):
The row of 8 pins are connected to the cathodes of the LEDs. The double pin header next to the shift register are the data pins which are connected to the microcontroller. The pins of the bottom row are connected to the pins above them, except for the last one in each row. The bottom one is data in, the top one is data out. When you stack these boards, you can connect the top 4 pins (output) to the bottom 4 pins (input) of the board above it. The data out of the bottom board will be connected to data in of the board above it. Pretty neat eh? The signal on the other pins of that connector are the same for all boards. They´re (in no particular order) Clock, Reset and Latch. The three pin connector (drawn in blue) is the power connector.

Although Fritzing is very easy to use, it has its limitations. Which is why I switched to KiCad, which is also open source and free, but it's much more professional. Id' say Fritzing is nice to learn the basics, but KiCad is great when you start to run into Fritzing's limitations. The learning curve for KiCad is much higher though, but there are some great tutorials that'll help you get started. Plus it has a 3D view :)

I've also designed an Anode driver board to hold a shift register and the MOSFETs, it can be connected the same way as the Cathode boards.
You've probably noticed the thick traces, those are needed to handle the 5 A current that will be flowing when the cube is fully lit. It's about 7 by 5 cm (3 by 2 inch).

The cool thing about these boards is that you can use them not just for a cube, but also for LED bars or LED matrices.
Above pictures are of older versions, the current design has some minor improvements.