BlinkWithoutDelay

はじめに

delay()関数を使わずに、LEDを点滅させます。これにより、点滅のコードの裏で異なる処理を行うことができるようになります。

Blinkでは、delay()を使い、いつ処理を実行するかを調整しました。この例では、delay()は使わずに、前回処理を行った時刻と現在の時刻とを比較しながら、ある一定時刻経過した際に、次の処理を行うことで、いつ処理を実行するかを調整します。

delay()では、待っている間は何も処理ができませんが、delay()を使わないことで、待っている間にも他の処理を行うことができるようになります。

プログラム

定義等

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
  Blink without Delay

  Turns on and off a light emitting diode (LED) connected to a digital pin,
  without using the delay() function. This means that other code can run at the
  same time without being interrupted by the LED code.

  The circuit:
  - Use the onboard LED.
  - Note: Most Arduinos have an on-board LED you can control. On the UNO, MEGA
    and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN
    is set to the correct LED pin independent of which board is used.
    If you want to know what pin the on-board LED is connected to on your
    Arduino model, check the Technical Specs of your board at:
    https://www.arduino.cc/en/Main/Products

  created 2005
  by David A. Mellis
  modified 8 Feb 2010
  by Paul Stoffregen
  modified 11 Nov 2013
  by Scott Fitzgerald
  modified 9 Jan 2017
  by Arturo Guadalupi

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
*/

// constants won't change. Used here to set a pin number:
const int ledPin =  LED_BUILTIN;// the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
const long interval = 1000;           // interval at which to blink (milliseconds)
 

const int型のledPinという変数を定義し、LED_BUILTIN(Arduino Unoでは13)を代入します。この変数は定数なので、これ以降は値を変更することはできません。

次に、int型のledStateという変数と、long型のpreviousMillis、intervalという変数を定義し、それぞれ、LOW、0、1000を代入します。これらの3つの変数は後から変更することができます。

また、上記の4つの変数は、全てのブロックの外側で定義されているので、ファイル有効範囲を持ちます。すなわち、このファイルで定義している全ての関数から参照することができます。さらに、記憶域クラス指定子の指定がないので外部結合となり、結果としてすべてのファイルから参照することができます。また、静的記憶域期間を持つため、プログラムの実行中はいつでも参照することができます。

setup()

44
45
46
47
48
void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}
 

pinMode()を使って、ledPin(13番ピン)を出力モードにします。

loop()

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

unsigned long型の変数 currentMillisを定義し、millis()の結果を代入します。Arduinoボードが現在のプログラムを起動してから経過した時間(ミリ秒単位)を代入することになります。

この変数は、関数ブロックの内側で定義されているので、このブロック(関数)の中からしか参照することができません(ブロック有効範囲を持つといいます)。また、この関数が呼ばれるたび(処理がブロックに入るたび)に新たに値を格納する領域がとられ、関数が終了するとその領域は解放されます。つまり、関数が呼ばれるたびに領域が初期化されます(自動記憶域期間を持つといいます)。ただし、今回は、毎回millis()の値を代入しているので、目に見える違いはありません。

次のif文で、(currentMillis - previousMillis) と interval とを比較し、(currentMillis - previousMillis)のほうがinterval以上の場合、すなわち、最後にLEDを操作してから、interval(=1000ミリ秒)以上時間がたっていた場合は、以下の処理を行います。そうでなければ何もせずに次のループに移ります。

  • previousMillisにcurrentMillisを代入し、最後にLEDを操作した時刻を記録します。previousMillisは、静的記憶域期間を持つため、この関数(loop())が終了しても、値は保持し続けられます。
  • ledStateがLOWの場合はHIGHを、そうでなければLOWをledStateに代入します。これによりledStateは反転します。
  • digitalWrite()を使って、ledPinにledState(HIGHもしくはLOW)を出力します。

このプログラムでは、LEDの点滅以外の処理(下の図でのその他の処理)を行っていないので、delay()を使った場合との違いはあまりありませんが、delay()で待っている間は他の処理はできないため、同時に複数の処理を行う場合に有効な技法です。

バージョン

Hardware:Arduino Uno
Software:Arduino 1.8.16

最終更新日

September 11, 2021

inserted by FC2 system