NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » LED array Timer

April 26, 2010
by derekw4
derekw4's Avatar

Hi everyone!

I just received my Nerdkit and have put together the LED array kit as well. I now want to take the LED array and turn it into a stopwatch timer. Does anyone have any ideas on how to do this, or can it even be done. Any help will be much appreciated.

Thanks!

April 27, 2010
by derekw4
derekw4's Avatar

The was I was think of completing this project was to use the crystal real time clock example shown on the tutorial page. Instead of displaying on the LCD, I want to display of the LED array.

Can this be done with high accuracy like on the LCD display?

April 27, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi derekw4,

I think what you are suggesting is absolutely possible. You might lose a bit of accuracy because of all the time the LED Array spends in the interrupts, but it will probably be fine. I would suggest putting together the version with the LCD first so you get familiar with how it all works, and then try to slowly merge the real time clock functionality into the LED Array. Sounds like a fun project.

Humberto

April 28, 2010
by derekw4
derekw4's Avatar

Question:

Will I need another 14.7456MHz crystal timer to make this procjet work or will I be able to use the one supplied.

The reason I ask is becuase it is used in the LED array as well as the LCD timer.

Thanks

April 28, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

HI derekw4,

Good question. To answer it you need to understand that the crystal is not being used solely to keep the time. The crystal on the MCU is being used to clock everything that is going on on the chip. Everything from the individual instructions loading one after the other, the timing of all the on board modules like the ADC, timers, UART, and PWM are all using the same 14.7456MHz clock.

The chip has three separate timer modules that you can use (referred to in the datasheet as timer0, timer1, and timer2). When you activate these timers they will count up "by themselves" using the 14.7456MHz timer as a source. Using interrupts, you can then react to certain events that happen with the timers, either an overflow, or a compare match. If I remember correctly the LED Array uses timer0, and the real time clock code uses timer1 to increment its counter, so you should not have too much trouble combining the code.

The trouble you might have is in the interrupt handling. Since the LED Array spends a lot of its time in the interrupt handling routine your clock might lose a little bit of its accuracy, but I doubt it will be noticeable.

So the short answer to your question is you do not need to have a separate clock, since the time keeping is being done by the MCU, using interrupts. Hope that answers your question.

Humberto

April 28, 2010
by derekw4
derekw4's Avatar

Thanks Humberto! That answers a lot.

April 29, 2010
by derekw4
derekw4's Avatar

In realtimeclock.c, I'm confused on how this statement keeps updating the_time variable. Is it because of the interupts, so the the_time variable is continuously updated?

while(1) { lcd_home(); fprintf_P(&lcd_stream, PSTR("%16.2f sec"), (double) the_time / 100.0); }

To display the time on the LED array. I was thinking of using something similar to lcd.c Is this the best way or is there a simpler way I'm not seeing?

April 29, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi derekw4,

The parts of the code you listed do not actually update the 'the_time' variable, that variable is updated by the interrupt handler that fires when the proper timer module overflows. Take a look at our interrupts tutorial, it is dealing with a much different project, but it gives a great introduction to interrupts and how they work. After that try to follow what happens in the realtimeclock_setup() and the SIGNAL(SIG_OUTPUT_COMPARE0A) functions. These two are the real meat of the program, if you understand how those work, you will be able to use timers and interrupts for a great many things!

Humberto

April 30, 2010
by derekw4
derekw4's Avatar

Thanks for all the help.

I have another question. On the LED array, the font_display function, is it possible to pass a variable into the function or does it have to be a char?

Timer is coming along great. I think this is the last set into making this LED timer a reality!

April 30, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi derekw4,

Possible is a very broad term =). Yes, it is absolutely possible to pass any type you want, but then you would have to deal with those cases inside the function. The led array code was written to render characters. Giving it the number 34 for example, will cause to render whichever character is represented by the ASCII code 34 (which is actually a double quote which is not in the font table so it will render a ? instead). Regardless, I think in the end you will have to be able to turn your numerical representation of a number i.e. the number 123, to the its individual characters i.e. the characters 1, 2, and 3, before you can render them on the LED Array.

There are a couple of ways I can think of to do this, it sounds like a pretty neat exercise.

Humberto

April 30, 2010
by derekw4
derekw4's Avatar

Alright. Well now i'm pretty lost on how to do this. What were the ideas you were thinking of if you dont mind me asking?

Thanks again

April 30, 2010
by derekw4
derekw4's Avatar

I have been trying to convert the int to a char string using sprintf. Then I try to call the indvidual parts of the string in font_display, but it doesn't seem to be working correctly.

I feel like I'm on the right path.

Any help on this would be great. Thanks again.

May 02, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi derekw4,

That certainly is one of (probably the easiest) way to do it. Go ahead and post the snippets of code, so we can look through it and find why it is not working.

Humberto

May 03, 2010
by derekw4
derekw4's Avatar

Here's the code.

