Skip to content

Instantly share code, notes, and snippets.

@KatsuhiroMorishita
Last active October 18, 2017 13:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KatsuhiroMorishita/991aecef885c81bd1fb39f36cca4ebd5 to your computer and use it in GitHub Desktop.
Save KatsuhiroMorishita/991aecef885c81bd1fb39f36cca4ebd5 to your computer and use it in GitHub Desktop.
チャタリング対策のクラスを実装したLEDを光らせるサンプルコードです。複数のボタンを待ち時間なしでスキャンできます。delay()を使っていないので、複数のボタンを同時に押されても判定可能です。
// 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