Learning Project: Binary LED Display

Hi, folks.

I just recently got myself an Arduino Duemilanove (Atmega 326) and a stack of electronic parts, and decided for an initial project that I’d build a binary display (eventually working up to a binary clock). I’ve built the circuit and written the code, but I can’t get it to work, so I thought I’d ask for some help.

Circuit diagram (note: diagram only shows eight LEDs, because that’s what I could fit easily; it really has ten):

The resistors are 470 ohms each, and the spec sheet for the LEDs says that they operate in the vicinity of 10-20mA.

The code:

int ledArrayLength = 10;
int pinOffset = 2;

void displayNumber( int value ) {
    if( value > -1 && value < pow( 2, ledArrayLength ) ) { //make sure number isn't larger than array can display
        for( int i = ledArrayLength - 1; i > -1; i-- ) {
            int pin = i + pinOffset;

            if( value >= pow( 2, i ) ) {
                digitalWrite( pin, HIGH );
                value -= pow( 2, i );
            } else {
                digitalWrite( pin, LOW );
            }
        }
    }
}

void setup() {
    Serial.begin( 9600 );

    for( int i = pinOffset; i < ledArrayLength + pinOffset; i++ ) {
        pinMode( i, OUTPUT );
    }
}

void loop() {
    for( int i = 0; i < pow( 2, ledArrayLength ); i++ ) {
        displayNumber( i );
        delay( 500 );
    }
}

I’ve tested the circuit for an individual LED and for a pair of LEDs and it worked exactly as expected. 0 didn’t light up anything; 1 lit up as XO; 2 lit up as OX; and 3 lit up as OO. When I add in the other eight LEDs, however, the entire things fails to respond. I still get output to the serial monitor, and that output tells me that the code is working properly*.

So… what’m I missing? Why does it work fine for one or two LEDs, but fails with ten?

  • I added in some Serial.print() calls that output the state of each pin as it did the digitalWrite call, and they came out as expected:

0 = XXXXXXXXXX
1 = XXXXXXXXXO
2 = XXXXXXXXOX
3 = XXXXXXXXOO
… and so on.

You tried it for 1 LED and 2 LEDs, why not add them one at a time till you get to 10?

The resistors sound a bit high to me (who knows nothing, I thought 250ohm) but if you can see the LEDs light then they must be fine. Since you say your code returns what you expect my suspicion turns to the wiring hence the suggestion you add LEDs one at a time.

For one thing pow() is a float function. It takes float arguments and returns float values. Round off errors can occur, even with integer arguments. So, the very first if test may not result in true like you expect.

Further use of the pow function produces the same erroneous results. You really need to develop a different method of computing two to the nth power. Perhaps a simple lookup table for 16 values.

The results you are seeing are consistent with expecting integer results from pow().

The simplest way to do the bit manipulation is with binary shift and mask operations (’<<’’, ‘>>’, ‘&’, etc).

For example, instead of calling pow(2, x), you could just bitshift ‘1’ left by the appropriate number of places.

Also check whether your power supply is capable of powering all those LEDs. Depending how you’re powering your Arduino, it may simply be running out of current.

I've got it up to four, and I think I just noticed something interesting.

One and two LEDs worked as long as I contained them all within the A-E rows on the breadboard; as soon as I crossed over into the F-J rows, they stopped working.

Likewise, while building on the A-E rows, everything worked fine as long as I stayed within the same half (approximately 33-63 on my board). As soon as I crossed into the other half, the fourth LED failed to work. When I rebuilt it so that the fourth one was still within the same half... it suddenly worked. Basically, it seems to work as long as the entire circuit is contained within a single quadrant (although the wire to ground can be anywhere along the side rail--it's currently in the pin closest to A1 on the breadboard).

So.. is there something about the functioning of breadboards I don't understand that is preventing this circuit from working across quadrants?

As I understand it, for any given number n, An-En are connected and Fn-Jn are connected; on the side rails, any given rail is connected all the way from top to bottom (from 1-63).

PeterH:
The simplest way to do the bit manipulation is with binary shift and mask operations (’<<’’, ‘>>’, ‘&’, etc).

For example, instead of calling pow(2, x), you could just bitshift ‘1’ left by the appropriate number of places.

Yeah, I’ve never quite managed to figure out bitshift operators. I intend to look into that once I get the thing working. (My eventual plan is to abstract the whole thing out into a class, and at that point I’ll focus on making it more efficient.)

PeterH:
Also check whether your power supply is capable of powering all those LEDs. Depending how you’re powering your Arduino, it may simply be running out of current.

At the moment, I’m powering it off the USB port of my laptop. The current issue seems likely. I think I’ll continue with radman’s suggestion and see if it seems to run out of juice at some point.

PaulS:
For one thing pow() is a float function. It takes float arguments and returns float values. Round off errors can occur, even with integer arguments. So, the very first if test may not result in true like you expect.

Further use of the pow function produces the same erroneous results. You really need to develop a different method of computing two to the nth power. Perhaps a simple lookup table for 16 values.

The results you are seeing are consistent with expecting integer results from pow().

As far as I can tell, though, the code is working expected. When I was using the serial monitor, I ran it as high as 64 and it produced the expected output every time, so I don’t think that’s what’s messing me up here. I imagine it’ll likely cause issues down the line, though, so I’ll definitely correct that before going too much further.

As I side note: wow, you guys respond fast. I’m used to waiting days for one or two answers on most forums. Thanks!

As I understand it, for any given number n, An-En are connected and Fn-Jn are connected; on the side rails, any given rail is connected all the way from top to bottom (from 1-63).

Depends on the breadboard. Some rails are split in the middle. You actually need to jumper across them if you want power along the whole rail.

Aren't the LEDs shorted out, as you've drawn them?

PeterH: Aren't the LEDs shorted out, as you've drawn them?

I don't think they are (and the times that they've worked so far seem to bear this out). They're diodes, so they'd prevent current from flowing the wrong way, right? I'm assuming you're talking about the part between the LEDs and ground. It's possible there's another short somewhere that I'm not spotting.

