Arduinoの配列の使い方――複数センサーの値を一元管理する設計術。

プログラミング・電子工作






Arduinoの配列の使い方――複数センサーの値を一元管理する設計術。|YOFUKASI AI




Arduino / 電子工作

Arduinoの配列の使い方――複数センサーの値を一元管理する設計術。

センサーが増えるたびに変数を増やしていませんか。配列の基本構文から、構造体との使い分け、複数センサーをまとめて扱う実践手順までを解説します。

YOFUKASI AI編集部 | 更新日:2026年8月18日 | 読了目安:約12分

Chapter 01 — Introduction

01なぜ複数センサーの管理に配列が必要なのか

結論から言えば、同種のセンサーを3個以上扱うプロジェクトでは、センサーごとに変数を用意する書き方は破綻しやすい。temp1temp2temp3のように変数を増やしていくと、読み取り処理・平均化処理・しきい値判定処理をセンサーの数だけコピペすることになり、センサーを1個追加するたびに複数箇所を修正する必要が生じる。配列(array)を使えば、これらの値をひとつの変数名とインデックス番号でまとめて扱い、for文と組み合わせて処理を1箇所に集約できる。

実例として、Arduino UNOを使って温度・湿度・気圧・PM2.5・CO2という5種類の環境センサーからデータを取得する自作プロジェクトの事例がある。この事例では、センサーごとに読み取りタイミングや待ち時間の制約が異なる点が課題として挙げられており、複数のセンサーを効率よく扱うロジックの設計が必要になっている。Arduino UNOで複数の環境センサーからデータ取得を行った事例(t-hom’s diary)では、CO2センサーの計測待ち時間を利用して他のセンサーの読み取りを並行させる設計が紹介されている。

編集部見解:センサー1〜2個の小規模なプロジェクトでは、個別の変数のままでも十分読みやすい。配列化の効果が顕著になるのは、同種のセンサーが3個を超え、かつ「読み取る」「平均する」「しきい値と比較する」といった処理が全センサー共通になってきたタイミングだと考えられる。
― YOFUKASI AI編集部

本記事では、Arduinoにおける配列の基本構文から、複数の型を扱いたい場合の構造体との使い分け、そして複数センサーのデータを実際に配列でまとめる手順までを、初心者から中級者を対象に体系的に解説する。



Chapter 02 — Background

02Arduinoにおける配列の基礎知識

配列(array)とは、同じ型のデータをインデックス番号でアクセスできる変数の集まりのことである。Arduino公式ドキュメントでも、配列はインデックス番号でアクセスされる変数の集まりであると定義されており、単純な配列の利用自体は比較的簡単に扱えると説明されている。

Arduinoにおける配列の一次情報は、Arduino公式 Language Reference「array」にまとまっている。公式リファレンスでは配列がインデックス番号でアクセスされる変数の集まりであり、Arduinoスケッチが書かれているC++言語における配列は複雑になり得るが、単純な配列を扱うのは比較的容易だと説明されている。また配列は0番から番号が振られる点についても配列は0から始まるインデックスを持ち、最初の要素はインデックス0にあると述べられている

実際に配列を使ったサンプルスケッチは、公式のビルトイン例でも公開されている。Arduino公式「How to Use Arrays」では、複数のLEDピン番号を配列にまとめ、for文で順番に点灯させるサンプルが紹介されており、配列を使うことでピンの順序を自由に入れ替えられる利点が説明されている。

用語の整理

  • 要素(element):配列を構成する1つ1つのデータ。
  • インデックス(index):配列内の要素の位置を示す番号。Arduino(C++)では0番から始まる。
  • 添字(そえじ):インデックスの別称。sensor[0][0]部分を指す。

配列とあわせて理解しておきたいのがスコープの概念である。関数の中だけで有効なローカル変数と、プログラム全体で共有されるグローバル変数の違いについては、Arduino公式 Language Reference「scope」で解説されている。複数センサーの値をグローバル配列として保持するか、関数内のローカル配列として都度取得するかは、後述の第4章・第5章で扱う設計判断のポイントになる。

Arduinoの基礎文法や、関数の作り方をまだ体系的に学んでいない場合は、先に基礎を押さえておくとこの先の理解がスムーズになる。Arduinoのコードの書き方の基礎はこちらの記事で詳しく解説している

Chapter 03 — Mechanism

03配列の仕組みと技術的背景

Arduinoの配列は、基本的に次の3通りの方法で宣言できる。

// (A) 要素数を指定して宣言のみ行う(値は未初期化)
int sensorValues[5];

// (B) 要素数を省略し、初期化リストで宣言と同時に値を設定する
int sensorPins[] = {A0, A1, A2, A3, A4};

// (C) 要素数を指定しつつ、初期化リストで値も設定する
float temperatures[3] = {21.5, 22.0, 20.8};

