Button pattern recognition

With the arduino i aim to get it to spin a motor when a single button is pressed in a specific way.
I have seen examples of this with a secret knock detector or a password box however i couldnt find any source code.
How do i get it to recognize patterns?
The pattern i wish to follow is
5 knocks -pause- 2 knocks

Maybe the code here will give you some ideas.

If not, give us a clearer idea of what you want to do.

...R

Froodle:
With the arduino i aim to get it to spin a motor when a single button is pressed in a specific way.
I have seen examples of this with a secret knock detector or a password box however i couldnt find any source code.
How do i get it to recognize patterns?

You could write code to detect different types of keypresses, for example:

  • one short click (click < 1s)
  • double click (two clicks in <1s)
  • one long click (button down for 1s...3s, then released)
  • one super long click (button down for >3s, then released)

So you could have up to 4 functions with a single button.

The disadvantage would be a delay in recognizing the pattern:
I.e. a single "short click" will be detectet after the "double click time" is over, because a single click may become a double click within one second.

A long click will be detected, after the button is released.

A super long click will be detected after pressing the button for 3 seconds.

Would be a little more coding than just state-change detection and debouncing, but can be done.

Another method would be "counting button clicks with timeout". You could easily count how often a button is pressed and released, and after the button is not pressed within a timeout time after last releasing it, the count is ready to be processed. So you could have even 5, 6, 7 or more actions with just one button.

I have used this state nachine as frontend for a menu system with a single button. The program is coded using my state machine library

#include <SM.h>
const byte btn = 4;
const int clickMin = 50;
const int clickMax = 350;

enum Click {noClick, sClick, dClick, lClick};
Click cmd;

SM clickCmd(cIdle);//click detection state machine

void setup(){
    Serial.begin(115200);
    pinMode(btn, INPUT);
}//setup()

void loop(){
  EXEC(clickCmd);
}//loop()

State cIdle(){
  if(digitalRead(btn)) clickCmd.Set(cPress);
}//cIdle()

State cPress(){
  if(clickCmd.Timeout(clickMin)) clickCmd.Set(cPclk);
}//cPress()

State cLong(){
  if(!digitalRead(btn)) clickCmd.Set(cIdle);
}//cLong()

State cRelease(){
  if(clickCmd.Timeout(clickMin)) clickCmd.Set(cPdbl);
}//cRelease()

State cDbl(){
  if(!digitalRead(btn)) clickCmd.Set(cIdle);
}//cDbl()

State cPclk(){
  if(!digitalRead(btn)) clickCmd.Set(cRelease);
  if(clickCmd.Timeout(clickMax)){
    clickCmd.Set(cLong);
    cmd = lClick;
    Serial.println("long click");
  }//if(Timeout)
}//cPclk()

State cPdbl(){
  if(digitalRead(btn)){
    clickCmd.Set(cDbl);
    cmd = dClick;
    Serial.println("Double click");
  }//if(press)
  if(clickCmd.Timeout(clickMax)){
    clickCmd.Set(cIdle);
    cmd = sClick;
    Serial.println("Single Click");
  }//if(Timeout)
}//cPdbl()

click detection state diagram.png

Cheers, i shall have a look at that code, i am unsure how i can be more clear however.
I want the motor to spin when i do the traditional button press of
5 knocks -pause- 2 knocks

Froodle:
the traditional button press of
5 knocks -pause- 2 knocks

Wonderful scope for human error.

...R

Froodle:
Cheers, i shall have a look at that code, i am unsure how i can be more clear however.
I want the motor to spin when i do the traditional button press of
5 knocks -pause- 2 knocks

Write code for a "state change detection" for "button pressed" and put the millis()-time in an array like

unsigned long buttonDownTime[7];

you remember the "millis()" result of the last 7 button presses.

Each time a new button is pressed, the oldest value shifts out and the newest time is put into the array.

Then you just look after the time differences if they meet your pattern:
The first four time differences have to be short below some value:
buttonDownTime[1]-buttonDownTime[0] -> short
buttonDownTime[2]-buttonDownTime[1] -> short
buttonDownTime[3]-buttonDownTime[2] -> short
buttonDownTime[4]-buttonDownTime[3] -> short
The next time difference has to be longer than some value:
buttonDownTime[5]-buttonDownTime[4] -> long
And last but not least the last time difference will have to be short again:
buttonDownTime[6]-buttonDownTime[5] -> short

If so, your pattern has been detected.