HOME > ものづくり(電子工作) > ブラウザ操作でIO制御 WebIO
2017.9.26-(更新中)

ブラウザ操作でIO制御 WebIO [XIAO版テキスト]

小山智史

(更新履歴)


目次

1. 概要
2. 動作環境
3. ソフトウェアの準備
4. Javascriptライブラリ(webio2.js)
5. 動作の説明
(付録1) Midiコマンドとの対応(WebIO2のプロトコル)
(付録2) Arduino Leonardo / XIAO / ATOM のピン接続


1. 概要

 WebIO は、MIDI通信を用いてブラウザからIO制御する仕組みです。

 上図左は、温湿度センサをつないだマイコン(図ではXIAO samd21)とパソコンをUSB接続でMIDI通信し、パソコンのWebブラウザの画面にセンサの値を表示する様子を表しています。

 上図右は、赤外線送信機をつないだマイコン(図ではATOM lite)とスマホをBluetooth接続でMIDI通信し、スマホでテレビのリモコン操作をする様子を表しています。

 どちらも、マイコンにはArduinoプログラム(webio2.ino)を書き込んでおき、パソコンやスマホからは見かけ上MIDIデバイスとなります。温湿度計やリモコンのWebアプリはJavascriptライブラリ(webio2.js)と一緒にサーバに置きます。また、MIDI通信の際にMIDIプロトコルの一部を入出力のために転用しています(付録1)。

 パソコンやスマホに特別なアプリは必要ありません。また、操作対象は「ブラウザが動作しているパソコンやスマホに接続したデバイス」で、遠隔地のデバイスを操作できるわけではありません。

 以下はWebIOを用いた制作例で、それぞれリンク先に詳しい説明があります。

ブラウザ画面に表示する温湿度計[リンク]
 大きなモニタに表示すれば、体育館やイベント会場などで熱中症対策に利用できます。
ブラウザ画面に表示するCO2モニタ[リンク]
 大きなモニタを使えば、イベント会場や飲食店の店頭などで換気の目安を表示できます(新型コロナ対策)。
ブラウザで操作する赤外線リモコン[リンク]
 通常のリモコンボタンを押せない重度障害者も、パソコンが操作できればリモコンを操作できます。
ブラウザと連動して自動演奏するミニドラム[リンク]
 ブラウザのメロディーと連動して、ミニドラムのスティックをモータで制御します。
電子工作の導入教材[リンク]
 ブラウザの操作でLEDをオンオフ、スイッチでブラウザ画面を操作、センサの値をブラウザ画面に表示などの簡単なWebアプリを作りながら、電子工作の導入教材として利用できます。

2. 動作環境

 以下のブラウザおよびマイコンで動作します。どのブラウザが Web MIDI API やWebBluetoothに対応しているかは「Can I Use」で確認できます。

USB接続の場合(パソコン)Bluetooth接続の場合(パソコン・スマホ)
ブラウザ Windows版Chrome, Edge など
(Web MIDI API 対応ブラウザ)
Windows版Chrome, Edge, Android版Chrome など
(Web MIDI APIおよび Web Bluetooth 対応ブラウザ)
マイコン Leonardo, ProMicro, Wio,
XIAO samd21, XIAO RP2040 など
(webio2.inoを書き込んでおく)
XIAO ESP32, XIAO ESP32S3,
ATOM lite, ATOM S3 lite など
(webio2.inoを書き込んでおく)

3. ソフトウェアの準備

 webio2.zipをダウンロードし、解凍すると、以下のファイルが復元されます。

4. Javascriptライブラリ(webio2.js)

 この章はWebアプリ(HTMLファイル)を作成する際にご覧ください。

 パソコンやスマホとマイコンの間の情報交換はMIDI通信で、ブラウザの Web MIDI API を介して行われます(付録1)。Webアプリから利用しやすいように、以下のようにArduino風のJavascriptの関数や定数をJavascriptライブラリ(webio2.js)で定義しています。

(1) 組み込み定数(拡張分)

