External tutorial on 7-Segment Displays (uses AVR)

Go To Last Post
31 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just finished this tutorial and thought it might be useful to some of the folks here.

http://www.embeddedrelated.com/s...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The 7 segment display is ubiquitous in the modern world

Actually, it is becoming less so - as people move on to matrix & graphic displays...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Neil,

I think you are under estimating that.
If you see how many questions on using a 7 segments display still regularly get asked I think it still is something people like to use

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did say, "becoming"

And I was thinking more of commercial products; yes, hobbyists are typically "behind" (sic)...

:wink:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I did say, "becoming"

In which case (like Nixie tubes) there's then a raft of "nostalgia" projects showing the way we used to display stuff - it never dies!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, thanks for the link (I found some interesting links to books in this site) and the notion of multiplexing, which is well explained, might last for a very long time....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:
I just finished this tutorial and thought it might be useful to some of the folks here.

An impressive amount of content on your blog!

A quick skim on the 7-seg article reveals at least one mistake:
" You also only need 8 current limiting resistors (and perhaps driver transistors) along with a driver transistor for each digit."

You don't actually need current limiting resistors. A 1ms pulse at a 1/8th duty cycle is fine for a 2V red LED, even with a 5V drive.

When testing the code, I'd agree series resistors are a good idea, since a bug in the code could burn out a segment.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

p.s. Ada! Really?

I have no special talents.  I am only passionately curious. - Albert Einstein

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A very nice blog-type of presentation, presenting a worked example for a particular layout.

I tend to keep the actual display update and multiplexing out of my ISRs. (As always, "it depends".) My master "tick" might be the 2.5ms as in the example and then all of the other AVR timing such as fetch/debounce every 10ms; display update every 200ms; soft timers; etc. are based off counting those ticks.

I tend to unroll the actual update, usually with a switch off the "dig_index". As noted in the link the pertinent pins are often/usually not in a nice row. I wouldn't necessarily blame the board layout person. A very popular model for us is the Mega48 family. With a crystal, only port D is "complete" 8 bits. And the USART is on that port. If the ADC is used, avoid switching loads on that port. Anyway, with unrolled update there are then explicit "turn off digit n pin" macros that generally resolve into a single CBI. Turn off the segments might be a series of CBI. Doing it individually avoids RMW considerations.

I thought that the repeated-subtract utoi() at 1100 bytes sounded quite large. From previous discussions e.g.
https://www.avrfreaks.net/index.p...
library itoa() takes about 100 bytes and my loop-based utoaz() takes about 200 bytes. Even unrolled for the digits and multiple loops 6x seems strange.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

I thought that the repeated-subtract utoi() at 1100 bytes sounded quite large. From previous discussions e.g.
https://www.avrfreaks.net/index.p...
library itoa() takes about 100 bytes and my loop-based utoaz() takes about 200 bytes. Even unrolled for the digits and multiple loops 6x seems strange.

Sorry for the confusion about the code size - those numbers are the entire program, taken right from the compiler/linker output, but I can certainly see why someone would think it just referred to the code under discussion. I'll add clarification.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ralphd wrote:
kk6gm wrote:
I just finished this tutorial and thought it might be useful to some of the folks here.

An impressive amount of content on your blog!


Thanks. Once I start I have a hard time stopping.

Quote:
A quick skim on the 7-seg article reveals at least one mistake:

Not a mistake, surely! But I do know others who say it's OK to drive the segment without any resistor. While that goes against the grain of my training, I understand that a turned-on driver mosfet, in a uC or externally, is just a resistor with a certain thermal capacity, so there's no theoretical reason to say it can't be done. It would be interesting to compare failure rates with and without resistors, vs the cost of the resistors.
Quote:
" You also only need 8 current limiting resistors (and perhaps driver transistors) along with a driver transistor for each digit."

You don't actually need current limiting resistors. A 1ms pulse at a 1/8th duty cycle is fine for a 2V red LED, even with a 5V drive.

When testing the code, I'd agree series resistors are a good idea, since a bug in the code could burn out a segment.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ralphd wrote:
p.s. Ada! Really?

Ada on ARM Cortex M - my dream team!

I've got a short video of my little ARM/Ada board generating a compiler-generated out of range exception and displaying the file name and line number on the LCD.

Which call would you rather get from a customer (or better, a beta tester!):

"I did XYZ and everything just locked up"

