【ラズパイ電子工作】周囲の明るさに応じて赤色バーLEDを点灯させる方法(SPI通信)

00_【ラズパイ電子工作】周囲の明るさに応じて赤色バーLEDを点灯させる方法(SPI通信)

光センサ(CdSセル)とは、硫化カドミウムを用いた光導電素子です。入射光に対して内部抵抗値が変化する性質を用いて明るさを計ることができます。

ラズベリーパイのGPIOは明るさ等のアナログ(A)信号を直接読み取ることはできません。光センサ(CdSセル)はADコンバータに接続して、ADコンバータとラズベリーパイをSPI通信等で接続することにより光センサから明るさを読み取ることができます。

この記事では、ラズベリーパイのプログラム(Python)から光センサ(CdSセル)で周囲の明るさを測定して赤色バーLEDの点灯する数を制御する方法を解説します。

注意
この記事中に記載されている内容はソースコード含めて電気設計人が自己流で行ったものです。一般的な方法とは相違がある可能性がありますので予めご了承ください。

光センサ(CdSセル)を用いて明るさを読み取る方法は以下のページで解説しておりますので、宜しければご覧ください。

RPD026【ラズパイ電子工作】光センサで明るさを読み取る方法(CdSセル)【ラズパイ電子工作】光センサで明るさを読み取る方法(CdSセル)

赤色バーLEDを制御する方法は以下のページで解説しております。

RPD028【ラズパイ電子工作】赤色バーLEDを点灯させる方法(OSX10201-R)【ラズパイ電子工作】赤色バーLEDを点灯させる方法(OSX10201-R) RPD033【ラズパイ電子工作】ボリュームに応じて赤色バーLEDを点灯させる方法(SPI通信)【ラズパイ電子工作】ボリュームに応じて赤色バーLEDを点灯させる方法(SPI通信) RPD036【ラズパイ電子工作】超音波センサで距離を測定して赤色バーLEDを点灯させる方法【ラズパイ電子工作】超音波センサで距離を測定して赤色バーLEDを点灯させる方法

1. 完成イメージ(明るさに応じて赤色バーLEDを制御する)

この記事で完成するものは以下のようになります。

10_完成イメージ

周囲を暗くした状態で、光センサ(CdSセル)にライトを当てます。

光センサ(CdSセル)は入射光に応じて内部抵抗値が変化する性質を用いて、ADコンバータに接続します。

ADコンバータは電圧をアナログ値として読み取り、SPI通信でラズパイと接続します。

  1. 光センサ(CdSセル)の状態をADコンバータで読み取る
  2. ADコンバータの値をSPI通信を用いてラズパイに取込む
  3. 読み取った値を元に赤色バーLEDを点灯する

2. 使用する部品

今回使用する部品は以下の通りです。

ラズベリーパイ本体(モデル3B+)

20_ラズベリーパイ3B+

『Raspberry Pi 3 Model B+』を使用します。※2020年8月時点で最新はRaspberry Pi 4になります。

ブレッドボード

20_ブレッドボート

LEDや抵抗といった各種部品や(後述する)ジャンパ線などを穴に差し込み、部品間を電気的に接続する板(ボード)です。

電子工作をする上で必須の部品です。

ジャンパ線

20_ジャンパ線

ブレッドボートに差し込み、電子部品の間を電気的に接続します。

↑の写真では両側が「ピン」になっており、ブレッドボートの穴に差し込んで使用します。

赤色バーLED:OXS10201-R

赤色バーLED_OXS10201-R

今回は「バーLED」であるOXS10201-Rを使用します。赤色のLEDが10ヶ横一列に配列され、各LEDのアノード・カソードは独立しています。(コモンラインは無し)

外形図、内部配線は以下のようになります。

データシート_OXS10201-R
出典:OSX10201-Xシリーズデータシート

抵抗器

抵抗器

LEDなどの電子部品は適した電圧と電流値が決められており、既定の範囲を超えると壊れてしまう恐れがあります。

抵抗器は電流の流れを妨げ、電子部品に流れる電流を抑える役割を担います。

今回は220Ωと10kΩの抵抗器を使用します。

ADコンバータ:MCP3002

MCP3002

(小さくてすいません…)

