「暗くなったら自動でライトが点く仕組み、自分で作れたら面白そう…」そう思ったことはありませんか?😊

実はArduinoと光センサー(CdSセル)を組み合わせるだけで、市販の常夜灯と同じ「明るさ連動の自動点灯ライト」が自作できます。しかも回路の仕組みをきちんと理解しながら作れるのが、電子工作の醍醐味です。

この記事では、光センサーの分圧回路の仕組みから、analogReadのしきい値キャリブレーション手順、シリアルモニタを使ったデバッグ、そして「暗くなったら点灯する常夜灯」の完成例まで、ひとつひとつ丁寧に解説します。

※ LEDの基本的な点滅(Lチカ)やPWM制御については、以下の記事で詳しく扱っています。本記事では光センサーの活用に特化して深掘りしていきます。


🔧 この記事の対象読者・難易度

Arduino light sensor circuit breadboard
Arduino light sensor circuit breadboard / Photo by Chengxin Zhao via Pexels
  • ✅ Arduinoで光センサーを使ってみたい方
  • ✅ 分圧回路の仕組みをちゃんと理解したい方
  • ✅ センサーのしきい値調整でつまずいている方
  • ✅ シリアルモニタを使ったデバッグに慣れたい方

難易度:★★☆☆☆(初級〜初中級)
LEDのLチカ程度の経験があればスムーズに進められます。


📦 用意するもの

  • Arduino Uno(またはArduino互換ボード)
  • 光センサー(フォトレジスタ / CdSセル)× 1
  • 抵抗 10kΩ × 1(分圧回路用)
  • LED(色は好みで)× 1
  • 抵抗 220Ω〜330Ω × 1(LED保護用)
  • ジャンパーワイヤー(数本)
  • ブレッドボード
  • USBケーブル(Type-B)
  • PC(Arduino IDEをインストール済み)

💡 光センサー(CdSセル)とは?仕組みをざっくり理解しよう

光センサー(フォトレジスタ、またはCdS=硫化カドミウムセル)は、光の量によって電気抵抗が変化する部品です。

  • ☀️ 明るいとき:抵抗が小さくなる(数百Ω〜数kΩ程度)
  • 🌙 暗いとき:抵抗が大きくなる(数十kΩ〜数百kΩ程度)

つまり「光の強さを抵抗値という電気的な量に変換してくれる」センサーです。Arduinoはこの抵抗値の変化を電圧の変化として読み取ることで、明るさを数値として把握できます。

なぜ10kΩの抵抗とセットで使うの?→ 分圧回路の仕組み

光センサー単体をArduinoにつないでも、残念ながら「明るさ」は読み取れません。抵抗値の変化を電圧の変化に変換する回路が必要で、これを分圧回路(ボルテージディバイダ)と呼びます。

回路のイメージはこうです:

5V ──── [CdSセル] ──── A0(Arduinoのアナログピン)
                          |
                       [10kΩ抵抗]
                          |
                         GND

5VとGNDの間に「CdSセルの抵抗」と「10kΩの固定抵抗」が直列に並んでいます。このとき、A0ピンにかかる電圧は次の式で求まります。

A0の電圧 = 5V × 10kΩ ÷ (CdSの抵抗 + 10kΩ)

たとえば……

  • 🌞 明るいとき(CdS抵抗 ≒ 1kΩ):5V × 10 ÷ (1+10) ≒ 4.5V → 高い電圧
  • 🌙 暗いとき(CdS抵抗 ≒ 100kΩ):5V × 10 ÷ (100+10) ≒ 0.45V → 低い電圧

このように光の量が「A0にかかる電圧」として現れるようになります。ArduinoのanalogRead()はこの電圧を0〜1023の整数値に変換して読み取ります(5V → 1023、0V → 0)。

⚠️ 10kΩ抵抗はCdSセルと同じオーダーの抵抗値を選ぶのがポイントです。抵抗が小さすぎると暗い場合の変化が読み取りにくくなり、大きすぎると明るい場合の変化が潰れてしまいます。一般的なCdSセルには10kΩがよく合います。


🔌 回路のつなぎ方

ブレッドボード上に以下のように接続してください。

光センサー(分圧回路)部分

  1. CdSセルの片方の足を 5Vピン に接続
  2. もう一方の足を アナログピンA0 に接続
  3. 同じA0の接続点から 10kΩ抵抗 を通して GND に接続

LED部分

  1. LEDの長い足(アノード)を 220Ω抵抗 を通して デジタルピン9番 に接続
  2. LEDの短い足(カソード)を GND に接続

⚠️ LEDの保護抵抗(220Ω)は必ず入れてください。省略するとLEDが壊れます。


📟 まずシリアルモニタでセンサー値を確認しよう


いきなりLEDを制御するのではなく、まずセンサーがどんな値を返しているか確認するのが成功への近道です。シリアルモニタはArduino内蔵のデバッグツールで、センサー値をリアルタイムにPC画面で確認できます。

// センサー値確認スケッチ:シリアルモニタで光センサーの値を見る

