私はプロのプログラマーですが、Arduinoの世界は初めてです。Arduinoの所有者の多くはプログラミングの基礎を知らず、この驚くべきテクノロジーを使用しても良い結果を得ることができないことに気づきました。
特に、Arduino割り込みは2つしかないため、必要がない場合は使用しないことをお勧めします。単一のセンサーまたはアクチュエーターに「美しい」コードを記述できる場合でも、実装する必要がある場合はより複雑なプロジェクトでは、それらを使用することはできません。確かに、割り込みを使用して1つのボタンを処理することは正しいと思いますが、管理するボタンが4つある場合はどうでしょうか。
このため、「タイムスライス」または「シングルステップ」の手法を使用して「ハートビート」スケッチを書き直しました。この手法を使用すると、ループ機能を実行するたびに、制御機能の「シングルステップ」のみを実行できるため、必要な数だけ挿入でき、使用しているすべてのセンサーに同じように迅速かつ応答します。そのために、実装する必要のある制御関数ごとにグローバルカウンターを使用し、ループ関数を実行するたびに、各関数の1つのステップを実行します。これは新しいスケッチです:
// Interrupt.ino - this sketch demonstrates how to implement a "virtual" interrupt using
// the technique of "single step" to avoid heavy duty cycles within the loop function.
int maxPwm = 128; // max pwm amount
int myPwm = 0; // current pwm value
int phase = 1; // current beat phase
int greenPin = 11; // output led pin
int buttonPin = 9; // input button pin
int buttonFlag = 1; // button flag for debounce
int myDir[] = {0,1,-1,1,-1}; // direction of heartbeat loop
int myDelay[] = {0,500,1000,500,3000}; // delay in microseconds of a single step
void setup()
{
pinMode(buttonPin, INPUT); // enable button pin for input
// it's not necessary to enable the analog output
}
void loop()
{
if(phase>0) heartbeat(); // if phase 1 to 4 beat, else steady
buttonRead(); // test if button has been pressed
}
// heartbeat function - each time is executed, it advances only one step
// phase 1: the led is given more and more voltage till myPwm equals to maxPwm
// phase 2: the led is given less and less voltage till myPwm equals to zero
// phase 3: the led is given more and more voltage till myPwm equals to maxPwm
// phase 4: the led is given less and less voltage till myPwm equals to zero
void heartbeat()
{
myPwm += myDir[phase];
analogWrite(greenPin, myPwm);
delayMicroseconds(myDelay[phase]);
if(myPwm==maxPwm||myPwm==0) phase = (phase%4)+1;
}
// buttonRead function - tests if the button is pressed;
// if so, forces phase 0 (no beat) and enlightens the led to the maximum pwm
// and remains in "inoperative" state till the button is released
void buttonRead()
{
if(digitalRead(buttonPin)!=buttonFlag) // if button status changes (pressed os released)
{
buttonFlag = 1 - buttonFlag; // toggle button flag value
if(buttonFlag) // if pressed, toggle between "beat" status and "steady" status
{
if(phase) myPwm = maxPwm; else myPwm = 0;
phase = phase==0;
analogWrite(greenPin, myPwm);
}
}
}
ご覧のとおり、コードは非常にコンパクトで実行が高速です。ハートビートループを4つの「フェーズ」に分割し、myDelay配列によって制御され、カウントの方向はmyDir配列によって制御されます。何も起こらない場合、pwm LEDピンの電圧はmaxPwm値に達するまで各ステップでインクリメントされ、ループはフェーズ2に入り、そこで電圧はゼロまでデクリメントされ、以下同様に元のハートビートが実装されます。
ボタンが押されると、ループはフェーズ0(ハートビートなし)に入り、LEDはmaxPwm電圧で調整されます。これ以降、ボタンが離されるまで、ループは安定したLEDを維持します(これにより、「デバウンス」アルゴリズムが実装されます)。ボタンをもう一度押すと、buttonRead機能がハートビート機能を再開し、フェーズ1に戻るため、ハートビートが復元されます。
ボタンをもう一度押すと、ハートビートが停止します。興奮や跳ね返りはまったくありません。