Last active
October 18, 2017 13:35
-
-
Save KatsuhiroMorishita/991aecef885c81bd1fb39f36cca4ebd5 to your computer and use it in GitHub Desktop.
チャタリング対策のクラスを実装したLEDを光らせるサンプルコードです。複数のボタンを待ち時間なしでスキャンできます。delay()を使っていないので、複数のボタンを同時に押されても判定可能です。
This file contains hidden or 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
// purpose: チャタリング対策のテスト | |
// 2016年に作った気がするが、その前だったかも。 | |
// ボタンを押すと、ただLEDが光るサンプルコード。チャタリング対策用のクラスがみそ | |
// author: Katsuhiro Morishita | |
// created: 2017-10-18 | |
// lisence: MIT | |
const int led1 = 4; | |
const int led2 = 5; | |
const int butt1 = 6; | |
const int butt2 = 7; | |
// 初期状態でLOW==0入力であることが前提 | |
// チャタリング防止を意識している | |
// 割り込みで定期的にIOを走査するなら、もっと簡単に書ける | |
class button | |
{ | |
private: | |
long backup_time; | |
int backup_io; | |
static const long search_time_width = 50000l; // unit is [us]. | |
long integral; | |
long sum_time_width; | |
static const float average_th = 0.8; | |
boolean available_me; | |
public: | |
boolean check_on(int io_condition) | |
{ | |
long t = micros(); | |
long time_width = t - backup_time; | |
if(time_width > search_time_width) | |
{ | |
//Serial.println("fuga"); | |
// 観測の時間間隔が開きすぎている場合(いつまでもONとみなされない) | |
this->integral = 0l; | |
this->backup_time = 0l; | |
this->sum_time_width = 0l; | |
this->available_me = false; | |
} | |
else | |
{ | |
//Serial.println("hoge"); | |
// 不定期観測用に区間積分を実施する。移動平均のイメージ。 | |
this->sum_time_width += time_width; | |
//Serial.println(this->sum_time_width); | |
if(this->sum_time_width > search_time_width) | |
{ | |
//Serial.println("tako"); | |
float average = (float)((double)this->integral / (double)this->sum_time_width); | |
long over_time = this->sum_time_width - search_time_width; | |
this->integral -= (long)((double)average * (double)over_time); | |
this->sum_time_width = search_time_width; | |
// trigger | |
this->available_me = true; | |
} | |
this->integral += time_width * (long)io_condition; | |
} | |
// backup | |
this->backup_time = t; | |
// judge | |
float average = (float)((double)this->integral / (double)this->sum_time_width); | |
if(average > average_th && this->available_me == true) | |
return true; | |
else | |
return false; | |
} | |
button() | |
{ | |
this->backup_time = 0l; | |
this->integral = 0l; | |
this->backup_io = 0; | |
this->sum_time_width = 0l; | |
this->available_me = false; | |
} | |
}; | |
// 変化した時だけアクションするためのオブジェクト | |
class boolean_edge | |
{ | |
private: | |
int backup; | |
public: | |
// false->true エッジを検出したらtrueを返す | |
boolean check(boolean v) | |
{ | |
boolean ans = false; | |
if(this->backup == false && v == true) | |
ans = true; | |
this->backup = v; | |
return ans; | |
} | |
boolean_edge() | |
{ | |
this->backup = false; | |
} | |
}; | |
void setup(){ | |
pinMode(led1, OUTPUT); | |
pinMode(led2, OUTPUT); | |
} | |
void loop(){ | |
static button button1; | |
static button button2; | |
static boolean_edge edge1; | |
static boolean_edge edge2; | |
int pin; | |
pin = digitalRead(butt1); | |
if(edge1.check(button1.check_on(pin))){ | |
digitalWrite(led1, HIGH); | |
}else{ | |
digitalWrite(led1, LOW); | |
} | |
pin = digitalRead(butt2); | |
if(edge2.check(button2.check_on(pin))){ | |
digitalWrite(led2, HIGH); | |
}else{ | |
digitalWrite(led2, LOW); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment