Hi, I was wondering if anyone can help me with the following:
I want to have a button that, when pressed, cycles through different parts of a program and only runs that part of the program. For example, when button pressed:
1 time: an LED would blink rapidly
2 times: an LED would blink slowly
3 times: an LED would blink in a different pattern, etc.
and when pressed and held, program would reset to 1st pattern (i.e., blinking rapidly)
Also, I would like the program to wait until the button is pressed before starting anything else.
So you have a few things to consider:
Debounce of the button. One way is to poll the button, when the input pin goes from High to Low (assuming you have internal pullups enabled and connect the pin to Gnd when the button is pressed)
is to wait say 100mS before reading the pin again. This gives the user enough time to press & release and for the mechanical bits of the button to stop moving.
So every 100mS you read the pin and keep track with a counter.
Next, need some decision making.
If after the 2nd press, is the user doing press & hold? Or just heavy handed?
How long do you wait after a press to decide if he's done pressing?
You would use some 'flags' in addition with the press counter to keep track of the decision flow.
Thank you for your response! Can you direct me to more information on flags and decision flow? I am a newbie.
Also, if I am unable to get this together in a couple of days, are you available to write some code for a fee? Hope that's appropriate for a forum post and my apologies if not.
Put each of the sections of code in a separate function and call the appropriate function based on the value in a variable that is incremented by each button press.
// Blink without "delay()" - multi!
const int led1Pin = 13; // LED pin number
const int led2Pin = 10;
const int led3Pin = 11;
const int button1 = 4;
int led1State = LOW; // initialise the LED
int led2State = LOW;
int led3State = LOW;
char bstate1 = 0;
unsigned long count1 = 0; // will store last time LED was updated
unsigned long count2 = 0;
unsigned long count3 = 0;
unsigned long bcount1 = 0; // button debounce timer. Replicate as necessary.
// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
boolean timeout(unsigned long *marker, unsigned long interval) {
if (millis() - *marker >= interval) {
*marker += interval; // move on ready for next interval
return true;
}
else return false;
}
// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
switch (*butnstate) { // Odd states if was pressed, >= 2 if debounce in progress
case 0: // Button up so far,
if (button == HIGH) return false; // Nothing happening!
else {
*butnstate = 2; // record that is now pressed
*marker = millis(); // note when was pressed
return false; // and move on
}
case 1: // Button down so far,
if (button == LOW) return false; // Nothing happening!
else {
*butnstate = 3; // record that is now released
*marker = millis(); // note when was released
return false; // and move on
}
case 2: // Button was up, now down.
if (button == HIGH) {
*butnstate = 0; // no, not debounced; revert the state
return false; // False alarm!
}
else {
if (millis() - *marker >= interval) {
*butnstate = 1; // jackpot! update the state
return true; // because we have the desired event!
}
else
return false; // not done yet; just move on
}
case 3: // Button was down, now up.
if (button == LOW) {
*butnstate = 1; // no, not debounced; revert the state
return false; // False alarm!
}
else {
if (millis() - *marker >= interval) {
*butnstate = 0; // Debounced; update the state
return false; // but it is not the event we want
}
else
return false; // not done yet; just move on
}
default: // Error; recover anyway
{
*butnstate = 0;
return false; // Definitely false!
}
}
}
void setup() {
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
pinMode(led3Pin, OUTPUT);
pinMode(button1, INPUT);
digitalWrite(button1,HIGH); // internal pullup all versions
}
void loop() {
// Toggle LED if button debounced
if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
if (led1State == LOW) {
led1State = HIGH;
}
else {
led1State = LOW;
}
digitalWrite(led1Pin, led1State);
}
// Act if the latter time (ms) has now passed on this particular counter,
if (timeout(&count2, 300UL )) {
if (led2State == LOW) {
led2State = HIGH;
}
else {
led2State = LOW;
}
digitalWrite(led2Pin, led2State);
}
if (timeout(&count3, 77UL )) {
if (led3State == LOW) {
led3State = HIGH;
}
else {
led3State = LOW;
}
digitalWrite(led3Pin, led3State);
}
}
I am not suggesting this is an immediate solution to your problem - it is anything but, but I do suggest you set it up, try it out, and then examine it for the pieces you need for your own project. It inherently contains flags, decision flow and state machines.
There is a "Gigs and Collaborations" section here for paid work, but if you genuinely cannot figure it out yourself in that couple of days, I am prepared to provide some support.