定数名内容
HIGH, LOW デジタル出力またはデジタル入力されたピンの状態
(HIGHは1、LOWは0)
OUTPUT, INPUT, INPUT_PULLUP
INPUT_ANALOG, OUTPUT_TONE,
OUTPUT_NEOPIXEL, OUTPUT_IR, INPUT_IR
pinMode()で設定する入出力のモード(値はマイコンにより異なる)
(INPUT, OUTPUT, INPUT_PULLUP以外は独自の名称)
D0~, A0~, G0~ デジタル入出力ピンおよびアナログ入力ピン
(値はマイコンにより異なる: 付録2参照)
TEMP, HUMI, CO2 I2C接続した温湿度センサSHT30/SHT31または
CO2センサSCD30の測定値を入力する仮想ピン

(2) 組み込み関数(拡張分)

関数名内容
pinMode(pin, mode) pinをmodeにする(modeは(1)の表参照)
digitalRead(pin) pinの値を読んでHIGH(1)またはLOW(0)の値を返す
digitalWrite(pin, HIGH)
digitalWrite(pin, HIGH, t)
pinにHIGH(1)を出力する...値はHIGH(1)またはLOW(0)
pinをt(ms) HIGH(1)にする
analogRead(a) aピンのアナログ値を読み、0~1023の値を返す。
TEMP(60), HUMI(61), CO2(62)は仮想ピン。
analogWrite(pin, value) pinにvalue(0~255)を出力する
sendNote(key, t) ピン6にkeyのブザー音をt[ms]出力する
keyの指定はmidiのノート番号(21~108)または文字列("A0"~"C8")
playNote(key, t) ブラウザからkeyの合成音をt[ms]出力する
keyの指定はmidiのノート番号(21~108)または文字列("A0"~"C8")
ただし 0 または "R" は休符
drumKick(key, t)
drumSnare(key, t)
drumHihat(key, t)
ブラウザからドラムの合成音を出力する
ブラウザからスネアの合成音を出力する
ブラウザからハイハットの合成音を出力する
talk(s)
talk(s,voice)

talk(s,voice,pitch)
talk(s,voice,pitch,speed)
ブラウザの合成音声でsを読み上げる(声はHaruka)
声を指定 日本語: 10 Google 日本語, 19 Ayumi, 20 Haruka, 21 Ichiro, 22 Sayaka
   英語: 1 US, 2 UK Female, 3 UK Male
声と音程(0.1~2)を指定
声と音程と速さ(0.1~10)を指定
servo(pin, pos) pinに接続したサーボの角度をpos(0~180)にする(pinは9と10を推奨)
motor(lspeed, rspeed)I2C接続した左右のモーターの速度をlspeed, rspeed(それぞれ-255~255)にする
pixel(i, r,g,b)
pixel(i, hue, brightness)
NeoPixelのi番目のLEDをr,g,bにする(それぞれ0~255)。
NeoPixelのi番目のLEDを色相hue(0~255), 明るさbrightness(0~255 省略時255)にする。
NeoPixelはピン4に接続
IRsend(protocol, command, address) IRリモート信号を出力する
$(id) document.getElementById(id)の短縮表現

 上記とは別に、以下の関数をプログラム中に定義すると特別な役割を果たします。

関数名内容
setup() ページが表示され、MIDIデバイスが認識された時にこの関数が呼び出される
loop() 20ms毎にこの関数が呼び出される
irreceive(protocol, address, command) IRリモコン信号を受信した時に呼び出される

5. 動作の説明

 ここでは、マイコンにXIAO samd21を使い、LEDとスイッチを接続した場合の動作を中心に説明します。

5.1 MIDIデバイス(マイコン)の接続

 MIDIデバイス(マイコン)をパソコンにUSB接続し、webio2.jsを使ったページ(このページもそうです)を表示すると、ページ冒頭にのような表示が現れます。これはSeeed XIAO M0という名前のMIDIデバイス(マイコン)が認識されていることを表しています。

 本物のMIDIデバイス(ここではnsx-39)を接続した場合は、ページ冒頭の表示がのようになり、ブラウザ画面の楽譜をMIDI音源(nsx-39)で演奏させるようなページを作ることができます。

 WebIOは、「さまざまな独自のMIDIデバイスを作って演奏(?)するページを作る」ということに他なりません。

 USB接続のMIDIデバイスが無い場合は、のような表示になります。ボタンを押すと、以下のような画面が現れます。

