Hello everybody! As the subject says, I need to program a single pushbutton to start and stop a function when pressing it. I (with some help) wrote a code for 2 LEDs blinking at the same time independently and I have the possibility to modify the rate and the duty cycle so I want a button to stop them blinking while I set those two and to make them start blinking again after setting them. I want to mention that I am a newbie and that maybe my code is a bit messy but it works flawlessly.
// eeprom settings
#include <EEPROM.h>
#define SETTING_VER "SBR2.0"
typedef struct {
float p;
float i;
float s;
char ver[sizeof(SETTING_VER)];
} SettingType;
SettingType settings = {
500,
50,
120,
SETTING_VER
};
bool loadConfiguration()
{
char savedVersion[sizeof(SETTING_VER)];
int eepromVersionOffset = sizeof(settings) - sizeof(SETTING_VER);
EEPROM.get(eepromVersionOffset,savedVersion);
if (strcmp(savedVersion, SETTING_VER) ==0)
{
EEPROM.get(0, settings);
}
}
bool saveConfiguration()
{
EEPROM.put(0, settings);
}//eeprom settings
//LCD
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x20, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
unsigned long currentMillis;
unsigned long previousMillis;
unsigned long previousMillis2;
int cycleTime = 500; // off + on end to end
int ppmCalc;
int onTime; //calculated from cycleTime and dutyCyclePercent
int offTime; //calculated from cycleTime and onTime
int interval; //the current interval for led1, either onTime or offTime
int interval2; //the current interval for led2, either onTime or offTime
byte cycleTimeDelta = 10; // blink rate increase/decrease by 10 every push
byte incrCycleButton = 6; //duty cycle increase button
byte decrCycleButton = 4; //duty cycle decrease button
byte dutyCyclePercent = 50; // default duty cycle percent
byte dutyCyclePercentDelta = 5; //duty cycle increase/decrease by 5% every button push
byte incrButton = 2; //blink rate increase button
byte decrButton = 3; //blink rate decrease button
byte ledPin = 7; //led1
bool ledState = 1; //led1 starts as 1
byte ledPin2 = 5; //led2
bool ledState2 = 0; // led2 starts as 0
bool incrCycleButtonState;
bool decrCycleButtonState;
bool incrCycleButtonStatePrev;
bool decrCycleButtonStatePrev;
bool incrButtonState;
bool decrButtonState;
bool incrButtonStatePrev;
bool decrButtonStatePrev;
bool dutyCycleWasChanged = false;
bool cycleTimeWasChanged = false;
void setup()
{
Serial.begin(9600);
lcd.begin(16,2);
lcd.clear();
// EEPROM LOADING SETTINGS
Serial.print("Before load: ");
Serial.print("DEFAULT PPM = ");
Serial.print(settings.s);
Serial.print("\tCycle Time: ");
Serial.print(settings.p);
Serial.print("\tDuty Cycle: ");
Serial.print(settings.i);
Serial.println(" %");
loadConfiguration();
Serial.print("After Load. ");
//Serial.print(settings.ver);
Serial.print("SAVED PPM = ");
Serial.print(settings.s);
Serial.print("\tCycleTime: ");
Serial.print(settings.p);
Serial.print("\tDuty Cycle: ");
Serial.print(settings.i);
Serial.println(" %");
cycleTime = settings.p;
dutyCyclePercent = settings.i;
ppmCalc = settings.s;
//EEPROM LOADING SETTINGS
//turn off L13
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
pinMode(incrButton, INPUT_PULLUP);
pinMode(decrButton, INPUT_PULLUP);
pinMode(incrCycleButton, INPUT_PULLUP); ////
pinMode(decrCycleButton, INPUT_PULLUP); ////
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
incrButtonState = digitalRead(incrButton);
incrButtonStatePrev = incrButtonState;
decrButtonState = digitalRead(decrButton);
decrButtonStatePrev = decrButtonState;
incrCycleButtonState = digitalRead(incrCycleButton); ////
incrCycleButtonStatePrev = incrCycleButtonState; ////
decrCycleButtonState = digitalRead(decrCycleButton); ////
decrCycleButtonStatePrev = decrCycleButtonState; ////
onTime = (unsigned long) dutyCyclePercent * cycleTime / 100;
offTime = cycleTime - onTime;
Serial.print("Initial cycleTime=");
Serial.print(cycleTime);
Serial.print(", of which onTime=");
Serial.print(onTime);
Serial.print(", offTime=");
Serial.println(offTime);
} //setup
void loop()
{ // LOADING SAVED SETTINGS FROM EEPROM
settings.p = cycleTime;
settings.i = dutyCyclePercent;
settings.s = ppmCalc;
lcd.setCursor(0,0);
lcd.print(ppmCalc);
lcd.print(" PPM ");
lcd.setCursor(9,0);
lcd.print(dutyCyclePercent);
lcd.print(" %");
currentMillis = millis();
checkForIncr(); // CHECK FOR BLINK RATE INCREASE BUTTON
checkForDecr(); // CHECH FOR BLINK RATE DECREASE BUTTON
checkCycleIncr(); // CHECK FOR DUTY CYCLE INCREASE BUTTON
checkCycleDecr(); // CHECK FOR DUTY CYCLE DECRESE BUTTON
ppm();
if (dutyCycleWasChanged || cycleTimeWasChanged) changeIntervals();
{ blinkTheLed(); //BLINK THE LEDS
blinkTheLed2(); //
}
if (cycleTimeWasChanged || dutyCycleWasChanged ); // DETECTS IF DUTY CYCLE AND BLINK RATE WERE CHANGED
{
saveConfiguration(); // AND STORES THEM TO EEPROM
}
} //loop
void checkForIncr() // BLINK RATE INCREASE BUTTON FUNCTION
{
// see https://www.arduino.cc/en/Tutorial/StateChangeDetection
// read the increment pin:
incrButtonState = digitalRead(incrButton);
// compare the buttonState to its previous state
if (incrButtonState != incrButtonStatePrev) //changed, don't yet know which way
{
if (incrButtonState == LOW) //changed and pressed, means a new press
{
if (dutyCyclePercent < 100)
{
Serial.print("Incrementing % ");
Serial.print(dutyCyclePercent);
dutyCyclePercent = dutyCyclePercent + dutyCyclePercentDelta;
dutyCycleWasChanged = true;
ledState = 1;
ledState2 = 0;
Serial.print(" to ");
Serial.print(dutyCyclePercent);
}
else
{
Serial.println(" already 100%");
}
}
delay(50);
}
// save the current state as the last state, for next time through the loop
incrButtonStatePrev = incrButtonState;
} //incr
void checkForDecr() //BLINK RATE DECREASE BUTTON FUNCTION
{
// read the decrement pin:
decrButtonState = digitalRead(decrButton);
// compare the buttonState to its previous state
if (decrButtonState != decrButtonStatePrev) //changed, don't yet know which way
{
if (decrButtonState == LOW) //changed and pressed, means a new press
{
if (dutyCyclePercent > 0)
{
Serial.print("Decrementing % ");
Serial.print(dutyCyclePercent);
dutyCyclePercent = dutyCyclePercent - dutyCyclePercentDelta;
dutyCycleWasChanged = true;
Serial.print(" to ");
Serial.print(dutyCyclePercent);
ledState = 1;
ledState2 = 0;
}
else
{
Serial.println(" already 0%");
}
}
delay(50);
}
// save the current state as the last state, for next time through the loop
decrButtonStatePrev = decrButtonState;
} //decr
void changeIntervals()
{
dutyCycleWasChanged = false;
cycleTimeWasChanged = false;
onTime = (unsigned long) dutyCyclePercent * cycleTime / 100;
offTime = cycleTime - onTime;
Serial.print(" Cycle Time = ");
Serial.print(cycleTime);
Serial.print(", new onTime=");
Serial.print(onTime);
Serial.print(", offTime=");
Serial.println(offTime);
} //changeIntervals
void blinkTheLed() // LED 1 BLINKING FUNCTION
{
if (currentMillis - previousMillis > interval)
{
// save the last time you blinked the LED
previousMillis = currentMillis;
// if led1 is off turn it on and vice-versa:
if (ledState == LOW)
{
ledState = HIGH;
interval = onTime;
lcd.setCursor(0,1);
lcd.print(">>>>");
lcd.setCursor(6,1);
lcd.print(char(255));
}
else
{
ledState = LOW;
interval = offTime;
lcd.setCursor(0,1);
lcd.print(">>>>");
lcd.setCursor(6,1);
lcd.print(" ");
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
} //blinkTheLed()
void blinkTheLed2() //LED 2 BLINKING FUNCTION
{
if (currentMillis - previousMillis2 > interval2)
{
// save the last time you blinked the LED
previousMillis2 = currentMillis;
// if led2 is off turn it on and vice-versa:
if (ledState2 == LOW)
{
ledState2 = HIGH;
interval2 = onTime;
lcd.setCursor(12,1);
lcd.print("<<<<");
lcd.setCursor(9,1);
lcd.print(char(255));
}
else
{
ledState2 = LOW;
interval2 = offTime;
lcd.setCursor(12,1);
lcd.print("<<<<");
lcd.setCursor(9,1);
lcd.print(" ");
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin2, ledState2);
}
} //blinkTheLed2()
void checkCycleIncr() // DUTY CYCLE INCREASE FUNCTION
{
incrCycleButtonState = digitalRead(incrCycleButton);
if (incrCycleButtonState != incrCycleButtonStatePrev)
{
if (incrCycleButtonState == LOW)
{
if (ppmCalc < 220)
{
cycleTimeWasChanged = true;
ppmCalc += cycleTimeDelta;
cycleTime = 60000 / ppmCalc;
ledState = 1;
ledState2 = 0;
Serial.print("PPM = ");
Serial.print(ppmCalc);
}
else
{
Serial.println("already MAX PPM ");
}
}
delay(50);
}
incrCycleButtonStatePrev = incrCycleButtonState;
}
void checkCycleDecr() // DUTY CYCLE DECREASE FUNCTION
{
decrCycleButtonState = digitalRead(decrCycleButton);
if (decrCycleButtonState != decrCycleButtonStatePrev)
{
if (decrCycleButtonState == LOW)
{
if (ppmCalc > 40)
{
ppmCalc -= cycleTimeDelta;
cycleTime = 60000 / ppmCalc;
cycleTimeWasChanged = true;
ledState = 1;
ledState2 = 0;
Serial.print("PPM = ");
Serial.print(ppmCalc);
}
else
{
Serial.println("already MIN PPM");
}
delay(50);
}
decrCycleButtonStatePrev = decrCycleButtonState;
}
}
void ppm() // CONVERTING BLINKING RATE TO BLINKS PER MINUTE (PULSES PER MINUTE)
{
ppmCalc = 60000 / cycleTime;
}
if (dutyCycleWasChanged || cycleTimeWasChanged) changeIntervals();
You know changeIntervals(); will run according to the result of ‘if()’
However:
{
blinkTheLed(); //BLINK THE LEDS
blinkTheLed2(); //
}
will run all the times.
Maybe you meant to have this:
{
changeIntervals();
blinkTheLed(); //BLINK THE LEDS
blinkTheLed2(); //
}
const byte ButtonPin = 6;// the Arduino pin number
byte startStopFlag;
void setup() {
pinMode(ButtonPin, INPUT_PULLUP);
}
void loop() {
if (button()) startStopFlag ^= 1;// toggle
}
bool button() {// a function to debounce the pushbutton
static int lastButtonState;
static unsigned long buttonDebounceTimestamp;
int buttonState = digitalRead(ButtonPin);// the pin that is your button
if (buttonState != lastButtonState && buttonState == LOW) {// transition is HIGH to LOW
if (millis() - buttonDebounceTimestamp >= 25UL) {// 25UL = 25ms = time for debounce
lastButtonState = buttonState;
buttonDebounceTimestamp = millis();
return true;
}
else {
return false;
}
}
else {
lastButtonState = buttonState;
return false;
}
}