本文へ移動
「1回だけ」と「ずっと」、
Arduinoはこの2つで動いている。
Arduino IDEで新しいスケッチを作ると、最初からvoid setup() {}とvoid loop() {}という2つの空っぽの箱が用意されています。この2つが何をする場所なのか、電源を入れてから実際にどんな順番で動くのかが分かれば、Arduinoのコードの読み書きは驚くほど楽になります。この記事では、身近な例えと豊富なコード例を使って、setup()とloop()の役割・実行順序・書き方を、専門用語ゼロから徹底的にわかりやすく解説します。
setup()とloop()は「何をする場所」か

料理に例えると分かりやすいかもしれません。setup()は「調理を始める前の下ごしらえ」です。まな板を出す、材料を洗う、包丁を用意する——これらは1回やれば十分で、料理中に何度もやり直す作業ではありません。一方loop()は「実際に鍋をかき混ぜ続ける作業」です。火にかけている間、味を見ながら何度も繰り返し行います。
Arduinoのコード(スケッチ)は、必ずこの2つの箱(関数)を持っています。setup()には「最初に1回だけ済ませておきたい準備」を、loop()には「ボードが動いている間、繰り返しチェックしたり実行し続けたい処理」を書きます。
void setup() {
// ここに書いた処理は「1回だけ」実行される
}
void loop() {
// ここに書いた処理は「ずっと繰り返し」実行される
}
setup()やloop()のような、名前が付いた処理のかたまりを「関数」と呼びます。voidは「この関数は結果の値を返さない」という意味の決まり文句で、Arduinoのsetup()とloop()には必ずこのvoidを付けます。正式な定義は、Arduino公式のsetup()言語リファレンス ↗とloop()言語リファレンス ↗で確認できます。基礎文法をさらに広く確認したい方はArduinoのコードの書き方(コピペ可20選)もあわせてご覧ください。
電源を入れてから実行される順番
Arduinoに電源を入れる(またはUSBケーブルを挿す、リセットボタンを押す)と、内部では次の順番で処理が進みます。
} に到達すると、setup()の役目は完全に終わります。setup()が実行されるのは「電源が入ってから最初の1回」だけです。その後は二度と実行されません。一方loop()は、電源を切るかリセットするまで、実行しては最初に戻る、を無限に繰り返します。
「setup()は1回しか実行されない」というのは、「電源を入れっぱなしにしている間は1回」という意味です。リセットボタンを押したり、USBケーブルを挿し直したり、新しいコードを書き込んだりすると、その都度また最初からsetup()が実行されます。これは「1回きりで二度と実行されない」のではなく、「起動するたびに、その最初に1回」と理解するのが正確です。
setup()に書くべき処理(例をたくさん)
setup()には、「最初に1回済ませておけば、あとはずっとそのままでいい」処理を書きます。代表的な例を見てみましょう。
例1:ピンの入力・出力を決める(pinMode)
void setup() {
pinMode(8, OUTPUT); // 8番ピンをLED用の出力に設定
pinMode(2, INPUT_PULLUP); // 2番ピンをボタン用の入力に設定
}
「このピンは信号を送る係(OUTPUT)」「このピンは信号を受け取る係(INPUT)」という役割分担は、電源が入っている間ずっと変わりません。だから1回設定すれば十分です。
例2:シリアル通信を始める(Serial.begin)
void setup() {
Serial.begin(9600); // パソコンとの通信速度を決めて通信を開始
}
パソコンとやり取りするための「窓口を開く」ような処理です。窓口は一度開けば、閉じるまでずっと開いたままなので、毎回開け直す必要はありません。
例3:起動した瞬間にしか決められない値を記録する
unsigned long startTime; // 変数はsetup()の外(グローバル)に置くことが多い
void setup() {
Serial.begin(9600);
startTime = millis(); // 「起動した瞬間の時刻」は、起動してみないと分からない
}
millis()は電源が入ってからの経過時間を返す関数なので、その値は起動してみて初めて分かります。「値そのものは書いた時点では決められないが、起動した瞬間に1回だけ確定させたい」というケースも、setup()の得意分野です。
例4:ライブラリの初期化(サーボ・LCDなど)
#include <Servo.h>
Servo myServo;
void setup() {
myServo.attach(9); // サーボモーターを9番ピンに接続する準備
myServo.write(0); // 起動時は0度の位置にしておく
}
サーボやLCD、センサーなどのライブラリを使う時の「準備運動」にあたる処理も、基本的にsetup()に書きます。
例5:起動時のあいさつメッセージ
void setup() {
Serial.begin(9600);
Serial.println("システムを起動しました"); // 起動時に1回だけ表示したい
}
「起動しました」というメッセージを毎回のloop()で表示していたら、画面が埋め尽くされてしまいます。1回だけ伝えたい情報も、setup()の得意分野です。
setup()に向いている処理
- pinModeによる入出力の設定
- Serial.begin()などの通信開始
- 変数の初期値の設定
- ライブラリ・センサー・モーターの準備
- 起動時に1回だけ出したいメッセージ
loop()に向いている処理(=setup()には不向き)
- ボタンやセンサーの値を毎回確認する処理
- LEDを点滅させ続けるような繰り返し動作
- 時間とともに変化させたい動き
loop()に書くべき処理(例をたくさん)
loop()には、「ボードが動いている間、何度も繰り返しチェックしたり実行し続けたい」処理を書きます。こちらも具体例で見ていきましょう。
例1:ボタンの状態を毎回確認する
void loop() {
if (digitalRead(2) == LOW) { // ボタンは「今この瞬間」の状態を毎回見る必要がある
digitalWrite(8, HIGH);
} else {
digitalWrite(8, LOW);
}
}
ボタンは「いつ押されるか」分かりません。だから1回だけ確認するのではなく、loop()の中で何度も何度も「今押されているか?」を確認し続ける必要があります。
例2:LEDを点滅させ続ける
void loop() {
digitalWrite(8, HIGH);
delay(500);
digitalWrite(8, LOW);
delay(500);
}
「点ける→消す→点ける→消す」という動きそのものが繰り返しなので、loop()の外では成立しません。
例3:センサーの値を継続的に読み取る
void loop() {
int sensorValue = analogRead(A0); // 周囲の状況は刻一刻と変わる
Serial.println(sensorValue);
delay(100);
}
明るさや温度、圧力といったセンサーの値は、時間とともに変わり続けます。今の状況を知りたいなら、繰り返し読み取り続けるしかありません。
例4:時間で少しずつ変化させる
int brightness = 0;
void loop() {
analogWrite(9, brightness); // LEDの明るさを少しずつ上げる
brightness = brightness + 1;
if (brightness > 255) {
brightness = 0;
}
delay(10);
}
「少しずつ」「だんだん」という変化は、1回では表現できません。loop()が何度も回ることで、初めて「変化」として成立します。
共通するキーワードは「毎回」「繰り返し」「変わり続ける」です。逆に言えば、これらのキーワードが当てはまらない処理は、loop()に書く必要がないということでもあります。
比較で理解する:1回だけ点灯 vs 繰り返し点滅
同じ「LEDを光らせる」という目的でも、setup()に書くかloop()に書くかで、まったく違う動きになります。実際に見比べてみましょう。
パターンA:setup()に書く → 1回だけ点灯したままになる
const int LED_PIN = 8;
void setup() {
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH); // 起動直後に1回だけ点灯を指示
}
void loop() {
// 何も書かない
}
このコードは「電源が入った瞬間にLEDを点ける」という1回きりの指示です。一度点いたLEDは、その後ずっとそのまま光り続けます(消す指示が二度と実行されないからです)。まるで壁のスイッチを1回押しっぱなしにしたような状態です。
パターンB:loop()に書く → 点滅し続ける
const int LED_PIN = 8;
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
delay(500);
digitalWrite(LED_PIN, LOW);
delay(500);
}
こちらは「点ける→0.5秒待つ→消す→0.5秒待つ」という一連の動作が、loop()によって何度も繰り返されます。結果として、LEDは点滅し続けます。
| 書く場所 | 実行される回数 | 結果 |
|---|---|---|
| setup() | 電源投入時に1回だけ | 点灯したまま(消える指示が来ない) |
| loop() | 電源が入っている間ずっと | 点滅を繰り返す |
パターンAのdigitalWrite(LED_PIN, HIGH)を、そのままloop()の中に1行だけ移動させてみてください。delay()を挟まなくても、Arduinoは1秒間に何千回もHIGHを送り続けるだけなので、見た目上はパターンAと同じ「点灯したまま」に見えます。「1回だけ書く」ことと「同じ内容を毎回書く」ことの違いを体感できます。
ありがちな失敗:初期化をloop()に書くとどうなる?
pinMode()やSerial.begin()のような「初期化」の処理を、うっかりloop()に書いてしまう失敗は、初心者に非常によく見られます。文法的にはエラーになりませんが、深刻な問題を引き起こすことがあります。
失敗例:Serial.begin()をloop()に書いてしまう
void setup() {
// Serial.begin()を書き忘れている
}
void loop() {
Serial.begin(9600); // ← 毎回シリアル通信を開始し直そうとしてしまう
Serial.println("Hello");
delay(500);
}
通信を「開始する」という処理を、1秒間に何千回も呼び出すことになります。実際には多くの場合、最初の数回はなんとなく動いているように見えても、通信が不安定になったり、シリアルモニタの表示が乱れたり、正常に動かなくなったりします。「毎回やり直す必要のない処理」を毎回やり直そうとすること自体が、無駄であり不具合の元です。
正しい書き方
void setup() {
Serial.begin(9600); // 通信の開始は1回だけでいい
}
void loop() {
Serial.println("Hello"); // 繰り返し送りたい内容だけをloop()に
delay(500);
}
同じ理屈で気をつけたい他の例
pinMode()をloop()に書くと、ピンの役割設定を毎回やり直すことになり、無駄が多いだけでなく一部の環境で意図しない挙動につながることがあります。myServo.attach(9)のようなライブラリの初期化をloop()に書くと、毎回接続をやり直そうとして、動きがカクついたり不安定になったりします。- 変数の初期値をloop()の中で毎回代入し直すと、その変数を「増やしていく」「変化させていく」使い方ができなくなってしまいます。
「これをもう一度実行したら、何か問題が起きるか?」と自問してみてください。答えが「起きる(無駄、不安定になる、やり直しになる)」ならsetup()向き、「問題ない、むしろ毎回必要」ならloop()向きです。
実践コード:起動メッセージ+繰り返しのセンサー読み取り
最後に、setup()とloop()それぞれの役割を1つのコードの中で組み合わせた、実践的な例を見てみましょう。ボタンとセンサーを使い、起動時のあいさつと、繰り返しの監視を両立させます。
const int SENSOR_PIN = A0;
const int BUTTON_PIN = 2;
const int LED_PIN = 8;
const int THRESHOLD = 500;
void setup() {
// ここから下は「起動時に1回だけ」の準備
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
Serial.println("=== センサー監視システム 起動 ===");
Serial.println("しきい値: 500");
}
void loop() {
// ここから下は「電源が入っている間ずっと」繰り返される監視
int sensorValue = analogRead(SENSOR_PIN);
bool buttonPressed = digitalRead(BUTTON_PIN) == LOW;
if (sensorValue >= THRESHOLD) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
if (buttonPressed) {
Serial.print("ボタン押下時のセンサー値: ");
Serial.println(sensorValue);
}
delay(50);
}
センサーの種類や使い分けをさらに詳しく知りたい方は、Arduino用センサー完全ガイド16選もあわせてご覧ください。ボタン回路の配線についてはボタン回路の基礎から応用までで詳しく解説しています。
setup()かloop()か迷った時の判断基準

