Instantly share code, notes, and snippets.
Last active
November 24, 2018 08:36
-
Save micw/8211f64559aae52ef0e888e350e52c26 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* D0 - output ok | |
* D5 - output ok | |
* D6 - output ok | |
* D7 - output ok | |
* | |
* D3 - output ok | |
* D4 - output ok, internal LED is inverse | |
* | |
* D3 - pullup input ok, bootet nicht wenn LOW | |
* D4 - pullup input ok, bootet nicht wenn LOW | |
* | |
* D3 - pullup input ok, bootet nicht wenn LOW | |
* D4 - pullup input ok, bootet nicht wenn LOW | |
* | |
* D1 - pullup input ok | |
* D2 - pullup input ok | |
*/ | |
int i=0; | |
typedef void (*BusActionFunction) (); | |
struct BusAction { | |
char input_type; | |
byte input_id; | |
byte state; | |
BusActionFunction callback; | |
}; | |
class Bus { | |
public: | |
Bus(unsigned int max_actions) : | |
max_actions(max_actions), | |
actions(new BusAction[max_actions]) { | |
} | |
void send(char input_type, byte input_id, byte state) { | |
// this->debug(input_type, input_id, state); | |
for (int i=0;i<this->action_num;i++) { | |
BusAction& action=this->actions[i]; | |
if (action.input_type!=input_type) continue; | |
if (action.input_id!=input_id) continue; | |
if (action.state!=state) continue; | |
action.callback(); | |
} | |
} | |
void debug(char input_type, byte input_id, byte state) { | |
if (input_type=='b') { // a button | |
Serial.print("BUTTON "); | |
Serial.print(input_id); | |
Serial.print(": "); | |
if (state==1) { | |
Serial.println("klicked"); | |
} else if (state==0) { | |
Serial.println("released"); | |
} else if (state==255) { | |
Serial.println("pressed"); | |
} | |
} else { | |
Serial.print("INPUT "); | |
Serial.print(input_type); | |
Serial.print(input_id); | |
Serial.print(": "); | |
Serial.println(state); | |
} | |
} | |
void on(char input_type, byte input_id, byte state, BusActionFunction bus_action_function) { | |
if (this->action_num>this->max_actions) { | |
Serial.println("Too much actions in bus!!"); | |
return; | |
} | |
this->actions[this->action_num++]={input_type,input_id,state,bus_action_function}; | |
} | |
private: | |
unsigned int max_actions; | |
unsigned int action_num; | |
BusAction* actions; | |
}; | |
class Button { | |
public: | |
static const char TYPE='b'; | |
static const int ACTION_KLICK=1; | |
static const int ACTION_HOLD=255; | |
static const int ACTION_RELEASE=0; | |
Button(unsigned int pin, Bus* bus, byte button_id) : | |
pin(pin), | |
bus(bus), | |
button_id(button_id) { | |
pinMode(pin,INPUT_PULLUP); | |
this->state=!digitalRead(pin); | |
this->state_since=millis(); | |
this->debounce_state=this->state; | |
this->holding=0; | |
} | |
void loop() { | |
boolean new_state=!digitalRead(pin); | |
if (new_state!=this->state) { | |
// debounce: a state change must be pressent for at least 50ms | |
if (new_state!=this->debounce_state) { | |
this->debounce_state=new_state; | |
this->debounce_state_since=millis(); | |
} else if (millis()-this->debounce_state_since>this->debounce_delay_ms) { | |
this->state=debounce_state; | |
this->state_since=millis(); | |
} | |
} | |
if (this->state) { // button pressed | |
if (holding==0) { | |
this->holding=1; | |
} else if ((this->holding==1) && (millis()-this->state_since>this->holding_delay_ms)) { | |
this->holding=2; | |
// state has changed | |
this->bus->send(TYPE,this->button_id,ACTION_HOLD); | |
} | |
} else if (this->holding>0) { // button released | |
if (this->holding==1) { // klick | |
this->bus->send(TYPE,this->button_id,ACTION_KLICK); | |
} else { // holding ended | |
this->bus->send(TYPE,this->button_id,ACTION_RELEASE); | |
} | |
this->holding=0; | |
} | |
} | |
private: | |
unsigned int pin; // pin of this button | |
Bus* bus; | |
byte button_id; | |
boolean state; // current state (0 or 1) | |
unsigned long state_since; // state since when - required for klick/hold logic | |
byte holding; // 0 if button is not pressed, 1 if button is pressed less than hold_time, 2 if it's pressed longer than hold time | |
const unsigned long holding_delay_ms=500; // if pressed longer than this, it's holding, otherwise klicked | |
boolean debounce_state; // for debounce | |
unsigned long debounce_state_since; // for debounce | |
const unsigned long debounce_delay_ms=50; | |
}; | |
class DimmableLed { | |
public: | |
DimmableLed(unsigned int pin): | |
pin(pin), | |
pwm_value(1023) { | |
pinMode(pin,OUTPUT); | |
update(); | |
} | |
void loop() { | |
if (dimming) { | |
if (millis()-last_dim<3) return; // dim every 3 ms -> 1 dim cycle ~ 3s | |
last_dim=millis(); | |
pwm_value+=dim_direction; | |
if (pwm_value<1) { // switch to dim_up | |
dim_direction=1; | |
pwm_value=1; | |
} else if (pwm_value>1300) { // max 1300 -> remain ~0.5s at 100% | |
dim_direction=-1; | |
pwm_value=1300; | |
} | |
update(); | |
} | |
} | |
void toggle() { | |
on_off=!on_off; | |
update(); | |
} | |
void dim_start() { | |
dimming=true; | |
if (!on_off) { // off -> dim up | |
dim_direction=1; | |
pwm_value=0; | |
on_off=true; | |
} else { // continue dim in other direction | |
dim_direction=-dim_direction; | |
if (pwm_value<1) pwm_value=1; | |
else if (pwm_value>1023) pwm_value=1023; | |
} | |
} | |
void dim_stop() { | |
dimming=false; | |
} | |
private: | |
unsigned int pin; | |
int pwm_value; | |
boolean on_off; | |
unsigned long last_dim=0; | |
short dim_direction=1; | |
boolean dimming; | |
void update() { | |
Serial.print(dim_direction); | |
Serial.print(" "); | |
Serial.println(pwm_value); | |
if (on_off && pwm_value>0) { | |
int v=pwm_value; | |
if (v<0) v=0; | |
else if (v>1023) v=1023; | |
analogWrite(pin,(int)pow(1023, v/1023.0)); | |
} else { | |
digitalWrite(pin,0); | |
} | |
} | |
}; | |
Bus bus(10); | |
Button b1=Button(D1,&bus,1); | |
DimmableLed led1(D4); | |
void setup() { | |
/* | |
pinMode(D1,INPUT_PULLUP); | |
pinMode(D2,INPUT_PULLUP); | |
*/ | |
Serial.begin(115200); | |
bus.on(Button::TYPE,1,Button::ACTION_KLICK,[]() { led1.toggle(); }); | |
bus.on(Button::TYPE,1,Button::ACTION_HOLD,[]() { led1.dim_start(); }); | |
bus.on(Button::TYPE,1,Button::ACTION_RELEASE,[]() { led1.dim_stop(); }); | |
} | |
void loop() { | |
b1.loop(); | |
led1.loop(); | |
/* | |
Serial.print(digitalRead(D1)); | |
Serial.print(" "); | |
Serial.println(digitalRead(D2)); | |
digitalWrite(D4,++i%10>5); | |
delay(100); | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment