光センサ(CdSセル)とは、硫化カドミウムを用いた光導電素子です。入射光に対して内部抵抗値が変化する性質を用いて明るさを計ることができます。
ラズベリーパイのGPIOは明るさ等のアナログ(A)信号を直接読み取ることはできません。光センサ(CdSセル)はADコンバータに接続して、ADコンバータとラズベリーパイをSPI通信等で接続することにより光センサから明るさを読み取ることができます。
この記事では、ラズベリーパイのプログラム(Python)から光センサ(CdSセル)を用いて明るさを読み取る方法を解説します。
今回はADコンバータとラズベリーパイをSPI通信を用いて接続します。SPI通信でADコンバータの値を読み取る方法は以下のページでも解説しておりますので、宜しければご覧ください。
【ラズパイ電子工作】SPI通信でADコンバータの値を読み取る方法(MCP3002)目次
1. 完成イメージ(明るさを読み取る)
この記事で完成するものは以下のようになります。
光センサ(CdSセル)から室内の明るさを読み取ります。光センサにライトを当てて明るさに変化を与えてみました。
※プログラム(Python)は後ほど解説します。
明るさを1秒間隔で読み取り、実行結果に表示させます。明るさは理論上1~1023が表示されます。光センサ(CdSセル)への入射光が多くなると数値が増大します。
2. 使用する部品
今回使用する部品は以下の通りです。
『Raspberry Pi 3 Model B+』を使用します。※2020年8月時点で最新はRaspberry Pi 4になります。
LEDや抵抗といった各種部品や(後述する)ジャンパ線などを穴に差し込み、部品間を電気的に接続する板(ボード)です。
電子工作をする上で必須の部品です。
ブレッドボートに差し込み、電子部品の間を電気的に接続します。
↑の写真では両側が「ピン」になっており、ブレッドボートの穴に差し込んで使用します。
(小さくてすいません…)
今回はSPI通信に対応したADコンバータである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セルGL5528を使用します。GL5528は入射光に対して内部抵抗値が変化します。
GL5528の主な仕様は以下の通りです。
外形寸法 | :直径5.1mm |
ピーク波長 | :540nm |
最大電圧 | :150VDC |
最大電力 | :100mW |
明抵抗 | :10k~20kΩ(10Lux時) |
暗抵抗 | :1MΩ |
LEDなどの電子部品は適した電圧と電流値が決められており、既定の範囲を超えると壊れてしまう恐れがあります。
抵抗器は電流の流れを妨げ、電子部品に流れる電流を抑える役割を担います。
今回は10kΩ(オーム)の抵抗器を使用します。
電子工作をするため、これまで解説した部品の他にもスイッチやセンサなど、色々な部品が必要になってきます。個々で購入するには手間がかかるため、最初はセット品を購入することをおススメします。
私は以下のセット品を購入しました!
また、これからラズベリーパイを購入する場合、ラズベリーパイ本体を含めたセット品を購入することをおススメします。
ラズベリーパイ本体を収めるケースや、OSをインストールするためmicroSDカードなど必要なものを個々に購入する手間を省くことができます。
3. 回路図・配線の様子
ラズベリーパイのプログラム(Python)から光センサ(CdSセル)を用いて明るさを読み取る回路を解説します。
回路図は以下のようになります。
SPI通信をする場合「制御するデバイスをマスタ」「制御されるデバイスをスレーブ」と呼び、マスタとスレーブは4本の信号線で接続します。
今回のようにラズベリーパイでADコンバータの値を読み取る場合、「マスタがラズベリーパイ」「スレーブがADコンバータ」となります。
ラズベリーパイをADコンバータ(MCP3002)とSPI通信するため、以下のように接続します。
ラズベリーパイのピン | MCP3002のピン | ジャンパ線 |
---|---|---|
SPICS0 | CS/SHDN(1番ピン) | 白色 |
SPIMOSI | Din(5番ピン) | 黄色 |
SPIMISO | Dout(6番ピン) | 青色 |
SPISCLK | CLK(7番ピン) | 白色 |
白色が被ってしまいました…ジャンパ線はこの色でなければいけない訳ではありません。
MCP3002とCdSセルを接続する必要があります。今回はMCP3002のCH0(2番ピン)とCdSセルの片側と10kΩの抵抗器に接続します。(青色のジャンパ線)
CdSセルのもう片側は3.3Vに接続します。(オレンジ色のジャンパ線)
最後に、10kΩの抵抗器の片側をGNDに接続します。(黒色のジャンパ線)
配線の様子です。こんな感じになりました。
↑では、フラットケーブルでGPIOの全ピンをブレッドボードに接続しています。回路図と実際の配線は異なる部分がありますがご了承ください。
※電気的には「回路図」と同じ意味です。
4. プログラム(Python)
光センサ(CdSセル)を用いて明るさを読み取るプログラム(Python)は以下のようになります。
#必要なモジュールをインポート
import spidev #SPI通信用のモジュールをインポート
import time #時間制御用のモジュールをインポート
import sys #sysモジュールをインポート
#SPI通信を行うための準備
spi = spidev.SpiDev() #インスタンスを生成
spi.open(0, 0) #CE0(24番ピン)を指定
spi.max_speed_hz = 1000000 #転送速度 1MHz
#連続して値を読み込む
while True:
try:
resp = spi.xfer2([0x68, 0x00]) #SPI通信で値を読み込む
volume = ((resp[0] << 8) + resp[1]) & 0x3FF #読み込んだ値を10ビットの数値に変換
print(volume) #変換した値を表示
time.sleep(1) #1秒間待つ
except KeyboardInterrupt:
#Ctrl+Cキーが押された
spi.close() #SPI通信を終了
sys.exit() #プログラム終了
SPI通信でMCP3002の値を読み取り、変換して画面に表示します。
#必要なモジュールをインポート
import spidev #SPI通信用のモジュールをインポート
import time #時間制御用のモジュールをインポート
import sys #sysモジュールをインポート
2~4行目で今回必要な「モジュール」を宣言します。
#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)
と記述します。
#連続して値を読み込む
while True:
try:
resp = spi.xfer2([0x68, 0x00]) #SPI通信で値を読み込む
volume = ((resp[0] << 8) + resp[1]) & 0x3FF #読み込んだ値を10ビットの数値に変換
print(volume) #変換した値を表示
time.sleep(1) #1秒間待つ
except KeyboardInterrupt:
#Ctrl+Cキーが押された
spi.close() #SPI通信を終了
sys.exit() #プログラム終了
「while文」は条件を指定して、その条件が真の時に繰り返し処理を行うものです。
while 条件式:
繰り返し処理を行うコード
↑の「条件式」にTrue
を指定することにより、条件式は常に真となりwhile文は無限に繰り返します。
ただし、このままではプログラム実行中に無限ループから抜け出す方法がありません。そこでwhile文の中にある「try文」と「except文」を使用します。
このtry-except文を用いることにより、while文の処理は以下のようになります。
while True:
try:
繰り返し処理を行うコード
except KeyboardInterrupt: #Ctrl+Cキーが押された
spi.close() #SPI通信を終了
sys.exit() #プログラムを終了
except KeyboardInterrupt:
は、キーボードのCtrl + cキーが押された時にwhile文の繰り返し処理から抜けて「GPIOのクリーンアップ」と「プログラムの終了」の処理を行います。
Ctrl + cキーが押されていないとき、try:文の中の処理を繰り返し行います。(以下で解説)
while文の中の「繰り返し処理を行うコード」は以下の通りです。つまり、Ctrl + Cキーが押されるまで以下の処理を繰り返します。
resp = spi.xfer2([0x68, 0x00]) #SPI通信で値を読み込む
volume = ((resp[0] << 8) + resp[1]) & 0x3FF #読み込んだ値を10ビットの数値に変換
print(volume) #変換した値を表示
time.sleep(1) #1秒間待つ
spi.xfer2([0x68, 0x00])
では、MCP3002のCH0(チャンネル0 アナログ入力)のアナログ値を取得します。
MCP3002から取得したデータはresp[0]
とresp[1]
の2バイトに分かれます。シフト演算子を用いて1ヶにまとめます。
time.sleep(1)
は何もせずに1秒間待ちます。
5. おわりに
この記事では、ラズベリーパイのプログラム(Python)から光センサ(CdSセル)を用いて明るさを読み取る方法を解説しました。
まだまだラズベリーパイ初心者の私ですが、以下の参考書が大変参考にさせて頂いております。
2冊とも初学者にも易しい内容になっており、ゼロからラズベリーパイを始める方にもオススメできる参考書です。