[C言語/Arduino] void loop関数の使い方や終了方法を解説

Arduinoプログラムにおいて、void loop()関数はメインループとして機能し、プログラムが実行されている間、繰り返し呼び出されます。

この関数内に記述されたコードは、デバイスがリセットされるか電源が切れるまで実行され続けます。

通常、void loop()関数を終了する方法はありませんが、while(1)ループやfor(;;)ループを使用して無限ループを作成することができます。

また、exit()関数を使用してプログラムを終了させることも可能ですが、Arduino環境では一般的ではありません。

この記事でわかること
  • void loop関数の基本的な役割とvoid setup関数との違い
  • 繰り返し処理やセンサーからのデータ取得、LEDの点滅制御の実装方法
  • void loop関数の終了方法と無限ループからの脱出方法
  • タイマーや状態遷移を用いた応用例
  • 処理速度の向上やメモリ使用量の削減といった最適化のポイント

目次から探す

void loop関数とは

Arduinoプログラムにおいて、void loop関数は非常に重要な役割を果たします。

この関数は、Arduinoが電源を入れられてから停止されるまで、繰り返し実行される部分です。

以下では、void loop関数の役割や関連する概念について詳しく解説します。

Arduinoプログラムにおける役割

Arduinoプログラムは、主にvoid setup関数void loop関数の2つの部分で構成されています。

void loop関数は、以下のような役割を持っています。

  • 繰り返し実行: void loop関数内のコードは、Arduinoが動作している間、無限に繰り返し実行されます。

これにより、センサーのデータを継続的に読み取ったり、LEDを点滅させたりすることが可能です。

  • リアルタイム処理: センサーの値を常に監視し、条件に応じてアクションを実行するなど、リアルタイムでの処理が求められる場面で活躍します。

void setup関数との違い

void setup関数void loop関数は、Arduinoプログラムの基本構造を形成する2つの関数ですが、それぞれの役割には明確な違いがあります。

スクロールできます
関数名主な役割
void setupプログラムの初期設定を行う。1回だけ実行される。
void loopプログラムのメイン処理を行う。無限に繰り返される。
  • void setup関数: Arduinoが起動したときに一度だけ実行され、ピンモードの設定やシリアル通信の初期化など、プログラムの初期設定を行います。
  • void loop関数: void setup関数の実行が完了した後に続けて実行され、Arduinoが動作している間、無限に繰り返されます。

無限ループの概念

void loop関数は、無限ループの概念に基づいて動作します。

無限ループとは、特定の条件が満たされるまで、または明示的に停止されるまで、同じ処理を繰り返し実行することを指します。

  • Arduinoにおける無限ループ: Arduinoでは、void loop関数が無限ループとして機能し、プログラムが停止されるまで継続的に実行されます。

これにより、センサーのデータを常に監視し、必要に応じてアクションを実行することが可能です。

無限ループは、リアルタイムでのデータ処理やデバイスの制御において非常に有効ですが、適切に設計しないと、プログラムが意図しない動作をする可能性もあるため、注意が必要です。

void loop関数の基本的な使い方

void loop関数は、Arduinoプログラムの中で繰り返し実行される部分であり、さまざまな用途に利用されます。

ここでは、void loop関数を使った基本的な実装方法について解説します。

繰り返し処理の実装

void loop関数は、繰り返し処理を実装するための基本的な構造を提供します。

以下は、void loop関数を使ってカウンタを増加させる簡単な例です。

#include <Arduino.h>
int counter = 0; // カウンタ変数の初期化
void setup() {
  Serial.begin(9600); // シリアル通信の初期化
}
void loop() {
  counter++; // カウンタを1増加
  Serial.println(counter); // カウンタの値をシリアルモニタに出力
  delay(1000); // 1秒間の遅延
}

このプログラムは、1秒ごとにカウンタの値を増加させ、その結果をシリアルモニタに出力します。

void loop関数が無限に繰り返されるため、カウンタはArduinoが動作している限り増加し続けます。

