9 digit numbers and words on 7 segment using large digit driver from Sparkfun

Hi,
I'm pretty certain this is my first post on the forums. I've been tinkering successfully and enjoyably with Arduinos for the best part of 12 years. I've successfully completed numerous projects and have read hundreds, possibly thousands of posts and tutorials over the years so do not post this lightly. I finally seem to have bitten off slightly more than I can chew, thinking that what I was attempting to do was straightforward.

A friend on mine is doing a one man theatre show and wants to display a series of numbers and words (mindful of the limitations of 7 seg displays) behind him as he talks to the audience. The choice of 7 segment displays is deliberate for aesthetic purposes, to be as far removed from a powerpoint presentation and still able to display data on stage.

He wants to cue through the numbers using a simple controller, one button for forward 1 cue 1 button for back 1 cue. The finished show is likely to have somewhere between 50 and 100 numbers/words to display

I thought this would be a doddle, I'll have it for you by the weekend I thought!

I have bought 9 off 6" 7 segment displays, 9 large digit driver boards and have soldered the boards to the digits and wired them all together in the manner described on the sparkfun large digit driver page.

i've connected them to a spark fun arduino Red, which to all intents and purposes seems to act like an UNO but with a bit of extra power handling.

I have fallen at the fist hurdle though

With only the example code provided by sparkfun, which to me was fairly impenetrable to start off with. I've been able to display up to 5 digits using the modified code below:

 /*
//This code has been clumsily butchered from the original sparkfun example to try and display larger numbers

Controlling large 7-segment displays
By: Nathan Seidle
SparkFun Electronics
Date: February 25th, 2015
License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

The large 7 segment displays can be controlled easily with a TPIC6C594 IC. This code demonstrates how to control
one display.

Here's how to hook up the Arduino pins to the Large Digit Driver

Arduino pin 6 -> CLK (Green on the 6-pin cable)
5 -> LAT (Blue)
7 -> SER on the IN side (Yellow)
5V -> 5V (Orange)
Power Arduino with 12V and connect to Vin -> 12V (Red)
GND -> GND (Black)

There are two connectors on the Large Digit Driver. 'IN' is the input side that should be connected to
your microcontroller (the Arduino). 'OUT' is the output side that should be connected to the 'IN' of addtional
digits.

Each display will use about 150mA with all segments and decimal point on.
*/

//GPIO declarations
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
byte segmentClock = 6;
byte segmentLatch = 5;
byte segmentData = 7;

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void setup()
{
Serial.begin(9600);
Serial.println("Large Digit Driver Example");

pinMode(segmentClock, OUTPUT);
pinMode(segmentData, OUTPUT);
pinMode(segmentLatch, OUTPUT);

digitalWrite(segmentClock, LOW);
digitalWrite(segmentData, LOW);
digitalWrite(segmentLatch, LOW);

int x = 0;

}

void loop()
{
showNumber(12345); //the number to be displayed (changed from 42 in original example)
}

//Takes a number and displays 2 numbers. Displays absolute value (no negatives)
void showNumber(float value)
{
int number = abs(value); //Remove negative signs and any decimals

//Serial.print("number: ");
//Serial.println(number);

for (byte x = 0 ; x < 5 ; x++) //increased this from 2 to 5 to display larger number anything above 6 doesnt seem to work though
{
 int remainder = number % 10;

 postNumber(remainder, false);

 number /= 10;
}

//Latch the current segment data
digitalWrite(segmentLatch, LOW);
delay(300); // I put these delays in to see if it would help with the digits syncing but they are redundant I think
digitalWrite(segmentLatch, HIGH); //Register moves storage register on the rising edge of RCK
delay(300); // I put these delays in to see if it would help with the digits syncing but they are redundant I think
}

