Skip to content

Instantly share code, notes, and snippets.

@lazygyu
Created June 19, 2016 07:50
Show Gist options
  • Save lazygyu/cc841cdbac181953bc4829e581468b12 to your computer and use it in GitHub Desktop.
Save lazygyu/cc841cdbac181953bc4829e581468b12 to your computer and use it in GitHub Desktop.
OneButton Volume Controller
#import <Arduino.h>
const long LONGPRESS_TIME = 1000;
const long CLICK_TIME = 200;
typedef void(*pFunc)(void);
class Button{
enum ButtonState {
NORMAL,
FIRSTDOWN,
PRESSDOWN,
FIRSTUP,
SECONDDOWN,
SECONDUP
};
enum ButtonEvent {
NONE,
CLICK,
PRESS,
DOUBLECLICK
};
private:
unsigned long start;
int pin;
ButtonState state;
pFunc onclick;
pFunc ondblclick;
pFunc onpress;
public:
void OnClick(pFunc _fn){
onclick = _fn;
};
void OnDoubleClick(pFunc _fn){
ondblclick = _fn;
};
void OnPress(pFunc _fn){
onpress = _fn;
};
Button(int _pin){
pin = _pin;
pinMode(pin, INPUT);
digitalWrite(pin, HIGH);
state = NORMAL;
start = 0;
onclick = NULL;
ondblclick = NULL;
onpress = NULL;
};
void update(){
volatile int sig = digitalRead(pin);
unsigned long n = millis();
if( state == NORMAL ){
if( sig == LOW ){
state = FIRSTDOWN;
start = n;
}
}else if(state == FIRSTDOWN){
if( sig == HIGH ){
state = FIRSTUP;
start = n;
}else if( sig == LOW && n > start + LONGPRESS_TIME ){
if( onpress != NULL ) onpress();
state = PRESSDOWN;
}
}else if(state == FIRSTUP){
if( n > start + CLICK_TIME ){
if( onclick != NULL ) onclick();
state = NORMAL;
}else if(sig == LOW){
state = SECONDDOWN;
}
}else if(state == SECONDDOWN){
if( sig == HIGH ){
if( ondblclick != NULL ) ondblclick();
state = NORMAL;
}
}else if(state == PRESSDOWN ){
if( sig == HIGH ){
state = NORMAL;
}
}
};
};
#include "Button.h"
#define P_BTN 7
#define ENC_A 2
#define ENC_B 3
Button btn(P_BTN);
volatile int lastEncoded = 0;
volatile unsigned long lastValue = 0;
volatile unsigned long encoderValue = 0;
unsigned int enc_delta = 1;
char buf;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);
pinMode(ENC_A, INPUT);
pinMode(ENC_B, INPUT);
digitalWrite(ENC_A, HIGH);
digitalWrite(ENC_B, HIGH);
delay(100);
btn.OnDoubleClick(dblclick_handler);
btn.OnPress(press_handler);
btn.OnClick(click_handler);
}
void click_handler(){
buf = 5;
Serial.print(buf);
}
void dblclick_handler(){
buf = 6;
Serial.print(buf);
}
void press_handler(){
buf = 4;
Serial.print(buf);
}
void updateEncoder(){
int MSB = digitalRead(ENC_A); //MSB = most significant bit
int LSB = digitalRead(ENC_B); //LSB = least significant bit
int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue +=enc_delta;
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue -=enc_delta;
lastEncoded = encoded; //store this value for next time
}
void loop() {
// put your main code here, to run repeatedly:
if(lastValue != encoderValue){
if( lastValue > encoderValue ){
buf = 2;
Serial.print(buf);
}else{
buf = 1;
Serial.print(buf);
}
lastValue = encoderValue;
}
btn.update();
delay(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment