このコードを改善することはできますか?遅延を別のものに置き換えることはできますか?

私の以前に解決した質問に基づいて超音波センサー距離計ヘルプ(解決済み)

遅れを使用し、残りのコードをすべて停止するよりも、LEDを点滅させるより良い方法はありますか?例えば、LEDはターンオンに設定され、ターンオフ直後に設定されます。これを行うより良い方法はありますか?

たとえば、LEDがオンになっている場合は、コードを遅延させます。つまり、遅延が終了するまで待機し、電源を切ってパターンを変更する必要があります。例えば、Arduinoが点滅の途中で新しいインターバルの点滅で中断することを許可しますか?これが混乱しているのであれば申し訳ありませんが、説明するのは難しいです。

簡単に言えば、 delay()を待っている間にArduinoが突然LEDの状態を変更できるようにする delay()

私が取り組んでいるコードはこれです:

#include 
#define TRIGGER_PIN  15
#define ECHO_PIN     2
#define MAX_DISTANCE 500
int LED1 = 3;
int LED2 = 16;
int LED3 = 9;
int LED4 = 6;

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

void setup() {
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
}

void loop() {
  delay(50);
  unsigned int uS = sonar.ping_median(10);
  int IN = sonar.convert_in(uS);
  if (IN <= 5) {
    analogWrite(LED4, 255);
    delay(100);
    analogWrite(LED4, 0);
  } else if (IN >= 5 && IN <= 12) {
    analogWrite(LED4, 1);
    delay(200);
    analogWrite(LED4, 0);
  } else if (IN >= 13) {
    analogWrite(LED4, 100);
    delay(300);
    analogWrite(LED4, 0);
  }
}
3
ru de
これについては、標準的なArdionoのチュートリアルがあります:遅延なしの点滅
追加された 著者 Sprogz,
タイマ/カウンタ割り込みを調べてください。
追加された 著者 RubberDuck,

3 答え

タイマーを取得するには millis()を使用できます:
millis() Arduinoからのミリ秒数を返します現在のプログラムを実行し始めました。

void loop(){
    if(millis() % 100 == 0){//%(modullo) is the rest of a division. 19%10=9 because10/10 = 1 and the rest is 9
        //you have wait 100 millisecond. When millis()%100 == 0 millis() is a multiple of 100.
    }
}

あなたのコードのためにこれを行うことができます:

int LED1 = 3;
int LED1 = 3;
int LED2 = 16;
int LED3 = 9;
int LED4 = 6;

//Ligth on -> 1 light off -> 0
int LED1Stat = 0;
int LED2Stat = 0;
int LED3Stat = 0;
int LED4Stat = 0;

void setup() {
 //put your setup code here, to run once:
  pinMode(LED1, OUTPUT);    //every 100 ms
  pinMode(LED2, OUTPUT);    //every 250 ms
  pinMode(LED3, OUTPUT);    //every 500 ms
  pinMode(LED4, OUTPUT);    //every 1000 ms

}

void loop() {
    //for no Delay
    if(millis()%100 = 0){
        LED1Stat = !LED1Stat;
        digitalWrite(LED1, LED1Stat);
    }
    if(millis()%250 = 0){
        LED2Stat = !LLED2Stat;
        digitalWrite(LED2, LED2Stat);
    }
    if(millis()%500 = 0){
        LED3Stat = !LED3Stat;
        digitalWrite(LED3, LED3Stat);
    }
    if(millis()%1000 = 0){
        LED4Stat = !LED4Stat;
        digitalWrite(LED4, LED4Stat);
    }
}

[編集]

long prevMillis = 0;
void loop(){
    if(millis()-prevMillis >= 100){
        LED1Stat = !LED1Stat;
        digitalWrite(LED1, LED1Stat);
        prevMillis = millis();
    }
    //...

}
2
追加された
これは、1)ループ呼び出しの間に1ミリ秒を保証できない場合、または2)何らかの理由でループ関数をミリ秒に1回呼び出すことができない場合、または3)ミリ秒がマイルストーンの1つをスキップした場合ミリ秒ごとに42ミリ秒ごとにジャンプする)。通常の方法で時間を追跡するほうがはるかに優れています( if((millis() - prevMillis)> = PERIOD){prevMillis + = PERIOD; do_stuff()}
追加された 著者 Tom Collins,

私は遅延機能が十分なクロックサイクルが完了するまで待つと思う。この関数はサイクル数をカウントし、十分に待つ必要があります。

タイマ/カウンタは、マイクロコントローラの一部であり、例えば、2つのイベント間の時間を測定するため、または定義された時間後に割り込みを生成するために使用される。利点は、あなたが待ってはいけない後にタイマーとコードを開始することができるということです。時間が終わったら、割込みを生成し、割込みハンドラで小さなコードを実行するだけです。

0
追加された
ハードウェアタイマーを設定するよりも、 millis()(実質的にソフトウェアタイマー)を使用する方が簡単です。
追加された 著者 Sprogz,

一般に、2つの別々のタスク(LEDを制御して何か他のものを実行するなど)を '同時に'したい場合は、遅延を使用しないでください。

代わりに何かが起こった(あなたのケースでLEDの色を切り替えるような)ので、時間を保つためにint型変数を使用してください。どのくらいの時間が経過し、それに作用するかをループ内でチェックするよりも。

例えば。

When you call analog writes with non zero values, set the variable to the current time. Than instead of the delay check if the current time minus the variable < 100 or 200 or 300 depending on the value you need and than set the analog write back to 0 (switching off the LED). In the rest of the loop you can do other tasks.

0
追加された