センサーからのデータ取得

void loop関数を使用して、センサーからのデータを継続的に取得することができます。

以下は、アナログセンサーの値を読み取る例です。

#include <Arduino.h>
const int sensorPin = A0; // センサーが接続されているピン
void setup() {
  Serial.begin(9600); // シリアル通信の初期化
}
void loop() {
  int sensorValue = analogRead(sensorPin); // センサーの値を読み取る
  Serial.println(sensorValue); // センサーの値をシリアルモニタに出力
  delay(500); // 0.5秒間の遅延
}

このプログラムは、アナログピンA0に接続されたセンサーの値を500ミリ秒ごとに読み取り、その結果をシリアルモニタに出力します。

LEDの点滅制御

void loop関数を使って、LEDを点滅させることも簡単に実現できます。

以下は、LEDを1秒ごとに点滅させる例です。

#include <Arduino.h>
const int ledPin = 13; // LEDが接続されているピン
void setup() {
  pinMode(ledPin, OUTPUT); // LEDピンを出力モードに設定
}
void loop() {
  digitalWrite(ledPin, HIGH); // LEDを点灯
  delay(1000); // 1秒間の遅延
  digitalWrite(ledPin, LOW); // LEDを消灯
  delay(1000); // 1秒間の遅延
}

このプログラムは、デジタルピン13に接続されたLEDを1秒間点灯させ、その後1秒間消灯させることで、LEDを点滅させます。

void loop関数が無限に繰り返されるため、LEDはArduinoが動作している限り点滅し続けます。

これらの例からもわかるように、void loop関数は、Arduinoプログラムにおける繰り返し処理の中心的な役割を果たしています。

void loop関数の終了方法

void loop関数は、Arduinoプログラムにおいて無限に繰り返されることが基本ですが、特定の条件下でループを終了させたり、プログラムを停止させたりする方法もあります。

ここでは、void loop関数の終了方法について解説します。

無限ループからの脱出

通常、void loop関数は無限ループとして動作しますが、特定の条件を満たしたときにループから脱出することができます。

以下は、ボタンが押されたときにループを終了する例です。

#include <Arduino.h>
const int buttonPin = 2; // ボタンが接続されているピン
void setup() {
  pinMode(buttonPin, INPUT); // ボタンピンを入力モードに設定
  Serial.begin(9600); // シリアル通信の初期化
}
void loop() {
  int buttonState = digitalRead(buttonPin); // ボタンの状態を読み取る
  if (buttonState == HIGH) { // ボタンが押された場合
    Serial.println("ループを終了します");
    while (true); // 無限ループでプログラムを停止
  }
  Serial.println("ループ中");
  delay(1000); // 1秒間の遅延
}

このプログラムでは、ボタンが押されるとwhile (true);によって無限ループに入り、void loop関数の通常の処理を停止します。

プログラムの停止方法

Arduinoでは、void loop関数を完全に停止することはできませんが、プログラムの動作を事実上停止させる方法があります。

以下は、すべての処理を停止させる例です。

#include <Arduino.h>
void setup() {
  Serial.begin(9600); // シリアル通信の初期化
}
void loop() {
  Serial.println("プログラムを停止します");
  while (true); // 無限ループでプログラムを停止
}

このプログラムは、while (true);を使用して、void loop関数内の処理を停止させます。

これにより、Arduinoは動作を続けますが、void loop関数内のコードは実行されません。

終了条件の設定

void loop関数内で特定の条件を設定し、その条件が満たされたときにループを終了することも可能です。

以下は、カウンタが特定の値に達したときにループを終了する例です。

#include <Arduino.h>
int counter = 0; // カウンタ変数の初期化
void setup() {
  Serial.begin(9600); // シリアル通信の初期化
}
void loop() {
  counter++; // カウンタを1増加
  Serial.println(counter); // カウンタの値をシリアルモニタに出力
  if (counter >= 10) { // カウンタが10以上になった場合
    Serial.println("ループを終了します");
    while (true); // 無限ループでプログラムを停止
  }
  delay(1000); // 1秒間の遅延
}