void setup() {
  Serial.begin(9600); // シリアル通信を9600bpsで開始
}

void loop() {
  int sensorValue = analogRead(A0); // センサーの値を読む(0〜1023)

  Serial.print("センサー値: ");
  Serial.println(sensorValue);      // 値を改行付きで出力

  delay(200); // 0.2秒ごとに更新
}

このスケッチをArduinoに書き込んだら、Arduino IDE上部の虫眼鏡アイコン(または「ツール」メニュー)からシリアルモニタを開いてください。ボーレートを9600に合わせることを忘れずに。

センサーの上に手をかざして暗くしたり、明るい場所にかざしたりしながら数値の変化を観察しましょう。たとえばこんな結果が得られるはずです 👇

  • 室内の蛍光灯下:センサー値 650〜750 前後
  • センサーを指で覆う(擬似的な暗闇):センサー値 100〜250 前後
  • スマホのライトを直当て:センサー値 900〜1023 前後

※ 値は使用するCdSセルの個体差や室内環境によって大きく異なります。この観察が次のキャリブレーション作業の根拠になります。


🎛️ しきい値のキャリブレーション手順

「暗くなったらLEDを点灯する」には、「どの値以下になったら暗いとみなすか」のしきい値(threshold)を決める必要があります。これはコピペした数値で済む話ではなく、実際の環境に合わせたキャリブレーションが必要です。

キャリブレーションの手順

ステップ1:「点灯させたい暗さ」の値を記録する

先ほどのシリアルモニタ確認スケッチを使って、「ここより暗くなったらLEDを点けたい」と思う状況(たとえば部屋の電気を消した状態、夕暮れを模した状態など)でのセンサー値を記録します。

ステップ2:「消灯していてほしい明るさ」の値を記録する

次に「昼間の明るい状態でLEDは消えていてほしい」状況のセンサー値を記録します。

ステップ3:しきい値を2つの値の中間に設定する

たとえば、暗い状態が値200、明るい状態が値700であれば、しきい値は中間の400〜450あたりが妥当です。誤検知を防ぐため、両端の値からある程度余裕を持たせるのがコツです。

チャタリング(誤作動)を防ぐヒステリシスの考え方

しきい値をひとつだけ設定すると、センサー値がしきい値付近でわずかに揺れるたびにLEDがON/OFFを繰り返してしまいます(チャタリング)。これを防ぐためにヒステリシス(上限と下限を別々に設定する)という考え方を使います。

// ヒステリシスを使ったしきい値設定の例
// 点灯開始:センサー値が 350 以下になったら
// 消灯開始:センサー値が 500 以上になったら

#define THRESHOLD_ON  350  // この値以下になったらLED点灯
#define THRESHOLD_OFF 500  // この値以上になったらLED消灯

ON/OFFの境界に「幅」を持たせることで、センサー値が少々ばらついても安定した動作が実現できます。


🌙 完成形:暗くなったら点灯する常夜灯スケッチ

キャリブレーションで決めたしきい値を組み込んだ、常夜灯の完成スケッチです。シリアルモニタへの出力も残してあるので、動作確認しながら使えます。

// 自動点灯ライト完成版:暗くなったらLEDが光る常夜灯
// ヒステリシス付きで誤作動を防止

const int SENSOR_PIN   = A0;  // 光センサー(CdSセル)のアナログピン
const int LED_PIN      = 9;   // LEDのデジタルピン

// ★ 自分の環境に合わせてこの値を調整してください
const int THRESHOLD_ON  = 350; // この値以下になったらLED点灯
const int THRESHOLD_OFF = 500; // この値以上になったらLED消灯

bool ledState = false; // 現在のLEDの状態(false=消灯)

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
  Serial.println("=== 自動点灯ライト 起動 ===");
}

void loop() {
  int sensorValue = analogRead(SENSOR_PIN);

  // シリアルモニタでリアルタイム確認
  Serial.print("センサー値: ");
  Serial.print(sensorValue);
  Serial.print("  LED: ");
  Serial.println(ledState ? "点灯" : "消灯");

  // ヒステリシスを使った点灯・消灯判定
  if (!ledState && sensorValue <= THRESHOLD_ON) {
    // 現在消灯中 かつ しきい値以下になった → 点灯
    ledState = true;
    digitalWrite(LED_PIN, HIGH);
    Serial.println(">> 暗くなりました。LED点灯!");

  } else if (ledState && sensorValue >= THRESHOLD_OFF) {
    // 現在点灯中 かつ しきい値以上になった → 消灯
    ledState = false;
    digitalWrite(LED_PIN, LOW);
    Serial.println(">> 明るくなりました。LED消灯。");
  }

  delay(100); // 0.1秒ごとにセンサーを読む
}

コードのポイント解説

  • const int THRESHOLD_ON = 350:点灯開始のしきい値。自分の環境に合わせて変更してください
  • const int THRESHOLD_OFF = 500:消灯開始のしきい値。ONより高めに設定することでヒステリシスを実現
  • bool ledState:現在のLED状態を記憶する変数。「今点いているかどうか」を管理することで不要なdigitalWrite呼び出しを防ぎます
  • !ledState && sensorValue <= THRESHOLD_ON:消灯中にしきい値以下になったときだけ点灯処理を実行
  • ledState && sensorValue >= THRESHOLD_OFF:点灯中にしきい値以上になったときだけ消灯処理を実行

