I have a small circuit that uses a Nano and I need to program a light up sequence. What I want to happen is when a button is in the on position, it lights up an led but I want it to flash on and off before it stays illuminated (its meant to mimic an engine turning on).
I have written some code so the sequencing is already sorted but the issue I have is that it just starts doing the loop over and over without pushing the button. It stays illuminated like I want after holding the button but I just cant get it stay off when the button isnt pressed.
Here is the code I have:
void setup()
{
pinMode(2, INPUT); // button
pinMode(13, OUTPUT); // LED
digitalWrite(13, LOW);
}
int pinState = LOW;
void loop()
{
int newState = digitalRead(2);
if (newState != pinState) // button state differs from last recorded state?
{
pinState = newState;
if (pinState == HIGH) // button newly pressed?
delay(1000);
digitalWrite(13, pinState);
delay(50);
digitalWrite(13, LOW);
delay(50);
digitalWrite(13, HIGH);
delay(50);
digitalWrite(13, LOW);
delay(100);
digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(300);
digitalWrite(13, pinState);
delay(500);
}
}
I am not experienced with coding so please be gentle. I realise this is probably pretty ugly code but....yeah.
After trying a few unreliable ways to poll a bushbutton, this is what I learned to use... It also calls a function to read the button, so I only need to insert the function call into the main sketch.
byte buttonPin = 2;
bool currentButtonState, lastButtonRead; // "is pressed" and "was pressed"
unsigned long timer; // debounce start time
unsigned long timeout = 50; // debounce length
unsigned long buttonCounter;
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP); // pin to button (N.O.) to GND
}
void loop() {
readButton();
}
void readButton() {
bool currentButtonRead = digitalRead(buttonPin); // read button pin
if (currentButtonRead != lastButtonRead) { // if button pin changes...
timer = millis(); // ...start a timer
lastButtonRead = currentButtonRead; // ... and store current state
}
if ((millis() - timer) > timeout) { // if button change was longer than debounce timeout
if (currentButtonState == HIGH && lastButtonRead == LOW) { // ... and State is "NOT pressed" while Button "IS PRESSED"
//==================================================
digitalWrite(LED_BUILTIN, HIGH); // The button was pressed...
showButton(buttonPin, ++buttonCounter);; // Put actions or function calls here
digitalWrite(LED_BUILTIN, LOW);
//==================================================
}
currentButtonState = currentButtonRead; // update button state
}
}
void showButton(int pin, int count) {
Serial.print("pin ");
Serial.print(pin);
Serial.print(" count ");
Serial.println(count);
}
THX for the two way to do it demo. Please see the edits to one your functions below.
I don't understand a need to "turn off" the timer. Not doing would eliminate the need to test that it is "on". And no need to use the ternary operator to ensure proper function of the timing mechanism. As far as I can think it through, you have that just so you can use zero as a flag value meaning the timer is "off".
The result is more than needs to be thought about. The function with changes appears to perform identically. I may be testing inadequately or maybe not waiting 49.7 days (or whatever it is) to see that the millis() rollover is handled correctly. Or something.
Aside from style differences, the algorithm is the one I use alla time for buttons. If there is some good reason to do what you did I need to know it. If not, why not switch to less code and fewer things anyone needs to figure out when reading it?
Besides the general advice to not overload the function of a variable. You wanna turn on and off something, use a variable that is the state of the timer.
void readButTmr ()
{
// if (timer && (msec - timer) < Timeout)
if (msec - timer < Timeout)
return; // nothing to do until timer expires
// timer = 0; // disable timer
bool but = digitalRead(buttonPin);
if (lastButtonRead != but) {
lastButtonRead = but;
if (LOW == but)
showButton(buttonPin, ++buttonCounter);
timer = msec; // ? msec : 1; // not zero
}
}
Did some tinkering, even had some help from AI and this is what I came up with. DOes exactly what I wanted, even managed to add a dimm when I release the button.
const int buttonPin = 2; // Pin connected to the button
const int ledPin = 9; // Pin connected to the flashing LED (PWM-capable pin)
const int alwaysOnLedPin = 8; // Pin connected to the always-on LED
bool buttonState = false; // Current state of the button
bool lastButtonState = false; // Last state of the button
bool ledFlashingDone = false; // Flag to track if flashing is completed
bool dimming = false; // Flag to track if dimming is in progress
unsigned long releaseTime = 0; // To store the time when the button was released
unsigned long dimmingStartTime = 0; // To store the time when dimming should start
unsigned long flashStartTime = 0; // To store the time when the flashing starts
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // Set button pin as input with internal pull-up resistor
pinMode(ledPin, OUTPUT); // Set flashing LED pin as output
pinMode(alwaysOnLedPin, OUTPUT); // Set always-on LED pin as output
digitalWrite(alwaysOnLedPin, HIGH); // Turn on the always-on LED
digitalWrite(ledPin, LOW); // Ensure flashing LED is off at the start
}
void loop() {
buttonState = digitalRead(buttonPin); // Read the current state of the button
if (buttonState == LOW) { // Button is pressed
if (!ledFlashingDone) {
flashStartTime = millis();
ledFlashingDone = true;
dimming = false; // Reset dimming flag
}
unsigned long elapsedTime = millis() - flashStartTime;
// Execute the flashing sequence based on timing
if (elapsedTime < 1000) {
// Wait for 1 second before flashing starts
digitalWrite(ledPin, LOW);
} else if (elapsedTime < 1050) {
digitalWrite(ledPin, HIGH); // LED on for 50 ms
} else if (elapsedTime < 1100) {
digitalWrite(ledPin, LOW); // LED off for 50 ms
} else if (elapsedTime < 1150) {
digitalWrite(ledPin, HIGH); // LED on for 50 ms
} else if (elapsedTime < 1250) {
digitalWrite(ledPin, LOW); // LED off for 100 ms
} else if (elapsedTime < 1350) {
digitalWrite(ledPin, HIGH); // LED on for 100 ms
} else if (elapsedTime < 1650) {
digitalWrite(ledPin, LOW); // LED off for 300 ms
} else if (elapsedTime < 2150) {
digitalWrite(ledPin, HIGH); // LED on for 500 ms
}
} else if (ledFlashingDone && !dimming) {
// Button was just released and flashing is done
if (millis() - releaseTime > 2000) { // Check if 2 seconds have passed
// Wait 2 seconds before starting dimming
dimmingStartTime = millis(); // Record when dimming should start
dimming = true;
} else {
releaseTime = millis(); // Update release time to track when button was released
}
}
if (dimming) {
// Gradually dim the LED over 1 second after the delay
unsigned long elapsedTime = millis() - dimmingStartTime;
if (elapsedTime < 1000) {
int brightness = map(elapsedTime, 0, 1000, 255, 0);
analogWrite(ledPin, brightness);
} else {
// After dimming, keep LED off and reset flags
analogWrite(ledPin, 0);
ledFlashingDone = false;
dimming = false;
}
}
lastButtonState = buttonState; // Update last button state
}