前回はタクトスイッチでLEDをトグル動作で点灯させてみました。↓
今回はアナログ値で入ってくる電圧をフォトレジスタで調整させ、それを「ACコンバーター」でA/D変換させて、暗い場合はLEDが点灯、明るい場合はLEDが消灯する回路を作ってみようと思います。
使用するな材料は下記の通りです。
・RaspberryPi
・150Ω抵抗
・10KΩ抵抗
・LED
・フォトレジスタ
・A/Dコンバーター(MCP3208)
・ジャンパーピン(オス-オス、オス-メス、各数本)
LEDを点灯させる回路は前回までの回路と同じく、GPIO4の回路をそのまま使います。タクトスイッチ回路の部分をADコンバーターに入れ替える感じです。
始めに
A/Dコンバーターとフォトレジスタについて
A/Dコンバーターは、AC(交流)をDC(直流)に変換する部品です。逆のものではD/Aインバーターがありますが、総じて単に「コンバーター」と呼ぶ場合があります。
フォトレジスタは、受光素子に当たる光量によって抵抗値が可変する部品です。明るければ抵抗値が高くなり、暗ければ抵抗値が低くなります。
これらを利用して、「明るさに合わせてLEDを点灯させる」回路を作成します。
ブロック図
おおまかな流れになりますが、図のような感じになります。
Raspberry Piの3.3VをA/Dコンバーターに入力信号として入れます。この入力値はアナログ(連続してつながる信号)信号になります。
Raspberry Piではこのアナログ入力をArduinoのように処理することが出来ないので、別途「A/Dコンバータ」を使用して、アナログ値をデジタル値に変化させます。
デジタル化された信号は、「SPI」と呼ばれる全二重のシリアル通信方式でRaspberry Piと通信します。
回路図と配線図
回路図
図の通り、A/Dコンバーターに入るアナログ入力は、Raspberry Piからの3.3Vをフォトレジスタを介して入ります。フォトレジスタの下にはプルダウン抵抗の10KΩがあります。
つまり、A/Dコンバーターが取り出す電圧は、周囲の明るさによって刻刻と変化します。
そしてこのA/Dコンバーターは、「12ビットコンバータ」とよばれており、受け取った電圧の値を2の12乗、0~4096の値に変化させる事が出来ます。
これは0~3.3Vを0~4096で表現できる事につながり、この数値を使う事によってより細かな処理を実行することが可能になります。
分かりやすく言えば、フォトレジスタを可変抵抗として考えた場合、プルダウン抵抗との関係もありますが、抵抗値をMAXまで上げるとそこで3.3Vを消費するのでA/Dコンバーターの入力は0の値に。半分位の抵抗値なら1.5V程度が入力になり、値は2000位になります。抵抗を0にしてしまえば、3.3VがそのままA/Dコンバータに入る事になるので値は4096になる、といった感じです。
この値を利用すれば、例えば100ならAの処理、200ならBの処理・・・と複数の処理を再現させることが可能になります。
あとはこの数値化したデータを2進数のデジタル化に変換し、SPI通信でRaspberry Piに送り、プログラミングに応じた内容が処理実行されるわけです。
例えばA/Dコンバーターの入力値が「2000以上ならGOIO4をHIGH」のプログラムがあれば、ある程度フォトレジスタ周辺を暗くしてやればLEDが点灯します。
今回使用するA/Dコンバーター(MCP3208)は入力チャンネルが8つあるので、それぞれがアナログの値を読み取ることができます。
他の端子には電源以外に、
・クロック(SPI CLK、SCLK)⇒同期を取るための信号
・チップ・セレクト(CS)⇒スレーブの選択するための信号
・マスタ出力/スレーブ入力(MOSI)⇒シリアルデータ通信
・マスタ入力/スレーブ出力(MISO)⇒シリアルデータ通信
となっています。
配線図
かなり見にくいですが、一応載せておきます。
プログラム
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# -*- coding: utf-8 -*- import RPi.GPIO as GPIO from time import sleep # MCP3208からSPI通信で12ビットのデジタル値を取得。0から7の8チャンネル使用可 def readadc(adcnum, clockpin, mosipin, misopin, cspin): if adcnum > 7 or adcnum < 0: return -1 GPIO.output(cspin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) GPIO.output(cspin, GPIO.LOW) commandout = adcnum commandout |= 0x18 # スタートビット+シングルエンドビット commandout <<= 3 # LSBから8ビット目を送信するようにする for i in range(5): # LSBから数えて8ビット目から4ビット目までを送信 if commandout & 0x80: GPIO.output(mosipin, GPIO.HIGH) else: GPIO.output(mosipin, GPIO.LOW) commandout <<= 1 GPIO.output(clockpin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) adcout = 0 # 13ビット読む(ヌルビット+12ビットデータ) for i in range(13): GPIO.output(clockpin, GPIO.HIGH) GPIO.output(clockpin, GPIO.LOW) adcout <<= 1 if i>0 and GPIO.input(misopin)==GPIO.HIGH: adcout |= 0x1 GPIO.output(cspin, GPIO.HIGH) return adcout GPIO.setmode(GPIO.BCM) # ピンの名前を変数として定義 SPICLK = 11 SPIMOSI = 10 SPIMISO = 9 SPICS = 8 # SPI通信用の入出力を定義 GPIO.setup(SPICLK, GPIO.OUT) GPIO.setup(SPIMOSI, GPIO.OUT) GPIO.setup(SPIMISO, GPIO.IN) GPIO.setup(SPICS, GPIO.OUT) LED = 4 GPIO.setup(LED, GPIO.OUT) try: while True: inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) if inputVal0 < 2000: GPIO.output(LED, GPIO.HIGH) else: GPIO.output(LED, GPIO.LOW) print(inputVal0) sleep(0.2) except KeyboardInterrupt: pass GPIO.cleanup() |
1行目の# -*- coding: utf-8 -*-は、プログラム内に「コメントアウト」と呼ばれる説明書きを日本語入力できるようにするために記述します。
コメントアウトを残す場合は、#を先頭につける事でその後の分がプログラムに反映されなくなります。ちなみにPython3ではuft-8の宣言なしでもコメントアウトが記述できるようです。
初期化の処理ではコメントアウトにある通り、分かりやすくGPIOピンをA/Dコンバーターの入出力名の変数に格納しています。また、前途したように各信号のIN,OUT設定を記述しています。
メイン文では「readadc」で関数を呼び出しています。
少し長くてややこしいですが、この関数が実行されると、inputVal0の値が返ってきます。その値のなかに前途した0~4096が含まれているので、例えば今回であれば「2000以下ならLED点灯」「2000以上ならLED消灯」となります。
これは関数の中の処理で、フォトレジスタによる抵抗値の変化で入力が数値化されるのを実現させています。
プログラムを走らせるとこんな感じになります。
次回はPWM制御をやろうかと思います。