PaulS:

As I understand it, for any given number n, An-En are connected and Fn-Jn are connected; on the side rails, any given rail is connected all the way from top to bottom (from 1-63).

Depends on the breadboard. Some rails are split in the middle. You actually need to jumper across them if you want power along the whole rail.

I’ve tried it both ways. This board, at least, seems to have the entire rail connected.

Aren't the LEDs shorted out, as you've drawn them?

I agree, the diagram seems to show the LEDs shorted. It may be that the diagram is incorrect, since some LEDs light.

radman:

Aren't the LEDs shorted out, as you've drawn them?

I agree, the diagram seems to show the LEDs shorted. It may be that the diagram is incorrect, since some LEDs light.

Shorted where?

Sidenote: now up to eight functioning LEDs, all kept within the same quadrant. No sign of current issues.

ryschwith: Shorted where?

Sidenote: now up to eight functioning LEDs, all kept within the same quadrant. No sign of current issues.

On your original diagram you have some green shading. I assume this shows positions that are electrically connected by the breadboard. That corresponds to what I'd expect to see. You show both legs of each transistor connected into the same group of connected sockets. This means the current would go through the breadboard instead of through the LED so none of them would light. To get them to light, you would need to stagger the two legs of each LED so that they were in separate rows in the breadboard. Most likely, this is what you've done and the picture is just a bit inaccurate.

Are the 'working' LEDs at the left end of the breadboard as show in your picture i.e. the end closest to the earth back to the arduino? This would suggest that your bridging link for the earth rail isn't doing its job. Check carefully that the rail you bridged is the same one you connected the LEDs to.

As far as the bitshift-versus-pow() thing goes, I don't know how fast floating point arithmetic is on the ATmega but there's no FP co-processor so they're probably among the slowest operations you can do. Bit shifting on the other hand is probably a single opcode. It's slightly ironic to be using floating point arithmetic to do bit manipulation. It would be considerably more ironic, if this turned out to be a performance critical application. 8)

PeterH: On your original diagram you have some green shading. I assume this shows positions that are electrically connected by the breadboard. That corresponds to what I'd expect to see. You show both legs of each transistor connected into the same group of connected sockets. This means the current would go through the breadboard instead of through the LED so none of them would light. To get them to light, you would need to stagger the two legs of each LED so that they were in separate rows in the breadboard. Most likely, this is what you've done and the picture is just a bit inaccurate.

Are the 'working' LEDs at the left end of the breadboard as show in your picture i.e. the end closest to the earth back to the arduino? This would suggest that your bridging link for the earth rail isn't doing its job. Check carefully that the rail you bridged is the same one you connected the LEDs to.

Oh dear god. I see what you mean. And no, the way I have it in that diagram is exactly how I had it on the breadboard, so yes, I was shorting them. When I was building it all in the A-E rows and it worked, I was using the LED to bridge from the row to the rail, thus eliminating the short. I did this to conserve space, and it didn't occur to me it'd actually make a difference.

Okay, off to rebuild now without being stupid...

(My description over there, right under my name? Now you know why.)

Ayup. That worked. Thanks, folks!

Now to spin up my rather rusty C++ skills...

the way I have it in that diagram is exactly how I had it on the breadboard

Now I admit I am completely lost. Still we solved the problem didn't we ? Gold stars to PeterH.

radman:

the way I have it in that diagram is exactly how I had it on the breadboard

Now I admit I am completely lost. Still we solved the problem didn't we ? Gold stars to PeterH.

I had the legs of the LED on G and I on the same row--so, for example, the annode would be at G60 and the cathode would be at I60. Since F60-J60 are all connected, there were two paths from G60 to I60: one through the LED, and one through H60. H60, obviously, had less resistance, and so there went the current.

You said you were seeing the LEDs light up. With the legs of the LEDs shorted together I would not have though any current would go through the LEDs at all and the LEDs would be off all the time. You would then have spotted the problem quite quickly. Still, if it works now all is well.