🔍 シリアルモニタを使ったデバッグの実践

「スケッチを書き込んだのにLEDが思うように動かない」……そんなときに頼りになるのがシリアルモニタです。上記の完成スケッチを書き込んだ状態でシリアルモニタを開くと、こんなログが流れるはずです。

=== 自動点灯ライト 起動 ===
センサー値: 712  LED: 消灯
センサー値: 698  LED: 消灯
センサー値: 421  LED: 消灯
センサー値: 312  LED: 消灯
>> 暗くなりました。LED点灯!
センサー値: 289  LED: 点灯
センサー値: 305  LED: 点灯
センサー値: 534  LED: 点灯
>> 明るくなりました。LED消灯。
センサー値: 650  LED: 消灯

よくあるトラブルと確認ポイント

❌ センサー値がずっと0か1023のまま変化しない

→ 分圧回路の接続を確認してください。CdSセルと10kΩ抵抗が直列に正しく接続されているか、A0ピンに中間点が接続されているかを見直しましょう。

❌ LEDがON/OFFを高速で繰り返す

THRESHOLD_ONTHRESHOLD_OFFの差が小さすぎます。差を150〜200程度に広げてみてください。

❌ 暗くしてもLEDが点灯しない

→ シリアルモニタで暗い状態の実際の値を確認し、THRESHOLD_ONをその値より高く設定し直してください。

❌ シリアルモニタに文字化けした文字が出る

→ シリアルモニタ右下のボーレート設定が9600になっているか確認してください。スケッチのSerial.begin(9600)と一致させる必要があります。


🚀 発展:センサー値に比例してLEDの明るさを変える


「暗いほどLEDを明るく光らせる」という、より自然な常夜灯の動作にしてみましょう。map()関数を使うとセンサー値の範囲をPWMの範囲に変換できます。

※ PWM(analogWrite)自体の基礎は「Arduino入門|電子工作初心者が最初に作るべきLEDプロジェクト5選」で詳しく解説しています。ここではセンサー値と連動させる部分に絞って説明します。

// 発展版:センサー値に応じてLEDの明るさを変える(PWMピン使用)

const int SENSOR_PIN = A0;
const int LED_PIN    = 9;  // PWM対応ピン(~マーク付き)

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(SENSOR_PIN); // 0〜1023

  // センサー値が低い(暗い)ほどLEDを明るく(255に近く)する
  // map(値, 入力最小, 入力最大, 出力最小, 出力最大)
  int brightness = map(sensorValue, 0, 1023, 255, 0);
  brightness = constrain(brightness, 0, 255); // 0〜255に収める

  analogWrite(LED_PIN, brightness);

  Serial.print("センサー値: ");
  Serial.print(sensorValue);
  Serial.print("  明るさ(PWM): ");
  Serial.println(brightness);

  delay(50);
}
  • map(sensorValue, 0, 1023, 255, 0):入力が0のとき出力255、入力が1023のとき出力0になるよう線形変換します
  • constrain(brightness, 0, 255):変換後の値を必ず0〜255の範囲に収めるための安全措置です

手でセンサーを覆うほどLEDがじわっと明るくなる……まるで本物の常夜灯みたいな動作が確認できるはずです。✨


📝 まとめ

この記事では、Arduinoと光センサー(CdSセル)を使った自動点灯ライトの制作を通じて、以下のことを学びました。

  • 分圧回路の仕組み:CdSセルと10kΩ抵抗を直列につなぐことで、抵抗値の変化を電圧の変化に変換できる
  • シリアルモニタを使ったセンサー値の観察:まず数値の挙動を確認することがキャリブレーションの第一歩
  • しきい値のキャリブレーション手順:環境ごとに「暗い状態の値」と「明るい状態の値」を実測して中間に設定する
  • ヒステリシスによる安定動作:ON/OFFのしきい値に幅を持たせてチャタリングを防ぐ
  • 発展:map()関数でPWM制御:明るさに連動してLEDの輝度を変化させる

「センサーの値を読んで、条件を判定して、出力を制御する」——この流れはArduino電子工作のあらゆる応用に共通する基本パターンです。光センサーで会得したこの感覚を、温度センサーや距離センサーにもぜひ応用してみてください。🎉

Lチカや電子工作キットの最初の一歩については、こちらの記事も参考にどうぞ。

📡 Arduinoをもっと深く学ぼう!

Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。

Arduinoロボット入門のおすすめコース・部品を見る →

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る

Arduinoをはじめよう 第4版 (Make: PROJECTS)

もしも

Arduinoをはじめよう 第4版 (Make: PROJECTS)

Arduino公式推薦の定番入門書

Amazonで見る

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

もしも

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

電子工作とプログラミングを同時に学べる

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。