LED1個が点滅するだけでは面白くない!という人に、それを応用して、たくさんのLEDをWebページのUI(ボタン)を使って点滅させてみましょう。
まず、 CHIRIMEN for Raspberry Pi 3 Hello World に従って、Raspberry Pi3のGPIO(Port26)にLEDを繋げます。そしてこのチュートリアルのソフトウェアでLEDが点滅動作することを確認してください。抵抗は470Ωを使います。(この後 沢山LEDをつなげるので、電流を流しすぎないように・・・)
次に、GPIOポート番号の20から27を使って、同じ回路を8回路分組み立てます。(26は既に上で組んでいますので7個追加ですね)
Raspberry Pi3のアース(GND)のピンはあまり沢山は用意されていませんので、ブレッドボードを使ってアースを分岐させるのがコツです。
ブラウザの画面上での色に合わせるためにはGPIO20と23に赤、21,24に緑、22,25に青、26,27に白のLEDを繋ぎます。
組みあがったら、以下のhtmlとjavascriptを使って動かしてみましょう。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>GPIO-Multi-Blink</title>
</head>
<body>
<script src="https://mz4u.net/libs/gc2/polyfill.js"></script>
<script src="mb.js"></script>
<input type="button" onclick="startFlash()" value="start flash"></input>
<input type="button" onclick="allOn()" value="ALL ON"></input>
<input type="button" onclick="setLed('1,0,0,1,0,0,0,0')" value="RED(20,23)"></input>
<input type="button" onclick="setLed('0,1,0,0,1,0,0,0')" value="GREEN(21,24)"></input>
<input type="button" onclick="setLed('0,0,1,0,0,1,0,0')" value="BLUE(22,25)"></input>
<input type="button" onclick="setLed('1,0,1,1,0,1,0,0')" value="MAGENTA(20,22,23,25)"></input>
<input type="button" onclick="setLed('1,1,0,1,1,0,0,0')" value="YELLOW(20,21,23,24)"></input>
<input type="button" onclick="setLed('0,1,1,0,1,1,0,0')" value="CYAN(21,22,24,25)"></input>
<input type="button" onclick="setLed('0,0,0,0,0,0,1,1')" value="WHITE(26,27)"></input>
<input type="button" onclick="allOff()" value="ALL OFF"></input>
</body>
</html>
var portPromise;
onload =function(){
console.log("onload");
portPromise = mainFunction();
}
async function mainFunction(){ // ポートを初期化するための非同期関数
var gpioAccess = await navigator.requestGPIOAccess(); // thenの前の関数をawait接頭辞をつけて呼び出します。
var ports = [];
var Vs = [0,0,0,0,0,0,0,0];
var portAddrs = [20,21,22,23,24,25,26,27];
for ( var i = 0 ; i < 8 ; i++ ){
ports[i] = gpioAccess.ports.get(portAddrs[i]);
await ports[i].export("out");
}
for ( var i = 0 ; i < 8 ; i++ ){
ports[i].write(Vs[i]);
}
return ( ports );
}
var flash = false;
async function startFlash(){
var ports = await portPromise;
var Vs = [0,0,0,0,0,0,0,0];
flash = true;
var i = 0;
while ( flash ){ // 無限ループ
await sleep(100); // 1000ms待機する
Vs[i] ^= 1; // v = v ^ 1 (XOR 演算)の意。 vが1の場合はvが0に、0の場合は1に変化する。1でLED点灯、0で消灯するので、1秒間隔でLEDがON OFFする。
ports[i].write(Vs[i]);
++i;
if ( i > 7 ){
i=0;
}
}
console.log("exit loop");
}
async function allOn(){
var ports = await portPromise;
flash = false;
await sleep(100); // 100ms待機する
for ( var i = 0 ; i < 8 ; i++ ){
ports[i].write(1);
}
}
async function allOff(){
var ports = await portPromise;
flash = false;
await sleep(100); // 100ms待機する
for ( var i = 0 ; i < 8 ; i++ ){
ports[i].write(0);
}
}
async function setLed(chFlags){
var chFlag = chFlags.split(",");
console.log(chFlag);
var ports = await portPromise;
flash = false;
await sleep(100); // 100ms待機する
for ( var i = 0 ; i < 8 ; i++){
if ( chFlag[i]=="1" ){
ports[i].write(1);
} else {
ports[i].write(0);
}
}
}
// 指定したms秒スリープする非同期処理関数
function sleep(ms){
return new Promise( function(resolve) {
setTimeout(resolve, ms);
});
}