今回はSPI通信に対応したADコンバータであるMCP3002を使用します。各ピンの機能は以下のようになります。

MCP3002データシート
出典:MCP3002データシート
1:CS/SHDN:チップセレクト
2:CH0:チャンネル0 アナログ入力
3:CH1:チャンネル1 アナログ入力
4:Vss:GND
5:Din:シリアルデータ入力
6:Dout:シリアルデータ出力
7:CLK:シリアルクロック
8:Vdd/Vref:電源(+2.7V~5.5V)

光センサ(CdSセル)

光センサ(CdSセル)

今回はCdSセルGL5528を使用します。GL5528は入射光に対して内部抵抗値が変化します。

GL5528の主な仕様は以下の通りです。

外形寸法:直径5.1mm
ピーク波長:540nm
最大電圧:150VDC
最大電力:100mW
明抵抗:10k~20kΩ(10Lux時)
暗抵抗:1MΩ

オススメの電子工作セット

電子工作をするため、これまで解説した部品の他にもスイッチやセンサなど、色々な部品が必要になってきます。個々で購入するには手間がかかるため、最初はセット品を購入することをおススメします。

電気設計人
電気設計人

私は以下のセット品を購入しました!

注意
ADコンバータ:MCP3002はこのセット内には入っていませんので、別途購入が必要です。

また、これからラズベリーパイを購入する場合、ラズベリーパイ本体を含めたセット品を購入することをおススメします。

ラズベリーパイ本体を収めるケースや、OSをインストールするためmicroSDカードなど必要なものを個々に購入する手間を省くことができます。

3. 回路図・配線の様子

ラズベリーパイのプログラム(Python)から光センサ(CdSセル)で周囲の明るさを測定して赤色バーLEDの点灯する数を制御する回路を解説します。

回路図

回路図は以下のようになります。

30_回路図

赤色バーLEDの各アノード(プラス側)にGPIOを個別に配線します。各LEDを左からA~Jとすると、各LEDとGPIOの関係は以下のように配線します。

LED区別GPIOジャンパ線色
LED_A(一番左側)GPIO 27番ポート白色
LED_BGPIO 22番ポート青色
LED_CGPIO 5番ポート黄色
LED_DGPIO 13番ポートオレンジ色
LED_EGPIO 26番ポート白色
LED_FGPIO 18番ポート青色
LED_GGPIO 23番ポート黄色
LED_HGPIO 24番ポートオレンジ色
LED_IGPIO 16番ポート白色
LED_J(一番右側)GPIO 21番ポート青色

各LEDのカソード(マイナス側)には抵抗器(220Ω)を介してGNDに接続します。(黒色のジャンパ線)

メモ
抵抗器に極性はありませんので、プラスとマイナスは気にしなくてOKです。

ラズベリーパイをADコンバータ(MCP3002)とSPI通信するため、以下のように接続します。

ラズベリーパイのピンMCP3002のピンジャンパ線
SPICS0CS/SHDN(1番ピン)白色
SPIMOSIDin(5番ピン)黄色
SPIMISODout(6番ピン)青色
SPISCLKCLK(7番ピン)白色

MCP3002とCdSセルを接続する必要があります。今回はMCP3002のCH0(2番ピン)とCdSセルの片側と10kΩの抵抗器に接続します。(青色のジャンパ線)

CdSセルのもう片側は3.3Vに接続します。(オレンジ色のジャンパ線)

最後に、10kΩの抵抗器の片側をGNDに接続します。(黒色のジャンパ線)

配線の様子

配線の様子です。こんな感じになりました。

31_配線の様子

光センサ(CdSセル)が見にくいですね…

31_配線の様子

オレンジ色の素子が光センサ(CdSセル)です。

↑では、フラットケーブルでGPIOの全ピンをブレッドボードに接続しています。回路図と実際の配線は異なる部分がありますがご了承ください。

※電気的には「回路図」と同じ意味です。

4. プログラム(Python)

光センサ(CdSセル)で周囲の明るさを測定して赤色バーLEDの点灯する数を制御するプログラム(Python)は以下のようになります。

ソースコード

#必要なモジュールをインポート
import RPi.GPIO as GPIO             #GPIO用のモジュールをインポート
import spidev                       #SPI通信用のモジュールをインポート
import time                         #時間制御用のモジュールをインポート
import sys                          #sysモジュールをインポート