//Given a number, or '-', shifts it out to the display
void postNumber(byte number, boolean decimal)
{
//    -  A
//   / / F/B
//    -  G
//   / / E/C
//    -. D/DP

#define a  1<<0
#define b  1<<6
#define c  1<<5
#define d  1<<4
#define e  1<<3
#define f  1<<1
#define g  1<<2
#define dp 1<<7

byte segments;

switch (number)
{
 case 1: segments = b | c; break;
 case 2: segments = a | b | d | e | g; break;
 case 3: segments = a | b | c | d | g; break;
 case 4: segments = f | g | b | c; break;
 case 5: segments = a | f | g | c | d; break;
 case 6: segments = a | f | g | e | c | d; break;
 case 7: segments = a | b | c; break;
 case 8: segments = a | b | c | d | e | f | g; break;
 case 9: segments = a | b | c | d | f | g; break;
 case 0: segments = a | b | c | d | e | f; break;
 case ' ': segments = 0; break;         // Can't work out why these cases are inculded when they can't be called or am I just being really thick???
 case 'c': segments = g | e | d; break;
 case '-': segments = g; break;
}

if (decimal) segments |= dp;

//Clock these bits out to the drivers
for (byte x = 0 ; x < 5 ; x++) // the 5 in this line of code is the number of digits displayed (when increased to 6 to display 123456 things go odd)
{
 digitalWrite(segmentClock, LOW);
 delay(300);
 digitalWrite(segmentData, segments & 1 << (7 - x));
 delay(300);
 digitalWrite(segmentClock, HIGH); //Data transfers to the register on the rising edge of SRCK
 delay(300);
}
}

If I change the code to add 6 digits (having worked up 1 extra digit at a time from the 42 example in the code) or more the number displayed remains 5 digitis long but is truncated ie the first digit is dropped

After lots of research I thought that this might be because of the use of float in the code limiting the number of digits that can be used.

So what I'm moving towards is a program that has an array with 50 to 100 alphanumeric words/numbers

As I understand it these will be displayed in a manner which is different to the technique used in the sparkfun example as I will not be applying mathematical functions to the variables (checking for signs, and decimals etc.) but will be displaying a series of strings. So I think I'm barking up the wrong tree attempting to modify the sparkfun code anyway...

I understand that this using an array of this size may require more memory, so figure that might be a another problem I come up against.

If someone could give me a steer as to how to go about this, I would be truly grateful...

Many thanks for reading and thanks in advance for any help/guidance you are able to offer

Dave

OK, first things first.

You need to go and read the forum instructions so that you can go back and modify your original post (not re-post it) - using the "More -> Modify" option below the right hand corner of your post - to mark up your code as such using the "</>" icon in the posting window. Just highlight each section of code (or output if you need to post that) from the IDE and click the icon.

In fact, the IDE itself has a "copy for forum" link to put these markings on a highlighted block for you so you then just paste it here in a posting window. But even before doing that, don't forget to use the "Auto-Format" (Ctrl-T) option first to make it easy to read. If you do not post it as "code" it can easily be quite garbled and is always more difficult to read due to the font.

It is inappropriate to attach it as a ".ino" file unless it is clearly too long to include in the post proper. People can usually see the mistakes directly and do not want to have to actually load it in their own IDE. And even that would also assume they are using a PC and have the IDE running on that PC.

Also tidy up your blank space. Do use blank lines, but only single blanks between complete functional blocks.

Are these the 7 segment leds ( 12 volt, common anode, 20mA per segment ):

Are these the led driver boards ( TPIC6C596 shift register with 15 ohm segment current limiting resistors):

You have 9 sets of each. If you have followed the instructions for chaining these together, and have respected the power requirements, then it is a pure software matter. That you have already got some digits to display is already a very good sign.

The first thing is that this is not going to scale up:

void loop()
{
  showNumber(12345); //the number to be displayed (changed from 42 in original example)
}

It looks like you are receiving into a float so you will lose precision and probably wont be able to handle both numbers and the subset of letters that you can display using seven segments.

I guess that, you will somewhere have to have an intermediate storage structure which represents the display, say something like:

char display[10] ;

where display[0] through to display[8] are the 9 "characters" you want to display and display[9] is a null terminator.