or

"I did XYZ and got a message on the screen that says paint_zebra.adb, line 257, then it locked up."

Assuming, that is, that the bad code even got past the compiler.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

"I did XYZ and got a message on the screen that says paint_zebra.adb, line 257, then it locked up."

A decent implementation of assert() and some well placed tests ought to be able to achieve something similar in C.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

"I did XYZ and got a message on the screen that says paint_zebra.adb, line 257, then it locked up."

A decent implementation of assert() and some well placed tests ought to be able to achieve something similar in C.

Yes, but the one takes no extra effort and never forgets a test or gets the test wrong or clutters up user code with lots of tests you have to dig through to find the guts of the routine. IMO there's no comparison.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:
ralphd wrote:
p.s. Ada! Really?

Ada on ARM Cortex M - my dream team!

I prefer more determinism in my code - my ideal language would be somewhere in between assembler and C.

To each his own...

I have no special talents.  I am only passionately curious. - Albert Einstein

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm just a neo-luddite and all this ADA stuff is not familiar.

But could you clear up one thing?

Quote:

got a message on the screen that says paint_zebra.adb, line 257, then it locked up.

In this microcontroller app that the user is running--where is the "screen"? where does the file name and line number come from?

GNAT sez the executable file size is not changed when the debug info is created.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
I'm just a neo-luddite and all this ADA stuff is not familiar.

But could you clear up one thing?

Quote:

got a message on the screen that says paint_zebra.adb, line 257, then it locked up.

In this microcontroller app that the user is running--where is the "screen"? where does the file name and line number come from?

GNAT sez the executable file size is not changed when the debug info is created.


There is what is called a last chance handler that is called on any non-handled exception (that is, not handled in the function or procedure that generates it). This procedure receives a C-pointer filename and an integer line number. I imagine it's the same mechanism that an assert would use. This info is stored in the debug image, I don't know the details.

In the last chance handler it's up to you to decide what to do with the info. Out of the box it just sets an LED and spins forever. I modified it to write the info to a character LCD, as seen in the 2nd Ada tutorial I posted at embeddedrelated. Or, one could send it out a serial port, write it to some debug memory, whatever makes sense.

I don't understand how GNAT can say the executable size is not changed. I'd have to see where they say that and in what context.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I modified it to write the info to a character LCD, as seen in the 2nd Ada tutorial I posted at embeddedrelated.

But that means you have to store that info in your microcontroller somewhere. While it could certainly be compressed more than a naive filename/line number pair for each possible trap point, that is still going to be sizable isn't it? (Aaah, I'll bet you can tell exactly from the build results of the app you are mentioning. About how many traps are there? Size of "executable"? Size of that added debug info?)

I suppose if the app is critical deserving full-blown ADA treatment, then no use trying to make a Mega48-class app. Put in a "big iron" microcontroller as you described. Even if a 100% penalty a 128kB app is really big as far as actual instructions go and going to 2x flash only costs a couple bucks more.

Quote:

I don't understand how GNAT can say the executable size is not changed. I'd have to see where they say that and in what context.

https://docs.adacore.com/gnat-un...

Quote:
32.1 The GNAT Debugger GDB

GDB is a general purpose, platform-independent debugger that can be used to debug mixed-language programs compiled with gcc, and in particular is capable of debugging Ada programs compiled with GNAT. The latest versions of GDB are Ada-aware and can handle complex Ada data structures.
...
When GNAT programs are compiled, the compiler optionally writes debugging information into the generated object file, including information on line numbers, and on declared types and variables. This information is separate from the generated code. It makes the object files considerably larger, but it does not add to the size of the actual executable that will be loaded into memory, and has no impact on run-time performance. The generation of debug information is triggered by the use of the -g switch in the gcc or gnatmake command used to carry out the compilations. It is important to emphasize that the use of these options does not change the generated code.
...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Quote:

I modified it to write the info to a character LCD, as seen in the 2nd Ada tutorial I posted at embeddedrelated.

But that means you have to store that info in your microcontroller somewhere. While it could certainly be compressed more than a naive filename/line number pair for each possible trap point, that is still going to be sizable isn't it? (Aaah, I'll bet you can tell exactly from the build results of the app you are mentioning. About how many traps are there? Size of "executable"? Size of that added debug info?)