#ポート番号の定義
Bar_led = [
    27, 22, 5, 13, 26, 18, 23, 24, 16, 21]   #変数"Bar_led"にリストを代入

#GPIOの設定
GPIO.setmode(GPIO.BCM)              #GPIOのモードを"GPIO.BCM"に設定
GPIO.setup(Bar_led, GPIO.OUT)       #GPIO(10ヶ)を出力モードに設定

#SPI通信を行うための準備
spi = spidev.SpiDev()               #インスタンスを生成
spi.open(0, 0)                      #CE0(24番ピン)を指定
spi.max_speed_hz = 1000000          #転送速度 1MHz

#数値からバーLEDを点灯させる関数
def barled_lighting(level):
    for i in range(0, level):               #点灯させるGPIO(左側)
        GPIO.output(Bar_led[i], GPIO.HIGH)  #GPIO点灯
    for i in range(level, 9):               #消灯させるGPIO(右側)
        j = i + 1
        GPIO.output(Bar_led[j], GPIO.LOW)   #GPIO消灯

#連続して値を読み込む
while True:
    try:
        resp = spi.xfer2([0x68, 0x00])                 #SPI通信で値を読み込む
        volume = ((resp[0] << 8) + resp[1]) & 0x3FF    #読み込んだ値を10ビットの数値に変換
        bright = volume / 1023 * 10                    #0~1023を0~10に変換
        print(int(bright))                             #変換した数値を表示
        barled_lighting(int(bright))                   #変換した数値を元にLEDを点灯
        time.sleep(0.1)                                #0.1秒間待つ

    except KeyboardInterrupt:
        #Ctrl+Cキーが押された
        GPIO.cleanup()              #GPIOをクリーンアップ
        spi.close()                 #SPI通信を終了
        sys.exit()                  #プログラム終了

SPI通信でADコンバータMCP3002の値を読み取り、赤色バーLEDに割り付けたGPIOを制御します。

プログラムの解説

#必要なモジュールをインポート
import RPi.GPIO as GPIO             #GPIO用のモジュールをインポート
import spidev                       #SPI通信用のモジュールをインポート
import time                         #時間制御用のモジュールをインポート
import sys                          #sysモジュールをインポート

2~5行目で今回必要な「モジュール」を宣言します。


#ポート番号の定義
Bar_led = [
    27, 22, 5, 13, 26, 18, 23, 24, 16, 21]   #変数"Bar_led"にリストを代入

変数”Bar_led”に27,22,5,13,26,18,23,24,16,21を代入します。この数値はGPIOのポート番号として扱い、後からポート番号を変更する場合はこの数値を変更します。


#GPIOの設定
GPIO.setmode(GPIO.BCM)              #GPIOのモードを"GPIO.BCM"に設定
GPIO.setup(Bar_led, GPIO.OUT)       #GPIO(10ヶ)を出力モードに設定

GPIOの設定を行います。

GPIO.setmode(GPIO.BCM)は、GPIOをポート番号で扱う方法に設定します。

GPIO.setup(Bar_led, GPIO.OUT)は、GPIO 10ヶを出力モードに設定します。


#SPI通信を行うための準備
spi = spidev.SpiDev()               #インスタンスを生成
spi.open(0, 0)                      #CE0(24番ピン)を指定
spi.max_speed_hz = 1000000          #転送速度 1MHz

SPI通信をする準備をします。SpiDev()メソッドはspiという名称でSPI通信をできるようにします。

spi.open(0, 0)は、CE0(24番ピン)に接続したデバイスと通信を開始します。仮にCE1(26番ピン)に接続したデバイスと通信する場合はspi.open(0, 1)と記述します。※今回はCE0(24番ピン)に接続します。


#数値からバーLEDを点灯させる関数
def barled_lighting(level):
    for i in range(0, level):               #点灯させるGPIO(左側)
        GPIO.output(Bar_led[i], GPIO.HIGH)  #GPIO点灯
    for i in range(level, 9):               #消灯させるGPIO(右側)
        j = i + 1
        GPIO.output(Bar_led[j], GPIO.LOW)   #GPIO消灯

