i have been trying to figure this one out for a wile. i am trying to get a traffic light to have 4 different modes of operation and be able to switch through them with the click of a spst button. i would like to have mode 1) yellow flash 1 second intervals. mode 2) same as yellow only with red flashing mode 3)US 3 light traffic setup and mode 4) 4 light traffic with yellow overlap.
i have the light code all set but im having a problem with the delays as it stops polling the button. i would like at a later time to add a pot to control how long the red and green lights are on.
and a static delay for yellows.
here is what i have. currently mode 4 is a place holder .
Time to look at the "BlinkWithoutDelay" example (File->Examples->2.Digital->BlinkWithoutDelay) to see how you schedule things without using delays. That way your sketch can spend a lot more time checking for button presses since the only other thing it needs to do is: "Is it time to change the lights?".
thank you for you help i have it switching great on the yellow and red flash mode. now the challenge is getting it to do it with timed lights.
i would like to have the delay for the red, yellow and green independently set.
i have revised the code also i think i need to implement debounce it skips from yellow flash to 3 light with out doing red flash
#include <Button.h>
int Greenpin = 12;
int Yellowpin = 11;
int Redpin = 10;
int buttonPresses = 0;
unsigned long changeTime;
Button button = Button(2,LOW);
int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
long interval = 1000;
void setup()
{
pinMode(Greenpin, OUTPUT);
pinMode(Yellowpin, OUTPUT);
pinMode(Redpin, OUTPUT);
}
void loop(){
if(button.isPressed()){
buttonPresses++;
mode();
}
else{
mode();
}
}
void mode(){
if(buttonPresses == 0){
yellowflash();
}
else if(buttonPresses == 1){
redflash();
}
else if(buttonPresses == 2){
threelight();
}
else if(buttonPresses <=3){
buttonPresses =0;
}
}
void yellowflash(){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(Greenpin, LOW);
digitalWrite(Redpin,LOW);
// set the LED with the ledState of the variable:
digitalWrite(Yellowpin, ledState);
}
}
void redflash(){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(Greenpin, LOW);
digitalWrite(Yellowpin,LOW);
// set the LED with the ledState of the variable:
digitalWrite(Redpin, ledState);
}
}
void threelight(){
digitalWrite(Redpin, LOW);
digitalWrite(Yellowpin, LOW);
digitalWrite(Greenpin, HIGH);
delay(5000);
digitalWrite(Redpin, LOW);
digitalWrite(Yellowpin, HIGH);
digitalWrite(Greenpin, LOW);
delay(1000);
digitalWrite(Redpin, HIGH);
digitalWrite(Yellowpin, LOW);
digitalWrite(Greenpin, LOW);
delay(5000);
}
For the timed lights, create a global "state variable" to keep track of which step you are at. Then you can act on the timer based on where you are in the sequence. It's a lot like the "buttonPresses" variable. Set the state to 0. Inside threeLight: if the state is 0 you set the light to GREEN, note the current time, and set the state to 1. If the state is 1 and the time that has passed is more than GreenInterval you set the light to YELLOW, note the current time, and set the state to 2. If the state is 2 and the time that has passed is more than YellowInterval you set the light to RED, note the current time, and set the state to 3. If the state is 3 and the time that has passed is more than RedInterval you set the state to 0 which causes the whole process to start again with GREEN. You can set GreenInteval, YellowInterval, and RedInterval whenever you want.
turn GREEN, set the state to 0, and store the current time.
PaulS:
Apparently, you misunderstood the purpose of the blink without delay example, or you would not have all those delay()s still in the code.
He took the delays out of the simple ON/OF cases (yellow and red) but did not know about coding a state machine to produce more complex patterns: green for a while, then yellow for a short time, then red for a different while...
the second problem i am having is the switch does not go to the redflashing when i press it. it jumps right to threelights. i think the debouncing is off.
#include <Bounce.h>
int Greenpin = 12;
int Yellowpin = 11;
int Redpin = 10;
int buttonPresses = 0;
int button = 2;
int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
long interval = 1000;
Bounce bouncer = Bounce(button,50);
void setup()
{
pinMode(button, INPUT);
pinMode(Greenpin, OUTPUT);
pinMode(Yellowpin, OUTPUT);
pinMode(Redpin, OUTPUT);
digitalWrite(button, HIGH);
}
void loop(){
bouncer.update ( );
int value = bouncer.read();
if ( value == LOW){
buttonPresses++;
}
mode();
}
void mode(){
if(buttonPresses == 0){
yellowflash();
}
else if(buttonPresses == 1){
redflash();
}
else if(buttonPresses == 2){
threelight();
}
else if(buttonPresses >= 3){
buttonPresses = 0;
}
}
void yellowflash(){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(Greenpin, LOW);
digitalWrite(Redpin,LOW);
digitalWrite(Yellowpin, ledState);
}
}
void redflash(){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(Greenpin, LOW);
digitalWrite(Yellowpin,LOW);
digitalWrite(Redpin, ledState);
}
}
void threelight(){
digitalWrite(Redpin, LOW);
digitalWrite(Yellowpin, LOW);
digitalWrite(Greenpin, HIGH);
delay(5000);
digitalWrite(Redpin, LOW);
digitalWrite(Yellowpin, HIGH);
digitalWrite(Greenpin, LOW);
delay(1000);
digitalWrite(Redpin, HIGH);
digitalWrite(Yellowpin, LOW);
digitalWrite(Greenpin, LOW);
delay(5000);
}
debouncing just is to delay reading a digital input to avoid noise, not to determine if its being held down or not, and without a bit of code every loop its going to look, see button is down and advance.
you need something to compare
if button != oldbutton THEN do something
if button == oldbutton THEN its being held and ignore it until its released again
This is how I would write it if I were writing it:
// Define the pins we are using
const int greenPin = 12;
const int yellowPin = 11;
const int redPin = 10;
const int buttonPin = 2;
enum color {
GREEN, YELLOW, RED, OFF}
lightState = OFF; // State of the three-light traffic light
int lightMode = 0; // Blinking yellow, Blinking red, or full color
unsigned long lastButtonPressTime;
bool lastButtonState;
const unsigned long buttonDebounceInterval = 100; // One peress per 1/10th second
bool blinkerOn = false; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long blinkInterval = 1000;
unsigned long greenInterval = 1000;
unsigned long yellowInterval = 1000;
unsigned long redInterval = 1000;
void setup()
{
pinMode(greenPin, OUTPUT);
pinMode(yellowPin, OUTPUT);
pinMode(redPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
// NOTE: The argument here would normally be 'enum color' but the way Arduino does things
// (it puts all function declarations at the top) it tries to declare the function before
// the declaration of the enum and gets and error. Fortunately enums work a lot like
// integers.
void setColor(int newColor)
{
// Turn all colors off to start
digitalWrite(greenPin, LOW);
digitalWrite(yellowPin, LOW);
digitalWrite(redPin, LOW);
switch (newColor)
{
case GREEN:
digitalWrite(greenPin, HIGH);
break;
case YELLOW:
digitalWrite(yellowPin, HIGH);
break;
case RED:
digitalWrite(redPin, HIGH);
break;
}
}
void loop(){
bool buttonState = digitalRead(buttonPin);
if (buttonState != lastButtonState && millis() - lastButtonPressTime > buttonDebounceInterval)
{
lastButtonState = buttonState;
lastButtonPressTime = millis();
if (buttonState == LOW) // Button is 'active low'?
lightMode++;
}
switch (lightMode)
{
case 0:
lightState = OFF; // Re-start at GREEN
flash(YELLOW);
break;
case 1:
lightState = OFF; // Re-start at GREEN
flash(RED);
break;
case 2:
threelight();
break;
default:
lightMode = 0;
}
}
// NOTE: The argument here would normally be 'enum color' but the way Arduino does things
// (it puts all function declarations at the top) it tries to declare the function before
// the declaration of the enum and gets and error. Fortunately enums work a lot like
// integers.
void flash(int flashColor){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > blinkInterval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
blinkerOn = !blinkerOn; // Toggle blinker
if (blinkerOn)
setColor(flashColor);
else
setColor(OFF);
}
}
void threelight(){
unsigned long currentMillis = millis();
switch (lightState)
{
case GREEN:
if (currentMillis - previousMillis > greenInterval)
{
previousMillis = currentMillis; //Re-start timer
lightState = YELLOW;
setColor(YELLOW);
}
break;
case YELLOW:
if (currentMillis - previousMillis > yellowInterval)
{
previousMillis = currentMillis; //Re-start timer
lightState = RED;
setColor(RED);
}
break;
case RED:
if (currentMillis - previousMillis > redInterval)
{
previousMillis = currentMillis; //Re-start timer
lightState = GREEN;
setColor(GREEN);
}
break;
default:
lightState = GREEN;
previousMillis = currentMillis;
setColor(GREEN);
}
}
@OP:
Notice how in John's code the { and } line up. Notice how everything in between is properly indented. Notice how much/little white space is used. Notice how much more readable his code is than yours.
The Tools + Auto format menu item is there for a reason. You should use it regularly.