A simple single digit seven segment display

Take a look at this one - Arduino Playground - SevenSegment Library.

Rather than having a separate pair of functions for each number, it has an array that stores the pattern for each number in a single byte and iterates through the bits to light the segments.

arduinohabib:
I wrote a simple library for a common cathode seven segment display, you can add it in a new tab.
Please feel free to use it or post comments!

What happens if I do this?

two();
seven();

That will make it display a two on top of a seven.

You first have to define which pins you connect abcdefg segments to in your sketch. Then if you type zero(); then the seven segment display will display zero, one(); will display one, etc. zerooff(); will turn zero off. clearall(); will turn everything off. This is an example:

#include"sevenseg.h"
int test;
#define a 13
#define b 12
#define c 11
#define d 10
#define e 9
#define f 8
#define g 7
#define dp 6
void setup(){
pinMode(a, OUTPUT);
pinMode(b, OUTPUT);
pinMode(c, OUTPUT);
pinMode(d, OUTPUT);
pinMode(e, OUTPUT);
pinMode(f, OUTPUT);
pinMode(g, OUTPUT);
pinMode(dp, OUTPUT);
}
void loop(){
zero();
delay(1000);
zerooff();
one();
delay(1000);
oneoff();
two();
delay(1000);
twooff();
three();
delay(1000);
threeoff();
four();
delay(1000);
fouroff();
five();
delay(1000);
fiveoff();
six();
delay(1000);
sixoff();
seven();
delay(1000);
sevenoff();
eight();
delay(1000);
eightoff();
nine();
nineoff();
}

[/quote]

Please use code tags instead of quote. It's the '#' button next to the quote tag button.

Why not just turn off the segments that aren't needed? Then you wouldn't need the xxxoff functions.

That's a great idea! Thanks a lot!

arduinohabib:
That will make it display a two on top of a seven.

You first have to define which pins you connect abcdefg segments to in your sketch. Then if you type zero(); then the seven segment display will display zero, one(); will display one, etc. zerooff(); will turn zero off. clearall(); will turn everything off. This is an example:

But then you either have to know what the current display is or call clearAll() which is slow because it writes every segment multiple times.

Wouldn't it be better to have "two()" and "seven()" turn off the segments they don't need as well as turn on the ones they do?

Please feel free to use i

Something like this is basically unusable in a real application. Its timing, critical to such an implementation is loop dependent and its scalability (to add more digits) is poor.

What you should do is to implement it inside of a timer. So all the user application does is to update the display buffer and the display routine will update the display in the background.

What timing? It just digitalWrite()s segment pins high or low.

Thanks so much for the feedback dear friends! I shall modify the library.

I will give you a skeleton:

  1. define a bunch of macros to turn on / off segments / digits. Those macros are Common Cathod or Common Anode aware.
  2. use a routine to initialize all pins.
  3. write a code that upon each call, display one digit from a buffer, and rolls over to the next.
  4. set up a timer, pointer a function pointer to the routine in 2) above.
  5. in the timer isr, execute the function pointer (now pointing to the routine in 2)).

Once that is up, the entire display function is transparent to the user. All the user code needs to do is to fill the buffer as needed and the display routine will update the buffer automagically.

@dhenry - Complete overkill for the requirement, and there are already libraries that do that, including the one I linked to earlier.

dhenry:
I will give you a skeleton:

  1. define a bunch of macros to turn on / off segments / digits. Those macros are Common Cathod or Common Anode aware.
  2. use a routine to initialize all pins.
  3. write a code that upon each call, display one digit from a buffer, and rolls over to the next.
  4. set up a timer, pointer a function pointer to the routine in 2) above.
  5. in the timer isr, execute the function pointer (now pointing to the routine in 2)).

Once that is up, the entire display function is transparent to the user. All the user code needs to do is to fill the buffer as needed and the display routine will update the buffer automagically.

Thank you so much @dhenry! Thank you for the support! I will go by what you said!

arduinohabib:

dhenry:
I will give you a skeleton:

  1. define a bunch of macros to turn on / off segments / digits. Those macros are Common Cathod or Common Anode aware.
  2. use a routine to initialize all pins.
  3. write a code that upon each call, display one digit from a buffer, and rolls over to the next.
  4. set up a timer, pointer a function pointer to the routine in 2) above.
  5. in the timer isr, execute the function pointer (now pointing to the routine in 2)).