You will load this array display[] from your stored phrases , then process each character in the array, converting its internal character representation into a series of segments and their status (lit/unlit) and push these out to the chain of shift registers which control the displays, somehow handling "undisplayable" characters. You'll probably find easier examples than the one you are working with.

Have you thought about how you are going to load and manage the 50 to 100 phrases you want to display ? 100 phrases is 1KB (1KB is, incidentally, the maximum for the built-in eeprom). Initially, as a proof of concept, you could embed these in the sketch itself.

Whatch the variables involved. Ant int can be from -32767 to + 32767. Un unsigned int can be from 0 to 65535. For 7 digits You need to make shure that long, or unsigned long is used.

Paul__B:
OK, first things first.

You need to go and read the forum instructions so that you can go back and modify your original post (not re-post it) - using the "More -> Modify" option below the right hand corner of your post - to mark up your code as such using the "</>" icon in the posting window. Just highlight each section of code (or output if you need to post that) from the IDE and click the icon.

In fact, the IDE itself has a "copy for forum" link to put these markings on a highlighted block for you so you then just paste it here in a posting window. But even before doing that, don't forget to use the "Auto-Format" (Ctrl-T) option first to make it easy to read. If you do not post it as "code" it can easily be quite garbled and is always more difficult to read due to the font.

It is inappropriate to attach it as a ".ino" file unless it is clearly too long to include in the post proper. People can usually see the mistakes directly and do not want to have to actually load it in their own IDE. And even that would also assume they are using a PC and have the IDE running on that PC.

Also tidy up your blank space. Do use blank lines, but only single blanks between complete functional blocks.

Sincere apologies for my formatting faux pas. Unfortunately due to Covid related work and child care pressure I'm only able to access my laptop for an hour or 2 a week (depending on toddler nap times) the rest of the time I'm trying to do things fumble fingered on an Android phone from the cab of a truck during tachograph breaks . This project is an attempt to retain some sanity by focusing on something other than what is going on around me.

6v6gt:
Are these the 7 segment leds ( 12 volt, common anode, 20mA per segment ):
https://www.sparkfun.com/products/8530

Are these the led driver boards ( TPIC6C596 shift register with 15 ohm segment current limiting resistors):
SparkFun Large Digit Driver - WIG-13279 - SparkFun Electronics

You have 9 sets of each. If you have followed the instructions for chaining these together, and have respected the power requirements, then it is a pure software matter. That you have already got some digits to display is already a very good sign.

The first thing is that this is not going to scale up:

void loop()

{
 showNumber(12345); //the number to be displayed (changed from 42 in original example)
}




It looks like you are receiving into a float so you will lose precision and probably wont be able to handle both numbers and the subset of letters that you can display using seven segments.

I guess that, you will somewhere have to have an intermediate storage structure which represents the display, say something like:

char display[10] ; 

where display[0] through to display[8] are the 9 "characters" you want to display and display[9] is a null terminator.

You will load this array display[] from your stored phrases , then process each character in the array, converting its internal character representation into a series of segments and their status (lit/unlit) and push these out to the chain of shift registers which control the displays, somehow handling "undisplayable" characters. You'll probably find easier examples than the one you are working with.

Have you thought about how you are going to load and manage the 50 to 100 phrases you want to display ? 100 phrases is 1KB (1KB is, incidentally, the maximum for the built-in eeprom). Initially, as a proof of concept, you could embed these in the sketch itself.

Hi 6v6gt,

This is VERY helpful thanks.

The 7 segment displays are the same ones you linked to (again apologies for not including link in my original post)

The driver boards are also the same ones you linked to.

Using the original spark fun code I've been able to display 2 digits repeated ie

424242424

So hardware all appears to be working ok.

When I display a 5 digit number the display shows:

123451234 (from memory, I can check again next Sunday morning, or possibly thursday afternoon, toddler nap routine permitting)

So that's ok too.

Your code suggestion is very helpful. I shall start working that up.

