0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GPIO3本+ADC6本で“18個の光センサ”を読む方法

Last updated at Posted at 2025-10-25

はじめに

電子工作初学者向けの記事です。
マイコンを用いて電子工作していると、GPIOやADCが不足する場合もあると思います。
ピン数の多いマイコンを使ったり、拡張IOポートを用いる解決方法もありますが、今回はマルチプレクサ(複数の信号を1本の出力線に切り替えて送るための技術)を紹介します。

背景

光センサを18個使いたいです。光の強さはアナログの電圧を計測することで計測できるので、マイコンのADC機能を用います。

ここで問題が発生しますが、今回使用するESP32はADCが18回路(ADC1:8回路/ADC2:10回路)あるものの、WiFi機能を用いるとADC2は使用不可となります。つまり、使用できるADCは8回路となり単純に考えれば光センサ18個の読み込みができません。

今回はマルチプレクサと呼ばれる、回路とソフトウェアの工夫により、少ないADCで多くのアナログ入力を実現する方法を紹介します。

手法概要

1つのADCに対して、複数の光センサを接続します。このまま普通に使ってしまうと、複数の光センサが競合してしまいますが、光センサのON/OFFも制御してあげます。

以下の回路図を見ると分かりやすいですが、ADCに接続されている光センサを1つだけONにして値を読み込み、読み込み終わったら次の光センサのみONにして値を読み込む、という手順を繰り返します。

回路図

光センサは6本*3セットで扱います。
各セットのONはトランジスタによって制御します(27, 14, 12ピンをLOWにすることで、光センサがONになる)。なお、2SA1015は記事投稿現在、手に入るものの生産終了です。購入できない場合は互換品を用いてください。
光センサは明るさによって電流を制御するため、10kΩの抵抗にかかる電圧を6本のADCで読み込むことで、明るさを取得します。

img20250513_18335523.jpg
トランジスタのベース抵抗値は、増幅が飽和するように設計されています。本記事ではトランジスタ周りの回路を紹介しませんので、もし分からない場合はWebで検索してください。

ソースコード

コメント入れています。
シリアル通信初期化やトランジスタ安定待ちでdelayを入れていますが、動作確認程度のつもりのため長めにしています。実際はもっと短くしても大丈夫だと思いますので、ここは現物合わせしてください。

以下のコードでは、シリアル通信で18個分の光センサの値が確認できます。

#include <Arduino.h>

// --- 配線(ESP32例) ---
// 6本のADC入力(列)
const int sensor_pin[6]     = { 34, 35, 32, 33, 25, 26 };
// 3本の選択線(行の切替)※LOWで選択、非選択はHIGH
const int sensor_ctl_pin[3] = { 27, 14, 12 };

// 18個の読み取り値(3行×6列)
int sensor_value[3][6];

void setup() {
  Serial.begin(115200);
  delay(300);

  // 選択線は出力(非選択=HIGHで初期化)
  for (int i = 0; i < 3; ++i) {
    pinMode(sensor_ctl_pin[i], OUTPUT);
    digitalWrite(sensor_ctl_pin[i], HIGH);
  }

  // ADCピンは入力
  for (int j = 0; j < 6; ++j) {
    pinMode(sensor_pin[j], INPUT);
  }
}

void loop() {
  // 3行を順番に選択して6列を読む → 合計18点
  for (int row = 0; row < 3; ++row) {
    // 行を選択(アクティブLOW)
    digitalWrite(sensor_ctl_pin[row], LOW);
    delay(3); // トランジスタの安定待ち(環境に応じて調整)

    for (int col = 0; col < 6; ++col) {
      sensor_value[row][col] = analogRead(sensor_pin[col]);
    }

    // 行の選択解除
    digitalWrite(sensor_ctl_pin[row], HIGH);
  }

  // --- シリアル出力(CSV:18個の値+改行)---
  // 順序:row0 col0..5, row1 col0..5, row2 col0..5
  for (int row = 0; row < 3; ++row) {
    for (int col = 0; col < 6; ++col) {
      Serial.print(sensor_value[row][col]);
      if (!(row == 2 && col == 5)) Serial.print(",");
    }
  }
  Serial.println();

  // サンプリング周期
  delay(25);
}

出力例は以下の通りです

123,456,789,234,567,890,111,222,333,444,555,666,777,888,999,1010,1111,1212
124,457,780,235,568,891,112,223,334,445,556,667,778,889,990,1011,1112,1213
...

おわりに

少ないIOピンで多くのセンサを制御する方法を紹介しました。
ソースコードを見ると分かりますが、センサを順番にONし読み込んでいるため、マルチプレクサを使用しない場合に比べて処理時間が長くなります。
一長一短ですので、作りたいシステムに応じて使用する技術を選択してみてください。

なお、本記事ではトランジスタによるマルチプレクサを実装しましたが、専用ICもあります。専用ICを用いると配線が楽になるため、こちらも制御したいセンサの数などに応じて、用途に合った手法を採用してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?