just wonder if someone can help me with a sketch that will count down on a set of 4 x 7 segment LEDs, from 60.00 to 00.00 (mm.ss).
Sure we can [smiley=thumbsup.gif]
But before we can help you'll have to tell us a bit more about your situation.
Do you already know how to control a single 7-segment display?
Do you know how to control multiple such displays?
Your a star DaveK!
Iv just got my 7seg LEDs so i have no real experience, but I understand the principle of Common Cathode or Common Anode and then 8 LEDs that can be set to high or low to make a number, and i figure 8+8+8+8 is more i/o's then iv got, so I picked up some MAX7219 Led drivers to help out.
But that's about it sir! :-/
was planning o using this system but with 4 not 8 LED displays
If you have 7 segments plus one common pin for each of 4 displays then you will need only 11 digital pins. This is because you can take advantage of a property of the human eye called persistence of vision which will make a short flash of an LED appear to persist for a moment. During this time you can flash the other LEDs with the result of all the LEDs appearing to be on at the same time.
You will want to put one resistor on each of the 7 pins driving the segments. It may seem as if you could use one resistor on the common pin, but this will not work as well. You'll find that as you turn on more segments the brightness of each segment will drop.
Initially I'd recommend driving the entire display directly from the Arduino. You'll be limited on the total current you can use per segment, but once you have it working you can modify it slightly to increase the current (and therefore the brightness).
Decided im going to try and get to grips with using the LED Driver, as there are a few other projects Im going to want it on......understand the diagram above now, apart from the capacitor C2, dose the white and black indicate it is a polarised capacitor, where as C1 is not?
Found this LedControl library code that runs 4 x 7 segments :), so how can I change it to give me a mm.ss countdown from 60.00 to 00.00 (and loop flashing continuously on 00.00 until reset)
//We always have to include the library
#include "LedControl.h"
/*
Now we need a LedControl to work with.
***** These pin numbers will probably not work with your hardware *****
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD
We have only a single MAX72XX.
*/
LedControl lc=LedControl(12,11,10,1);
/* we always wait a bit between updates of the display */
unsigned long delaytime=250;
void setup() {
/*
The MAX72XX is in power-saving mode on startup,
we have to do a wakeup call
*/
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,8);
/* and clear the display */
lc.clearDisplay(0);
}
/*
This method will display the characters for the
word "Arduino" one after the other on digit 0.
*/
void writeArduinoOn7Segment() {
lc.setChar(0,0,'a',false);
delay(delaytime);
lc.setRow(0,0,0x05);
delay(delaytime);
lc.setChar(0,0,'d',false);
delay(delaytime);
lc.setRow(0,0,0x1c);
delay(delaytime);
lc.setRow(0,0,B00010000);
delay(delaytime);
lc.setRow(0,0,0x15);
delay(delaytime);
lc.setRow(0,0,0x1D);
delay(delaytime);
lc.clearDisplay(0);
delay(delaytime);
}
/*
This method will scroll all the hexa-decimal
numbers and letters on the display. You will need at least
four 7-Segment digits. otherwise it won't really look that good.
*/
void scrollDigits() {
for(int i=0;i<13;i++) {
lc.setDigit(0,3,i,false);
lc.setDigit(0,2,i+1,false);
lc.setDigit(0,1,i+2,false);
lc.setDigit(0,0,i+3,false);
delay(delaytime);
}
lc.clearDisplay(0);
delay(delaytime);
}
void loop() {
writeArduinoOn7Segment();
scrollDigits();
}
First you'll need to write the code to handle a countdown timer. This should be easy enough to do with a couple of variables for minute and second and a delay in your main loop. Each time you change the variables, use setDigit to write the digits to the display (you may find use for the div and mod operators).
You can print your variables to the serial port to verify that the variables contain the intended values.
Wooooooooooooooooooooooosh!
that kind of went over my head.... :-/
Try writing down in broken English what you want to happen in what order, based on what conditions, breaking the overall problem down into smaller bits. If each bit seems small enough to tackle on its own, go for it, otherwise break it down again. Then take each bit in turn and work out how to implement it on its own (without the rest of the functionality). When you can do each thing separately you ought to be able to put them together to make your complete solution. It sounds like at the moment you're trying to grasp/do everything at once and that can be overwhelming.
An example might be something like this (we call it pseudo-code):
wait for button push
set minutes to 60
set seconds to 0
while not (seconds == 0 and minutes == 0)
display minutes, seconds
wait for one second
set seconds = seconds - 1
if seconds == -1 then
set seconds = 59
set minutes = minutes - 1
end if
end while
display minutes, seconds
beep for ten seconds
goto start
Now you might decide to tackle the display routine. You could break that down into:
display minutes
display seconds
and display minutes would be:
display tens digit
display units digit
and display tens digit would be:
work out segments to light
light 'em up
This way of working lends itself to breaking your program down into reusable functions - I believe it used to be known as "top down, stepwise refinement" in the days before OOP came along.
Hopefully this gives you a pointer as to how you could tackle it.
Andrew
You make it sound easy.......but im still going to need more help!
So Far iv got this pseudo-code:
wait for power on
set minutes to 60
set seconds to 0
display minutes, seconds
wait 1 second then -1 second 60-00
wait 1 minutes then -1 minute 60-00
when 00 second and 00 minute display 00.00 1 seocond hi one second low - loop till reset.
#include "LedControl.h"
LedControl lc=LedControl(12,11,10);
void setup() {
/*
The MAX72XX is in power-saving mode on startup,
we have to do a wakeup call
*/
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,8);
/* and clear the display */
lc.clearDisplay(0);
}
;D
I would start by doing the most basic operation. Enable a single segment and write something to it. Don't worry about counting anything down or looping, etc. Leave the loop routine empty and just init the module and get something displayed from setup.
still having issues, not sure if the tick++ is right, and am getting an error
error: expected declaration before '}' toke
#include "LedControl.h" // Include the LedControl library
LedControl lc=LedControl(12,11,10,1); // Set up an LED object on pins 12,11,10
int seconds_ones;
int minutes_ones;
int seconds_tens; // Initialise values for tens and ones units of m,s
int minutes_tens; // these are the values actually sent to the LEDs
volatile unsigned char tick;
unsigned char seconds = 0;
unsigned char minutes = 60; // Inititialise actual values for mm,ss
ISR (TIMER2_OVF_vect) { // When timer2 overflows...
tick++; // increment tick
display_time (); // send the time to the LEDs to be displayed
}
void display_time () { // Function to display the time
seconds_ones = seconds % 10; // Get the 1's digit of seconds
if (seconds>=10){ // If seconds greater than 10
seconds_tens = seconds / 10;} // Get 10's digit of seconds
else {
seconds_tens = 0;} // Otherwise 10s is 0
minutes_ones = minutes % 10; // Repeat for minutes
if (minutes>=10){
minutes_tens = minutes / 10 ;}
else {
minutes_tens = 0;}
lc.setDigit(0,0,(byte)seconds_ones,false); // Send digits to LEDs
lc.setDigit(0,1,(byte)seconds_tens,false);
lc.setDigit(0,2,(byte)minutes_ones,false);
lc.setDigit(0,3,(byte)minutes_tens,false);
}
void loop () {
if (tick) { // If a tick has occured
seconds = seconds - 1; // Increment the seconds
tick = 0; // reset the tick flag
if (seconds>59){ // If a minute has passed
seconds = 0; // Send seconds back to 0
minutes = minutes - 1; // Increment the minutes
minutes = 0; // Send the minutes back to 0
}
}
}
} //"error: expected declaration before '}' toke"
}
HELP!!!! :-?
- You have too many curly braces at the end.
- If you're counting DOWN, why are you testing for seconds
to be greater than 59? You should be looking to see if the
value of seconds is < 0. When that occurs, reset the value
of seconds to 59. - At the declaration, set variable 'tick' to 0, just to be sure it's
properly initialized. - Remove "display_time()" from your ISR -- you don't need
that functionality in your ISR. Put it in the loop() function after
all the seconds and minutes have been accounted for. In an ISR
you want to get in and get out as quickly as possible. Setting the
'tick' variable is all you really need to do there. - In 'loop()' you keep reseting the minutes to 0. I suspect you've
forgotten an 'if' statement.
Thanks so much rusty, really good info!
Just 2 things:
where should the missing 'if' statement go?
And im also getting
In function 'void loop()':
error: a function-definition is not allowed here before '{' toke
Really cant express just how thankful i am for your help Rusty in Texas!!!! :-*
#include "LedControl.h" // Include the LedControl library
LedControl lc=LedControl(12,11,10,1); // Set up an LED object on pins 12,11,10
int seconds_ones;
int minutes_ones;
int seconds_tens; // Initialise values for tens and ones units of m,s
int minutes_tens; // these are the values actually sent to the LEDs
volatile unsigned char tick;
unsigned char seconds = 0;
unsigned char minutes = 60; // Inititialise actual values for mm,ss
ISR (TIMER2_OVF_vect) { // When timer2 overflows...
tick++; // increment tick
}
void display_time () { // Function to display the time
seconds_ones = seconds % 10; // Get the 1's digit of seconds
if (seconds>=10){ // If seconds greater than 10
seconds_tens = seconds / 10;} // Get 10's digit of seconds
else {
seconds_tens = 0;} // Otherwise 10s is 0
minutes_ones = minutes % 10; // Repeat for minutes
if (minutes>=10){
minutes_tens = minutes / 10 ;}
else {
minutes_tens = 0;}
lc.setDigit(0,0,(byte)seconds_ones,false); // Send digits to LEDs
lc.setDigit(0,1,(byte)seconds_tens,false);
lc.setDigit(0,2,(byte)minutes_ones,false);
lc.setDigit(0,3,(byte)minutes_tens,false);
}
void loop () {
if (tick) { // If a tick has occured
seconds = seconds - 1; // Increment the seconds
tick = 0; // reset the tick flag
if (seconds<0){ // If a minute has passed
seconds = 0; // Send seconds back to 0
minutes = minutes - 1; // Increment the minutes
minutes = 0; // Send the minutes back to 0
display_time (); // send the time to the LEDs to be displayed
}
where should the missing 'if' statement go?
Think about it. If you decrement 'minutes' do you always want the
minutes to reset to zero? That's what your code is doing.
Or maybe you need to determine when minutes goes negative... If
'minutes' goes negative, do you reset to 59 or, maybe, do you stop
the clock? You have to decide how you want your countdown clock
to act.
And im also getting -- In function 'void loop()':
error: a function-definition is not allowed here before '{' toke
From what you posted in a Code section, I'd say your curly braces
still don't match. For every { you MUST have a matching }.
In Arduino, you MUST have a loop() function (which you have) and
you MUST have a setup() function. You appear to be missing the latter.
In setup() you might want to initilize your display to 60:00. Your choice!
And don't forget to initialize your 'tick' variable.
Thanks Rusty, think Im really close now thanks to your tips.....well it compiles!!!
only thing is its running remarkably fast instead of:
seconds_ones = 1 second
seconds_tens = 10 seconds
minutes_ones = 1 minute
minutes_tens = 10 minute
it seems to be run at
seconds_ones =0.001
seconds_tens = 0.01
minutes_ones = 0.1 second
minutes_tens = 1 second
(the two right most LEDs flash far to fast to read?)
#include "LedControl.h" // Include the LedControl library
LedControl lc=LedControl(12,11,10,1); // Set up an LED object on pins 12,11,10
int seconds_ones;
int minutes_ones;
int seconds_tens; // Initialise values for tens and ones units of m,s
int minutes_tens; // these are the values actually sent to the LEDs
volatile unsigned char tick;
unsigned char seconds = 59;
unsigned char minutes = 59; // Inititialise actual values for h,m,s
int mins_increase = 0;
ISR (TIMER2_OVF_vect) { // When timer2 overflows...
tick++; // increment tick
display_time (); // send the time to the LEDs to be displayed
}
void display_time () { // Function to display the time
seconds_ones = seconds % 10; // Get the 1's digit of seconds
if (seconds>=10){ // If seconds greater than 10
seconds_tens = seconds / 10;} // Get 10's digit of seconds
else {
seconds_tens = 0;} // Otherwise 10s is 0
minutes_ones = minutes % 10; // Repeat for minutes
if (minutes>=10){
minutes_tens = minutes / 10 ;}
else {
minutes_tens = 0;}
lc.setDigit(0,0,(byte)seconds_ones,false); // Send digits to LEDs
lc.setDigit(0,1,(byte)seconds_tens,false);
lc.setDigit(0,2,(byte)minutes_ones,false);
lc.setDigit(0,3,(byte)minutes_tens,false);
}
void setup_timer2 () { // Set up function
TCCR2A = 0;
TCCR2B = 0; // stop timer
TCNT2 = 0; // reset timer2 counter
ASSR = (1 << AS2); // select external clock source
TIMSK2 = (1 << TOIE2); // enable timer2 overflow interrupt
TCCR2B = (1 << CS22) | (1 << CS20); // prescaler = 128, restarts timer
}
void setup () {
setup_timer2 (); // Set up the timer options
lc.shutdown(0,false); // Turn on the LEDs
lc.setIntensity(0,15); // Set intensity to full
}
void loop () {
if (tick) { // If a tick has occured
seconds = seconds - 1; // the seconds
tick = 0; // reset the tick flag
if (seconds>0){ // If a minute has passed
seconds = 59; // Send seconds back to 0
minutes = minutes - 1; // the minutes
if (minutes >0){ // If an hour has passed
minutes = 59; // Send the minutes back to 0
}
}
}
}
I'd say you need to divide that clock interrupt down some more.
16MHz / 128 / 256 is nearly 500Hz.
Thanks AWOL,
How would i go about adjusting the code, is it just TCCR2B = (1 << CS22) | (1 << CS20);
thant needs to be change, and what values should I use?
To get back to some old issues here.
- Why is display_time() back in your interrupt handler?
- You've gone back decrementing your seconds and minutes
but still testing for them being greater than zero. - What's the difference between:
seconds_ones = seconds % 10; // Get the 1's digit of seconds
if (seconds>=10) { // If seconds greater than 10
seconds_tens = seconds / 10; // Get 10's digit of seconds
}
else {
seconds_tens = 0;
}
and
seconds_ones = seconds % 10;
seconds_tens = seconds / 10;
True, the former is faster (because no division is evaluated) but it's
only faster 1/6 of the time! And this is not an application that needs
millisecond optimizations.
4) Have you looked at the MsTimer2 library? Have it call a routine every
1,000-milliseconds that will decrement your time variables and then
display the time on your LEDs? Using this library you don't have to
worry about twiddling any registers as the library does that for you.
Oh, another thing:
The variables seconds_ones and tens as well as minutes_ones and tens
don't have to global variables, they can/should be local to your display_time()
function.