Page 139

PWM colours breadboard layout

Page 140

void state1(); void state2(); void state3(); void state4(); void state5(); void state6(); void (*states[])(void) = { state1, state2, state3, state4, state5, state6 }; void setup() { Serial.begin(115200); } void loop() { for(int i = 0; i < 6; i++){     states[i](); } } void state1() { if(Serial) {Serial.println("State 1");} delay(2000); } void state2() { if(Serial) {Serial.println("State 2");} delay(2000); } void state3() { if(Serial) {Serial.println("State 3");} delay(2000); } void state4() { if(Serial) {Serial.println("State 4");} delay(2000); } void state5() { if(Serial) {Serial.println("State 5");} delay(2000); } void state6() { if(Serial) {Serial.println("State 6");} delay(2000); }

Page 141

#define C6 1047 volatile bool pedRequest = false; const int RED_TRAFFIC = 8; const int AMBER_TRAFFIC = 7; const int GREEN_TRAFFIC = 6; const int DONT_CROSS = 5; const int CROSS = 4; const int PED_BUTTON = 2; const int PED_SOUNDER = 3; void setup() { Serial.begin(115200); pinMode(RED_TRAFFIC, OUTPUT); pinMode(AMBER_TRAFFIC, OUTPUT); pinMode(GREEN_TRAFFIC, OUTPUT); pinMode(DONT_CROSS, OUTPUT); pinMode(CROSS, OUTPUT); pinMode(PED_BUTTON, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(PED_BUTTON), intHandler, FALLING); } void intHandler() { pedRequest = true; } void state1() { int leds[] = {     RED_TRAFFIC, AMBER_TRAFFIC, GREEN_TRAFFIC,     DONT_CROSS, CROSS}; if(Serial) {Serial.println("Testing LEDs");} for (int i = 0; i < 5; i++) {     digitalWrite(leds[i], HIGH);     delay(500);     digitalWrite(leds[i], LOW); } if(Serial) {Serial.println("Testing Sound");} for(int i = 0; i < 5; i++) {     tone(PED_SOUNDER, C6, 250);     delay(500); } noTone(PED_SOUNDER); if(pedRequest) {     pedRequest = false;     if(Serial) {      Serial.println("Pedestrian Button Pressed");     } } }

Page 143

void state2() { if(Serial) {     Serial.println("State 2"); } unsigned long startMillis = millis(); digitalWrite(GREEN_TRAFFIC, LOW); digitalWrite(DONT_CROSS, HIGH); digitalWrite(AMBER_TRAFFIC, HIGH); do {      }while((unsigned long)(millis() - startMillis) < 3000); }

Page 143

unsigned long milliMe; unsigned long stopVal = 2000ul; unsigned long startVal = 0xFFFFFFFF; unsigned int target = 1000; void setup() { Serial.begin(115200); startVal -= 10000; milliMe = startVal; } void loop() { unsigned long lastMilli = milliMe; for(int i = 0; i < 32767; i++) {     milliMe++;     if((unsigned long)(milliMe - lastMilli) >= target) {      Serial.print("Simulated mills() at: ");      Serial.print(milliMe);      Serial.print(", lastMilli: ");      Serial.print(lastMilli);      Serial.println(" difference >= target");      lastMilli = milliMe;     }     if(milliMe < startVal && milliMe > stopVal) {      break;     } } }

Page 144

The complete program

