Hi, i´m doing a simple code example making some leds go like "the fantastic car lights" when i push a pushbutton and stopping when i push it again, but i have a problem, if i push in the middle of the sequence, nothing happens, i must push it in the beginning of the sequence or hold the button down until that moment. I want to end the sequence at any moment, so i accept suggestions, thanñs a lot, here is my code.
int retardo=20; //I nicializamos la variable que usaremos para el retardo
int i=0; // Contador
int pulsacion=0;
int estadoActual=0;
int estadoAnterior=0;
void setup(){
pinMode(3, INPUT); // configuramos el pin 3 como entrada
for (i=5; i<=9;i++){ // Ponemos los pins 5,6,7,8,9 como salida
pinMode (i, OUTPUT);
}
}
void loop(){
estadoActual=digitalRead(3); //Leemos el estado del pulsador
if (estadoActual!=estadoAnterior){
if ((estadoActual^estadoAnterior)&estadoActual)
pulsacion++;
}
estadoAnterior=estadoActual;
if ((pulsacion%2)!=0)
parpadeo();
}
void parpadeo(){
//if (estadoActual==HIGH){ // si no esta pulsado no parpadean los leds, en el momento que se pulsa parapadean mientras este pulsado
for (i=5; i<9; i++){ // Encendemos y apagamos de izquierda a derecha dejando una estela
digitalWrite (i, HIGH);
delay (retardo);
digitalWrite (i+1, HIGH); // Estela
delay (retardo);
digitalWrite (i, LOW);
delay (retardo*2);
}
for (i=9; i>5;i--){
digitalWrite (i, HIGH); // Encendemos de derecha a izquierda dejando una estela
delay (retardo);
digitalWrite(i-1, HIGH); // Estela
delay (retardo);
digitalWrite (i, LOW);
delay (retardo*2);
}
//}else{
digitalWrite (5, LOW);
//}
}
The problem is caused by the use of the delay() function, of which you have many in your code. This extends the time taken by the for loops, which is what you want, but that prevents the buttons being read until the end of the for loops.
Two suggestions.
(1) Read the button state in inside the for loops and exit the for loop if a button press is detected.
Or, much better, but would require a complete re-write of your code
(2) Do all the timing using the millis() function so that you can check the button state more frequently because the code will not be blocked waiting for multiple delays in for loops. Look at the BlinkWithoutDelay example in the IDE for an idea of how to use millis() as a timer. Basically, each time through loop() you check whether the the button is pressed and if so act on it, If not you check whether it is time to turn on/off the next LED. If so you do it and if not you carry on until it is then take action.
This is very well suited for implemention by a state machine. This code is based on my state machine library found here: http://playground.arduino.cc/Code/SMlib
The state diagram is attached
#include <SM.h>
SM KnightRider(Idle);
const int button = 3;
int buttonState;//for edge detection
int light;
void setup(){
for (light=5; light<=9; light++) pinMode (light, OUTPUT);
}//setup()
void loop(){
EXEC(KnightRider);//run statemachine
}//loop()
State Idle(){
for(light=5; light<=9; light++) digitalWrite(light, 0);//turn lights off
light = 0;
if(RE(digitalRead(button), buttonState)) KnightRider.Set(RunUpH, RunUpB);
}//Idle()
State RunUpH(){//set outputs and count
digitalWrite((11+light)/2, 1);//light on
digitalWrite((8+light++)/2, 0);//light off
light %= 9;
}//RunUpH()
State RunUpB(){//check input and timing
if(RE(digitalRead(button), buttonState)) KnightRider.Set(Idle);//stop
if(KnightRider.Timeout(20)){//next step after 20 ms
if(light == 0) KnightRider.Set(RunDwnH, RunDwnB);//final step, change state
else KnightRider.Set(RunUpH, RunUpB);//otherwise step in same direction
}//if(KnightRider)
}//RunUpB()
State RunDwnH(){//set outputs and count
digitalWrite((18-light)/2, 1);//light on
digitalWrite((21-light++)/2, 0);//light off
light %= 9;
}//RunDwnH()
State RunDwnB(){//check inputs and timing
if(RE(digitalRead(button), buttonState)) KnightRider.Set(Idle);//stop
if(KnightRider.Timeout(20)){//next step after 20 ms
if(light == 0) KnightRider.Set(RunUpH, RunUpB);//final step change state
else KnightRider.Set(RunDwnH, RunDwnB);//otherwise step in same direction
}//if(KnightRider)
}//RunDwnB()