目次

L チカしてみよう (初めての GPIO)

1. はじめに

まずは CHIRIMEN for Raspberry Pi (以下 CHIRIMEN Raspi) を使って Web アプリから「L チカ」(LED を点けたり消したり) するプログラミングをしてみましょう。CHIRIMEN Raspi の基本的な操作方法を学び、実際に L チカするコードを読み書きします。

CHIRIMEN for Raspberry Pi とは

CHIRIMEN for Raspberry Pi は、Raspberry Pi (以下 Raspi) で動作する IoT プログラミング環境です。Web GPIO APIWeb I2C API といった JavaScript でハードを制御する API を活用したプログラミングにより、Web アプリ上で Raspi に接続した電子パーツを直接制御できます。

CHIRIMEN for Raspberry Pi の活用イメージ

2. 事前準備 (機材確認)

用意するもの

基本ハードウエア

CHIRIMEN for Raspberry Pi の起動に最低限必要となる基本ハードウエアは次の通りです。

Raspi の起動に必要なハードウエア一覧

L チカに必要となるパーツ

基本ハードウエアに加え「L チカ (えるちか)」を実施するには下記パーツも追加で必要です。

Lチカに必要なパーツ一覧

SD カードへ CHIRIMEN for Raspberry Pi 環境を書き込む

起動する前に、SD カードへ CHIRIMEN Raspi 環境(起動イメージファイル) を書き込んでおく必要があります。

手順は CHIRIMEN for Raspberry Pi 3 の SD カードを作成する を参照してください。

3. CHIRIMEN for Raspberry Pi を起動してみよう

接続方法

機材が揃ったら、いよいよ Raspi を接続して起動してみましょう。基本ハードウエアを下図のように接続してください。(Raspi への電源ケーブルの接続は最後にしましょう)

接続方法

もしよくわからない場合には、Raspberry Pi Hardware Guide なども参照してみると良いでしょう。

電源ケーブルの接続、あるいは、スイッチ付きケーブルの場合はスイッチの ON により Raspi が起動します。

起動確認

電源を入れると Raspi の microSD コネクタ横の赤い LED が点灯し、OS の起動後、下記のようなデスクトップ画面が表示されたら CHIRIMEN Raspi の起動に成功しています (OS イメージや画面サイズにより細部は異なることがあります)。おめでとうございます!

CHIRIMEN for Raspberry Pi desktop 画面

残念ながら上記画面が表示されなかった!?

違う画面が表示される場合には、CHIRIMEN Raspi とは異なる SD カードで起動された可能性があります。その場合は、SD カードの作成手順 に従って CHIRIMEN 用のイメージを作成してください。

電源を入れても何も画面に映らないような場合には、配線が誤っている可能性があります。配線を再度確認してみましょう。LED が点灯していない場合、AC アダプタまで電気が来ていないかも知れません。トラブルシューティングページ も参考にしてください。

WiFi の設定

デスクトップ画面が表示されたら、さっそく WiFi を設定して、インターネットに繋げてみましょう。 CHIRIMEN Raspi では、ネットワークに繋がずローカルファイルでプログラミングも可能ですが、JS BinJSFiddle あるいは CodeSandbox などブラウザ上で動くエディタを活用することで、より簡単にプログラミングできます。

ぜひ、最初にインターネットに接続しておきましょう。WiFi の設定は、タスクバーの右上の WiFi アイコンから行えます。

WiFi設定

4. 「L チカ」をやってみよう

無事、Raspi の起動と WiFi の設定が行えたら、いよいよ L チカに挑戦してみましょう。

そもそも「L チカ」って何?

「L チカ」とは、LED を点けたり消したりチカチカ点滅させることです。今回は「LED を点ける」「LED を消す」をプログラムで繰り返し実行することで実現します。

配線してみよう

LED を点けたり消したりするためには、Raspi と正しく配線する必要があります。 LED は 2 本のリード線が出ていますが、長い方がアノード(+側)、短い側がカソード(-側)です。

L チカのための配線図は、基本的な作例集(examples)と一緒に、下記にプリインストールされています。

/home/pi/Desktop/gc/gpio/LEDblink/schematic.png

example-files

それでは、まず先に回路図の画像 schematic.png をダブルクリックして見てみましょう。

example: LEDblink の配線図

LED のリード線の方向に注意しながら、この図の通りにジャンパーワイヤやブレッドボードを使って配線してみましょう。

配線図では LED の下側のリード線が折れ曲がり長い方がアノード (+側) です。schematic.pngで使用されている抵抗は"120Ω"です。使用する抵抗は、LED にあったものを使用してください。