関数barled_lighting(level)は、引数levelの数値を元に赤色バーLEDの点灯する数を制御します。

例えば、変数levelの値が4の場合、for文を用いてリストBar_ledの添え字(インデックス)が0~4となります。

リストBar_ledの0~4の要素は27,22,5,13,26のため、GPIO.output(Bar_led[i], GPIO.HIGH)にてGPIO 27,22,5,13,26番ポートの電圧をHigh(3.3V)にします。これらのGPIOは赤色バーLEDの左側から接続されており、High(3.3V)になったLEDはここで点灯します。

GPIO.output(Bar_led[j], GPIO.LOW)は、赤色バーLEDの残り(右側)のGPIOの電圧をLow(0V)にします。


#連続して値を読み込む
while True:
    try:
        resp = spi.xfer2([0x68, 0x00])                 #SPI通信で値を読み込む
        volume = ((resp[0] << 8) + resp[1]) & 0x3FF    #読み込んだ値を10ビットの数値に変換
        bright = volume / 1023 * 10                    #0~1023を0~10に変換
        print(int(bright))                             #変換した数値を表示
        barled_lighting(int(bright))                   #変換した数値を元にLEDを点灯
        time.sleep(0.1)                                #0.1秒間待つ

    except KeyboardInterrupt:
        #Ctrl+Cキーが押された
        GPIO.cleanup()              #GPIOをクリーンアップ
        spi.close()                 #SPI通信を終了
        sys.exit()                  #プログラム終了

「while文」は条件を指定して、その条件が真の時に繰り返し処理を行うものです。

Python
while 条件式:
    繰り返し処理を行うコード

↑の「条件式」にTrueを指定することにより、条件式は常に真となりwhile文は無限に繰り返します。

メモ
無限に繰り返すことを、無限ループと表現したりします。

ただし、このままではプログラム実行中に無限ループから抜け出す方法がありません。そこでwhile文の中にある「try文」と「except文」を使用します。

このtry-except文を用いることにより、while文の処理は以下のようになります。

Python
while True:
    try:
        繰り返し処理を行うコード
    except KeyboardInterrupt:               #Ctrl+cキーが押された
        GPIO.cleanup()                      #GPIOをクリーンアップ
        spi.close()                         #SPI通信を終了
        sys.exit()                          #プログラム終了

except KeyboardInterrupt:は、キーボードのCtrl + cキーが押された時にwhile文の繰り返し処理から抜けて上記のプログラム終了の処理を行います。

Ctrl + cキーが押されていないとき、try:文の中の処理を繰り返し行います。(以下で解説)


while文の中の「繰り返し処理を行うコード」は以下の通りです。つまり、Ctrl + cキーが押されるまで以下の処理を繰り返します。

    resp = spi.xfer2([0x68, 0x00])                 #SPI通信で値を読み込む
    volume = ((resp[0] << 8) + resp[1]) & 0x3FF    #読み込んだ値を10ビットの数値に変換
    bright = volume / 1023 * 10                    #0~1023を0~10に変換
    print(int(bright))                             #変換した数値を表示
    barled_lighting(int(bright))                   #変換した数値を元にLEDを点灯
    time.sleep(0.1)                                #0.1秒間待つ

spi.xfer2([0x68, 0x00])は、ADコンバータMCP3002のCH0(チャンネル0 アナログ入力)のアナログ値を取得します。

MCP3002から取得したデータはresp[0]resp[1]の2バイトに分かれるため、シフト演算子を用いて変数”volume”にまとめます。

変数”volume”には0~1023の数値が格納されます。今回、赤色バーLEDの数は10ヶのため、bright = volume / 1023 * 10で0~10に変換します。

barled_lighting(int(bright))は、変数”bright”を整数型に変換して21~26行目の関数に渡します。

time.sleep(0.1)は何もせずに0.1秒間待ちます。

5. おわりに

ラズベリーパイのプログラム(Python)から光センサ(CdSセル)で周囲の明るさを測定して赤色バーLEDの点灯する数を制御する方法を解説しました。

まだまだラズベリーパイ初心者の私ですが、以下の参考書が大変参考にさせて頂いております。

2冊とも初学者にも易しい内容になっており、ゼロからラズベリーパイを始める方にもオススメできる参考書です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です