0

I am building a traffic light system. So when the button is not pressed, led 1 and 4 will turn on for 4 seconds, then led 2 and 3 will turn on for 4 seconds. If the button is pressed, the led for pedestrian (led 5) will wait and turn on only when the led 2 is on (it means that when we press the button, if led 1 and 4 are on, then led 5 will wait until led 1 and 4 are off). Only led 5 and 2 will turn on at this time, others will be off. After 2 seconds, led 5 will be off, led 3 will be on for 2 seconds. Led 2 will be on for the entire time (4 seconds). Then we return to normal. But the problem is when I run the program, all 4 leds are on.

#include <avr/io.h>
#include <avr/interrupt.h>

volatile int second = 1;

volatile boolean buttonPressed = false;

enum light_state {EW, SN, PES, START_UP};
enum light_state state;

int main(void) {

  DDRB = 0xFF; //Set LEDs as output

  DDRD &= ~(1 << 2); //Set button as input
  PORTD |= (1 << PORTD2);

  EIMSK |= (1 << INT0); //enable PORTB2 as external interrupt
  EICRA |= (1 << ISC01); //detect falling edge
  EIFR |= (1 << INTF0); //clear flag

  TCCR1B |= (1 << WGM12) | (1 << CS12) | (1 << CS10); //turn on CTC mode and set up Timer 1 with the prescaler of 1024
  OCR1A = 15624; //enable output Compare A Match Interrupt
  TIMSK1 = 1 << OCIE1A; //set CTC compare value to 2 Hz at 16 MHz AVR clock , with a prescaler of 1024

  sei();
  while (1) {
    if (!buttonPressed) {
      switch (state) {
        case EW:
          PORTB &= ~((1 << PORTB1) | (1 << PORTB4));
          PORTB |= (1 << PORTB2) | (1 << PORTB3);
          state = SN;
          break;
        case SN:
          PORTB |= (1 << PORTB1) | (1 << PORTB4);
          PORTB &= ~((1 << PORTB2) | (1 << PORTB3));
          state = EW;
          break;
        case START_UP :
          PORTB &= ~((1 << PORTB1) | (1 << PORTB2) | (1 << PORTB3) | (1 << PORTB4));
          state = SN;
          break;
        default:
          state = START_UP;
          break;
        }
      second = 1;
    } else {
      switch (state) {
        case PES:
          PORTB |= (1 << PORTB2) | (1 << PORTB5);
          PORTB &= ~((1 << PORTB1) | (1 << PORTB3) | (1 << PORTB4));
          state = SN;
          break;
        case SN:
          PORTB |= (1 << PORTB2) | (1 << PORTB3);
          PORTB &= ~((1 << PORTB1) | (1 << PORTB4));
          state = EW;
          break;
        case START_UP :
          PORTB &= ~((1 << PORTB1) | (1 << PORTB2) | (1 << PORTB3) | (1 << PORTB4) | (1 << PORTB5));
          state = PES;
          break;
        default:
          state = START_UP;
          break;
      }
      buttonPressed = false;
      second = 1;
    }
  }
}

ISR(INT0_vect) {
  buttonPressed = true;
}

ISR(TIMER1_COMPA_vect) {
  if (buttonPressed) {
    if (second == 2) {
        second = 1;
    }
  }
  second++;
}
Trần Thiên
  • 33
  • 1
  • 1
  • 6
  • 1
    You should probably be more specific about what is the correlation between LEDs in your description and all the variables in your code. Can the code be refactored so it can be compiled and tested on a desktop instead of a controller/emulator only? (I'm guessing most people here can/will only test it on a desktop unless given specific instructions how to do it on an emulator) – Meisner Oct 24 '21 at 07:26
  • You should make a FSM. A finite state machine is the best way to program such problems, and can be proven correct and complete. Also, you should heed the advice above and code the algorithm on a desktop. As your code reads now, your states are inside other conditions, which is atypical for a solid FSM style. – TomServo Oct 27 '21 at 00:07
  • thanks for all the advice guys. i figure it out – Trần Thiên Oct 29 '21 at 02:33

0 Answers0