void realtimeclock_setup() {

  // setup Timer0:
  // CTC (Clear Timer on Compare Match mode)
  // TOP set by OCR0A register

TCCR0A |= (1<<WGM01);

 // clocked from CLK/1024
 // which is 14745600/1024, or 14400 increments per second

TCCR0B |= (1<<CS02) | (1<<CS00);

// set TOP to 143
// because it counts 0, 1, 2, ... 142, 143, 0, 1, 2 ...
// so 0 through 143 equals 144 events

OCR0A = 143;

// enable interrupt on compare event
// (14400 / 144 = 100 per second)

TIMSK0 |= (1<<OCIE0A);

}

volatile int8_t sec1;
volatile int8_t sec2;
volatile int8_t min1; 
volatile int8_t min2;
volatile int8_t hr1;
volatile int8_t hr2;

char s1[3];
char s2[3];
char m1[3];
char m2[3];
char h1[3];
char h2[3];

SIGNAL(SIG_OUTPUT_COMPARE0A) {
  // when Timer0 gets to its Output Compare value,
  // one one-hundredth of a second has elapsed (0.01 seconds).
 sec1++;
 sec1 = sec1/100;
 if(sec1>9){
    sec1=0;
    sec2++;
    delay_ms(1000);
        }if(sec2>5){
        sec2=0;
        min1++;
           }if(min1>9){
           min1=0;
           min2++;
             }if(min2>5){
              min2=0;
              hr1++;
                 }if(hr1>9){
                  hr1=0;
                  hr2++;

}

sprintf(s1,"%d", sec1);
sprintf(s2,"%d", sec2);
sprintf(m1,"%d", min1);
sprintf(m2,"%d", min2);
sprintf(h1,"%d", hr1);
sprintf(h2,"%d", hr2);

}

int main() {

  ledarray_init();
  realtimeclock_setup();
 // activate interrupts
 sei();

 // init serial port
 uart_init();
 FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
 stdin = stdout = &uart_stream;

 while(1){

// test letters    
ledarray_blank();

 font_display(h2[0], 0);  
 font_display(h1[0], 4); 
 font_display(':', 7);     
 font_display(m2[0], 8);   
 font_display(m1[0], 12);     
 font_display(':', 15);     
 font_display(s2[0], 16);   
 font_display(s1[0], 20);
  ledarray_blank();

}

Thanks for all the help!

May 03, 2010
by bretm
bretm's Avatar
sec1++;          // this increments sec1 to "1" the first time through
sec1 = sec1/100; // and this resets it to zero again (integer division)
if(sec1>9){      // so sec1>9 will never happen
   sec1=0;
   sec2++;
   delay_ms(1000);  // shouldn't pause for 1000ms in an interrupt
                    // that runs once every 10ms

sprintf(h2,"%d", hr2);  // will do bad things once hr2>99
May 03, 2010
by bretm
bretm's Avatar

Also, in your font_display calls, you're never displaying more than one digit from each of the strings so there's really no reason to create and use those strings at all. Just do digit+'0' to convert a digit to a printable character.

May 03, 2010
by derekw4
derekw4's Avatar

So I don't need the strings.

So how does digit+'0' work? --Little confused on what you mean there.

May 03, 2010
by bretm
bretm's Avatar

Let's say sec1=7 which means that s1="7", which is a string. The value s1[0] is the first character of the string, which is '7'. Characters are represented internally in C as numbers. In this case the character '7' is represented by a byte with a value of 55. The character '0' is represented 48. (This is a result of the C compiler following the American Standard Code for Information Interchange, or ASCII.)

If you take '0' and add 7 to it, you get 48+7 which is 55 which is also '7'. In other words, replace s1[0] with sec1+'0'

May 03, 2010
by derekw4
derekw4's Avatar

Thanks a lot. The timer now works.

Now I have another problem which i can't seem to figure out. The display looks like HH:MM:SS so when it first starts counting it would display 00:00:01, well it does display this but the minutes are dimmer than the seconds and the hours are dimmer than the minutes almost to the point were you can't see them.

I ran the test pattern again to make sure all me LEDs light up and they do with the right intensity, so it's not a wiring problem. Any one have any theories why this would happen.

May 03, 2010
by derekw4
derekw4's Avatar

I think it's because I change the timer on the LED array to timer 2 clk/8.

Could this be the reason?

May 03, 2010
by bretm
bretm's Avatar

That's strange. I would have guessed it would be the other way around (hours brightest) because you're calling ledarray_blank() immediately after setting the seconds display.

How well does it work if you don't call ledarray_blank?

May 04, 2010
by derekw4
derekw4's Avatar

I took the ledarray_blank off after seconds and this was the outcome. I still have ledarray_blank before hours.

May 04, 2010
by bretm
bretm's Avatar

That still means you're blanking the display immediately after writing out the seconds, because it starts a new while() loop. Seconds will be visible for a shorter amount of time, so should be dimmer. Can you just blank the display once before the while() loop and then not blank it again, just letting the new digits overwrite the previous?

May 04, 2010
by derekw4
derekw4's Avatar

I will try that, but hours are the ones that are dimmer. Thanks for the help

Post a Reply

Please log in to post a reply.

Did you know that you can control 120 LEDs with just 17 microcontroller pins? Learn more...