WebIOPiでRaspberry Piに繋いだフルカラーLEDを操作する
ロボットの目にRGBフルカラーLEDをつけたので、スマホからLEDを操作できるようにしたい。
ラズパイでWebIOPiが動作するように設定してあるので、操作画面とスクリプトを作る。
できあがったものはこんな感じ↓
WebIOPiでロボットのLED発光色を操作する pic.twitter.com/wqNnvDWK6E
— 電子猫 (@denshicat) 2019年9月11日
作りかた
発光色に応じたボタンをクリックすることで、RGBの三色のうちの任意の1〜3色をONにし、他をOFFにする。
ON-OFFの切り替えだけで出せるカラーは、単色で発光させたときのred, green, blueに加えて、2色を同時に発光させたyellow, cyan, magenta、3色を発光させたwhite、計7色となる。
より細かな色合いを出すのは処理が複雑になるし、7色もあれば十分楽しいので、今回はこの7色+消灯で8つの状態を切り替えられるようにする。
まずはラズパイのGPIOを操作するスクリプトから。
これは、WebIOPi起動時に読み込むスクリプトファイルに記述する。
import webiopi from time import sleep from distutils.util import strtobool # GPIOライブラリの取得 GPIO = webiopi.GPIO # LEDのRGBに対応するGPIO。ここでは23,24,25を使う LED_R = 23 LED_G = 24 LED_B = 25 LED_STATE = GPIO.LOW # デバッグ出力を有効に webiopi.setDebug() # WebIOPiの起動時に呼ばれる関数 def setup(): webiopi.debug("Script with macros - Setup") # GPIOのセットアップ GPIO.setFunction(LED_R, GPIO.OUT) GPIO.setFunction(LED_G, GPIO.OUT) GPIO.setFunction(LED_B, GPIO.OUT) GPIO.digitalWrite(LED_R, LED_STATE) GPIO.digitalWrite(LED_G, LED_STATE) GPIO.digitalWrite(LED_B, LED_STATE) # WebIOPiにより繰り返される関数 def loop(): webiopi.sleep(5) # WebIOPi終了時に呼ばれる関数 def destroy(): webiopi.debug("Script with macros - Destroy") # GPIO関数のリセット(入力にセットすることで行う) GPIO.setFunction(LED_R, GPIO.IN) GPIO.setFunction(LED_G, GPIO.IN) GPIO.setFunction(LED_B, GPIO.IN) # Javascriptから呼ぶマクロ @webiopi.macro def setLED(gpio, led_state): global LED_STATE LED_STATE = strtobool(led_state)#渡された文字列をbool値に変換して使用する GPIO.digitalWrite(int(gpio), LED_STATE) return LED_STATE
次に、Javascript。WebIOPiの操作画面のHTMLから読み込むファイル。
function setLED(color){ const gpio_r = 23; const gpio_g = 24; const gpio_b = 25; let state_r, state_g, state_b; // RGBのうちどれを点灯させるか色ごとに指定する if (color == 'white') { state_r = 'on'; state_g = 'on'; state_b = 'on'; } else if (color == 'red') { state_r = 'on'; state_g = 'off'; state_b = 'off'; } else if (color == 'green') { state_r = 'off'; state_g = 'on'; state_b = 'off'; } else if (color == 'blue') { state_r = 'off'; state_g = 'off'; state_b = 'on'; } else if (color == 'yellow') { state_r = 'on'; state_g = 'on'; state_b = 'off'; } else if (color == 'cyan') { state_r = 'off'; state_g = 'on'; state_b = 'on'; } else if (color == 'magenta') { state_r = 'on'; state_g = 'off'; state_b = 'on'; } else if (color == 'black') {// 消灯 state_r = 'off'; state_g = 'off'; state_b = 'off'; } webiopi().callMacro('setLED', [gpio_r, state_r]); webiopi().callMacro('setLED', [gpio_g, state_g]); webiopi().callMacro('setLED', [gpio_b, state_b]); // ボタンのクラスを付け替える const led_btns = document.getElementsByClassName('btn_led'); for (let led_btn of led_btns) { led_btn.classList.remove('btn_led--active'); } document.getElementById('led_' + color).classList.add('btn_led--active'); }
そして、HTML。操作画面のボタンを作り、スクリプトと紐付けする。
<div class="btn_led_wrap"> <span class="btn_led btn_led--active" id="led_black" onClick="setLED('black')"></span> <span class="btn_led" id="led_white" onClick="setLED('white')"></span> <span class="btn_led" id="led_red" onClick="setLED('red')"></span> <span class="btn_led" id="led_yellow" onClick="setLED('yellow')"></span> <span class="btn_led" id="led_green" onClick="setLED('green')"></span> <span class="btn_led" id="led_cyan" onClick="setLED('cyan')"></span> <span class="btn_led" id="led_blue" onClick="setLED('blue')"></span> <span class="btn_led" id="led_magenta" onClick="setLED('magenta')"></span> </div>
ページを読み込んだタイミングでは、消灯状態(black)をアクティブにしておく。
本当はspanじゃなくてbuttonとかでマークアップした方がわかりやすいのかもだけど、フォーカスとか面倒だからspanとかdiv使ってしまう。
あと当然このHTMLファイルでjsとcssを読み込んでおく。
最後に、CSS。ボタンの配置と装飾をする。
.btn_led_wrap { position: fixed;// 配置方法や場所はよしなに bottom: 20px; width: 100%; display: flex; justify-content: center; } .btn_led { box-sizing: border-box; height: 36px; width : 36px; margin: 4px; border : 10px solid #fff; border-radius: 50%; transition: all 0.1s; } .btn_led--active { border-width: 0; } #led_white { background-color: rgb(230,230,230);} #led_red { background-color: rgb(255,100,100);} #led_yellow { background-color: rgb(255,255,100);} #led_green { background-color: rgb(100,255,100);} #led_cyan { background-color: rgb(100,255,255);} #led_blue { background-color: rgb(100,100,255);} #led_magenta { background-color: rgb(255,100,255);} #led_black { background-color: rgb(60,60,60);}
各色のドットをクリックすると対応する色でLEDが点灯し、選択したボタンがいい感じに大きくなる。
今回はとてもスムーズに実現できたけど、ただLEDを操作するだけでこんなに色々書くことになるあたり、ロボットって大変だなぁと思いました。
つづく。