I'll take a look at the size difference, but I really don't know how many tests the compiler inserts. Many times it can prove that a certain error is not possible, so it doesn't insert a test.

Quote:
I suppose if the app is critical deserving full-blown ADA treatment, then no use trying to make a Mega48-class app. Put in a "big iron" microcontroller as you described. Even if a 100% penalty a 128kB app is really big as far as actual instructions go and going to 2x flash only costs a couple bucks more.

I heard that it was the British MoD that requested/funded AdaCore's AVR port, so I guess they saw a big benefit in all the other things Ada brings to the table even for the AVR.

The number I've seen AdaCore quote is 10-20% additional execution time for code with all checks on, but I've never seen a size increase number.

Quote:
Quote:
I don't understand how GNAT can say the executable size is not changed. I'd have to see where they say that and in what context.

https://docs.adacore.com/gnat-un...

Quote:
32.1 The GNAT Debugger GDB

GDB is a general purpose, platform-independent debugger that can be used to debug mixed-language programs compiled with gcc, and in particular is capable of debugging Ada programs compiled with GNAT. The latest versions of GDB are Ada-aware and can handle complex Ada data structures.
...
When GNAT programs are compiled, the compiler optionally writes debugging information into the generated object file, including information on line numbers, and on declared types and variables. This information is separate from the generated code. It makes the object files considerably larger, but it does not add to the size of the actual executable that will be loaded into memory, and has no impact on run-time performance. The generation of debug information is triggered by the use of the -g switch in the gcc or gnatmake command used to carry out the compilations. It is important to emphasize that the use of these options does not change the generated code.
...


OK, so it's in the object file but not the executable. Maybe gdb is smart enough that IT accesses the filename/line info in the obj file when gdb detects that an exception occurs. That would make sense.

Last Edited: Fri. Aug 15, 2014 - 08:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This was in that same document. Makes perfect sense now.

Quote:
When a program is bound and linked, the debugging information is collected from the object files, and stored in the executable image of the program. Again, this process significantly increases the size of the generated executable file, but it does not increase the size of the executable program itself. Furthermore, if this program is run in the normal manner, it runs exactly as if the debug information were not present, and takes no more actual memory.

However, if the program is run under control of GDB, the debugger is activated. The image of the program is loaded, at which point it is ready to run. If a run command is given, then the program will run exactly as it would have if GDB were not present. This is a crucial part of the GDB design philosophy. GDB is entirely non-intrusive until a breakpoint is encountered. If no breakpoint is ever hit, the program will run exactly as it would if no debugger were present. When a breakpoint is hit, GDB accesses the debugging information and can respond to user commands to inspect variables, and more generally to report on the state of execution.

So the "executable program" does not increase in size, but the "executable image of the program" does. :wink:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
that means you have to store that info in your microcontroller somewhere ... that is still going to be sizable isn't it?

Yes, of course it is :!:

That's the tradeoff!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

OK, so it's in the object file but not the executable. Maybe gdb is smart enough that IT accesses the filename/line info in the obj file when gdb detects that an exception occurs. That would make sense.


I found another GNAT page that had explanations of the options for "last-chance". Indeed some of them seem tailored to keeping any "executable" overhead to a minimum.

http://docs.adacore.com/gnat-hie...
Search page for "last"...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No resistor for an LED?

If I were still interviewing folks for this kind of work, one question I would ask would be something like, "Since the code generates a pulse of sufficiently short duration that he LED does not receive excess current, does the LED need a current limiting resistor anyway?" And if the answer was 'no', I'd not hire that person.

You cannot design a perfect computer system and you must account for reasonable failure modes. If a computer can fail while that pulse is high - leaving the pin high - it will fail high and it will burn out the LED. If you are cheap to the point of fraudulence you can go ahead and leave out the resistor because your system will be long gone before the inevitable failure and you can always hope the buyer won't trace the failure back to you. Is losing a potential future customer worth saving a few cents on a product?

Smiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

smileymicros wrote:
No resistor for an LED?

If I were still interviewing folks for this kind of work, one question I would ask would be something like, "Since the code generates a pulse of sufficiently short duration that he LED does not receive excess current, does the LED need a current limiting resistor anyway?" And if the answer was 'no', I'd not hire that person.