ここまでの内容を、実際にコードを書く時にすぐ使えるチェックリストにまとめました。書こうとしている1行が「setup()向きか、loop()向きか」迷ったら、上から順番に確認してみてください。
これは「準備」か、それとも「動作」か。準備(設定・初期化)ならsetup()、動作(監視・出力・変化)ならloop()です。
もう一度実行したら問題が起きるか。問題が起きる(通信の開始し直し、状態のリセットなど)ならsetup()向きです。
「今この瞬間」の情報が必要か。ボタンやセンサーのように刻一刻と変わる値を扱うならloop()です。
「1回だけ伝えたい」情報か。起動メッセージやしきい値の表示のように、1回で十分な情報はsetup()に書きます。
時間とともに「変化」させたいか。だんだん明るくする、少しずつ角度を変えるといった変化は、loop()が繰り返されることで初めて表現できます。
「これは1回だけでいいか、それとも何度も必要か?」——この一言に立ち返るだけで、多くの場合は自然と答えが見えてきます。
FAQ・まとめ
setup()とloop()は必ず両方書かないといけませんか?
はい。Arduinoのスケッチにはsetup()とloop()の両方が必須です。中に何も処理を書かない場合でも、void setup() {}やvoid loop() {}のように空の状態で残しておく必要があります。どちらか一方でも欠けているとコンパイルエラーになります。
setup()は本当に1回しか実行されないのですか?
電源を入れっぱなしにしている間は1回だけです。ただし、リセットボタンを押す、電源を入れ直す、新しいスケッチを書き込むといったタイミングでは、その都度setup()が最初からもう一度実行されます。「電源が入っている1回の間に1回」と考えると正確です。
pinModeやSerial.begin()はloop()に書いてはいけませんか?
文法的にはloop()の中に書いてもエラーにはなりませんが、絶対におすすめしません。loop()は1秒間に何千回も繰り返される場所なので、同じ初期化処理を毎回無駄に実行することになり、通信が不安定になったり、意図しない動作の原因になったりします。初期化は必ずsetup()に書きましょう。
setup()とloop()、どちらに書くか迷った時はどう判断すればいいですか?
「電源を入れた瞬間に1回だけ済ませておきたい準備」ならsetup()、「ボードが動いている間、繰り返しチェックしたり実行し続けたい動作」ならloop()に書きます。迷ったら「これは1回だけでいいか、それとも何度も必要か」を自問すると判断しやすくなります。
setup()は「電源投入時に1回だけの下ごしらえ」、loop()は「動いている間ずっと続く本番の動作」——この役割分担さえ体に染みつけば、他の人が書いたArduinoのコードを読む時も、「あ、これは準備だな」「これは繰り返しの監視だな」と自然に読み分けられるようになります。まずは5章の点灯と点滅のコードを実際に書き換えて、体で違いを確かめてみてください。
コメント