1

My traffic light code for the Arduino doesn't run. I was wondering if anyone could point out where my issues lie. The red and green LEDs should be on for 15 seconds and the amber on for 5 seconds.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint-gcc.h>
/*15 second interrupt*/
#define INTERRUPTS 975


/* 
 * col = current colour of light. 
 * 'g', 'a', 'r', 'o'
 */
volatile uint8_t count;
volatile char col;

ISR(TIMER0_OVF_vect)
{
    count++;
    if (count >= INTERRUPTS){
        if (col == 'g'){
            /*switch to amber*/
            col = 'a';
            /*reset counter*/
            count = 0;
            /*timer counter to 171 as we only need 85 clicks for 5s*/
            TCNT0 = 171;
            PORTD = 0b00000010;
        } else if(col == 'a'){
            col = 'r';
            count = 0;
            TCNT0 = 0;
            PORTD = 0b00000100;
        } else if (col == 'r'){
            col = 'o';
            counter = 0;
            TCNT0 = 171;
            PORTD = 0b00000010;
        } else if (col == 'o'){
            col = 'g';
            count = 0;
            TCNT0 = 0;
            PORTD = 0b00000001;
        } else{
            return;
        }
    } else{
        if(col == 'g' || col == 'r'){
            TCNT0 = 0;
        } else if(col == 'a' || col == 'o'){
            TCNT0 = 171;
        }
    }
    return;
}

int main(void)
{
    /* normal mode */
    TCCR0A = 0b00000000;
    /* prescaler = 1024 */
    TCCR0B = 0b00000101;
    /* enable overflow interrupts */
    TIMSK0 = 0b00000001;
    TCNT0 = 0;
    sei();
    /*Initialise output*/
    DDRD = 0b11111111;
    count = 0;
    col = 'g';
    PORTD = 0b00000001;
    while (1){
    }
}
0

3 Answers 3

3
#define INTERRUPTS 975

volatile uint8_t count;

if (count >= INTERRUPTS){

count is an 8 bit integer, so the maximum value of it is 255. Therefor count will never be bigger of equal to 975.

Use volatile uint16_t count; instead.

PS instead of messing with the TCNT0 register, I'd use 2 different values of INTERRUPTS to change between 15 and 5 second intervals.

Something like if( count>=975 || ( (col=='g'||col=='r') && count>=325 ) ){

5
  • How would I time using 2 different values? Won't the 5 second count occur every time so the 15 second interrupt never occurs?
    – JVDM92
    Commented Nov 24, 2016 at 16:12
  • Something like if( count>=975 || ( (col=='g'||col=='r') && count>=325 ) ){
    – Gerben
    Commented Nov 24, 2016 at 16:22
  • Ok, nice, thanks for the advice. Does everything else look ok, I won't have a board to test it again until Monday.
    – JVDM92
    Commented Nov 24, 2016 at 16:28
  • It would be nicer to use an enum rather than a char for the current colour. And then use a switch rather than if () {} else if () .... But those are style points rather than functionality.
    – Andrew
    Commented Nov 24, 2016 at 16:38
  • Looks okay. Though I'd make it more readable. E.g. use two extra letters and change col to color.
    – Gerben
    Commented Nov 24, 2016 at 19:08
1

As far that i understand, you set the color using the Ports directly. In case green and red you set PORTD = 0b00000010;

5
  • Yes, for example to turn on the amber light I directly toggle the port so the amber LED will be turned on. If the color is currently green or red then 0b0000010; will turn on the next LED which is amber in both cases.
    – JVDM92
    Commented Nov 24, 2016 at 15:12
  • Ah, yes i see, my fault. Commented Nov 24, 2016 at 15:25
  • Well that's the theory anyway, but it doesn't work for some reason
    – JVDM92
    Commented Nov 24, 2016 at 15:52
  • And what does it do instead, is the timer not working, or does the lighth not work? Commented Nov 25, 2016 at 6:48
  • The lights are the issue
    – JVDM92
    Commented Nov 25, 2016 at 9:17
1

If you want solution with a timer, I suggest to setup a 35 second cycle (35 = 15+15+5). Then, you will trigger next LED when 0,15,30 seconds passed, and restart cycle at 35 seconds.

Other ways to achieve same effect are: 1. Use classic delay() function.

while (true)
{
    TurnOn(Green);
    delay(15000);
    TurnOn(Red);
    delay(15000);
    TurnOn(Amber);
    delay(5000);
}
  1. use millis() function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.