実際に配線してみると、こんな感じになりました。

配線してみました

参考

example を実行してみる

配線がうまくできたら、さっそく動かしてみましょう。 L チカのためのサンプルコードは先ほどの配線図と同じフォルダに格納されています。

/home/pi/Desktop/gc/gpio/LEDblink/index.html

index.html をダブルクリックすると、ブラウザが起動し、先ほど配線した LED が点滅しているはずです!

ブラウザ画面

browser

L チカの様子

Lチカ成功

L チカに成功しましたか?!

うまくいかなかったら?

配線に誤りがないか (特にジャンパーワイヤを指す Raspi 側のピン)、複数のタブで同じ L チカコードを開いていないかなどを確認しても原因が分からない場合、F12 キーやブラウザのメニュー → 「その他のツール」→「デベロッパーツール」で Console を開いて何かエラーメッセージが出ていないか確認してください。詳しくは トラブルシューティングページ を参考にしてください。

5. コードを眺めてみよう

さきほどは、L チカをデスクトップにある example から実行してみました。実は、CHIRIMEN Raspi にはもうひとつ、「オンラインの example」が用意されており、オンライン版ではコードを書き換えながら学習を進められます。

今度はオンラインの example からさきほどと同じ L チカを実行してコードを眺めてみましょう。

その前に一つ注意です。CHIRIMEN Raspi での GPIO などの操作には排他制御があり、同一の GPIO ピンを複数のプログラムから同時操作はできません。同一ページもしくは同一ピンを使うページを同時に開くと正しく動作しません。

オンラインの example を起動する前に、必ず先ほど開いた file:///home/pi/Desktop/gc/gpio/LEDblink/index.html のブラウザウィンドウ (タブ) は閉じてください。先に既存ウィンドウを閉じておかないと、サンプルが正常に動作しなくなります。

既に開いているウィンドウを確実に閉じるには、一度ブラウザを閉じてから、再度ブラウザを起動すると確実です (通常はタブだけ消しても十分です)。

ブラウザの再起動

オンラインの example の実行

それでは、さっそくオンラインの example を実行してみます。 配線は、さきほどのままで OK です。

オンラインの example へのリンクは、ブラウザを起動後、ブックマークバーにあるExamplesのページの中にあります。

https://r.chirimen.org/gpio-blink へのリンク

そのまま起動すると下記のような画面になります。(下記スクリーンショットはアクセス直後の画面から JS Bin のタイトルバー部の「Output」タブを 1 回押して非表示にしています)

JS BinでのLチカexample画面

それでは、コードを眺めてみましょう。

HTML

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta content="width=device-width" name="viewport">
    <title>GPIO-Blink</title>
  </head>
  <body>
    <script src="https://r.chirimen.org/polyfill.js"></script>
    <script src="s0.js"></script>
  </body>
</html>

polyfill.js という JavaScript ライブラリを読み込んでいます。これは Web GPIO API と、Web I2C API という W3C でドラフト提案中の 2 つの API への Polyfill (新しい API を未実装のブラウザでも同じコードが書けるようにするためのライブラリ) で、最初に読み込むとそれ以降のコードで GPIO や I2C を操作する JavaScript API が使えるようになります。

** /home/pi/Desktop/gc/gpio/LEDblink/index.html などの example では、インターネット未接続時にも動作するよう Polyfill を含めたコード一式をローカルにコピーしてあるので node_modules/@chirimen-raspi/polyfill/polyfill.js のようなパスで読み込みます。オンラインにホストされている最新版を読み込む場合には https://r.chirimen.org/polyfill.js を指定します。**

JavaScript

async function mainFunction() {
  // プログラムの本体となる関数。非同期処理を await で扱えるよう全体を async 関数で包みます
  var gpioAccess = await navigator.requestGPIOAccess(); // 非同期関数は await を付けて呼び出す
  var port = gpioAccess.ports.get(26);
  var v = 0;

  await port.export("out");
  for (;;) {
    // 無限ループ
    await sleep(1000); // 無限ループの繰り返し毎に 1000ms 待機する
    v = v === 0 ? 1 : 0; // vの値を0,1入れ替える。1で点灯、0で消灯するので、1秒間隔でLEDがON OFFする
    port.write(v);
  }
}

// await sleep(ms) と呼べば指定 ms 待機する非同期関数
// 同じものが polyfill.js でも定義されているため省略可能
function sleep(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}

mainFunction(); // 定義したasync関数を実行します(このプログラムのエントリーポイント)

注記