I had thought about memory, I realised that I would be right on the limit. From my initial research I had considered using a board with more memory, like the Due maybe? An extra £20 or £30 on another board could save me weeks of head scratching. I started with a Red add that was the board used in the spark fun 'tutorial' so I figured I would minimize the number of factors that were different from the original example into I understood what way going on.

Thanks again for your help.

(I'll be able to sort my code formatting in my original post by next weekend, I promise :slight_smile: )

OK. Since you are not regularly at the keyboard at the moment, I guess it is better to wait until you are in a position to try things. However, I'll just say this now because it may save you ordering something unnecessarily.

  1. The Sparkfun Red Board SparkFun RedBoard - Programmed with Arduino - DEV-13975 - SparkFun Electronics will work for this with out additional expense and could handle all those phrases, but it may not be so convenient because you would have to hard code all the phrases in your sketch(and force them into flash memory). This means that you have to recompile your sketch each time to manage the phrases. (Flash memory is 32KB and a large amount of this is available for your data)

  2. Then you have various other options, if you want the user to be able to manage phrases without a recompilation. Probably an SD card is best because you can manage that on a PC using an editor. But also external eeproms are cheap and big, but then you have to include in your sketch some code to allow the user to update it.

So it think it is important to have an idea of how this data should be managed before investing too much more additional resources in the project.

6v6gt:
OK. Since you are not regularly at the keyboard at the moment, I guess it is better to wait until you are in a position to try things. However, I'll just say this now because it may save you ordering something unnecessarily.

  1. The Sparkfun Red Board https://www.sparkfun.com/products/13975 will work for this with out additional expense and could handle all those phrases, but it may not be so convenient because you would have to hard code all the phrases in your sketch(and force them into flash memory). This means that you have to recompile your sketch each time to manage the phrases. (Flash memory is 32KB and a large amount of this is available for your data)

  2. Then you have various other options, if you want the user to be able to manage phrases without a recompilation. Probably an SD card is best because you can manage that on a PC using an editor. But also external eeproms are cheap and big, but then you have to include in your sketch some code to allow the user to update it.

So it think it is important to have an idea of how this data should be managed before investing too much more additional resources in the project.

That's an interesting idea, I'd read about borrowing memory from elsewhere in the distant past which I guess is what you're talking about, that sounds really interesting.

I think your idea of the SD card is probably the best way to go though, it would be really good for the operator to be able to edit the contents themselves whilst on tour.

The show will inevitably evolve and it would be good for the performer to be able to just dump a new CSV on an SD card (or even have different cards with different versions of the show)

I think I might have an ethernet shield kicking around somewhere that has an SD slot on it, so that might be the way forward. It might be at least 10 years old based on the project I used it for was in the last house we lived in, so I'm guessing there might be a few more options available now.

Before you go too far down the road, be sure to evaluate up front what words you want to display and how this will work on your planned displays. The letters “m”, “k”, “x” and “w” are impossible to display meaningfully on a standard 7 seg display. That eliminates lots of words. “V” is tough although if not located near a “u” can be finessed.

Are those limitations acceptable for the production?

Neopixels would give you more flexibility.

steve20016:
Before you go too far down the road, be sure to evaluate up front what words you want to display and how this will work on your planned displays. The letters “m”, “k”, “x” and “w” are impossible to display meaningfully on a standard 7 seg display. That eliminates lots of words. “V” is tough although if not located near a “u” can be finessed.

Are those limitations acceptable for the production?

Neopixels would give you more flexibility.

Good point Steve, This exact limitation is what is driving the creative process.

I think the whole thing is actually a massive set up so that he can display:

80085

And other school boy humour.

A 7 segment display was chosen deliberately because of it's low tech appearance and limitations.

To be as far as possible from the powerpoint presentation.

Technology and art can be uncomfortable bedfellows sometimes, but that is a much longer conversation!

Makes sense. (59009!)

In the next stage of my progress I have worked up this code, it's commented heavily, so although long it should help somebody like me who has been trying to work this out for weeks!

This sketch counts from 0 to 9 using a really short piece of code that I found a lot easier to understand than the example on the Sparkfun tutorial... that's probably just down to me though :slight_smile:

[code]
// For use with Sparkfun LARGE DIGIT DRIVER BOARDS (may work with other shift registers but that's down to you!)
// Prepared by Dave Wilkie based on a method learnt by watching a video by Kristian Blåsol entitled: Using a 74HC595 to connect an Arduino to a 7-segment LED display - Anything Arduino episode 9
// This sketch was written to work with Sparkfun large digit driver boards using the wiring method outlined in the Sparkfun Large Digit Driver Board hookup guide.
// I could not get my head round the mehtod used in the Sparkfun example so hopefully this might be easier to understand for some people.

// Here is a lookup table to show how to display each individual digit:
// digit    corresponding decimal number
//   1                 96
//   2                 93
//   3                117
//   4                102
//   5                 55
//   6                 63
//   7                 97
//   8                127
//   9                103
//   0                123
// Using the method used in this sketch/program Each segment has a numerical value as shown below in this diagram:

//                            1 (top segment value=1
//                          -----
//            Top left    2|     |64 top Right
//      Middle Horizontal   --4--
//    Bottom Left         8|     |32 Bottom Right segment
//     Bottom horizontal    --16-
//
// So referring to the above diagram  if we wanted to display a number 8 we would add together 1+2+4+64+8+16+32 = 127
// so this bit of code:
// shiftOut(segmentData, segmentClock, MSBFIRST, 127);
// will display a number 8
// to display a number 1 we want the right 2 segments with a combined value of 64+32=96
// therefore:
// shiftOut(segmentData, segmentClock, MSBFIRST, 96);
// Would display a number 1
// This is a simple sketch to count from 0 to 9, if using a single 7 segment unit the numbers will count up on the single digit, if additional digits are connected as per the spark fun guide then the numbers will scroll to the right as they count up
// This is due to the fact that as the latch pin is raised and lowered each large digit driver board will shunt the configuration that is on it out of the right handside to be stored by the next digit and so on down the line.
// If you have 9 digits (as I have) in order to display a nine digit number one would write the latch pin low ShiftOut 9 digits and then write the latch pin high again.
// Think of the data being written as a flow of water flowing left to right and the latch Pin acting as a dam to stop the flow at whatever point the data is at. Once data flows out of the furthest right digit it is lost/deleted/evaporates/goes over the waterfall!

byte segmentLatch = 5;// Pin 5 goes to LAT on the IN side of the first Spark fun large digit driver board
byte segmentClock = 6;// Pin 6 goes to CLK on the IN side of the first large digit driver board
byte segmentData = 7;// Pin 7 goes to SER (as in Serial Data) on the IN side of the first large digit driver board
int charArray[10] = {123, 96, 93, 117, 102, 55, 63, 97, 127, 103}; // These values are the codes required to display the digits 0 to 9 See lookup table in the commenst above.

void setup()
{

  Serial.begin(9600);
  pinMode(segmentLatch, OUTPUT);
  pinMode(segmentData, OUTPUT);
  pinMode(segmentClock, OUTPUT);
}
void loop()
{

  
  for (int i = 0; i <= 9; i++) {  // this is instigates a loop which counts from 0 to 9, each time the loop goes round it increments the count by one and displays the next character in the array. 
    //The array is there to change the digit required to the code needed to display it
   
    digitalWrite(segmentLatch, LOW);
    shiftOut(segmentData, segmentClock, MSBFIRST, charArray[i]);
    digitalWrite(segmentLatch, HIGH);
    Serial.print ("charArray="); // these lines are so you can monitor what's going on via the serial monitor... they're not essential
    Serial.print (charArray[i]); // these lines are so you can monitor what's going on via the serial monitor... they're not essential
    Serial.print ("i="); // these lines are so you can monitor what's going on via the serial monitor... they're not essential
    Serial.println (i); // these lines are so you can monitor what's going on via the serial monitor... they're not essential
    delay (500); // dealy is here just to slow things down so it's easier to see what's going on.
  }
   
}

[/code]