Once that is up, the entire display function is transparent to the user. All the user code needs to do is to fill the buffer as needed and the display routine will update the buffer automagically.

Thank you so much @dhenry! Thank you for the support! I will go by what you said!

No...that's way too complex for what's needed.

The library can be improved but there's no need for interrupts or anything like that.

How about doing it with direct port manipulation, speed it up quite a bit.
Or define it to drive the digits from an array:

display[] = {
B00111111, // 0 
B00000110, // 1
B01011011, // 2
B01001111, // 3
B01100110, // 4
B01101101, // 5
B01111011, // 6
B00000111, // 7
B01111111, // 8
B01101111, // 9
}
// write the digits, assume PORTD with bit0 = asegment, 1=b,2=c,3=d,4=e,5-f,6=g, 7=decimal point it used
//    a
// f    b
//    g
// e   c
//    d
// clear the bits
PORTD = PORTD & 0x00
// now set the font
PORTD = display[x]; // x = 0 to 9, or bigger if define some other characters: A,b,C,d,E,F,H,L,P,U, -,_,

and do the library stuff.
That would make it real quick!
Or share the 8 bits across 2 ports if you didn't want to commit D0,D1 to LED driver (serial pins).

Thank you very much. I might have a little trouble figuring it out, but I'll try. Thanks again

Thank you very much!. I may have a little trouble with it but I'll figure it out. Thanks again! :slight_smile: :slight_smile: :slight_smile:

What you really want to do, in order to benefit from your efforts in writing this piece of code, is to make it flexible and modular enough so that you can re-use it sometime down the road.

The issue with typical LED displays, and the benefits of using chips like max72xx, is that they have to be constantly updated in a multiplexing environment. That means you cannot put them into a loop yet be assured of the performance in any given projection.

The purpose of my proposal is to make the LED display look like a controller-based LCD display: all you need to be concerned about is the buffer and the actual display related activities are handled behind the scenes, completely transparent to you.

To get you started, think of the segment led displays as a dot matrix display. Your display routines are simply transmitting the buffer data to the segment pins / digit pins. Your user application can load up whatever segment information they want into the buffer and it will be displayed there.

Let's say that you are dealing with a 8-digit 7-segment display, common cathod (aka max7219 clone).

You need to figure out a flexible way to define the segment pins

#define SEG_A  2 //led's segment A connected to pin 2
#define SEG_B  5 //led's segment B connected to pin 5
...
#define SEG_DP 10 //led's segment DP connected to pin 10

//macros to turn on / off a pin, common cathod
#define SEG_ON(pin)  pinWrite(pin, HIGH)
#define SEG_OFF(pin) pinWrite(pin, LOW)

Similarly, you can define the digital pins

#define DIG0  11  //digit0 on pin 11
..
#define DIG7  13  //digit7 on pin 13

//macros to turn on / off a digit pin, common cathod
#define DIG_ON(pin)  pinWrite(pin, LOW)
#define DIG_OFF(pin) pinWrite(pin, HIGH)

Now, those routines are for common cathode displays. But by changing them quickly, you can reuse the same macro names in a common anode display, or to use a npn switch / pnp switch. The rest of your code remains unchanged.

Using pin names helps repurpose the code in different project, or to facilitate layout / wiring.

With that out of the way, you can write a fairly simple display routine:

volatile unsigned char led_buffer[DIGS_MAX]; //display buffer. DIGS_MAX defines the max number of led digits allowed

void led_display(void) {
  static unsigned char dig=0; //digital counter

  dig += 1; //increment the digit
  if (dig == DIGS_MAX) dig = 0; //reset dig if max digit has been reached

  //turn off all digits
  DIG_OFF(DIG0); DIG_OFF(DIG1); ...

  SEGs_OUT(led_buffer[dig]); //send out segment information

  //turn on the digit
  //can be implemented more cleanly with an array
  switch (dig) {
    case 0: DIG_ON(DIG0); break;
    case 1: DIG_ON(DIG1); break;
  ...
  }
}

So each time, led_display() is called, it displays a number on the led.