一覧の中から接続するMIDIデバイス(この例では ATOM C3)を選択し、ボタンを押します。これで ATOM C3 というMIDIデバイスとBluetooth接続されます。

 以下では、MIDIデバイス(マイコン)として XIAO samd21 をUSB接続することを想定して説明しています。 XIAO ESP32C3 をBluetooth接続しても同じように動作します。

5.2 ブラウザの操作でLEDの点灯・消灯

 画面上のボタンが押されるとプログラムが実行される例(led1.html)です。

<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>LEDの点灯・消灯</title> <script src=webio2.js></script> </head><body> <h2>LEDの点灯・消灯</h2> <button onclick=digitalWrite(D9,1)>点灯</button> <button onclick=digitalWrite(D9,0)>消灯</button> <script> function setup(){ // --- はじめに自動実行 --- pinMode(D9,OUTPUT); // D9を出力に } </script> </body></html>

 led1.html が表示され、MIDIデバイス(マイコン)が認識されると、setup関数が呼び出されます。

 setupの関数定義の中の

はD9ピンをOUTPUTモード(出力)にする指示です。

 pinMode関数はwebio2.jsの中で定義されています。また、D9はピン番号、OUTPUTは入出力モードで、その値もwebio2.jsの中で定義されています。値は使用するマイコンによって異なり、MIDIデバイス(マイコン)が認識された時点で自動的に値が決まります。XIAO samd21の場合、D9の値は9、OUTPUTの値は1です。

 pinMode(9,1)が呼び出されると、 [0xE8,0x09, 0x0F] の3バイトのMIDIデータがMIDIデバイス(マイコン)に送信されます(MIDIデータの詳細は付録1)。

 MIDIデバイス(マイコン)は3バイトのMIDIデータを受け取り、内容を解読し、9ピンを出力モードにします。

 ボタンが押されると、

が呼び出され、これはD9ピンに1を出力する指示です。digitalWrite関数はwebio2.jsの中で定義されていて、digitalWrite(9,1)が呼び出されると、 [0xE8, 0x09, 0x0F] の3バイトのMIDIデータがMIDIデバイスに送信されます(MIDIデータの詳細は付録1)。

 MIDIデバイス(マイコン)は3バイトのMIDIデータを受け取ると、内容を解読し、9ピンに1(高い電圧)を出力し、LEDが点灯します。

 同様に、ボタンが押されると、

が呼び出され、 [0xE8, 0x09, 0x0F] の3バイトのMIDIデータがMIDIデバイスに送信されます。MIDIデバイス(マイコン)は3バイトのMIDIデータを受け取ると、9ピンに0(低い電圧)を出力し、LEDが消灯します。

5.3 スイッチの状態をブラウザ画面に表示

 スイッチの状態(オフで1, オンで0)をブラウザ画面に表示する例(button2.html)です。LEDも連動して点灯・消灯します。

<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>スイッチの状態</title> <script src=webio2.js></script> </head><body> <h2>スイッチの状態</h2> <span id=VAL style='font-size:80pt'></span> <script> function setup(){ // --- はじめに自動実行 --- pinMode(D2,INPUT_PULLUP);// D2をプルアップ入力に pinMode(D9,OUTPUT); // D9を出力に } function loop(){ // --- 20ms毎に自動実行 --- var val=digitalRead(D2); // D2の値を読み取りvalに代入 digitalWrite(D9,val); // D9にvalを出力 $("VAL").innerHTML=val; // ブラウザ画面にvalを表示 } </script> </body></html>

 button2.html が表示され、MIDIデバイス(マイコン)が認識されると、setup関数が呼び出されます。

 setupの関数定義の中に記載されている

はD2ピンをINPUT_PULLUPモードにする指示で はD9ピンをOUTPUTモードにする指示です。D2はピン番号、INPUT_PULLUPは入出力モードで、XIAO samd21の場合、D2の値は2、INPUT_PULLUPの値は2になっています。

 pinMode(9,1)が呼び出されると、 [0xE8,0x09, 0x01] の3バイトのMIDIデータがMIDIデバイス(マイコン)に送信され、MIDIデバイス(マイコン)はこれを受け取り、内容を解読し、9ピンを出力モードにします。

 pinMode(2,2)が呼び出されると、 [0xE8,0x02, 0x02] の3バイトのMIDIデータがMIDIデバイス(マイコン)に送信され、MIDIデバイス(マイコン)はこれを受け取り、内容を解読し、2ピンをプルアップ入力モードにします。2ピンにはスイッチがつながっていて、スイッチがオフの時に1(高い電圧)、オンの時に0(低い電圧)になります。マイコンは定期的(20ms毎)にこの値を読み取り、「初回および変化があった時」に、[0xE8,0x09, 0x0E](ピンが0の時)または[0xE8,0x09, 0x0F](ピンが1の時)の3バイトのMIDIデータをパソコンに送信します。

 Javascriptプログラムでは、20ms毎に実行されるloop関数の中の

で、D2ピンの値(0または1)がvalに代入されます。続く で、[0xE8, 0x09, 0x0E](valが0の時)または[0xE8, 0x09, 0x0F](valが1の時)の3バイトのMIDIデータがMIDIデバイス(マイコン)に送信されます。

 MIDIデバイス(マイコン)は3バイトのMIDIデータを受け取ると、内容を解読し、9ピンに0(低い電圧)または1(高い電圧)を出力します。

 loop関数の中では引き続き、

で「VAL」の箇所(<span id=VAL ...></span>)にvalの値(0または1)を表示します。


(付録1) Midiコマンドとの対応(WebIO2のプロトコル)

機能 send(PC → I/O) receive(I/O → PC)JavaScript関数備考
byte1byte2byte3 byte1byte2byte3
8x [midi] NoteOff 1000nnnn0kkkkkkk0vvvvvvv 1000nnnn0kkkkkkk0vvvvvvv 音を停止
9x[midi] NoteOn 1001nnnn0kkkkkkk0vvvvvvv 1001nnnn0kkkkkkk0vvvvvvv sendNote(key, t)
sendNote(key, t, ch)
key0-125のブザー音をt[ms]出力
ch0-15を指定できる
Ax[midi] Pressure 1010nnnn0kkkkkkk0vvvvvvv
Bx[midi] Control Change 1011nnnn0ccccccc0vvvvvvv
Reset 1011nnnn0111100100000000 reset() Reset All Control
AllNoteOff 1011nnnn0111101100000000 All Note Off
Cx[midi] Program Change 1100nnnn0ppppppp setVoice(ch, voice) ch0-15を音源0-127に
Dx[midi] Pressure 1101nnnn0vvvvvvv
Ex[midi] Pitch Bend 1110nnnn0lllllll0mmmmmmm
(Reserved) 512Byte 11100xxx
(E0-E7)
0xxxxxxx0xxxxxxx 11100xxx
(E0-E7)
0xxxxxxx0xxxxxxx
PinMode
DigitalOut
11101000
(E8)
00pppppp0000mmmm
0000111v
pinMode(pin, mode)
digitalWrite(pin,val)
digitalWrite(pin,1,t)
pin0-63のpinModeをmode0-13に
pin0-63を0/1に
tを指定した場合は t[ms] 1に
DigitalIn 11101000
(E8)
00pppppp0000111v digitalRead(pin) pin0-63の値0/1 (20ms毎に更新)
AnalogOut 11101000
(E8)
01vppppp0vvvvvvv analogWrite(pin, val) pin0~31を0-255に
ServoMotor
Motor
11101001
(E9)
00vppppp
00v1111p
0vvvvvvv
0vvvvvvv
servo(pin, val)
servo(pin, val, t)
motor(lspeed, rspeed)
pin0~29のサーボモーターを0-180に
tを指定した場合はt[ms]後に停止
L(30) R(31)モーターのスピードを -128~127に
(Reserved) 32Byte 11101001
(E9)
01xxxxxx0xxxxxxx
AnalogIn 11101001
(E9)
0vvvvvpp0vvvvvvv analogRead(pin) TEMP(0:60),HUMI(1:61),CO2(2:62)の値0-4095
AnalogIn 1110101v
(EA-EB)
0vvppppp0vvvvvvv analogRead(pin) pin0~31の値0-1023(20ms毎に更新)
NeoPixel 11101010
(EA)
0rgbllll0rrrrrrr Pixel(LED, R,G,B) LED0-15の色をR(0-255)G(0-255)B(0-255)に
11101011
(EB)
0ggggggg0bbbbbbb
IRsend 11101100
(EC)
0ppppppp0000aacc IRsend(&IRDATA) IRリモート信号を送信
IRDATA内に protocol, address, command
11101101
(ED)
0aaaaaaa0aaaaaaa
11101110
(EE)
0ccccccc0ccccccc
IRreceive 11101100
(EC)
0ppppppp0000aacc IRreceive(&IRDATA) IRリモート信号を受信
IRDATA内に protocol, address, command
11101101
(ED)
0aaaaaaa0aaaaaaa
11101110
(EE)
0ccccccc0ccccccc
(Reserved) 64Byte 11101111
(EF)
0xxxxxxx0xxxxxxx 11101111
(EF)
0xxxxxxx0xxxxxxx
Fx[midi] SysEx 1111xxxx 1111xxxx

(付録2) Arduino Leonardo / XIAO / ATOM のピン接続

UNO/NANO(参考)

D0/TX
D1/RX
D2
D3#
D4
D5#
D6#
D7
D8
D9#
D10#
D11#
D12
D13/LED
D14/A0
D15/A1
D16/A2
D17/A3
D18/A4/SDA
D19/A5/SCL
A6
A7
LeonardoProMicro
D0/TX
D1/RX
D2/SDA
D3#/SCL
D4/A6
D5#
D6#/A7
D7
D8/A8
D9#/A9
D10#/A10
D11#-
D12/A11-
D13#/LED-
-D14
-
-
-
D18/A0
D19/A1
D20/A2
D21/A3
D22/A4
D23/A5
60/TEMP(仮想ピン)
61/HUMI(仮想ピン)
62/CO2(仮想ピン)
XIAO samd21 XIAO RP2040 XIAO ESP32C3 XIAO ESP32S3
0/D0/A026/D0/A02/D0/A01/D0/A0
1/D1#/A127/D1#/A13/D1#/A12/D1#/A1
2/D2#/A228/D2#/A24/D2#/A23/D2#/A2
3/D3#/A329/D3#/A35/D3#/A34/D3#/A3
4/D4#/A4/SDA6/D4#/SDA6/D4#/SDA5/D4#/A4/SDA
5/D5#/A5/SCL7/D5#/SCL7/D5#/SCL6/D5#/A5/SCL
6/D6#/A60/D6#21/D6#43/D6#
7/D7#/A71/D7#20/D7#44/D7#
8/D8#/A82/D8#8/D8#7/D8#/A8
9/D9#/A94/D9#9/D9#8/D9#/A9
10/D10#/A103/D10#10/D10#9/D10#/A10
13/D13#/LED---
60/TEMP(仮想ピン)
61/HUMI(仮想ピン)
62/CO2(仮想ピン)
ATOM liteATOMS3 lite
G25/SDAG38
G21/SCLG39
G22G5
G19G6
G23G7
G33G8
G26/Grove out/SDAG2/Grove out/SDA
G32/Grove in/SCLG1/Grove in/SCL
G27/RGB-LED35/RGB-LED
G12/IR-LEDG4/IR-LED
G39/buttonG41/button
60/TEMP(仮想ピン)
61/HUMI(仮想ピン)
62/CO2(仮想ピン)

(付録3) Leonardo / XIAO / ATOM のピンモード

mode Leonardo
ProMicro
XIAO samd21
XIAO RP2040
XIAO ESP32 C3/S3
ATOM C3/S3 lite
INPUT 001
OUTPUT 113
INPUT_PULLUP225
INPUT_PULLDOWN-39
INPUT_ANALOG6
OUTPUT_ANALOG7
OUTPUT_TONE10
OUTPUT_NEOPIXEL11
INPUT_IR-12
OUTPUT_IR-13

koyama88@cameo.plala.or.jp