Pages: [1] 2   Go Down
Author Topic: 4 digit 7-segment counter with only 1 shift register  (Read 7900 times)
0 Members and 1 Guest are viewing this topic.
ON, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 13
What have you done with your Arduino today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm a new Arduino user (convert?) and wanted to do something simple for my first project. As I hadn't seen anything similar to my approach I thought I would post my results to share with others. The result is a 4 digit counter I made from a pair of 2 digit common cathode 7-segment displays. Similar projects used a 75HC595 for each digit. I went for a multiplexed approach with a single shift register driving the segments (anodes) and 4 digital i/o pins each driving a NPN transistor to switch in each cathode one at a time. I connected all the 'a' segments of each display to each other and then connected that to the QA output of the shift register. See the great tutorial elsewhere on this site. Similarly, connect each of the 'b' thought 'h' segments of the display to each other and to the corresponding pin on the shift register. Next I wired in the cathode drivers by driving each one with a 2N3904 transistor so as to not overload the Arduino pins. Specific details are in the code comments. The sketch just counts from 0 to 9999 and then starts over. Not much really but I had a lot of fun making it and learned a lot about Arduino in the process. The next step is to attach the DS1307 and turn the display into yet-another-arduino-clock. Here is the code:

/*

 2011-10-26
 
 Paul Jenkins
 
 This code is in the public domain.
 
 //
 
 Example code for driving a 4 digit common cathode 7-segment display with
 a 74HC595 8-bit shift register and 4 NPN transistors.

 The 74HC595 shift register attaches to pins 8, 11 and 12 of Arduino.
 See Arduino ShiftOut tutorial for more info:
   http://www.arduino.cc/en/Tutorial/ShiftOut
   
 Arduino digital pins 4 to 7 drive the cathode for digits 1 through 4.
 Digit 1 is the leftmost. Wire the emitter of the NPN transistor to ground.
 Connect the Arduino digital pin to the base of the transistor via a
 1 k-ohm resistor so as not to provide excessive base drive and damage
 the transistor. Connect the collector of the transistor to the cathode of
 the display.
 
 Be sure to use current limiting resistors from the shift register outputs
 Qa to Qf to the anode segments of the LED display. I used 220 ohm resistors.

 * Shift Register  Arduino
 * 14  SER           11       Serial Input
 * 11  SRCLK         12       Shift Clock
 * 12  RCLK           8       Latch Enable

*/

// Define the bit-patterns for the 7-segment displays
const byte SevenSeg[16] =
{
     // Hex digits
     B11111100, B01100000, B11011010, B11110010,   // 0123
     B01100110, B10110110, B10111110, B11100000,   // 4567
     B11111110, B11110110, B11101110, B00111110,   // 89AB
     B00011010, B01111010, B10011110, B10001110,   // CDEF
 
};

// Pin connected to latch pin (RCLK,12) of 74HC595
const int latchPin = 8;
// Pin connected to clock pin (SRCLK,11) of 74HC595
const int clockPin = 12;
// Pin connected to Data in (SER,14) of 74HC595
const int dataPin  = 11;
// Pin connected to cathodes
const int disp1 = 7;  // Displays are numbered from left to right
const int disp2 = 6;  // as disp1 to disp4.
const int disp3 = 5;  // Scan displays quickly and use POV to display
const int disp4 = 4;  // 4 digits with only 1 shift register

//
void setup()
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin,  OUTPUT);
  pinMode(disp1, OUTPUT);
  pinMode(disp2, OUTPUT);
  pinMode(disp3, OUTPUT);
  pinMode(disp4, OUTPUT);

//
void loop()
{
for (int i=0; i < 10000; ++i)
  {
    // Display i as 4 digits on the display.
    // No leading zero blanking.
    for (int j=0; j<20; j++) // Draw the display several times to slow it down
      SevenSegDisplay(i);
  }
}