#define C6 1047 #define BEEP 250 #define THRD_SEC 330 #define HALF_SEC 500 #define SECS_3 3000 #define SECS_2 2000 #define SECS_7 7000 #define SECS_6 6000 #define MAX_WAIT 10000 void state1(); void state2(); void state3(); void state4(); void state5(); void state6(); void (*states[])(void) = { state1, state2, state3, state4, state5, state6 }; volatile bool pedRequest = false; const int RED_TRAFFIC = 8; const int AMBER_TRAFFIC = 7; const int GREEN_TRAFFIC = 6; const int DONT_CROSS = 5; const int CROSS = 4; const int PED_BUTTON = 2; const int PED_SOUNDER = 3; void setup() { pinMode(RED_TRAFFIC, OUTPUT); pinMode(AMBER_TRAFFIC, OUTPUT); pinMode(GREEN_TRAFFIC, OUTPUT); pinMode(DONT_CROSS, OUTPUT); pinMode(CROSS, OUTPUT); pinMode(PED_BUTTON, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(PED_BUTTON), intHandler, FALLING); } void loop() { for(int i = 0; i < 6; i++){     states[i](); } } void intHandler() { pedRequest = true; } void state1() { pedRequest = false; unsigned long startMillis = millis(); digitalWrite(DONT_CROSS, HIGH); digitalWrite(GREEN_TRAFFIC, HIGH); digitalWrite(AMBER_TRAFFIC, LOW); while(true) {     unsigned long currentMillis = millis();     if(pedRequest) {      if((unsigned long)(currentMillis - startMillis) >= MAX_WAIT) {         break; // pedestrian request and minimum time condition met      }     } } } void state2() { unsigned long startMillis = millis(); digitalWrite(GREEN_TRAFFIC, LOW); digitalWrite(DONT_CROSS, HIGH); digitalWrite(AMBER_TRAFFIC, HIGH); do { }while((unsigned long)(millis() - startMillis) < SECS_3); } void state3() { unsigned long startMillis = millis(); digitalWrite(RED_TRAFFIC, HIGH); digitalWrite(AMBER_TRAFFIC, LOW); digitalWrite(DONT_CROSS, HIGH); do { }while((unsigned long)(millis() - startMillis) < SECS_3); } void state4() { unsigned long startMillis = millis(); unsigned long lastMillis = startMillis; digitalWrite(RED_TRAFFIC, HIGH); digitalWrite(CROSS, HIGH); digitalWrite(DONT_CROSS, LOW); tone(PED_SOUNDER, C6, BEEP); while(true) {     unsigned long currentMillis = millis();     if((unsigned long)(currentMillis - lastMillis) >= HALF_SEC){      tone(PED_SOUNDER, C6, BEEP);      lastMillis = currentMillis;     }     if((unsigned long)(currentMillis - startMillis) >= SECS_7) {      break; // timed end of state 4     } } noTone(PED_SOUNDER); } void state5() { unsigned long startMillis = millis(); unsigned long trafficMillis = startMillis; unsigned long pedMillis = startMillis; digitalWrite(AMBER_TRAFFIC, HIGH); digitalWrite(RED_TRAFFIC, LOW); digitalWrite(CROSS, HIGH); while(true) {     unsigned long currentMillis = millis();     if((unsigned long)(currentMillis - trafficMillis) >= HALF_SEC){      digitalWrite(AMBER_TRAFFIC, digitalRead(AMBER_TRAFFIC) ^ 1);      trafficMillis = currentMillis;     }     if((unsigned long)(currentMillis - pedMillis) >= THRD_SEC){      digitalWrite(CROSS, digitalRead(CROSS) ^ 1);      pedMillis = currentMillis;     }     if((unsigned long)(currentMillis - startMillis) >= SECS_6) {      break; // timed end of state 5     } } } void state6() { unsigned long startMillis = millis(); unsigned long lastMillis = startMillis; digitalWrite(DONT_CROSS, HIGH); digitalWrite(CROSS, LOW); digitalWrite(AMBER_TRAFFIC, HIGH); while(true) {     unsigned long currentMillis = millis();     if((unsigned long)(currentMillis - lastMillis) >= HALF_SEC){      digitalWrite(AMBER_TRAFFIC, digitalRead(AMBER_TRAFFIC) ^ 1);      lastMillis = currentMillis;     }     if((unsigned long)(currentMillis - startMillis) >= SECS_2) {      break; // timed end of state 6     } } }

Page 148

extern volatile unsigned long timer0_millis; void resetMillis(){ uint8_t oldSREG = SREG; // copy the status Register cli(); // disable interrupts timer0_millis = 0; // zero the millis counter SREG = oldSREG; // reset the status Register }

Page 149 and page 150

#define BOUNCE_TIME 50 volatile bool pedRequest = false; volatile bool suspRequest = false; unsigned long suspenseTime = millis(); // used to debounce button bool suspended = false; const int RED_TRAFFIC = 8; const int AMBER_TRAFFIC = 7; const int GREEN_TRAFFIC = 6; const int DONT_CROSS = 5; const int CROSS = 4; const int PED_BUTTON = 2; const int PED_SOUNDER = 9; const int REMOTE_SUSPEND = 3;

pinMode(REMOTE_SUSPEND, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(REMOTE_SUSPEND), suspHandler, FALLING);

void suspHandler() { unsigned long currentMillis = millis(); if((unsigned long)(currentMillis - suspenseTime) > BOUNCE_TIME) {     suspRequest = true;     suspenseTime = currentMillis; } } void state7() { unsigned long trafficMillis = millis(); unsigned long pedMillis = trafficMillis; digitalWrite(AMBER_TRAFFIC, HIGH); digitalWrite(RED_TRAFFIC, LOW); digitalWrite(CROSS, HIGH); digitalWrite(DONT_CROSS, LOW); digitalWrite(GREEN_TRAFFIC, LOW); while(true) {     if(suspRequest) { return;}     unsigned long currentMillis = millis();     if((unsigned long)(currentMillis - trafficMillis) >= HALF_SEC){      digitalWrite(AMBER_TRAFFIC, digitalRead(AMBER_TRAFFIC) ^ 1);      trafficMillis = currentMillis;     }     if((unsigned long)(currentMillis - pedMillis) >= THRD_SEC){      digitalWrite(CROSS, digitalRead(CROSS) ^ 1);      pedMillis = currentMillis;     } } }

Page 150

void loop() { for(int i = 0; i < 6; i++){     if(suspRequest) {      suspRequest = false;      suspended = !suspended;      if(suspended) {         states[0] = state7;         i = 0;      } else {         states[0] = state1;         i = 1; // restart at pedestrian safe point      }     }     states[i](); } }