Hello All,
I found this script and I am trying to alter it for my needs. I am trying to make the led turn on after a long button press and the turn off after another long button press.
3000ms long press
I sort of have it working but for some reason that I can't figure out why, the script turns on the led at times with a short button press, and I don't see where the short press is coming from.
This is a state machine and it is confusing to me.
Please advise. There is a link in the script to the original script. I am showing my edited script.
Thank you
// ---------------------------------------------
// millis_and_finite_state_machine.ino https://wokwi.com/arduino/projects/314526434594914882
// // ---------------------------------------------
// millis_and_finite_state_machine.ino
// ---------------------------------------------
// License: The Unlicense, Public Domain.
// Author: Koepel
// 2019 january 23
// ---------------------------------------------
//
// millis and a finite state machine
//
// This sketch uses a button and is going through a few different states.
// The serial monitor tells what to do.
//
// The "State Change Detection" example is used.
// The "Blink without Delay" example is used.
// Variables of the "bool" type are used to pass on information.
// Two "previousMillis" variables are used, but a single "previousMillis"
// could be used, because they do not overlap.
//
// The finite state machine has a few ..._INIT states.
// They are used to make a setup for the new state.
//
// A push button is connected between pin 4 and GND.
//
// I want to change this sketch:
// When the led is off and the button is pressed for a long time,
// then I want to turn the led on and after some time turn it off.
//
// An 'enum' is the best way to for a list of the states.
enum
{
STATE_IDLE_INIT,
STATE_IDLE,
STATE_ON_INIT,
STATE_ON_BEFORE_BUTTON,
STATE_ON_BUTTON_2_SECONDS,
STATE_OFF_INIT,
STATE_OFF,
STATE_BLINK_INIT,
STATE_BLINK,
} state;
const int buttonPin = 4;
int last_button_value = HIGH; // pin 2 is HIGH when button is not pressed
unsigned long previousMillisButton;
const int ledPin = 6;
int led_value;
unsigned long previousMillisBlinking;
bool blinking; // boolean variable, should the led blink or not.
bool police_lights_on = false;
void setup()
{
Serial.begin(115200);
Serial.println( "The sketch has started.");
pinMode( buttonPin, INPUT_PULLUP);
pinMode( ledPin, OUTPUT);
}
void loop()
{
unsigned long currentMillis = millis();
// ---------------------------------------------------
// BUTTON
// ---------------------------------------------------
// Detect if the button changes, and pass
// that information on, to the finite state machine.
// Only the event of the change is passed on, because
// this sketch did not need to know the state
// of the button, only a change.
// ---------------------------------------------------
bool buttonPressed = false;
bool buttonReleased = false;
int button_value = digitalRead( buttonPin);
if( button_value != last_button_value)
{
if( button_value == LOW) // low is button pressed
{
buttonPressed = true;
}
else
{
buttonReleased = true;
}//if else
last_button_value = button_value;//remember the last button value
}//if
// ---------------------------------------------------
// FINITE STATE MACHINE
// ---------------------------------------------------
// The final state machine uses information to
// make decisions.
// ---------------------------------------------------
switch( state)
{
case STATE_IDLE_INIT:
// Before going to the actual "idle" state, a message is printed.
Serial.println( "Press the button to turn the led on.");
state = STATE_IDLE;
break;
case STATE_IDLE:
// This "idle" state is when there is nothing to do.
// This state is executed until a button is pressed.
// It "waits" until a button is pressed, but it does
// not really wait, since it is run over and over again.
if( buttonPressed)
{
//my add or edit
state = STATE_ON_BUTTON_2_SECONDS;
// state = STATE_ON_INIT; //orig
}
break;
case STATE_ON_INIT:
// The state when the led is "on" is split into three states.
// This is the initial part to turn the led on and print a message.
if (police_lights_on)
{
Serial.println("police_lights_on");
Serial.println(police_lights_on);
digitalWrite( ledPin, HIGH);
Serial.println( "Press button longer than two seconds to turn it off.");
state = STATE_ON_BEFORE_BUTTON;
}
else
{
digitalWrite( ledPin, LOW);
state = STATE_ON_BEFORE_BUTTON;
}
break;
case STATE_ON_BEFORE_BUTTON:
// This state "waits" until a button is pressed.
// As soon as a button is pressed, the value of millis()
// is stored, to be able to calculate how long the button is pressed.
if( buttonPressed)
{
//previousMillisButton = currentMillis;//orig
state = STATE_ON_BUTTON_2_SECONDS;//orig
}
break;
case STATE_ON_BUTTON_2_SECONDS:
// When the button is released before 2 seconds are passed,
// then return to the state to "wait" for the button.
if( buttonReleased)
{
state = STATE_ON_BEFORE_BUTTON;//keep looping until the correct button press time has been satisfied
}
else
{
if( currentMillis - previousMillisButton >= 3000)
{
//my add or edit
previousMillisButton = currentMillis;
//state = STATE_OFF_INIT; //orig
Serial.println( "Turn on Police light");
if (!police_lights_on)
{
police_lights_on = true;
state = STATE_ON_INIT;
break;
}
else
{
police_lights_on = false;
Serial.println( "Turn OFF Police light");
state = STATE_OFF_INIT;
break;
}
}
}
break;
case STATE_OFF_INIT:
digitalWrite( ledPin, LOW);
Serial.println( "Press button to blink the led.");
state = STATE_OFF; //orig
break;
case STATE_OFF:
if( buttonPressed)
{
//state = STATE_BLINK_INIT;//orig
state = STATE_ON_BUTTON_2_SECONDS;
}
break;
case STATE_BLINK_INIT:
// Set up the blinking.
// Updating the previousMillisBlinking is not really required.
previousMillisBlinking = currentMillis;
blinking = true;
Serial.println( "Press button to stop blinking.");
state = STATE_BLINK;
break;
case STATE_BLINK:
// This state "waits" until a button is pressed.
// At the moment the button is pressed, the led could be on or off.
// Therefor the led is turned off, to be sure that it will be off.
if( buttonPressed)
{
blinking = false;
digitalWrite( ledPin, LOW); // be sure to turn led off
state = STATE_IDLE_INIT;
}
break;
}
// ---------------------------------------------------
// BLINK WITHOUT DELAY
// ---------------------------------------------------
// Blinking the led is outside the final state machine.
// The final state machine can turn the blinking on and off.
// ---------------------------------------------------
/*
if( blinking)
{
if( currentMillis - previousMillisBlinking >= 300)
{
previousMillisBlinking = currentMillis;
if( led_value == LOW)
{
led_value = HIGH;
}
else
{
led_value = LOW;
}
digitalWrite( ledPin, led_value);
}
}
*/
//delay( 10); // a delay as a simple way to debounce the button
}