複数のセンサーを扱う際は、ピン番号の配列とセンサー値の配列をペアで用意し、for文で同じインデックスを使って両方にアクセスするのが基本形になる。

const int sensorPins[3] = {A0, A1, A2};
float sensorValues[3];

void readAllSensors() {
  for (int i = 0; i < 3; i++) {
    int raw = analogRead(sensorPins[i]);
    sensorValues[i] = raw * (5.0 / 1023.0); // 電圧に変換
  }
}

2次元配列と構造体という選択肢

センサーの「現在値」だけでなく「過去数回分の履歴」も持たせたい場合は、2次元配列を使うことで表形式のデータを扱える。2次元配列の宣言方法や添字の考え方については、日本語で図解付きに解説した記事がある。Arduino IDE(2次元配列の使い方)(NOBのArduino日記!)では、2次元配列が表のようなデータを扱うときに便利な変数であり、行と列を指定することで配列の要素に連続してアクセスできると説明されている。

編集部想定シナリオ
温度・湿度・照度のように型もセンサーの性質も異なる複数のデータを扱う場合、単純な配列では「同じ型しか格納できない」という制約に突き当たる。この場合はstruct SensorReading { float value; int pin; unsigned long lastRead; };のような構造体を定義し、その構造体の配列を用意することで、型の異なる複数の値を1つの要素としてまとめて扱える。

一方で、配列のサイズを大きくしすぎるとメモリを圧迫する点には注意が必要である。Arduino UNOに搭載されているATmega328Pは、SRAM(変数を保持するための揮発性メモリ)の容量が非常に小さい。Arduino 入門 番外編11【搭載メモリについて】(おもろ家)では、SRAMのメモリサイズが小さいためプログラム作成時にはSRAMのメモリサイズを意識する必要があり、特に文字列や配列を使用する場合はメモリがすぐになくなってしまうため注意が必要だと説明されており、同記事内でUNOのSRAM容量が2キロバイトである点も紹介されている。センサー履歴を保持する2次元配列を大きくしすぎると、この上限に達しやすい。

圧力センサーや筋電センサーのように、複数チャネルのアナログ値を継続的に読み取るセンサーの実例は、以下の記事でも詳しく扱っている。配列を使った読み取り処理の実装イメージをつかむ際の参考になる。



Chapter 04 — Comparison

04配列・構造体・個別変数の比較と選択肢

複数センサーの値をどう保持するかは、センサーの数と型の統一性によって最適解が変わる。以下に3つの選択肢を整理する。

項目 A. 個別変数(配列不使用) B. 単純配列 C. 構造体の配列(struct配列)
向いている規模 センサー1〜2個 同種センサー3個以上 異種データを組にして扱う場合
扱えるデータの型 制約なし(個別に型指定) 同じ型のみ 異なる型を1要素にまとめられる
for文との相性 低い(個別に記述が必要) 高い 高い
可読性 少数なら高い センサー数が多いほど高い 設計次第で高い

※各手法の適用規模の目安は編集部見解を含む。配列と構造体の文法的な定義についてはArduino公式 Language Reference「array」を参照。

迷った場合の目安として、「今後センサーの種類・数が増える予定があるか」を基準にするとよい。将来的にセンサーが増える見込みがあるなら、最初から単純配列または構造体配列で設計しておくと、後からの拡張が容易になる。

Chapter 05 — Practice

05実践:複数センサーのデータを配列でまとめる5ステップ

ここでは「3個の温度センサーの値を配列で管理し、平均値としきい値判定を行う」という編集部想定シナリオを題材に、個別変数のべた書きコードを配列に置き換える具体的な手順を示す。

  1. STEP1. 個別変数になっている箇所を洗い出す

    現在のコードの中で、temp1temp2temp3のように連番の変数名が使われている箇所を探す。同じ処理(読み取り・変換・比較)が変数ごとに繰り返し書かれていれば、配列化の候補になる。

    実例:温度センサー3個分の読み取り処理が、変数名だけ違う形で3回コピペされていることを確認した(合計約15行)。
  2. STEP2. ピン番号配列とデータ配列をペアで宣言する

    センサーが接続されているピン番号をconst int配列として固定し、読み取った値を格納する配列を別に用意する。要素数はセンサーの個数と一致させる。

    実例:const int tempPins[3] = {A0, A1, A2};float temps[3];の2つの配列を宣言した。センサーを1個追加する場合も、この2箇所の要素数を変更するだけで済む構成にした。
  3. STEP3. for文で読み取り処理を1箇所に集約する

    sizeof(tempPins) / sizeof(tempPins[0])で要素数を取得し、for文の範囲として使う。これにより、配列の要素数を変更してもfor文の条件を書き換える必要がなくなる。

    実例:for (int i = 0; i < 3; i++) { temps[i] = readTemp(tempPins[i]); }という3行に、元は15行あった読み取り処理を集約した。
  4. STEP4. 平均値・しきい値判定も配列ベースの処理に置き換える

    個別変数を1つずつ比較していた判定処理を、配列を走査するループに置き換える。平均値の算出も同様に、合計値をfor文で積み上げてから要素数で割る形にする。

    実例:3個の温度の平均を求める処理をfloat sum = 0; for (int i = 0; i < 3; i++) sum += temps[i]; float avg = sum / 3;という形に統一した。しきい値28.0℃を超えたセンサーの本数をカウントする判定も同じループ内に追加した。
  5. STEP5. シリアル出力でセンサーごとの値を確認する

    配列化した後も、デバッグ時にはどのセンサー(どのインデックス)の値が想定と違うかを個別に確認できるようにしておく。for文の中でインデックス番号とあわせてシリアル出力する。

    実例:Serial.print("Sensor "); Serial.print(i); Serial.print(": "); Serial.println(temps[i]);という出力を追加したところ、3個中1個のセンサー(インデックス1)だけ配線の接触不良で異常値を返していたことが判明した(編集部想定シナリオ)。