CHIRIMEN Raspi はウェブブラウザをプログラムの実行環境として用いてシステムを構築します。ウェブブラウザが実行できるプログラムのプログラミング言語は JavaScript です。JavaScript を学んだことのない人は、まずこちらの資料「JavaScript 1 Day 講習」を履修しましょう。

非同期処理について

物理デバイス制御やネットワーク通信などを行う際には、応答待ち中にブラウザが停止しないよう非同期処理を使う必要があります。 本チュートリアルではこれを async 関数 で記述しています。非同期処理を知らない人や async 関数を使ったことがない人は、必要に応じてこちらの資料「非同期処理 (async await 版)」 も参照してください。

非同期処理を使いこなすのは難しいですが、本チュートリアルでは次のルールでコードを書けば大丈夫です:

非同期関数を await なしで呼び出すと返り値は Promise オブジェクトとなるため Promise について理解しておかなければ返り値の判断や実行順序が入れ替わって意図せぬ挙動になります。例えば、ポートの初期化を await なしで呼び出すと、初期化完了前に次の行の処理を続け、初期化未完了のハードを操作しようとして失敗したり、ネットワーク通信完了前に受信データを読みだそうとして失敗します。

ハードを触るときは常に非同期呼び出しをする (その処理を含む関数も入れ子で非同期呼び出しする) と決めておけば迷うことなく、コードの実行順序も上から下に見たとおりの順番で実行されて読みやすくなります。

Note:

本チュートリアルで非同期処理を async 関数に統一している理由は、記述がシンプルで初心者も読み書きしやすいコードになるからです。この機能は比較的新しい JavaScript 言語機能 (ECMASCript 2017) ですが、Raspi 上で使う上で問題はありません (様々なウェブブラウザでのサポート状況)。

処理の解説

今回の JavaScript ファイルで、最初に呼び出されるコードは await navigator.requestGPIOAccess() です。 ここで先ほど出て来た Web GPIO API を使い、gpioAccess という GPIO にアクセスするためのインタフェースを取得しています。

関数の呼び出しに await 接頭詞を付けることに注意してください。 この関数は非同期関数ですが、その処理の完了を待ってから次の処理をする必要があります。そして await 接頭詞を使うので、それを含む関数(mainFunction())は async 接頭詞を付けて非同期関数として定義しなければなりません。

コードを読み進める前に、ここで少し GPIO について記載しておきたいと思います。

GPIO とは

GPIOは、「General-purpose input/output」の略で汎用的な入出力インタフェースのことです。

Raspi に実装されている 40 本のピンヘッダから GPIO を利用することができます。(40 本全てのピンが GPIO として利用できるわけではありません)

CHIRIMEN Raspi では Raspi が提供する 40 本のピンヘッダのうち、下記緑色のピン(合計 17 本)を Web アプリから利用可能な GPIO として設定しています。

Raspi の GPIO 端子は、GND 端子との間に、0V もしくは 3.3V の電圧を印加(出力)したり、逆に 0V もしくは 3.3V の電圧を検知(入力)したりすることができます。LED は数 mA の電流を流すことによって点灯できる電子部品のため、印加する電圧を 3.3V(点灯)、0V(消灯) と変化させることで L チカが実現できるのです。

詳しくはこちらのサイトの解説などを参考にしてみましょう。

Raspi PIN配置図

GPIOPort の処理

さて、コードに戻りましょう。 var port = gpioAccess.ports.get(26); で GPIO の 26 番ポートにアクセスするためのオブジェクト を取得しています。続いて、 await port.export("out") で GPIO の 26 番を「出力設定」にしています。これにより LED への電圧の切り替えが可能になっています。

最後に await sleep(1000) で 1000ms = 1 秒 待機させて無限ループをつくることで、 1 秒毎に port.write(1)port.write(0) を交互に呼び出し、GPIO 26 番に対する電圧を 3.3V → 0V → 3.3V → 0V と繰り返し設定しています。

LED は一定以上の電圧 (赤色 LED だと概ね 1.8V 程度、青色 LED だと 3.1V 程度) 以上になると点灯する性質を持っていますので、3.3V になったときに点灯、0V になったときに消灯を繰り返すことになります。

まとめると下図のような流れになります。

シーケンス

example を修正してみよう

JS Bin の JavaScript のペイン (コードが表示されているところ) をクリックするとカーソルが表示されコード修正も可能です。 試しにいろいろ変えてみましょう。

まとめ

このチュートリアルでは、下記を実践してみました。

このチュートリアルで書いたコードは以下のページで参照できます:

次の『チュートリアル 1. GPIO の使い方』では GPIO の入力方法について学びます。