void DisplayADigit(int dispno, byte digit2disp)
{
 
  // Turn off the shift register pins
  // while you're shifting bits:
  digitalWrite(latchPin, LOW);
 
  AllDispOff();  // Turn off all cathode drivers.
 
  // shift the bits out:
  shiftOut(dataPin, clockPin, LSBFIRST, digit2disp);
 
  digitalWrite(latchPin, HIGH);  // Set latch high to set segments.
 
  digitalWrite(dispno, HIGH);  // Drive one cathode low to turn on display.
 
  delay(5);  // Wait a bit for POV

}

void AllDispOff()
{
  // Turn all cathode drivers off
  digitalWrite(disp1, LOW);
  digitalWrite(disp2, LOW);
  digitalWrite(disp3, LOW);
  digitalWrite(disp4, LOW);
}

void SevenSegDisplay(int number)
{
  int d1,d2,d3,d4; // Temporary values for thousands, hundreds, tens and units
 
  if (number > 9999)
     number = 9999;  // Do some bounds checks to avoid strangeness
  if (number < 0)
     number = 0;
 
  d1 = (int) (number / 1000);    // Get thousands
  number = number - (d1 * 1000);
  d2 = (int) (number / 100);     // Get hundreds
  number = number - (d2 * 100);
  d3 = (int) (number / 10);      // Get tens
  d4 = number - (d3* 10);        // Get units
 
  DisplayADigit(disp1,byte(SevenSeg[d1]));  // Show thousands
  DisplayADigit(disp2,byte(SevenSeg[d2]));  // Show hundreds
  DisplayADigit(disp3,byte(SevenSeg[d3]));  // Show tens
  DisplayADigit(disp4,byte(SevenSeg[d4]));  // Show units
 
}
Logged

Fun = Arduino + Imagination

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nice work!

If you attached a second shift register and use 4 of its outputs to drive the NPN transistors you are driving with digital pins, you may save those 4 pins and even go to 8 7-segment displays smiley-wink The shift registers are cheap.
Logged


