前回、フォトレジスタとA/Dコンバーターを使い、周囲の明るさに反応してLEDを点灯させる回路を作成しました。↓
今回は可変抵抗とA/Dコンバーターを使ってPWMを制御し、RGBフルカラーLEDを点灯させてみようと思います。
使用する材料は下記の通りです。
・RBGフルカラーLED
・10KΩ~100KΩの半固定抵抗 × 3
・12ビットA/Dコンバーター(MCP3208)
・330Ω抵抗 × 3
・ジャンピングワイヤー(オスーオスとオス-メス複数)
Raspberry Pi単体でもPWMを使用する事ができますし、そもそもPWMを使わなくても可変抵抗だけで明るさの調整は出来ますが、今回のようにA/Dコンバータを使い、PWMも制御する事で、今後電子工作を続ける中で役に立つ知識が得られるかと思います。
初めに
PWM「パルス幅変調」について
デジタル信号は「0」「1」でやり取りする為、基本的には「ON」「OFF」のような動作しかできません。
例えばモーターを駆動させようとした時、「HIGH」の信号で一定の速度でしか動かせないのです。「LOW」なら止まるので、「動かす」「止める」の2択です。
しかし、これに中間的要素を作る事ができます。
図にあるように、50Hz(1秒間に50回ON,OFFする)で、HIGHの信号にある程度の一定の幅を持たせてみます。すると、その幅の1秒間における割合によって「デューティー比」が決まり、この%の変化によって疑似的にアナログ値の変化のような動きを実現できます。
3.3Vの電圧をPWMに変換するとすれば、このデューティー比を変化させる事によって、0~3.3Vをある程度制御できるわけです。0%ならLOWの信号と同じなので0V、100%ならHIGHの信号と同じなので3.3V、50%なら1.5V前後(極端に言えば)とか、そういった感じです。
少し話がそれますが、似たような技術に「スイッチング電源」があります。これはコイルやコンデンサを回路に組み込み、もっと高速にON,OFFを繰り返す事で昇圧、降圧を可能にしています。
CDでは「PCM」変調(今は違うかも?)が利用されていて、これは音声を標本化、量子化したあとの「符号化」にあたるもので、音声の強弱に合わせてパルスの幅を変えているのですね。PWMとの違いは「幅が一定でない」所です。
RBGフルカラーLEDについて
今回使用するLEDは、1つのLEDで「赤」「青」「緑」の色の3原色を点灯させる事ができます。
図のようにLEDの足は4本あり、写真のLEDでは左から「赤」「共通カソード」「青」「緑」になります。一番長い足が「共通アノード」もしくは「共通カソード」になります。
共通部分をどちらで取るかによって、制御する方向が変わります。
LEDの順方向はアノードからカソードですので、共通アノードのLEDの場合は、カソードを3色のピンそれぞれから回路をのばして、点灯させたい色のカソードを「LOW」にする事でそのラインの色が点灯します。
共通カソードの場合は、アノードの3色のピンそれぞれに回路をつなげて、点灯させたい色のアノードを「HIGH」にする事でそのラインの色が点灯します。
今回使用するのは「共通カソード」になります。
このように部品は大きく分けて2種類ありますので、購入の際は注意が必要ですね。
回路構成
ブロック図
かなり大まかですが、今回のLED点灯の流れは図のようになります。
アナログ(変化する電圧)の入力をA/Dコンバータで0~4095に数値化し、それをデジタル信号でラズパイにSPI通信で送ります。
ラズパイはその信号を基にPWM制御をGPIOピンから送り出します。
PWMのデューティー比によって、LEDの発光の強さが変わります。
回路図
左側がGPIO制御、右側がLED点灯回路になります。
先ず3.3Vが可変抵抗に入り、ここで0~3.3Vのアナログ値に変える事が出来ます。※ちなみにこの可変抵抗はプルダウン抵抗もかねていますね。
その後A/Dコンバータで0~4095に数値化し、それをデジタル信号に変えてラズパイにSPI通信で送ります。
ラズパイはその信号を基に、後述するプログラム通りPWM制御をGPIO4、17、27から送り出します。
各色のLEDはPWMのデューティー比によって、発光の強さが変わります。
3色同時に点灯できるので、全てMAXの明るさにすれば「白」っぽく見えるはずです。
ちなみに、今回使用するPWMは「ソフトウェアPWM」と呼ばれるもので、少し精度が悪いものになります。反対に、精度のいいPWMを「ハードウェアPWM」と呼びます。
Raspberry Piは「ハードウェアPWM」が2ピンしかない為、今回はその他のGPIOピンで使える「ソフトウェアPWM」を利用します。
配線図
プログラム
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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# -*- coding: utf-8 -*- import RPi.GPIO as GPIO from time import sleep # 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ビットを読む 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) GPIO.setup(25, GPIO.OUT) GPIO.setup(24, GPIO.OUT) GPIO.setup(23, GPIO.OUT) p0 = GPIO.PWM(25, 50) p1 = GPIO.PWM(24, 50) p2 = GPIO.PWM(23, 50) p0.start(0) p1.start(0) p2.start(0) adc_pin0 = 0 adc_pin1 = 1 adc_pin2 = 2 try: while True: inputVal0 = readadc(adc_pin0, SPICLK, SPIMOSI, SPIMISO, SPICS) inputVal1 = readadc(adc_pin1, SPICLK, SPIMOSI, SPIMISO, SPICS) inputVal2 = readadc(adc_pin2, SPICLK, SPIMOSI, SPIMISO, SPICS) duty0 = inputVal0*100/4095 duty1 = inputVal1*100/4095 duty2 = inputVal2*100/4095 p0.ChangeDutyCycle(duty0) p1.ChangeDutyCycle(duty1) p2.ChangeDutyCycle(duty2) sleep(0.2) except KeyboardInterrupt: pass p0.stop() p1.stop() p2.stop() GPIO.cleanup() |
36~50行目までは、使用するGPIOとSPIの入出力を定義しています。
51~59行目は、PWMの使用と、PWMの初期値(デューティー比)、A/Dコンバータの入力ピンとの紐づけが行われています。
本文で「readadc」の関数が呼び出され、6行目から34行目までのプログラムが実行され、LEDが点灯する仕組みです。
実際に動作させるとこんな感じになります。↓
次回は、PWMでサーボモーターを制御してみたいと思います。