このプログラムは、カウンタが10に達するとwhile (true);によって無限ループに入り、void loop関数の通常の処理を停止します。

これらの方法を用いることで、void loop関数の動作を制御し、特定の条件下でプログラムの動作を停止させることができます。

void loop関数の応用例

void loop関数は、Arduinoプログラムにおける繰り返し処理の中心的な役割を果たしますが、応用することでより複雑な制御を実現することができます。

ここでは、void loop関数を使ったいくつかの応用例を紹介します。

タイマーを使った制御

タイマーを使って、特定の時間間隔で処理を実行することができます。

以下は、1秒ごとにLEDを点滅させる例です。

#include <Arduino.h>
const int ledPin = 13; // LEDが接続されているピン
unsigned long previousMillis = 0; // 前回の時間を記録
const long interval = 1000; // 1秒間隔
void setup() {
  pinMode(ledPin, OUTPUT); // LEDピンを出力モードに設定
}
void loop() {
  unsigned long currentMillis = millis(); // 現在の時間を取得
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis; // 前回の時間を更新
    digitalWrite(ledPin, !digitalRead(ledPin)); // LEDの状態を反転
  }
}

このプログラムは、millis()関数を使って経過時間を測定し、1秒ごとにLEDの状態を反転させます。

これにより、LEDが1秒間隔で点滅します。

状態遷移を用いたプログラム

状態遷移を用いることで、複雑な動作を管理することができます。

以下は、ボタンを押すたびにLEDの点灯状態が変わる例です。

#include <Arduino.h>
const int buttonPin = 2; // ボタンが接続されているピン
const int ledPin = 13; // LEDが接続されているピン
int ledState = LOW; // LEDの初期状態
int buttonState; // ボタンの状態
int lastButtonState = LOW; // 前回のボタン状態
void setup() {
  pinMode(buttonPin, INPUT); // ボタンピンを入力モードに設定
  pinMode(ledPin, OUTPUT); // LEDピンを出力モードに設定
}
void loop() {
  buttonState = digitalRead(buttonPin); // ボタンの状態を読み取る
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      ledState = !ledState; // LEDの状態を反転
      digitalWrite(ledPin, ledState); // LEDの状態を設定
    }
    delay(50); // デバウンスのための遅延
  }
  lastButtonState = buttonState; // ボタンの状態を更新
}

このプログラムは、ボタンが押されるたびにLEDの点灯状態を切り替えます。

状態遷移を用いることで、複数の状態を管理しやすくなります。

複数タスクの管理

void loop関数を使って、複数のタスクを同時に管理することも可能です。

以下は、LEDの点滅とセンサーのデータ取得を同時に行う例です。

#include <Arduino.h>
const int ledPin = 13; // LEDが接続されているピン
const int sensorPin = A0; // センサーが接続されているピン
unsigned long previousMillis = 0; // 前回の時間を記録
const long interval = 1000; // 1秒間隔
void setup() {
  pinMode(ledPin, OUTPUT); // LEDピンを出力モードに設定
  Serial.begin(9600); // シリアル通信の初期化
}
void loop() {
  unsigned long currentMillis = millis(); // 現在の時間を取得
  // LEDの点滅制御
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis; // 前回の時間を更新
    digitalWrite(ledPin, !digitalRead(ledPin)); // LEDの状態を反転
  }
  // センサーのデータ取得
  int sensorValue = analogRead(sensorPin); // センサーの値を読み取る
  Serial.println(sensorValue); // センサーの値をシリアルモニタに出力
  delay(500); // センサーのデータ取得間隔
}

このプログラムは、LEDの点滅とセンサーのデータ取得を同時に行います。

millis()関数を使って時間管理を行うことで、複数のタスクを効率的に管理することができます。

