Arduino Uno R4 WiFiとフォトレジスタを使って簡易日照量計を作ってみた

屋外や窓際の明るさをざっくり把握したい時、まず試しやすいのが Photoresistor (フォトレジスタ / CdSセル)を使った方法です。今回も、「エレクトロニクスを簡単に」をテーマとしてArduino Uno R4 WiFiPhotoresistor を使って、現在の明るさと合計の日照量を表示する簡易システムを作ってみました。

今回の構成はシンプルで、Photoresistorを電圧分圧回路としてつなぎ、Arduinoのアナログ入力で値を読みます。その値をLCDに表示しつつ、時間方向に積算して、どれだけ明るい状態が続いたかも見えるようにしました。

なお、今回の合計の日照量は、厳密なlux (ルクス) 積算ではなく、相対的な明るさを累積した簡易スコアです。まずはPoCとして、明るさの変化と累積傾向を見える化することを主眼にしています。

目次

はじめに: 現在値だけでなく累積も見たい

日照量や明るさを測る時、瞬間的な値だけ見ても、その場の様子は分かります。ただ、実際には「今日どれだけ明るい時間があったか」「窓際と室内でどのくらい差が出るか」のように、時間を通した積み上がりも気になることがあります。

そこで今回は、Photoresistorで読み取った明るさをそのまま表示するだけでなく、一定間隔ごとに加算して累積値を作るようにしました。こうすることで、たとえば「午前中はよく日が当たっていた」「今日は全体的に暗かった」といった傾向も分かりやすくなります。

ただし、今回の累積値は照度計のような物理量ではなく、相対的な明るさスコアの合計です。そのため、まずは簡易日照量メーターとして使うイメージです。

ローカル計測の基本構成

まずは基本となる、Photoresistorの抵抗変化をArduinoで読み取り、LCDに現在の明るさと累積値を表示するシステムを構築しました。

今回の構成では、Photoresistor単体ではなく、10KΩ抵抗と組み合わせた電圧分圧回路にしています。Arduinoのアナログ入力は「電圧」を読むため、抵抗値の変化をそのまま読むのではなく、明るさに応じて変わる電圧へ変換してA0へ入力する、という考え方です。SparkFun Learn

表示にはI2C接続のLCD 1602を使い、配線本数を少なくしつつ、現在値と累積値をその場で見られるようにしました。

使用した主な部品

・Arduino Uno R4 WiFi
・Photoresistor
・10KΩ抵抗
・I2C LCD 1602
・ブレッドボード
・ジャンパーピン
・Type-C USBケーブル

Arduino Uno R4 WiFiの特徴

マイコンには Arduino Uno R4 WiFiを使用しました。公式ドキュメントによると、このボードは Renesas RA4M1 (48MHz動作のArm Cortex-M4) を採用し、256KB Flash、32KB SRAMを備えています。また、ESP32-S3 により Wi-Fi / Bluetooth 接続にも対応しています。小さなセンサー読み取りPoCから、あとでクラウド連携やダッシュボード化へ広げる用途とも相性が良い構成です。
Arduino Docs
今回のような日照量計測では、まずはA0でアナログ値を読むだけの小さな実験から始められますし、あとからWi-Fi経由でログを送ったり、複数地点を比較したりと発展させやすい点も扱いやすいところです。
Arduino Docs
RA4M1 -48MHz Arm Cortex-M4 と LCDコントローラおよびHMI用静電容量式タッチセンサ搭載 32 ビットマイクロコントローラ

ローカル計測イメージ

今回の仕組みでは、LCDに次のような情報を表示します。

1行目: 現在の明るさ
2行目: 累積した日照量スコア

たとえば、
Now: 68%
Sum: 12345pt
のような表示になります。

ここでの Sum は、毎秒ごとに現在の明るさ%を足し込んだ値です。
たとえば、100%の明るさが1秒続けば100ポイント、50%の明るさが1秒続けば50ポイント加算されるイメージです。

つまりこの累積値は、明るさ×時間を簡易的に表したものです。

開発環境と実装のポイント

開発環境には Visual Studio CodePlatformIO IDE を使用しました。PlatformIOでは、board = uno_r4_wifiplatform = renesas-raframework = arduino の設定で利用できます。PlatformIO

アナログ入力の考え方

Arduinoのアナログ入力では、入力された電圧をADC (アナログ-デジタル変換回路)で数値に変換します。Arduinoの基本的なアナログ入力の説明では、0V~5Vの入力電圧を0~1023の値として扱う例が紹介されています。つまり、A0に入る電圧が高いほど、読み取り値も大きくなります。Arduino Analog Read Serial

今回のPhotoresistor回路では、明るさに応じてA0に入る電圧が変わるため、その結果として0~1023の範囲で明るさの変化が数値化されるという流れです。Arduino Analog Read Serial

累積値の考え方