ON, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 13
What have you done with your Arduino today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the suggestion liudr. I hadn't thought of that. I'll check the data sheet on the 595 to see if it can sink the current of all seven segments being on at once. I had bought a whole tube of the shift registers 'cuz they were so cheap and I figured I might burn out 1 or 2 of them in my tinkering. Some times I check the wiring *after* applying power.  smiley-evil I only have a small 30-row breadboard right now so it is packed. When I get to my bigger bb I'm going to take your suggestion and expand it to 6 digits (that's all the displays I have). Then there will be room for the time chip and battery too and I can include seconds with the time.

Somewhere I remember seeing a circuit similar to what you described to drive a 44780 type LCD in 8-bit mode with the RS and E lines wired to a second 595. There may even be a shield or breakout board (AdaFruit?) that does this. Personally I find it more fun and educational to build the circuits myself first on a breadboard and play with them rather than buy a ready-to-go solution.

I will post new code once I make the modifications. Cheers!
Logged

Fun = Arduino + Imagination

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I also have tubes of 595s. IIRC, 20ma per channel and some max current per chip. I use 5 arduino pins and 2 595 to sense 16 keys and control 8 leds.
Picture:
http://liudr.wordpress.com/gadget/phi-panel/on2_32/

http://liudr.wordpress.com/gadget/phi-panel/assembly7_32/

« Last Edit: October 27, 2011, 10:18:25 pm by liudr » Logged


ON, CA
Offline Offline
Newbie
*
Karma: 0
Posts: 13
What have you done with your Arduino today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you Dr Liu for your words of encouragement. I never did go ahead with adding the digit drivers to a second shift register as I got busy with other aspects of the Arduino. I may add another pair of digits and a second shift register and make my breadboard circuit into a shield at some point in the future. I did add a DS1307 to this circuit and make a simple clock (who doesn't make a clock with their Arduino at some point  smiley-wink ) and this also taught me some valuable lessons.

I was thinking of maybe adding some discrete LEDs to the shift register outputs and physically placing them on a design such as a Christmas tree and then getting the Arduino to blink them in various patterns. Perhaps in response to motion in the room (I do have an ultrasonic sensor board squirreled away somwhere) or sound. Maybe even play a tune (I've discovered RTTTL and got the Arduino to play music). I will be sure to share any results with my fellow forum members. This is such an awesome community and I want to give back as much as I can as I have benefited so much from reading other posts and being inspired by what all of you are doing with your Arduinos. Cheers.
Logged

Fun = Arduino + Imagination

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Random thought: a x-mas tree only kids can light up. You take two sonic rangers one mount high 4 ft and one mount low, 2ft from floor. If the top one senses nothing and the bottom one senses something, turn on the blink sequence. Certainly you can sense ghosts too if only the top sensor returns values (assuming ghosts reflect ultrasonic waves of course).
Logged


Minneapolis, MN USA
Offline Offline
Full Member
***
Karma: 2
Posts: 162
Never catch a falling soldering iron...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually, you should not source or sink more than 6mA per pin on a 74HC595 and not more than 70mA for the whole chip.  It's not intended to drive LEDs.  If you have all 7 segments on at 20mA, that's 140mA. 

I designed the Digit Shield to use a single 595 and a 74LS247 BCD to 7-segment driver to multiplex four 7-segment displays.  Four of the 595 outputs control PNP transistors sourcing current to the common anode displays.  The other 4 outputs drive the 4 inputs of the 74LS247 to set the value of the current digit.  This approach only requires 3 Arduino pins, plus one more to control the decimal points.  The shield uses pins 2,3,4,5.

More info: http://nootropicdesign.com/digitshield/

Logged

Bristol, UK
Offline Offline
Full Member
***
Karma: 1
Posts: 125
part time tinkerer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

megabump! not wanting to start a new thread when this one is perfectly acceptable!\

if exchanging the smaller digits for larger ones, specifically the KINGBRIGHT SA23-11EWA, rated at;
12v supply voltage, and 140mA max current

and using the TPIC6B595 in place of the 595, (150mA max supply current, 50v max voltage)

is the 2N3904 NPN transistor still a viable component? the data sheet does state;

collector base 60v
collector emitter 40v
emitter-base voltage 6v
collector current 200mA

All of my numbers are inside these figures, but a little yay or nay from the community will help!

Thanks
Logged

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 524
Posts: 26471
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

TPIC6B595 sinks current.
NPN transistor generally used to sink current also.
You want PNP to source current into the common anodes.
http://www.kingbrightusa.com/images/catalog/SPEC/SA23-11EWA.pdf
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Bristol, UK
Offline Offline
Full Member
***
Karma: 1
Posts: 125
part time tinkerer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

so, if i've understood you right, then this is what i've come up with...

it doesn't work however, hence my posting in here.

the 3rd segment isn't wired in here, but its run the same as the second.
at the moment, i'm running the arduino from the usb 5v, and the segments are from the 12v and the gnd's are connected (as shown)

also, the code i have is for 4 segments, and i'm only using 3, so i've just commented out the thousand section of the code, and reduced the number code to 999 instead of 9999

tiny edit, the segment is actually common cathode
http://il.rsdelivers.com/product/kingbright/sc23-11ewa/he-red-7-segment-led-sc23-11ewa-23in/4516587.aspx



Code:
// Define the bit-patterns for the 7-segment displays
const byte SevenSeg[16] =
{
     // Hex digits
     B11111100, B01100000, B11011010, B11110010,   // 0123
     B01100110, B10110110, B10111110, B11100000,   // 4567
     B11111110, B11110110, B11101110, B00111110,   // 89AB
     B00011010, B01111010, B10011110, B10001110,   // CDEF
 
};

//Pin to clear the register
const int clearPin = 7;    // Pin connected to clear pin (SRCLR) of TPIC6B595
const int latchPin = 8;    // Pin connected to latch pin (RCK) of TPIC6B595
const int clockPin = 12;   // Pin connected to clock pin (SRCK) of TPIC6B595
const int dataPin = 11;    // Pin connected to Data in (SER IN) of TPIC6B595

// Pin connected to cathodes
const int disp1 = 7;  // Displays are numbered from left to right
const int disp2 = 6;  // as disp1 to disp4.
const int disp3 = 5;  // Scan displays quickly and use POV to display
const int disp4 = 4;  // 4 digits with only 1 shift register

void setup() {
  pinMode(clearPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin,  OUTPUT);
  pinMode(disp1, OUTPUT);
  pinMode(disp2, OUTPUT);
  pinMode(disp3, OUTPUT);
  pinMode(disp4, OUTPUT);
 
  // Always start by setting SRCLR high
  digitalWrite( clearPin, HIGH);
 
  // delay a little and then set
  delay(100);
}


void loop()
{
  for (int i=0; i < 1000; ++i)
  {
    // Display i as 4 digits on the display.
    // No leading zero blanking.
    for (int j=0; j<20; j++) // Draw the display several times to slow it down
      SevenSegDisplay(i);
  }
}

void DisplayADigit(int dispno, byte digit2disp){
 
  // Turn off the shift register pins
  // while you're shifting bits:
  digitalWrite(latchPin, LOW);
 
  AllDispOff();  // Turn off all cathode drivers.
 
  // shift the bits out:
  shiftOut(dataPin, clockPin, LSBFIRST, digit2disp);
 
  digitalWrite(latchPin, HIGH);  // Set latch high to set segments.
  digitalWrite(dispno, HIGH);  // Drive one cathode low to turn on display.
 
  delay(5);  // Wait a bit for POV
}

void AllDispOff(){
  // Turn all cathode drivers off
  digitalWrite(disp1, LOW);  // thousands off
  digitalWrite(disp2, LOW);  // hundreds off
  digitalWrite(disp3, LOW);  // tens off
  digitalWrite(disp4, LOW);  // units off
}

void SevenSegDisplay(int number)
{
  int d1,d2,d3,d4; // Temporary values for thousands, hundreds, tens and units
 
  if (number > 999)
     number = 999;  // Do some bounds checks to avoid strangeness
  if (number < 0)
     number = 0;
 
  d1 = (int) (number / 1000);    // Get thousands
  number = number - (d1 * 1000);
  d2 = (int) (number / 100);     // Get hundreds
  number = number - (d2 * 100);
  d3 = (int) (number / 10);      // Get tens
  d4 = number - (d3* 10);        // Get units
 
//  DisplayADigit(disp1,byte(SevenSeg[d1]));  // Show thousands (3 digits, don't show)
  DisplayADigit(disp2,byte(SevenSeg[d2]));  // Show hundreds
  DisplayADigit(disp3,byte(SevenSeg[d3]));  // Show tens
  DisplayADigit(disp4,byte(SevenSeg[d4]));  // Show units
 
}
« Last Edit: April 22, 2013, 07:03:03 pm by kelvinmead » Logged

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 524
Posts: 26471
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

PNP needs to connect to +5, LEDs are all upside down,
TPIC6B595 gets power from 5V, not 12.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Bristol, UK
Offline Offline
Full Member
***
Karma: 1
Posts: 125
part time tinkerer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the tpic needs 5v... damn, read the sheet wrong, read as max 50v input doh. how sensitive are these chips? have i probably destroyed it by pumping 12v in? i never got the pop / burn / smell...

i appreciate that the leds are the wrong way around in this diagram now

where the pnp needs to connect to +5, am i wrong in thinking that the output of the leds goes to the collector, the output (digital 5v) from the arduino goes to the base, and then the emitter goes to gnu?

so the transistor is acting like a switch, when the base goes HIGH the current flows to gnd, lighting the led?
Logged

Bristol, UK
Offline Offline
Full Member
***
Karma: 1
Posts: 125
part time tinkerer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ahh, i get it, ive got the transistor connected to gnd, when it should be supplying the current.

ill be back!
Logged

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 524
Posts: 26471
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

50V on the open drain outputs, yes, not on the vcc line. They are most likely goners.


* 4x7_tpic6b595_pnp.jpg (54.72 KB, 960x720 - viewed 143 times.)
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Bristol, UK
Offline Offline
Full Member
***
Karma: 1
Posts: 125
part time tinkerer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thats what i managed, albeit without the resistors across the transistors.

and i have a crossed gnd somewhere as the mac just instantly shutdown when i added power... :-/

fresh eyes in the morning.

thanks mr crossroads.
Logged

Pages: [1] 2   Go Up
Jump to: