QRコード光通信

2台のスマートフォンの画面を向かい合わせ、送る側は QR コードを次々に表示し、受け取る側は「どこが届いたか」を QR コードで返します。送る側は届いた部分を飛ばして、まだ届いていない部分だけを送り直します。Wi-Fi もモバイル回線も使いません。データは端末の外に出ません。

実用品ではなく、画面とカメラだけでどこまで通信できるかを試す実験です。Android 2 台で試したところ、速さは毎秒約 300 バイトで、450 KB の画像を送るのに約 26 分かかりました。

送るもの

置き方

  1. 2台ともこのページを開き、片方で「送る」、もう片方で「受け取る」を押します。
  2. 画面どうしを 15〜25cm 離して向かい合わせ、上端(前面カメラのある側)どうしをそろえます。QR コードは画面の上端に出るので、相手のカメラの正面に来ます。
  3. 近すぎると前面カメラのピントが合いません。「相手の QR コードを探しています」が消えるまで、距離を変えてみてください。
  4. 手で持つより、片方を机に置き、もう片方を本などに立てかけるほうが安定します。
詳細設定

version と表示時間は、送る側の設定です。自動のときは、受け取る側が「表示した枚数のうち何枚読めたか」を返すので、それから 1 秒あたりに届くバイト数を見積もり、1 段ずつ試して速くなるほうを採ります。

コラム

QR コードの通信は、なぜ毎秒 300 バイトしか出ないのか?

このツールで Android 2 台の間で 450 KB の画像を送ったところ、約 26 分かかりました。毎秒約 300 バイトです。画面とカメラだけの通信でも、ほかの例では毎秒 200 KB 近く出ているものがあります。何が違うのでしょうか。

答え: 返事を返すために画面を向かい合わせているので、受け取る側は前面カメラで読むことになります。前面カメラで読めたのは 37×37 マスの小さな QR コード(1 枚 72 バイト)で、それを毎秒 4〜5 枚しか読めませんでした。

速さは「1 枚に載るバイト数 × 1 秒に読める枚数」

このツールは、送るデータを 7 バイトずつ 17 桁の数字に直して QR コードに載せます。Web ブラウザの読み取りの機能は結果を文字列で返すので、バイト列をそのまま載せると文字コードの推定で壊れるからです。数字なら、そのまま載せた場合の 98.8% を運べます。37×37 マスの QR コード(version 5)に誤り訂正を M で載せると、数字が 202 桁入ります。202 桁はバイトに直すと 83 バイトで、そこから番号や位置などの見出し 11 バイトを引いた 72 バイトがデータです。受け取る側は毎秒 4〜5 枚読めていたので、72 × 4.5 ≒ 320 で、毎秒約 320 バイトになります。実測の約 300 バイトとほぼ合います。

速くするには、1 枚に載せる量を増やすか、1 秒に読む枚数を増やすかのどちらかです。たとえば 57×57 マス(version 10)なら 1 枚 200 バイトになり、同じ枚数でも毎秒約 900 バイトになります。ただ、前面カメラは背面カメラより画素が少ないものが多く、マスが細かくなると読めなくなります。実機では、始めに試した 41×41 マス(version 6)から 37×37 マスに下がりました。

ほかの例と比べると

返事を返すかどうかで、置き方が決まる

Decimen は送る一方で、受け取る側は返事を返しません。その代わりに、元のデータから作った大量のフレームを流し、受け取る側は「どれでもよいので必要な枚数より 15% ほど多く」集めれば元に戻せる符号(ファウンテン符号)を使っています。返事が要らないので、受け取る側は画面を相手に見せる必要がなく、背面カメラを送る側の画面に向けられます。

このツールは、受け取る側が「どこが届いたか」を QR コードで返し、送る側は届いた部分を飛ばします。どちらの端末も、画面を見せながら相手の画面を撮るので、画面と同じ面にある前面カメラを使うことになります。返事があるので、読み損ねた部分だけを送り直せて、送る側は受け取る側の読み取りの速さに合わせて切り替えの間隔を変えられます。その代わりに、カメラの性能で一番低いほうに合わせることになりました。

速くするための案

まだ試していない案が 4 つあります。互いに邪魔しないので、組み合わせられます。