Hi, I need help writing a program where a single LED will mimic the pattern of button presses after a time delay. An example would be I press the button wait half a second, press it again, press it immediately again after letting go and then press it again after another half-second. After a certain amount of time has passed (let's say 3 seconds) with no button presses, The LED lights up the same way I had pressed the button. (lights up, waits for half a second and lights up again etc)
You need to create a ‘list’ of presses with tine stamps. (use millis() values), then you can play back that list at a later time, using the delta between each timestakp as the interval for ‘playback’.
I would start with a sketch to debounce button presses and detect state changes:
const byte ButtonPin = 2;
const unsigned long DebounceTime = 10;
boolean ButtonWasPressed = false;
unsigned long ButtonStateChangeTime = 0; // Debounce timer
void setup()
{
pinMode (ButtonPin, INPUT_PULLUP); // Button between Pin and Ground
}
void loop()
{
unsigned long currentTime = millis();
boolean buttonIsPressed = digitalRead(ButtonPin) == LOW; // Active LOW
// Check for button state change and do debounce
if (buttonIsPressed != ButtonWasPressed &&
currentTime - ButtonStateChangeTime > DebounceTime)
{
// Button state has changed
ButtonWasPressed = buttonIsPressed;
ButtonStateChangeTime = currentTime;
if (ButtonWasPressed)
{
// Button was just pressed
}
else
{
// Button was just released
}
}
}
Then add a list to hold the pattern of delays. Every time the button changes state, add the time since the last change to the list. If it has been three seconds since the last change, play back the list: Turn the LED on and, for each entry in the list, delay that long and toggle the LED.
Hi, welcome to this forum.
I have made such a sketch, but if this is for school then you will not learn from it when I just give a link.
Hint: Taking the value of millis() can be called taking a "timestamp". So you have to store all the timestamps in an array to remember them. Recording the events and playing them back can be done at the same time.
Instead of timestamps as others suggested, you could use an array as a fixed resolution circular buffer to be played back in a loop.
First decide on a "sampling rate"/resolution for the bufer i.e. if you record the button state 10 times for a second, your buffer/array needs to hold 30 boolean values (button ON/OFF).
Then make a loop - record state X, play back to LED state X-30, increase X by one, repeat.
I think you assumption that the pattern will be three seconds long is mistaken. The OP specified that the pattern is played back when there has been no button push for three seconds. I don't think there is a limit to the length of the pattern (aside from memory limitations).
Oops, you're right.
I got bored so I wrote the sketch. I have not tested it but it does compile without errors or warnings. It only uses 49% of RAM on an UNO so if you need more than 500 presses and releases...
You can screw it up if your hold the button down for more than 65 seconds.
const unsigned PatternCountLimit = 500;
unsigned PatternDelays[PatternCountLimit];
unsigned PatternCount = 0;
const byte ButtonPin = 2;
const unsigned DebounceTime = 10;
boolean ButtonWasPressed = false;
unsigned long ButtonStateChangeTime = 0; // Debounce timer
void setup()
{
pinMode(ButtonPin, INPUT_PULLUP); // Button between Pin and Ground
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
unsigned long currentTime = millis();
unsigned timeSinceLastChange = currentTime - ButtonStateChangeTime;
boolean buttonIsPressed = digitalRead(ButtonPin) == LOW; // Active LOW
// Check for button state change and do debounce
if (buttonIsPressed != ButtonWasPressed &&
timeSinceLastChange > DebounceTime)
{
// Button state has changed
ButtonWasPressed = buttonIsPressed;
ButtonStateChangeTime = currentTime;
if (buttonIsPressed)
{
// Button was just pressed
if (PatternCount > 0 && PatternCount < PatternCountLimit)
{
PatternDelays[PatternCount++] = timeSinceLastChange;
}
}
else
{
// Button was just released
if (PatternCount < PatternCountLimit)
{
PatternDelays[PatternCount++] = timeSinceLastChange;
}
}
} // End button state change detection
// Has the button been released for 3 seconds?
if (PatternCount > 0 && !buttonIsPressed && timeSinceLastChange > 3000)
{
// Time to play back
digitalWrite(LED_BUILTIN, HIGH);
for (unsigned i = 0; i < PatternCount; i++)
{
delay(PatternDelays[i]);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // Toggle
}
digitalWrite(LED_BUILTIN, LOW);
PatternCount = 0; // reset for new pattern
}
}
Sketch by @johnwasser in Wokwi simulation:
It needs a waiting time of three seconds before playing back.
We have now seven replies, and @korst has not responded yet.
It has this:
Sorry for the late reply. I honestly forgot that I had made this post. Thank you @johnwasser for providing a sketch for me to test.
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.