Friday, January 01, 2010

How to control a 7-segment LED using an Arduino

A couple of weeks ago Make: Online posted a link to a project on connecting a 7-Segment LED to the Arduino. It uses the technique of using one pin for each LED segment, which does get the job done, but it also gobbles a lot of pins in the process. I wanted to try to use binary data to reduce the number of pins used.

Method:

Binary data can code values 0 to 7 in 3 bits and values 0 to 15 in four, so a 7-segment LED could use as few as 3 lines for each display but taking advantage of that would require a logic circuit on the board to decode the data. I was short on transistors to make my own decoder, but I still have an assortment of 74LS logic devices I got from Jameco around 2003.

Unfortunately, all three of the three chips I had (74LS47, 74LS138, 74LS139) that would get me close to what I wanted assumed a common anode on my 7 segment display, and I had a common cathode display (RadioShack's stocked-in-store display). So I waited out the weekend and then went by Sparkfun and got a few of these common anode displays.

Back at home, I wired up two of the displays to two 74LS47 chips. The easy part of this was that matching up the diagrams of the two devices was a matter of drawing a line from little a to little a. The tougher part was putting a 100 ohm resistor in that line and routing it across my breadboard. I did get everything hooked up and running well on the 3 volts.

Next I had to get signal lines from the Arduino to the breadboard which quickly became a rat's nest of wires. I knew from my time in the shop that every wire was increasing the confusing and the potential for creating a fault I would never find, so I stopped and made a cable.

I had on hand a cat-5 cable my dog chewed up during one of her first couple of months with us. Slicing it open, I found 8 stranded wires twisted into four color-coded pairs. I used crimp connectors and two 1x4 housings to make an 8 to 8 cable to carry the data to each chip.

With the cable, it was time to write some code.

The 74LS47 takes 4 lines of binary coded data (BCD) and turns them into a map of the associated decimal number.

For my first pass, I used a switch case to set four separate variables for each display, each containing one of the four bits. This worked as long as I was sending the same data to each display. But the same thing could be accomplished with an extra set of jumpers on the breadboard, so clearly I needed different data to each.

This step ended up simplifying the code because using the switch case to set all 8 bits would require 99 cases. What I found trying to avoid that was bitRead(x,n). This allowed me to use the bits of my value as the code to send the chip.

The heart of my new sketch is this:

    for (d=0; d<4; d++){
digitalWrite(Rled[d],bitRead(j,d));
digitalWrite(Lled[d],bitRead(i,d));
}


This loops through two arrays which contain the pins (i.e. 7,8,9,10) and sets the pin high or low depending on the value of that bit (d) in the current number (i or j).

Result:



The results are quite satisfactory. I'm using a 0 to 9 loop for the 10s digit and another 0 to 9 loop for the ones. The 10s increments once for each loop of the ones. The size of the full sketch is 2378 bytes and I'm using only 8 of 14 digital pins to get the output. This compares to 3212 bytes for my switch case code and 8 pins for the original example.

Next:

My next steps with this project are to use button input to affect the numbers displayed. My plan is to make a universal gaming die where the user selects 4, 6, 8, 10, 12, 20, or 100 faces, presses the go button, and gets a random output. Results to follow!

Labels: , , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home