OK, here's a version of the pedestrian crossing, with encapsulated timing and debounce functions. Didn't have the enthusiasm for the full junction code.
// Pedestrian crossing lights
// Code by Paul__B of Arduino forum.
const int led13Pin = 13; // LED pin number
const int PgrnPin = 6;
const int PredPin = 5;
const int RgrnPin = 4;
const int RyelPin = 3;
const int RredPin = 2;
const int button1 = 10;
int led13State = LOW; // initialise the LED
int PgrnState = LOW;
int PredState = LOW;
int RgrnState = LOW;
int RyelState = LOW;
int RredState = LOW;
char bstate1 = 0;
boolean press = false;
unsigned long count1 = 0; // will store last time LED was updated
unsigned long count2 = 0;
unsigned long count3 = 0;
unsigned long count4 = 0;
unsigned long count5 = 0;
unsigned long bcount1 = 0; // button debounce timer. Replicate as necessary.
// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
boolean timeout(unsigned long *marker, unsigned long interval) {
if (millis() - *marker >= interval) {
*marker += interval; // move on ready for next interval
return true;
}
else return false;
}
void setout(unsigned long *marker) {
*marker = millis(); // initialise
}
// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
switch (*butnstate) { // Odd states if was pressed, >= 2 if debounce in progress
case 0: // Button up so far,
if (button == HIGH) return false; // Nothing happening!
else {
*butnstate = 2; // record that is now pressed
*marker = millis(); // note when was pressed
return false; // and move on
}
case 1: // Button down so far,
if (button == LOW) return false; // Nothing happening!
else {
*butnstate = 3; // record that is now released
*marker = millis(); // note when was released
return false; // and move on
}
case 2: // Button was up, now down.
if (button == HIGH) {
*butnstate = 0; // no, not debounced; revert the state
return false; // False alarm!
}
else {
if (millis() - *marker >= interval) {
*butnstate = 1; // jackpot! update the state
return true; // because we have the desired event!
}
else
return false; // not done yet; just move on
}
case 3: // Button was down, now up.
if (button == LOW) {
*butnstate = 1; // no, not debounced; revert the state
return false; // False alarm!
}
else {
if (millis() - *marker >= interval) {
*butnstate = 0; // Debounced; update the state
return false; // but it is not the event we want
}
else
return false; // not done yet; just move on
}
default: // Error; recover anyway
{
*butnstate = 0;
return false; // Definitely false!
}
}
}
void setleds() {
digitalWrite(led13Pin, led13State);
digitalWrite(PredPin, PredState);
digitalWrite(PgrnPin, PgrnState);
digitalWrite(RredPin, RredState);
digitalWrite(RyelPin, RyelState);
digitalWrite(RgrnPin, RgrnState);
}
boolean ispress() { // One-directional read of button - sets but does not clear!
if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
press = true;
}
return(press);
}
void setup() {
Serial.begin(9600);
pinMode(led13Pin, OUTPUT);
pinMode(PgrnPin, OUTPUT);
pinMode(PredPin, OUTPUT);
pinMode(RgrnPin, OUTPUT);
pinMode(RyelPin, OUTPUT);
pinMode(RredPin, OUTPUT);
pinMode(button1, INPUT);
digitalWrite(button1,HIGH); // internal pullup all versions
press = false;
Serial.println("Starting ...");
}
void loop() {
// All red phase
RredState = HIGH;
RyelState = LOW;
RgrnState = LOW;
PredState = HIGH;
PgrnState = LOW;
setleds();
Serial.println("Red phase");
setout(&count3);
while (!timeout(&count3, 3000UL )) {
ispress(); // Check on the button
}
// Road Green
RredState = LOW;
RyelState = LOW;
RgrnState = HIGH;
PredState = HIGH;
PgrnState = LOW;
setleds();
Serial.println("Road green");
setout(&count3);
while (!timeout(&count3, 8000UL )) { // Reasonable time on green
ispress(); // Check on the button
}
Serial.println("Green stale, wait on button");
while ( press == false ) // Now wait for the button
{
if (timeout(&count2, 300UL )) {
if (led13State == LOW) {
led13State = HIGH;
}
else {
led13State = LOW;
}
digitalWrite(led13Pin, led13State);
}
ispress();
}
led13State = LOW;
digitalWrite(led13Pin, led13State);
Serial.println("Button sensed");
setout(&count3);
while (!timeout(&count3, 4000UL )) { // Do not respond immediately!
}
// Road Yellow
RredState = LOW;
RyelState = HIGH;
RgrnState = LOW;
PredState = HIGH;
PgrnState = LOW;
setleds();
Serial.println("Road yellow");
setout(&count3);
while (!timeout(&count3, 5000UL )) {
}
// Road Red
RredState = HIGH;
RyelState = LOW;
RgrnState = LOW;
PredState = HIGH;
PgrnState = LOW;
setleds();
Serial.println("Road red");
setout(&count3);
while (!timeout(&count3, 3000UL )) {
}
// Walk Green
RredState = HIGH;
RyelState = LOW;
RgrnState = LOW;
PredState = LOW;
PgrnState = HIGH;
setleds();
press = false;
Serial.println("Walk");
setout(&count3);
while (!timeout(&count3, 6000UL )) {
}
// Flash Don't Walk
RredState = HIGH;
RyelState = LOW;
RgrnState = LOW;
PgrnState = LOW;
Serial.println("Flash Don't Walk");
setout(&count3);
while (!timeout(&count3, 7000UL )) {
if (timeout(&count2, 500UL )) {
if (PredState == LOW) {
PredState = HIGH;
}
else {
PredState = LOW;
}
setleds();
}
ispress(); // Check on the button
}
}