2 sketches are examples for beginners.
The first shown is the latest. The second sketch of 2.
It does not show what would bury the main lesson in details.
It does some entangling of tasks, save that for later.
The second sketch here is the delay version just to show the difference in code and how it acts. The top sketch is a conversion of the delay version to a non-blocking version.
// NonBlockedSketchLedAndButton v1.1 by GoForSmoke 03/15/24
// compiles, untested so far
// expect: ground pin 7 to toggle blink off/on
const byte blinkPin = 13; // Uno board LED pin13
const byte buttonPin = 7; // a jumper from pin 7 to GND = pressed
byte buttonStateNow, buttonStatePrev; // to compare what is to what was
const byte debounce = 10; // ms delay while the contacts settle, dirty signal
unsigned int debounceStart; // interval is debounce above
byte blinkState; // led13 0=OFF, not-0=ON
unsigned long blinkStart, blinkInterval = 500; // ON/OFF times are equal
const unsigned long interval = 500; // so blinkInterval can reset after change
void setup()
{
pinMode( blinkPin, OUTPUT ); // LOW by default
// blinkState is 0 by default
pinMode( buttonPin, INPUT_PULLUP ); // pin reads 0 when the button to ground is down
buttonStateNow = buttonStatePrev = 1; // start with button up as last pin read
}
void blink() // only blinks when blinkInterval > 0
{
static unsigned long waitStart, waitMs; // time values, always unsigned
if ( blinkInterval == 0 ) // here is where the blink is stopped if true
{
return; // let loop() run so that this can check later.
}
if ( waitMs > 0 ) // if-timer runs when set then turns itself off
{
// working with time, End Time - Start Time = Elapsed Time
// that formula always works even across rollover (no problem).
if ( millis() - waitStart >= waitMs ) // see if wait is over
{
waitMs = 0; // wait is over, turn wait off!
}
}
else
{
blinkState = !blinkState; // != is NOT =, toggle 0 <==> 1
digitalWrite( blinkPin, blinkState );
waitMs = blinkInterval;
waitStart = millis();
}
return;
}
void button() // this works, it's not the quickest but is simpler than quicker code!
{
static byte State = 0; // local variable only the function uses
static unsigned long waitStart, waitMs; // local vars
if ( waitMs > 0 ) // if-timer for delays set in this function
{
if ( millis() - waitStart >= waitMs ) // check if elapsed time >= wait time
{
waitMs = 0;
}
}
else // no timer delay this time
{
switch ( State ) // now we run the state machine!
{
case 0 : // looking for change from button WAS up and is NOW down.
buttonStateNow = digitalRead( buttonPin );
if ( buttonStateNow == 0 && buttonStatePrev == 1 ) // press detected
{
waitMs = debounce; // time to spend ingnoring button bounce
waitStart = millis(); // setting start time to NOW
State = 1;
}
else if ( buttonStateNow == 1 && buttonStatePrev == 0 ) // release detected
{
waitMs = debounce; // setting the interval of ignoring the pin
waitStart = millis(); // when the blink is to start... is NOW
}
buttonStatePrev = buttonStateNow; // done with the read, make it previous
break; // leave the switch-case
case 1 :
if ( blinkInterval > 0 ) // if the blink is still active
{
blinkInterval = 0; // stop blinking
digitalWrite( blinkPin, LOW ); // the led may be ON or OFF, make sure it's OFF
}
else // the blink must be OFF
{
blinkInterval = interval; // blink at interval, restarts blinking
}
State = 0; // so now it goes back to waiting for button press
break; // exit the switch-case
}
}
return;
}
void loop() // this will run so fast the order of functions makes no difference
{
button();
blink();
}
This is the Blocked version, a before picture the above was made from. Together they may help beginners get non-blocking code.
// BlockedSketchLedAndButton v1.1 by GoForSmoke 03/13/24
// for 1.1 a lot of comments have been added.
// This sketch is not PERFECT.
// It explores doing 2 things "at once" with delay-code.
// How responsive the button acts says how well it works.
// this began with a simple Blink With Delay Sketch.
// This sketch adds an ON/OFF toggle button with delay debounce.
// compiles, untested so far
// expect: ground pin 7 to toggle blink off/on
// expect this to take a while to notice button action.
// expect the button response to be quicker when blink is OFF.
// this is a Before Sketch. The After Sketch does not Block Execution.
// note for Beginners
// Arduino variable type byte can be 0 to 255, easy to type.
// variable type unsigned int can be 0 to 65535, Arduino name is word.
// Where an int uses 16 bits of RAM, Arduino byte uses only 8.
// When I only need a byte, I don't use more on Arduinos.
const byte debounce = 10; // ms delay to ignore contact bouncing.
const byte blinkPin = 13; // LED pin to blink
const byte buttonPin = 7; // the name says it
byte buttonStateNow; // pin state may be 0 (LOW) or not-0 (HIGH).
byte buttonStatePrev; // see if pin state changed from Prev to Now.
byte blinkState; // the LED is 0 (LOW) or not-0 (HIGH)
// using 0 for LOW and not-0 for HIGH gives options not used here
// and that is the way the chip works.
// When you have 8 bits for one T/F... they can ALL be used.
unsigned int blinkInterval = 500; // so far the blink ON time = OFF time
const unsigned int interval = 500; // to restore the working value
// the button works by making blinkInterval = 0 or = interval
void setup()
{
pinMode( blinkPin, OUTPUT ); // LOW by default
// blinkState = 0; // by default
pinMode( buttonPin, INPUT_PULLUP ); // up is 1, down is 0
buttonStateNow = buttonStatePrev = 1; // start values initialized
}
void blink() // can be turned OFF and ON through blinkInterval
{
if ( blinkInterval > 0 ) // button toggled to ON by default
{
blinkState = !blinkState; // 0 <==> 1
digitalWrite( blinkPin, blinkState ); // led blink
delay( blinkInterval );
}
}
void button() // works by changing blinkInterval, OFF turns LED OFF.
{
buttonStateNow = digitalRead( buttonPin );
// button press detect, state was 1, now 0
if (( buttonStateNow == 0 ) && ( buttonStatePrev == 1 )) // press detected
{
delay( debounce ); // contact switch changes are briefly DIRTY
if ( blinkInterval > 0 ) // if blink is ON, turn it OFF
{
blinkInterval = 0; // stop blinking
blinkState = 0;
digitalWrite( blinkPin, blinkState );
}
else // if blink is OFF, turn it ON
{
blinkInterval = interval; // blink interval restored
}
}
// button release detect, state was 0, now 1
else
{
if (( buttonStateNow == 1 ) && ( buttonStatePrev == 0 )) // release detected
{
delay( debounce ); // DIRTY on both press and release, a few ms.
}
}
buttonStatePrev = buttonStateNow; // button done, make Prev = Now
}
void loop()
{
button(); // which comes first doesn't really matter
blink(); // try running blink first if yer not sure!
}