Four digit 7 segment display

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

I have a four digit 7 segment display. I want to turn on my ATMega and have something be displayed. Then I want to press a button on PB0 and switch the display to something else. I want to be able to switch back and forth.

This is my code/pseudo-code. When I turn on my microcontroller it displays one thing. Then when I press the button it changes. But when I press the button again it doesn't switch back.

It is a four digit common anode display. I am multiplexing each digit. The problem is that if I try to introduce a 250ms delay for debouncing the 7 segment display doesn't work properly.

# define F_CPU 8000000
#include 
#include 

int main(void)
{	
	
	DDRA=0XFF; //7seg port
	PORTA=0XFF;
	DDRB &= ~(1 << PINB0);// button 
	PORTB |= 1 << PINB0;  //button
 
	int flag;
  
    while(1)
    {
		
if (bit_is_clear(PINB, 0))//if button is pressed down set flag to 1 so that the other thing is displayed
	{
	flag = 1;
	//_delay_ms(250);//debounce delay?
	}
		
	if (!bit_is_clear(PINB, 0))//if button is not pressed keep showing the first thing.
	{
	flag = 0;
	//_delay_ms(250);//debounce delay?
	}
				
	if (flag==0)
	{
portb=turn on digit 1
porta=something1
5ms delay

portb=turn on digit 2
porta=something2
5ms delay

portb=turn on digit 3
porta=something3
5ms delay

portb=turn on digit 4
porta=something4
5ms delay
		
	}

	if (flag==1)
	{
portb=turn on digit 1
porta=somethingelse1
5ms delay

portb=turn on digit 2
porta=somethingelse2
5ms delay

portb=turn on digit 3
porta=somethingelse3
5ms delay

portb=turn on digit 4
porta=somethingelse4
5ms delay
	}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Silly question but why do you test the PB0 state twice? Surely if it isn't 1 it must be 0. That's why God invented the word "else".

The possible problem with testing it twice is that it may have changed state between one test and the next. So both (or neither) conditions may be true.

Oh and why "int" for a flag? You only need a byte (at most) to hold a 0/1 state.

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

ok I switched to this, no difference:

if (bit_is_clear(PINB, 0))//if button is pressed down set flag to 1 so that the other thing is displayed
   {
   flag = 1;
   //_delay_ms(250);//debounce delay?
   }else{
      
   //if (!bit_is_clear(PINB, 0))//if button is not //pressed keep showing the first thing.
  // {
   flag = 0;
   //_delay_ms(250);//debounce delay?
   } 

What would I use instead of int?

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

Quote:

What would I use instead of int?

unsigned char

or

uint8_t

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:
Quote:

What would I use instead of int?

unsigned char

or

uint8_t

What about boolean? cant't you do something like boolean=true or boolean=false. Is that smaller than an int?

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

Quote:
What about boolean?

If your compiler supports it, then you can use that. You will likely need to

#include 

Quote:
Is that smaller than an int?

Reference your compiler documentation. (Yes, it is highly likely that it will be smaller than an int.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Ok so I've used else and an unsigned char. But the original problem remains, how do I switch between two different things being displayed?

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

One underlying problem is that you introduce a delay of 250 ms for debouncing.
Then you handle digit1 and a 5 ms delay.
Then you handle digit2 and a 5 ms delay.
Then you handle digit3 and a 5 ms delay.
Then you handle digit4 and a 5 ms delay.

All in all, this means that you have digi1 displayd for 5 ms, digit2 displayed for 5 ms, digi3 displayd for 5 ms and then digi4 displayed for 255 ms.

That is what I can make out of your pseudocode.

Fi that matches your ecellently non-to-the-point description

Quote:
display doesn't work properly

is unknown to me.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

I said I was mutliplexing. Obviously if I'm switching between digits every 5ms to give the illusion to the human eye that all four digits are on simultaneously turned on and I introduce a delay of 250ms the display will show something strange. Yes, the last digit always stays on, the first three seem to be switching between the first message that should be displayed and the second, without touching the button.

Would it make any difference if I had the button pressed check in main and message1 and message2 in two separate function outside of main?

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

As the multiplexing of the digits is something that must continue and can never stop (otherwise the dopey human watching will spot what's going on!) I think most people would be tempted to run the actual display stuff itself as a separate (unstoppable) process. On the whole that would mean a timer interrupt. The "input" to the interrupt is going to be just 4 bytes (or I guess you might squeeze it into two?) which say what should be displayed on each of the 4 digits.

At it's leisure the foreground process (your loop in main) can then write new values to those 4 bytes from time to time. It can take as long as it likes and if it wants to pause after making a display change it's quite at liberty to do that because, unabated, ticking away in the background is the display output routine that simply just gets on with the job of multiplexing the display segments.

So perhaps start by implementing a regular timer interrupt and get it to the point where it will just display whatever 4 bytes happen to be in your display array (or separate variables if you prefer - though an array will likely make it easier to use the same code for all four digits).

Then worry about the stuff that holds state, reads buttons, sets what is to be displayed separately. As I say the only connection between that and the display routine are the 4 bytes that are shared.

Now believe it or not you probably aren't the very first person who's ever wanted to do this. So if you search here or just google generally for "7 segment multiplex timer interrupt (avr)" I'm pretty sure you are only going to find about 100,000 instances of this being done previously.

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

So if I were to do this:


int main()
{
check button
delay 250ms
}

timerinterrupt //every 5ms
{

}

Would the timer interrupt have priority over the delay? So I press the button, the 250ms delay loop starts, will the timer interrupt trigger every 5ms while the 250ms loop is running or does it wait for delay to finish?

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

Yes, the interrupt will interrupt normal code and that's why it's called "interrupt" ;)

Although it is also possible to do it without using timers. First you need a new variable and initially set it to 0. Since you handle the displays every 5ms you can increment the variable every 5ms. And then when the variable reaches a specified amount (if you want 250ms it would be 50) reset the variable and check the button state.

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

Quote:

Now believe it or not you probably aren't the very first person who's ever wanted to do this.

As an experiment I just typed "multiplexing four 7 segment displays" into Google. It gives 699,000 hits. Certainly the ten on the first page of results all look very useful. While many use an AVR (Arduino in fact) it doesn't even really matter whether it's an AVR design or not. The way you actually do it is pretty similar whatever the MCU - all that changes a bit is the syntax and the way things like timers and interrupts work - but you can still see the general technique.

As a further experiment I added "timer interrupt" to the search terms above. That reduced it to 396,000 results. Many also look very interesting.

Some of the results were even on avrfreaks.net (including this thread!)