Search code examples
c++arduinoarduino-unoarduino-idearduino-c++

Converting code written with delay to millis() instead


I have a basic code I wrote on Arduino, however, I need to change the delay to Millis instead.

Whatever I do I can't get it to work, it's always getting stuck at a red light and won't ever turn green.

I'm posting the original delay code as code I wrote using Millis seems useless and may confuse what I'm trying to do.

const int redPin = 2;
const int yellowPin = 3;
const int greenPin = 4;

int redDuration = 10000;
int greenDuration = 5000;

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(yellowPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
}

void loop() {
  setTrafficLight(1,0,0);
  delay(redDuration);
  setTrafficLight(1,1,0);
  delay(2000);
  setTrafficLight(0,0,1);
  delay(greenDuration);
  setTrafficLight(0,1,0);
  delay(2000);
}

void setTrafficLight(int redState, int yellowState, int greenState) {
  digitalWrite(redPin, redState);
  digitalWrite(yellowPin, yellowState);
  digitalWrite(greenPin, greenState);
}

Solution

    1. Save the time when it started waiting.
    2. If the difference of current time and the start time become the time to wait, proceed to the next status.
    const int redPin = 2;
    const int yellowPin = 3;
    const int greenPin = 4;
    
    int redDuration = 10000;
    int greenDuration = 5000;
    
    unsigned long startTime;
    int status = 0; // using enum may be better
    
    void setup() {
      pinMode(redPin, OUTPUT);
      pinMode(yellowPin, OUTPUT);
      pinMode(greenPin, OUTPUT);
      startTime = millis();
      status = 0;
    }
    
    void loop() {
      unsigned long currentTime = millis();
      switch (status) {
        case 0: // initial state
          setTrafficLight(1, 0, 0);
          status = 1;
          break;
        case 1: // waiting instead of delay(redDuration)
          if (currentTime - startTime >= redDuration) {
            setTrafficLight(1, 1, 0);
            startTime = currentTime;
            status = 2;
          }
          break;
        case 2: // waiting instead of first delay(2000)
          if (currentTime - startTime >= 2000) {
            setTrafficLight(0, 0, 1);
            startTime = currentTime;
            status = 3;
          }
          break;
        case 3: // waiting instead if delay(greenDuration)
          if (currentTime - startTime >= greenDuration) {
            setTrafficLight(0, 1, 0);
            startTime = currentTime;
            status = 4;
          }
          break;
        case 4: // waiting instead of second delay(2000)
          if (currentTime - startTime >= 2000) {
            startTime = currentTime;
            status = 0;
          }
          break;
        default: // for in-case safety
          status = 0;
          break;
      }
    }
    
    void setTrafficLight(int redState, int yellowState, int greenState) {
      digitalWrite(redPin, redState);
      digitalWrite(yellowPin, yellowState);
      digitalWrite(greenPin, greenState);
    }