これらの応用例を通じて、void loop関数を活用することで、より複雑で多機能なArduinoプログラムを作成することが可能です。

void loop関数の最適化

void loop関数は、Arduinoプログラムの中で繰り返し実行されるため、効率的に動作させることが重要です。

ここでは、void loop関数の最適化に関するいくつかのポイントを紹介します。

処理速度の向上

処理速度を向上させるためには、void loop関数内のコードを効率的に記述することが重要です。

  • 不要な遅延の削減: delay()関数を多用すると、プログラムの応答性が低下します。

millis()関数を使って非同期的に時間を管理することで、遅延を最小限に抑えることができます。

  unsigned long previousMillis = 0;
  const long interval = 1000;
  void loop() {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      // タスクを実行
    }
  }
  • 計算の最適化: 複雑な計算をループ内で繰り返し行うと、処理速度が低下します。

可能であれば、計算を事前に行い、結果を変数に保存して再利用するようにします。

メモリ使用量の削減

Arduinoのメモリは限られているため、効率的に使用することが求められます。

  • 変数のスコープを限定する: 変数は必要な範囲でのみ宣言し、スコープを限定することでメモリ使用量を削減できます。

グローバル変数を多用せず、ローカル変数を活用しましょう。

  • データ型の選択: 必要以上に大きなデータ型を使用しないようにします。

例えば、int型の代わりにbyte型char型を使用することで、メモリを節約できます。

  • 配列のサイズを最適化: 配列はメモリを多く消費するため、必要最小限のサイズに設定します。

デバッグのポイント

デバッグは、プログラムの動作を確認し、問題を解決するために重要です。

  • シリアルモニタの活用: Serial.print()を使って、変数の値やプログラムの進行状況をシリアルモニタに出力することで、プログラムの動作を確認できます。
  Serial.println("プログラム開始");
  Serial.print("変数の値: ");
  Serial.println(variable);
  • LEDを使ったデバッグ: LEDを点灯させることで、プログラムの特定のポイントに到達したことを確認することができます。

これは、シリアルモニタが使用できない場合に有効です。

  • 段階的なテスト: プログラムを小さな部分に分けてテストすることで、問題の特定が容易になります。

各部分が正しく動作することを確認してから、全体を統合します。

これらの最適化手法を用いることで、void loop関数の効率を向上させ、Arduinoプログラムのパフォーマンスを最大限に引き出すことができます。

よくある質問

void loop関数はなぜ無限ループなのか?

void loop関数が無限ループである理由は、Arduinoが常にセンサーのデータを監視し、リアルタイムでデバイスを制御する必要があるためです。

Arduinoは、電源が供給されている限り動作し続けることを前提として設計されており、void loop関数はその間、継続的に実行されることで、プログラムが常に最新の状態を反映できるようにしています。

void loop関数を使わずにプログラムを作成できるか?

void loop関数を使わずにArduinoプログラムを作成することはできません。

Arduinoのプログラム構造は、void setup関数void loop関数を基本としており、void loop関数は必ず必要です。

void loop関数がないと、Arduinoはプログラムを実行することができません。

ただし、void loop関数内で何も処理を行わないようにすることは可能です。

void loop関数内での遅延処理はどうすれば良いか?

void loop関数内での遅延処理は、delay()関数を使うことが一般的ですが、delay()はプログラムの実行を一時停止させるため、他の処理ができなくなります。

これを避けるためには、millis()関数を使って非同期的に時間を管理する方法が推奨されます。

これにより、他のタスクを並行して実行しながら、特定の時間間隔で処理を行うことができます。

まとめ

void loop関数は、Arduinoプログラムにおける繰り返し処理の中心的な役割を果たします。

この記事では、void loop関数の基本的な使い方から応用例、最適化方法、よくある質問までを網羅しました。

これらの知識を活用して、より効率的で機能的なArduinoプログラムを作成してみてください。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • DXライブラリ (10)
  • Arduino (1)
  • URLをコピーしました!
目次から探す