Reputation: 31
I am trying to make this thing where every time a micro limit switch is HIGH (pressed), it starts this process that turns on a red LED for fifty seconds, then blinks the LED for about ten seconds, and then finally turns off the red, and turns on a green LED for about 50 seconds. Also, I am doing all of this on an Arduino.
The big problem that I am having pertains to breaking the loop every time the limit switch is not pressed. I want this series of LED events only to occur when the switch is pressed. The code below uses the delay method, which I know will not work for this project because the button state change will not be recognized during the LED events. I put it below just so you all can understand what I am trying to achieve.
Also, I am relatively new to the Arduino so every bit of help is greatly appreciated. Thanks.
Here is the code that I mentioned above :
const int buttonPin = 2;
const int ledPin = 12;
const int ledPin1 = 9;
int buttonState = 0;
void setup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(ledPin1, OUTPUT);
Serial.begin(115200);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
delay(50000);
digitalWrite(ledPin, LOW);
delay(1000);
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
digitalWrite(ledPin1, HIGH);
delay(50000);
}
else if (buttonState == LOW) {
digitalWrite(ledPin, LOW);
digitalWrite(ledPin1, LOW);
}
}
Upvotes: 3
Views: 756
Reputation: 1967
For these types of problems I really like to use switch()
statements to create a state machine. I would also recommend that you do not use the delay()
function at all, but rather calculate how much time has passed since you had last looped. Here is a quick example that I came up with... I apologize if it has any errors in it, I was in a bit of a hurry. If you are having trouble following the logic, let me know and I will add more comments.
#define WAIT_TIME_50S 50000 /* 50,000ms = 50s */
#define WAIT_TIME_10S 10000 /* 10,000ms = 10s */
#define WAIT_TIME_1S 1000 /* 1,000ms = 1s */
/* Create an enumeration 'type' with the different states that you will
be going through. This keeps your switch statement very
descriptive and you know exactly what happens as you go from
state to state. */
typedef enum
{
SWITCH_RELEASED,
RED_LED_ON_50S,
RED_LED_BLINK_10S,
GREEN_LED_ON_50S,
RESET_LEDS
} LedState_t;
const int buttonPin = 2;
const int ledPinRed = 12;
const int ledPinGreen = 9;
int buttonState = LOW;
void loop()
{
static LedState_t currentState = RESET_LEDS;
static unsigned long previousTime_ms = 0;
static unsigned long previousBlinkTime_ms = 0;
unsigned long currentTime_ms = 0;
static int ledState = LOW;
buttonState = digitalRead(buttonPin);
switch (currentState)
{
case SWITCH_RELEASED:
if (buttonState == HIGH)
{
currentState = RED_LED_ON_50S;
digitalWrite(ledPinRed, HIGH);
previousTime_ms = millis();
}
break;
case RED_LED_ON_50S:
if (buttonState == LOW)
{
currentState = RESET_LEDS;
}
else
{
currentTime_ms = millis();
if ((currentTime_ms - previousTime_ms) >= WAIT_TIME_50S)
{
previousTime_ms = currentTime_ms;
previousBlinkTime_ms = currentTime_ms;
ledState = LOW;
digitalWrite(ledPinRed, ledState);
currentState = RED_LED_BLINK_10S;
}
}
break;
case RED_LED_BLINK_10S:
if (buttonState = LOW)
{
currentState = RESET_LEDS;
}
else
{
currentTime_ms = millis();
if ((currentTime_ms - previousTime_ms) >= WAIT_TIME_10S)
{
previousTime_ms = currentTime_ms;
digitalWrite(ledPinRed, LOW);
digitalWrite(ledPinGreen, HIGH);
currentState = GREEN_LED_ON_50S;
}
else if ((currentTime_ms - previousBlinkTime_ms) >= WAIT_TIME_1S)
{
previousBlinkTime_ms = currentTime_ms;
if (ledState == HIGH)
{
ledState = LOW;
}
else
{
ledState = HIGH;
}
digitalWrite(ledPinRed, ledState);
}
}
break;
case GREEN_LED_ON_50S:
if (buttonState == LOW)
{
currentState = RESET_LEDS;
}
else
{
currentTime_ms = millis();
if ((currentTime_ms - previousTime_ms) >= WAIT_TIME_50S)
{
currentState = RESET_LEDS;
}
}
break;
case RESET_LEDS:
digitalWrite(ledPinRed, LOW);
digitalWrite(ledPinGreen, LOW);
currentState = SWITCH_RELEASED;
break;
}
}
Upvotes: 0
Reputation: 1510
The simplest way to achieve what you want is splitting loop()
function into several small functions, and splitting delays into many small delays. For example to handle your first waiting you need something like this:
bool wait50secondsOnHigh()
{
for (int counter = 0; counter < 5000; counter++)
{
if (digitalRead(buttonPin) == LOW)
{
return false;
}
digitalWrite(ledPin, HIGH);
delay(10);
}
return wait1secondOnLow();
}
loop()
{
if (!wait50secondsOnHigh())
{
digitalWrite(ledPin, LOW);
digitalWrite(ledPin1, LOW);
}
}
Other waiting functions can be written in similar fashion: you check your button every 10 milliseconds N times, if it's HIGH
you continue, if it's LOW
you return false. After you're done, you call next function. Last function in sequence will simply return true
:
bool wait50secondsOnHighLed1()
{
for (int counter = 0; counter < 5000; counter++)
{
if (digitalRead(buttonPin) == LOW)
{
return false;
}
digitalWrite(ledPin1, HIGH);
delay(10);
}
return true;
}
Once you will have a function for each waiting you can refactor the code to avoid duplications, but I leave it as an exercise to you :)
You can also use special libraries for event handling, for example http://playground.arduino.cc/Code/QP but for a beginner I would recommend a simpler approach. Events are hard to debug, especially on Arduino. But one you get more comfortable with Arduino, you should try to experiment with them.
By the way: I think you should switch off led1
at the end.
Upvotes: 1