うな(。・ε・。)

Android, iOS, AppEngine まわりのめもめも

かんたんな変調・復調を実装してみる

超音波通信を実装してみたくて、もっともカンタンに実装できる方法を調査してみました。

もっとも単純な方法で、ノイズがのってもいいような伝達手段を考えます。

変調・復調

波形(音波)に情報を載せることを変調、波形から情報を取り出すことを復調といいます。

FSK変調

変調方式の一つです。 一定時間ごとに、低周波と高周波を切り替えます。低周波を0, 高周波を1に割り当てることによりビット列を表すことができます。

振幅にいくらノイズが載ろうが問題ないこと、復調が比較的単純に行えることから、単純な実装をしたいときに使われます。

実装的には、出力サイン波の周波数をビット列に合わせて切り替えるだけなのでカンタンです。(サイン音波を出すのはオーディオでは基本なのでカンタンです)

https://raw.githubusercontent.com/ezefranca/FSK-Arduino-iOS7/master/FSK-Demo/image.png

FSK復調 (FFT)

あまり直感的な方法ではないですが、波形をフーリエ変換にかければ、周波数成分をとりだすことができます。つまり、どんな周波数が波形に乗っているかがわかります。

ですから、一定時間ごとに波形をフーリエ変換にかけてやり、もっとも大きい周波数成分が低周波、高周波のどちらに近いかを判定することで、その時間帯のビットを取り出してやることができます。 この方法の利点はいくら低周波帯にノイズが乗ろうがまったく無視することができることです。

フーリエ変換FFT という派生アルゴリズムでさまざまな言語に実装されていますので楽チンです。

下図は 16kHz, 18kHz の音波を発生させ、iOS のアプリを用いて FFT しグラフとして表示した結果になります。

f:id:liedderoptik:20151030182155j:plain

16kHz, 18kHz 帯にキレイに線が立っています。低周波帯に環境音のノイズがたくさん乗っていることもわかります。

開始文字・終端文字

どこからどこまでが一つの通信なのかを表すコードを決めておきます。ASCII コードにはそのようなコードがあらかじめ定義されているので、それを用いればいいです。(従って、ビット列は ASCII コードを使って文字列として表すことにします)

  • SOH(x01) = 通信開始
  • EOT(x04) = 通信終了

"Hello" を送るためには次のようなビット列を送ることになります。

01 48 65 6C 6C 6F 04 (文字多くなるため16進数)

FSKの伝送効率

FSKの伝送効率は「一定時間」をいくらとるかによります。一定時間を T と書けば、T 秒ごとに一つのビットが決まるため、1/T [bit/s] が伝送効率になります。

仮に低周波に 18kHz を使い、T としてその 16 周期分をとると、T = 0.000888.. となります。ですから、伝送効率は 1136.4 [bit/s] となり、おおよそ 1 秒に 142 バイトを送ることのできる計算になります。原始的ですね。

FSKの誤差

次の原因で誤差が生じます。

  • いくら周期をとるか
  • 低周波と高周波でいくら周波数の違いがあるか
  • ノイズがのっていないか

誤差をカバーするために通信の最後にチェックサムを付加してやるのがいいと思います。

参考文献