Arduinoのコードの書き方の基本
以下の記事では、Arduinoコードの書き方について、驚くほど深くかつ詳細に解説します。Arduinoプログラミングの基礎から応用まで、この1記事を読めば全体像がわかる構成を目指します。適宜、サンプルコードや表を交えながら進めていきます。
目次
- Arduinoとは何か
- Arduinoプログラムの基本構造
- Arduino IDEと開発環境
- データ型と変数の使い方
- 基本的な関数(
setup()
とloop()
) - ピン入出力:デジタルとアナログ
- 制御構文(if, for, while など)
- 関数の定義と使い方
- 配列・文字列・ポインタ
- 割り込み(Interrupts)の基本
- ライブラリの利用方法
- シリアル通信(Serialモニタ)
- メモリ管理とプログラム最適化の基礎
- よく使うサンプルコード集
- まとめと次のステップ
1. Arduinoとは何か
Arduinoは、マイクロコントローラを搭載した開発ボードと、プログラミング環境(Arduino IDE)を中心としたオープンソースハードウェアのプラットフォームです。主に電子工作やIoT、プロトタイプ開発などで広く使われています。
- 代表的なモデル: Arduino Uno, Arduino Mega, Arduino Nano, Arduino Leonardo など
- 特徴:
- シンプルでわかりやすいプログラミング環境
- 豊富なライブラリが用意されている
- 世界中のコミュニティがサポート
2. Arduinoプログラムの基本構造
Arduinoのプログラム(スケッチと呼ばれる)は大きく次の二つの関数が必ず含まれます。
void setup() { ... }
void loop() { ... }
setup()関数
・Arduinoが起動して最初に1回だけ呼ばれる関数。
・ピンのモード設定(入力/出力)やシリアル通信の初期化など、最初に必要な設定を行う。
loop()関数
・setup()
関数が終了した後、無限に呼び出され続ける関数。
・メインループとして、プロセスを常に回し続けるイメージ。
この2つの関数だけで最低限のプログラム構造が成り立ちます。Arduinoのプログラムは“イベントドリブン”ではなく、“ループ”で常に走り続けるのが特徴です。
3. Arduino IDEと開発環境
Arduinoの公式開発環境はArduino IDEです。以下のような特徴があります。
- コードのコンパイル、書き込み(アップロード)がワンクリックで可能
- シリアルモニタ機能で簡単にデバッグ
- スケッチ(プログラム)をフォルダ単位で管理
- 豊富なライブラリマネージャ
基本的な作業手順
- Arduino IDEを起動
- ボードの種類とポートを設定
- コードを書く
- コンパイル
- 書き込み(アップロード)
- シリアルモニタやLEDなどを使って動作を確認
4. データ型と変数の使い方
マイコン上で動作するため、メモリサイズを気にしたデータ型選びが重要です。Arduino Unoなどの8ビットマイコンではメモリ(SRAM)が2KB程度しかありません。
主なデータ型一覧
データ型 | ビット数 | 値の範囲(符号付き) | メモ |
---|---|---|---|
boolean | 8 | true (1) / false (0) | 1バイト消費 |
char | 8 | -128 ~ 127 | char は文字型にも使う |
unsigned char | 8 | 0 ~ 255 | |
int | 16 | -32768 ~ 32767 | AVR系Arduinoの場合 |
unsigned int | 16 | 0 ~ 65535 | |
long | 32 | -2,147,483,648 ~ 2,147,483,647 | |
unsigned long | 32 | 0 ~ 4,294,967,295 | |
float | 32 | IEEE 754準拠 | 精度は高くない |
double | 32 | IEEE 754準拠 | Unoなどではfloat と同じ精度 |
メモリ消費を抑えたい場合は、int
の代わりにbyte
やchar
を使うなど、プロジェクト規模にあわせて工夫が必要です。
変数宣言例
int sensorValue = 0; // アナログセンサの値を格納
boolean ledState = false; // LEDの点灯状態を管理
unsigned long counter = 0; // 大きなカウンタ値を扱いたいとき
5. 基本的な関数(setup()
と loop()
)
Arduinoの最小限のスケッチは以下のようになります。
void setup() {
// 初期設定をここに書く
Serial.begin(9600); // シリアル通信を9600bpsで開始
pinMode(LED_BUILTIN, OUTPUT); // ボード内蔵LEDを出力モードに設定
}
void loop() {
// メインループ
digitalWrite(LED_BUILTIN, HIGH); // LED点灯
delay(1000); // 1秒待機
digitalWrite(LED_BUILTIN, LOW); // LED消灯
delay(1000); // 1秒待機
}
delay()関数:
指定したミリ秒だけプログラムを停止(待機)させる。
他の処理はその間止まるため、リアルタイム性が必要な場面では注意が必要。
6. ピン入出力:デジタルとアナログ
Arduinoではデジタルピンとアナログピンを使って様々な入出力を行います。
デジタルピン
pinMode(pin, mode);
で入出力モードを指定(INPUT
, OUTPUT
, INPUT_PULLUP
)。
digitalWrite(pin, HIGH/LOW);
で出力のHIGH/LOWを指定。
digitalRead(pin);
で入力を読み取り(HIGHかLOW)。
デジタル出力例
pinMode(13, OUTPUT); // ピン13を出力に設定
digitalWrite(13, HIGH); // ピン13をHIGHに
digitalWrite(13, LOW); // ピン13をLOWに
アナログ入力(ADC)
Arduino Unoの場合、A0~A5までのアナログ入力ピンが用意されている。
analogRead(pin);
で0~1023の値を取得(10ビットADC)。
取得値を利用してセンサ値などを読み取る。
アナログ入力例
int sensorVal = analogRead(A0); // A0ピンの値を取得(0~1023)
Serial.println(sensorVal);
アナログ出力(PWM)
Arduino UnoではD3, D5, D6, D9, D10, D11などのピンでPWMが可能。
analogWrite(pin, value);
で0~255の範囲を指定して“疑似的な”アナログ出力(PWM)を行う。
PWM出力例
analogWrite(9, 128); // ピン9に対して約50%デューティ比のPWM出力
7. 制御構文(if, for, while など)
C言語と同じ構文が使えます。代表的なものを簡単におさらいしましょう。
if文
if (sensorVal > 500) {
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
for文
for (int i = 0; i < 10; i++) {
Serial.println(i);
}
while文
int count = 0;
while (count < 5) {
Serial.println("Hello");
count++;
}
switch文
switch (mode) {
case 0:
// 処理
break;
case 1:
// 処理
break;
default:
// それ以外
break;
}
いずれも一般的なC/C++構文と同様なので、Arduino固有というよりはマイコンCの素直な使用感です。
8. 関数の定義と使い方
setup()
や loop()
以外にも、自由に関数を定義してコードを整理できます。
int addTwoNumbers(int a, int b) {
return a + b;
}
void setup() {
Serial.begin(9600);
}
void loop() {
int result = addTwoNumbers(3, 4);
Serial.println(result);
delay(1000);
}
・ 関数はプロトタイプ宣言(ヘッダ宣言)が無くても、Arduino IDEが自動的に対応してくれます。
・ 大規模になるときは、.ino
ファイルを分割したり、ライブラリ化を検討するのも手です。
9. 配列・文字列・ポインタ
Arduino C++でも配列やポインタを使えます。メモリ管理がシビアな場面が多いので注意が必要です。
配列
int values[5] = {10, 20, 30, 40, 50};
void setup() {
Serial.begin(9600);
}
void loop() {
for (int i = 0; i < 5; i++) {
Serial.println(values[i]);
}
delay(1000);
}
文字列
Arduinoでは、Cスタイルの文字列(ヌル終端)と、String
クラスの2種類が使えます。
・ Cスタイル文字列: メモリ効率が高いが扱いはやや面倒
・ String
クラス: 直感的だが、ヒープ断片化(メモリフラグメンテーション)の原因になることがある
String
クラスの例
String message = "Hello Arduino";
Serial.println(message);
Cスタイルの例
char msg[] = "Hello Arduino";
Serial.println(msg);
メモリの余裕がないマイコンの場合は、Cスタイル文字列のほうが無難です。
ポインタ
C/C++のポインタ構文が利用できます。配列操作や関数への受け渡しで活躍します。ただし、メモリの上書きバグは最悪システムクラッシュを起こすため、細心の注意を払いましょう。
10. 割り込み(Interrupts)の基本
Arduino UnoなどのAVR系マイコンには、外部割り込みやピン変化割り込みなどが用意されています。割り込みを使うことで、特定のイベント(入力ピンの変化など)にリアルタイムで反応させられます。
外部割り込みの例
volatile boolean state = false;
void setup() {
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), toggleState, CHANGE);
Serial.begin(9600);
}
void loop() {
if (state) {
Serial.println("Interrupt Triggered!");
state = false;
}
delay(100);
}
void toggleState() {
state = true;
}
・ volatile
修飾子を使うことで、割り込みハンドラとメインループで変数を共有するときの最適化を防ぐ。
・ 割り込みルーチン(ISR)内では処理を最小限に抑えるのが鉄則です。
11. ライブラリの利用方法
Arduino IDEには様々なライブラリが用意されており、追加でインストールすることもできます。例えば、LCDや各種センサ、モータドライバなど、多くのデバイスを簡単に制御できます。
例:ライブラリのインストール方法
- Arduino IDEを開く
- メニューから「スケッチ」→「ライブラリを管理」
- 検索窓で使いたいライブラリを検索し、インストール
- スケッチ上で
#include <ライブラリ名.h>
と記述
例:LiquidCrystalライブラリ
#include <LiquidCrystal.h>
// RS, E, D4, D5, D6, D7 の順にピンを指定
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
lcd.begin(16, 2); // 16桁×2行
lcd.print("Hello World!");
}
void loop() {
}
12. シリアル通信(Serialモニタ)
Arduino IDEには、PCとArduino間のシリアル通信を簡単に確認できるシリアルモニタがあります。
シリアル通信の基本
Serial.begin(9600);
で通信速度(ボーレート)を設定
Serial.print()
や Serial.println()
で文字列・数値などを送信
Serial.available()
で受信バッファにデータがあるかチェック
Serial.read()
で受信データを1バイト読み取り
例:PCから入力された文字をエコーバックする
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
char c = Serial.read();
Serial.print("You typed: ");
Serial.println(c);
}
}
13. メモリ管理とプログラム最適化の基礎
Arduino Unoの場合、
・ フラッシュメモリ(プログラム領域):32KB
・ SRAM(変数や配列):2KB
・ EEPROM(不揮発性メモリ):1KB
これらのリソースを超えると正常に動作しなくなるため、適切な最適化が必要です。
メモリ節約のヒント
- 文字列を
F()
マクロでフラッシュメモリに置くSerial.println(F("This string won't use SRAM"));
- 不要なライブラリの削除
- グローバル変数を減らし、ローカル変数を活用
String
オブジェクトの動的生成を避け、Cスタイルの文字列を使う- 配列はサイズを厳密に管理し、必要以上に大きくしない
EEPROMの活用
設定値などを保持したい場合はEEPROM
ライブラリを使って書き込むことができます。ただし書き込み回数に上限があるため注意。
#include <EEPROM.h>
void setup() {
EEPROM.write(0, 123); // アドレス0に123を書き込む
}
void loop() {
int val = EEPROM.read(0);
Serial.println(val);
delay(1000);
}
14. よく使うサンプルコード集
ここでは、Arduino初心者がよく利用するパターンをいくつか紹介します。
(1) ブリンク(Blink)
もっとも基本的なLED点滅スケッチ。
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
(2) アナログセンサの読み取りと表示
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorVal = analogRead(A0);
Serial.print("Sensor Value: ");
Serial.println(sensorVal);
delay(500);
}
(3) フェード(LEDの明るさ制御)
void setup() {
pinMode(9, OUTPUT);
}
void loop() {
for (int i = 0; i < 256; i++) { analogWrite(9, i); delay(10); } for (int i = 255; i >= 0; i--) {
analogWrite(9, i);
delay(10);
}
}
(4) ボタン入力でLEDを点滅
const int buttonPin = 2;
const int ledPin = 13;
boolean buttonState = false;
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // プルアップを使用
pinMode(ledPin, OUTPUT);
}
void loop() {
// ボタンが押されたらLOWになる
if (digitalRead(buttonPin) == LOW) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
(5) シリアル通信でLED制御
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if (Serial.available() > 0) {
char c = Serial.read();
if (c == '1') {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("LED ON");
} else if (c == '0') {
digitalWrite(LED_BUILTIN, LOW);
Serial.println("LED OFF");
}
}
}
15. まとめと次のステップ
ここまで、Arduinoにおけるプログラミングの基礎から、割り込みやメモリ管理、ライブラリ活用など、かなり深い内容を解説しました。Arduinoは入門者にも易しく、なおかつ奥が深いプラットフォームです。C/C++の文法やマイコンの仕組みを理解することで、より高度なプロジェクトに挑戦できるようになります。
次のステップとしては、以下のような取り組みをおすすめします。
- 外部センサやモジュールの利用
温度センサ、超音波センサ、RGB LED、フルカラーLCDなどを使ったプロジェクト - 無線通信やネットワークへの拡張
Wi-Fiモジュール(ESP8266/ESP32)、Bluetooth、LoRaなどを用いたIoTプロジェクト - 複数タスクの同時処理に挑戦
割り込み、ミリ秒単位のタイマー、状態マシンによる非ブロッキング動作 - メモリやパフォーマンスを意識したプログラム最適化
フラッシュメモリやSRAMの節約、効率の良いデータ構造の設計 - C++のオブジェクト指向を用いたコードの再利用性向上
クラスを定義して複雑なプロジェクトを読みやすく拡張しやすいコード構造にする
Arduinoの魅力は、初心者でもすぐにハードウェア制御ができること、そして拡張性が高く上級者でも深い学びを得られることです。本記事の内容をベースに、ぜひ実際のプロジェクトを組み立ててみてください。
何かわからないことが出てきたら、本記事を振り返りつつ、公式ドキュメントやコミュニティフォーラムをチェックしてみてください。皆様のArduinoライフが充実したものになることを願っています。
コメント