今回は、読み取った明るさを0~100%に変換し、それを1秒ごとに累積しています。
この方式にすると、実装がシンプルで、しかも「明るい時間が長いほど合計値が増える」という直感的な表示になります。

ただし、これはあくまで相対的な日照量スコアです。厳密な照度積算ではないので、観測条件をそろえて比較する用途に向いています。

実装上の注意

今回の構成はシンプルですが、そのままでは“ルクス”にはなりません。理由は、Photoresistorの個体差や周囲環境、角度、固定抵抗値の選び方によって値が変わるからです。そのため、まずは「明るさの傾向を見る」 目的で使い、必要であれば後から校正していくのが自然です。

また、LCDのI2Cアドレスは 0x27 を想定していますが、モジュールによっては 0x3F の場合もあります。その場合はコード中のアドレスを変更してください。

配線情報

今回は、Photoresistor + 10KΩ抵抗の分圧回路を作り、その中点をA0へ接続します。
LCDは I2C接続にしています。

配線表

モジュール

信号

接続先

補足

Photoresistor

片側

Arduino の5V

明るさで抵抗値が変わります。

Photoresistor

もう片側

ArduinoのA0

A0と分圧の中点を共有します。

10KΩ 抵抗

片側

ArduinoのA0

Photoresistorと同じ中点です。

10KΩ 抵抗

もう片側

ArduinoのGND

分圧回路の下側です。

I2C LCD 1602

SDA

Arduino Uno R4 WiFi のSDA

I2C通信用です。

I2C LCD 1602

SCL

Arduino Uno R4 WiFi のSCL

I2C通信用です。

I2C LCD 1602

VCC

Arduinoの5V

モジュール仕様に応じて給電します。

I2C LCD 1602

GND

ArduinoのGND

共通GNDです。

配線イメージを言葉で整理すると

Photoresistor まわりは、次のような分圧回路になります。

5V
 ↓
Photoresistor
 ↓
A0
 ↓
10KΩ 抵抗
 ↓
GND

このように、Photoresistor と 10KΩ抵抗を直列につなぎ、その間の電圧をA0で読む形です。SparkFunの入門例でも、Photoresistorの片側を5V、もう片側をA0、さらにA0から10KΩでGNDへ落とす配線が紹介されています。SparkFun Learn

LCD側は、SDASCL の2本でつなぐだけなので、比較的すっきり組めます。

実際のプログラム

今回のローカル計測版で使用したプログラムは以下の通りです。
Photoresistorの値をA0から読み取り、現在の明るさと累積日照量スコアをLCDへ表示します。
※本プログラムは、生成AIを用いて作成しております。

cpp

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
const int lightPin = A0;

// 毎秒積算する
const unsigned long sampleIntervalMs = 1000;
unsigned long lastSampleTime = 0;

// 累積日照量スコア
unsigned long totalLightPoints = 0;

// 表示更新は少し細かめに
unsigned long lastDisplayTime = 0;
const unsigned long displayIntervalMs = 300;

int lastPercent = 0;
int lastRaw = 0;

void setup() {
  Serial.begin(115200);
  analogReadResolution(10);
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Light Meter");
  lcd.setCursor(0, 1);
  lcd.print("Starting...");
  delay(1000);
  lcd.clear();
  Serial.println("Photoresistor light measurement started.");
}

void loop() {
  unsigned long now = millis();
  
  // 現在の値を読む
  lastRaw = analogRead(lightPin);
  
  // 0~1023
  lastPercent = map(lastRaw, 0, 1023, 0, 100); // 0~100%
  
  // 1秒ごとに累積
  if (now - lastSampleTime >= sampleIntervalMs) {
    totalLightPoints += lastPercent;
    lastSampleTime = now;
    Serial.print("Raw: ");
    Serial.print(lastRaw);
    Serial.print(" / 1023");
    Serial.print(" | Now: ");
    Serial.print(lastPercent);
    Serial.print("%");
    Serial.print(" Sum: ");
    Serial.print(totalLightPoints);
    Serial.println(" pt");
  }
  
  // LCD更新
  if (now - lastDisplayTime >= displayIntervalMs) {
    lcd.setCursor(0, 0);
    lcd.print("Now: ");
    lcd.print(lastPercent);
    lcd.print("%   ");
    lcd.setCursor(0, 1);
    lcd.print("Sum: ");
    lcd.print(totalLightPoints);
    lcd.print("pt   ");
    lastDisplayTime = now;
  }
}

ini

[env:uno_r4_wifi]
platform = renesas-ra
board = uno_r4_wifi
framework = arduino
monitor_speed = 115200
lib_deps =
  marcoschwartz/LiquidCrystal_I2C

プログラムのポイント