センサー値をArduinoからPython側に送って可視化・分析する場合の実例は、以下の記事でも扱っている。配列でまとめたデータをシリアル通信で送信する際の参考になる。

ArduinoとPythonを組み合わせたリハビリ応用の実例はこちらの記事で紹介している。複数の圧センサー値を継続的に取得し、臨床データとして扱う構成の参考になる。

Chapter 06 — Pitfalls

06注意点・よくある誤解

!誤解1. 配列の添字は1番から始まる

Arduino(C++)の配列は0番から始まる。要素数3の配列であれば有効な添字は0・1・2までで、3にアクセスすると配列の範囲外を読み書きしてしまう。for文の条件をi <= 3のように書き間違えると、この範囲外アクセスが発生しやすい。

!誤解2. 配列は大きくしておくほど安全だ

将来の拡張を見越して配列サイズを必要以上に大きく確保すると、Arduino UNOのようにSRAM容量が小さいボードではメモリ不足の原因になりやすい。センサーの点数や履歴の必要件数から逆算し、必要最小限のサイズに留めるのが基本となる。

!誤解3. センサーが少なくても配列化した方が「格好良い」コードになる

配列化のメリットが発揮されるのは、同じ処理を繰り返すセンサーが複数ある場合である。センサーが1〜2個で今後も増える予定がないなら、個別変数のままの方がコードの意図が伝わりやすいこともある。配列化は目的ではなく手段であることを意識したい。



Chapter 07 — FAQ

07FAQ

Q.Arduinoの配列とは何ですか。複数の変数を用意するのと何が違いますか。
A.配列(array)は、同じ型のデータをインデックス番号でまとめてアクセスできる変数の集まりです。sensor1、sensor2、sensor3のように個別の変数を用意する代わりに、sensor[0]、sensor[1]、sensor[2]のように1つの名前でまとめて扱えるため、for文と組み合わせて処理をひとつのロジックに集約できます。

Q.配列の添字(インデックス)は何番から始まりますか。
A.Arduino(C++)の配列は0番から始まります。要素数が5個の配列であれば、有効な添字は0から4までで、5にアクセスすると配列の範囲外を読み書きすることになり、意図しない値やクラッシュの原因になります。

Q.複数のセンサーを配列で管理するとき、型が違うセンサー同士は同じ配列にまとめられますか。
A.通常の配列は同じ型のデータしか格納できません。温度(float)とデジタルスイッチの状態(bool)のように型が異なるセンサーをまとめて管理したい場合は、構造体(struct)を定義し、その構造体の配列を使うことで、型の異なる複数の値をひとつの要素としてまとめて扱えます。

Q.配列のサイズはどのくらいまで大きくして良いですか。
A.Arduino UNOなどATmega328Pベースのボードは、SRAMの容量が2キロバイトと小さいため、配列のサイズを増やしすぎるとメモリ不足によって動作が不安定になることがあります。センサーの数や必要な履歴データの点数から逆算し、必要最小限のサイズに留めることが推奨されます。

Q.配列の要素数はどうやって取得すればよいですか。
A.sizeof(配列名) / sizeof(配列名[0]) という書き方で、配列全体のバイト数を1要素あたりのバイト数で割ることで、要素数を求めることができます。配列を初期化リストで宣言した場合、要素数を書き換えるたびにfor文の条件を修正する手間を省けます。

Q.配列を使うとコードが読みにくくなることはありませんか。
A.センサーが1〜2個程度であれば、個別の変数のままの方がかえって読みやすい場合もあります。配列化のメリットが大きくなるのは、同種のセンサーが3個以上あり、同じ処理(読み取り・平均化・しきい値判定など)を繰り返す場面です。センサー数が少ないうちは無理に配列化しない、というのも実務上の判断のひとつです(編集部見解)。

参考文献

関連記事(内部リンク)


関連記事

特集記事

コメント

この記事へのコメントはありません。

TOP
CLOSE