You cannot design a perfect computer system and you must account for reasonable failure modes. If a computer can fail while that pulse is high - leaving the pin high - it will fail high and it will burn out the LED. If you are cheap to the point of fraudulence you can go ahead and leave out the resistor because your system will be long gone before the inevitable failure and you can always hope the buyer won't trace the failure back to you. Is losing a potential future customer worth saving a few cents on a product?

Smiley


Yeah, the only case where I can imagine no resistors -might- make business sense is something like ten million cheap Christmas doodads that will mostly never be used again after January, and most people won't bother to return it if it fails. A pretty limited scenario, which is why I objected to the use of the word "mistake".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:
I just finished this tutorial and thought it might be useful to some of the folks here.
Nicely done!

Admittedly I haven't given it a thorough read, but I see no mention of charlieplexing. This is easy to do, requires no additional components over traditional multiplexing, and reduces the number of I/O lines required to the greater of the number-of-digits and the number-of-segments-plus-one.

Up to nine digits with eight segments (A-G + DP) can be driven with nine I/O lines.

Each additional digit requires one additional line, i.e. 12 digits would require 12 I/O lines.

The only catch is you can't use packaged groups of digits. Such packages are wired such that common segments are driven by the same pin. Charlieplexing requires each digit to be driven by a different subset of the I/O lines. The down side is that you need individual digit packages, and the PCB routing becomes somewhat more complicated.

Here's a good start:
https://www.google.ca/search?q=7...

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, Joey. I've known about charlieplexing for a long time, but never actually tried it. I just filed it away in the "that's clever!" section of my head. Maybe I'll write about it in a future post.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

smileymicros wrote:
No resistor for an LED?

IIf you are cheap to the point of fraudulence

A guy that calls people who don't do things his way "fraudulent".

I could say something about people that have to cover every possible way things can go wrong rather than focusing on the probable, but I wont... I seem to recall moderators saying the forums are supposed to be technical, not opinion, even though it it's a do as I say, not as I do rule.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:
Thanks, Joey. I've known about charlieplexing for a long time, but never actually tried it. I just filed it away in the "that's clever!" section of my head. Maybe I'll write about it in a future post.

You can even control 8 segments with 2 IO lines. I call it "Gracieplexing" after my middle daughter.
I explained how to do it with 6, but haven't got around to posting the circuit for 8.
http://nerdralph.blogspot.ca/201...

I have no special talents.  I am only passionately curious. - Albert Einstein

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:

Yeah, the only case where I can imagine no resistors -might- make business sense is something like ten million cheap Christmas doodads that will mostly never be used again after January, and most people won't bother to return it if it fails. A pretty limited scenario, which is why I objected to the use of the word "mistake".

It actually is a mistake since you said you "need" the resistors.
If you said you recommend the resistors, then it wouldn't be a mistake.

There's lots of projects that don't use series resistors. Off the top of my head I remember a couple on simpleavr.com.

I have no special talents.  I am only passionately curious. - Albert Einstein

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would be genuinely interested in hearing about commercial products that don't use limiting resistors (or some other form of explicit, designed-in current limiting).

IMO what this comes down to is designing to the spec sheets vs. "whatever works for a couple of days here on the bench." Thus my interest in commercial designs, especially ones that can be proven to be within spec for LEDs and drivers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ralphd wrote:
smileymicros wrote:
No resistor for an LED?

IIf you are cheap to the point of fraudulence

A guy that calls people who don't do things his way "fraudulent".

I could say something about people that have to cover every possible way things can go wrong rather than focusing on the probable, but I wont... I seem to recall moderators saying the forums are supposed to be technical, not opinion, even though it it's a do as I say, not as I do rule.

This sort of failure is not 'probable' it is inevitable. I point this out because there are novices reading AVRFreaks who might be mislead by folks apparently lacking real world experience with good hardware engineering design practices. I worked for a consumer electronics company that would manufacture millions of a given design and they would kill to save a penny on that design - however, they did not leave out current limiting resistors on LEDs.

Do a bit of research on this topic and you'll see which concept is technical and which is opinion. I'd be delighted to see actual evidence that your opinion about LED use is correct. I am still learning.

Also, I see no reason for you to insult the moderators, just submit my post to them and ask for help if you think I've broken some rule.

Oh and where you say:

Quote:
I could say something about people that have to cover every possible way things can go wrong rather than focusing on the probable, but I wont...
Funny rhetoric that, but I'll take it as a complement since I do in fact design with knowledge of potential failures in mind, so thanks.

Smiley