Web Serial API を利用できる p5.js用のライブラリ「p5.web-serial」で micro:bit とのシリアル通信（p5.js Web Editor・MakeCodeを利用）

今まで見かけていた「p5.js でシリアル通信を使うライブラリ」というと、公式ページで紹介されている「[p5-serial/p5.serialport](https://github.com/p5-serial/p5.serialport)」があったのですが、それとは別の最近リリースされたっぽいライブラリを見かけました。
そこで、その新しいライブラリを [p5.js Web Editor](https://editor.p5js.org/)上で試してみた、というのがこの記事の内容です。

## ongzzzzzz/p5.web-serial の仕組みについて
今回試してみるのは「[ongzzzzzz/p5.web-serial](https://github.com/ongzzzzzz/p5.web-serial)」というライブラリです。
上記の「p5-serial/p5.serialport」との違いは、Webページ上でシリアル通信を実現する方法です。

「p5-serial/p5.serialport」のほうは、「p5.serialcontrol application または p5.serialserver」という仲介役となるアプリを動かしつつ、それと別に p5.js のプログラムを動かす構成になるようです。
一方、「ongzzzzzz/p5.web-serial」のほうはブラウザの Web Serial API を用いており、そのような仲介役になるアプリを別に用意することなくシリアル通信を行えます。ただし、[Web Serial API をサポートしているブラウザは限定的（基本的に Chrome系のみ）](https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility)であるため、その点は注意が必要です。

### 【余談】 Web Serial APIについて
余談ですが、Web Serial API を利用した通信について、過去にいくつか記事を書いているので、Web Serial API が気になるという方は、よろしければご覧ください。

- 過去に書いた記事
   - [Web Serial API を使って micro:bit からセンサーの値（XYZ）を読み取る＆リアルタイムなグラフ化](https://qiita.com/youtoy/items/6394a5570ddd54a2ce87)
   - [Web Serial API を使って micro:bit からセンサーの値を読み取る（途中段階まで）](https://qiita.com/youtoy/items/9606c58369796a65f8f5)
   - [Web Serial API を使った micro:bit への値の書き込み](https://qiita.com/youtoy/items/f77dc205e817f31a4e18)
   - [Web Serial API を最短の手順で試したくてやったこと（micro:bit を利用）](https://qiita.com/youtoy/items/a0071a6d2ef7f6930d33)

## ongzzzzzz/p5.web-serial を使ってみる
それでは、p5.js Web Editor上で ongzzzzzz/p5.web-serial を使ってみます（ブラウザは Google Chrome を利用します）。

### 簡単な動作確認まで行う
まずは、index.html に以下の行を追加します（※ [公式の GitHubリポジトリで紹介されているリンク](https://github.com/ongzzzzzz/p5.web-serial#getting-started)です）。

```html
    <script src="https://cdn.jsdelivr.net/gh/ongzzzzzz/p5.web-serial/lib/p5.web-serial.js"></script>
```

そして、script.js のほうで公式のサンプルを動かしてみます。
`// additional code here...` と書かれた部分は何も修正せずという状態で、動作確認だけを行います。

```javascript
let port, reader, writer;

async function setup() {
  createCanvas(400, 400);

  // additional code here...

  noLoop();
  ({ port, reader, writer } = await getPort());
  loop();
}

function draw() {
  background(220);
}
```

上記のプログラムを実行すると、プレビュー画面のほうに以下の表示が行われます。
![サンプルの実行例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/a78b1522-d41e-c8da-aa55-3623bc9dd661.png)

そして、表示された2つのボタンのうちの左側のものを押すと、以下のように Web Serial API の利用許可を求めるダイアログが表示されました。
![APIの利用要求](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/bebfdadf-d6a5-2f46-40d9-710867915c06.png)
ここで本来は、シリアル通信に使いたいシリアルポートを選択する操作を行うのですが、今時点ではシリアル通信をさせたいデバイスをつないでないので、表示が出ることだけ確認しておきます。

### デバイスとの通信を行ってみる（ブラウザからの書き込み）
[Sending data from the browser to the Arduino](https://github.com/ongzzzzzz/p5.web-serial#sending-data-from-the-browser-to-the-arduino) という部分を見つつ、ブラウザからの書き込みを試してみます。

#### p5.js側のプログラム
ちなみに、公式ページには以下の例が書かれています。

```javascript
async function draw() {
	if (port) {
		try {
			if (mouseIsPressed) {
                // do something...
				await writer.write("clicked!\n");
			}
			else {
                // do something...
				await writer.write("not clicked!\n");
			}
		} catch (e) { console.error(e) }
	}
}
```

こちらは、デバイスとの間でのシリアル通信できる状態で、マウスのボタンを押しているかどうかによって、異なる文字列を書きこむもののようです。

先ほど動作確認を行ったプログラムに混ぜ込みつつ、少し変更を加えて動かしてみます。
まず、sketch.js は以下にしました。

```javascript
let port, reader, writer;

async function setup() {
  createCanvas(400, 400);

  noLoop();
  ({ port, reader, writer } = await getPort());
  loop();

  frameRate(4);
}

async function draw() {
  if (port) {
    try {
      if (mouseIsPressed) {
        background("BLUE");
        await writer.write("AAA\n");
      } else {
        background("BLACK");
      }
    } catch (e) {
      console.error(e);
    }
  }
}
```

#### micro:bit側のプログラム
あとはデバイス側の準備です。
[p5.web-serial/examples/web-to-arduino/main.ino](https://github.com/ongzzzzzz/p5.web-serial/blob/main/examples/web-to-arduino/main.ino) に Arduino用のサンプルプログラムが掲載されていますが、自分は過去の Web Serial API のお試しで使った micro:bit を使います。

micro:bit用のプログラムは、以下の内容のものを MakeCode で作りました。

![MakeCode で作ったプログラム](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/cd853a74-522a-22fe-3ae7-7ad99b259b95.png)

それでは micro:bit へプログラムを書きこみましょう。

#### 実際の動作の様子
プログラムを書き込み済みの micro:bit と PC を USB で接続した状態で、p5.js のプログラムを実行します。

プレビュー画面に表示される以下の画面で、「Add a device」と書かれたボタンを押し、その後に表示されるダイアログ上に micro:bit という名前を含むものがあると思いますので、それを選んでください。
そして、「Connect!」と書かれたほうのボタンを押します。
![シリアルポートの選択のプルダウンが表示される](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/1ccb5b7d-da6d-ad67-85a7-ad17167f6c89.png)

そうすると、プレビュー画面が以下のような表示になるので、プレビュー画面上をマウスでクリックしてください。マウスをクリックしてない時は黒背景で、クリックをした時に青背景になると思います。

![micro:bitとの接続後の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/a8fefe9e-2342-ec09-96a7-96f98e2ecec1.png)

そして、クリックをした時には micro:bit側で、以下の動画にあるような LED表示の変化が起こると思います。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/p5js?src=hash&amp;ref_src=twsrc%5Etfw">#p5js</a> のプログラムと <a href="https://twitter.com/hashtag/microbit?src=hash&amp;ref_src=twsrc%5Etfw">#microbit</a> との Web Serial API を使ったシリアル通信！（mouseIsPressed に反応する形）<br>↑記事も書いた<br><br>●Web Serial API を利用できる p5.js用のライブラリ「p5.web-serial」で micro:bit とのシリアル通信（p5.js Web Editor・MakeCodeを利用）<br>　<a href="https://t.co/3vsdSUi5xV">https://t.co/3vsdSUi5xV</a> <a href="https://t.co/i7hymLvFDV">pic.twitter.com/i7hymLvFDV</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1510205250481065987?ref_src=twsrc%5Etfw">April 2, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

無事、意図通りに動いたことを確認できました。