analogRead(A0) で、Photoresistorの分圧回路から得られた電圧を読み取っています。
・Arduinoの基本的なアナログ入力の説明では、0V~5Vが0~1023の範囲へ変換される例が使われています。今回はこの考え方に合わせて、10bit前提で扱っています。ArduinoAnalog Read Serial
map() を使って、読み取り値を0~100%に見やすく変換しています。
totalLightPoints は、1秒ごとに現在の%値を足し込むことで累積しています。
・つまり、今回の Sum相対的な累積日照量であり、ポイント (pt) として扱っています。
・LCDの1行目に現在値、2行目に累積値を表示することで、今の明るさこれまでの積み上がりを同時に確認できます。

動作確認

プログラムを書き込んだら、LCD表示を見ながら値の変化を確認します。

たとえば、
・Photoresistorを手で覆う
・室内照明の下に置く
・窓際に近づける
・スマホのライトを当てる

といった操作をすると、1行目の Now が変化します。
そして、明るい状態が続くほど2行目Sum が速く増えていきます。

この累積値を見ることで、単なる瞬間値だけでなく、時間を通した明るさの違いも分かりやすくなります。

発展編:ログ保存や可視化への拡張

LCDでその場の値を見るだけでもPoCとしては十分ですが、実際に使うなら 「今見る」から「あとで振り返る」に広げたくなります。

Arduino Uno R4 WiFiESP32-S3を搭載しており、Wi-Fi / Bluetooth に対応しています。そのため、今回のような日照量データを起点にして、一定間隔で値を送信する、クラウドへ記録する、Webダッシュボードでグラフ化するといった拡張がしやすい構成です。Arduino Docs

例えば、以下のような使い方が考えられます。

・窓際の日照変化を1日記録する
・室内照明の明るさ変動を確認する
・植物の設置場所の明るさ比較をする
・朝/昼/夕方の累積明るさ傾向を見る

今後の展望(改善案)

今回の試作は「相対的な明るさ」と「その累積」を見ることが主目的ですが、さらに改善するなら次のような方向があります。

しきい値調整
 今回は%表示をしていますが、環境によって暗い / 明るいの基準は変わるので、しきい値を調整すると使いやすくなります。
積算の単位改善
 今回は単純にポイント加算ですが、サンプリング周期を明示して %・秒 相当として扱ったり、時間換算表示を加えたりすると、より意味が分かりやすくなります。
平均化処理
 値が細かく揺れる場合は、複数回の平均を取ってから表示・積算すると安定します。
リセット機能追加
 ボタンを付けて累積値をリセットできるようにすると、1日ごとの比較などがしやすくなります。

関連技術・参考トピック

Photoresistorは、明るさで抵抗値が変化する受動部品であり、Arduinoのアナログ入力と組み合わせると、最小限の部品で光の変化を数値化できます。入門例では、10KΩ抵抗との分圧回路として使う構成が一般的です。SparkFun Learn

また、Arduinoのアナログ入力では、入力電圧をADCで数値に変換するという基本の流れを理解しておくと、Photoresistor以外のセンサーにも応用しやすくなります。ArduinoAnalog Read Serial

開発環境としての PlatformIO も、ボード設定やシリアルモニタをまとめて扱いやすく、PoCを整理しながら進めたい時に便利です。PlatformIO

無線という観点では、Renesasは近年Wi-Fi 6/ Bluetooth LE 対応MCU (RA6シリーズ) やコンボモジュール(RRQ61051) も展開しています。
今回の作例でそこまで踏み込んでいるわけではありませんが、IoT機器が「つながること」を前提に設計される流れの中で、より低消費電力・高機能な常時接続デバイスへ広げていく方向性を考える参考になります。
WiFi/BLE-MCU(RA6シリーズ)
WiFi/BLEモジュール(RRQ61051)

まとめ

今回は、Arduino Uno R4 WiFi PhotoresistorI2C LCD 1602 を使って、現在の明るさと簡易的な合計の日照量を表示する仕組みを作ってみました。

構成自体はとてもシンプルですが、
・Photoresistorの抵抗変化を使う
・10KΩ抵抗と組み合わせて分圧回路にする
・A0で電圧を読む
・LCDに現在値を表示する
・明るさを時間方向に積算して累積値も表示する

という流れを通して、明るさの瞬間値と傾向の両方を見える化できる題材になりました。

いきなり高機能な照度センサーへ進む前に、まずは明るさの変化と日照の積み上がりをArduinoで見るところから始めたい時に、ちょうどよいテーマだと思います。

参考リンク

Arduino UNO R4 WiFi 公式ドキュメント
PlatformIO: Arduino Uno R4 WiFi ポード情報
Arduino公式: Analog Read Serial
SparkFun Learn: Reading a Photoresistor
RA4M1-48MHz Arm Cortex-M4とLCDコントローラおよびHMI用静電容量式タッチセンサ搭載32ビットマイクロコントローラ | Renesas
WiFi/BLE-MCU (RA6シリーズ)
WiFi/BLEモジュール (RRQ61051)