2014年9月26日金曜日

Beetle Module 使ってみた

 初めまして。石川高専の長田といいます。
 私、インターンシップのため24日から横山商会さんで研修させて頂いているのですが、今日は、その課題の一つとして、横山商会さんが開発しておられる無線モジュールのBeetle Moduleを使わせて頂いたので、それについていろいろ書いてみます。

1.Beetle Moduleについて


 このビジュアル…まさにビートル!! かっこいい。

 はい。見た目は置いておいて、Beetle Moduleとはなんぞやと思われる方もいると思いますので、説明させていただきますと、無線通信を行うために基板に接続して使用するモジュールです。

 ARIB STD-T108規格に対応し、モジュール単体で電波を飛ばせる距離が長く、中継なしでも長距離通信を実現できます。また、使用する周波数帯に応じて3つの通信モードを選択可能なので、幅広い用途に使えます。

 今回は、一台のPCに、Beetle Moduleを装着した基板を二つ繋いで、互いに無線通信を行います。その際にやりとりする信号を、PCとのシリアル通信で制御します。

 まずはそのために必要なものを揃えます。
  1. Beetle Moduleを装着した基板およびUSBケーブル
  2. PCとモジュールとのシリアル通信を可能にする通信ソフト
 大まかにこんな感じです。まず、PCと接続してみます。

 このように二つ繋ぎます。
 接続したら、ちゃんとPCが認識しているか確認します。
 デバイスマネージャを開いて、ポートの項目を開きます。
 COM4とCOM5に、しっかり認識されていますね。

 では、さっそく無線通信…の前に、PCからシリアル信号を送るための環境を揃えねば。
ポートを指定して通信を行うTeraTermというソフトがあるので、それをインストールします。
まずはTeraTermで検索して出てくる公式サイトを開きます。

2.環境構築


 とりあえず最新版を選択し、ダウンロード→インストールを行いました。
 では、必要なモノは揃ったので、TeraTermを起動しさっそく無線通信を試してみます。

 先ほどのデバイスマネージャで確認したポートを選択して、OK。
 さらに追加でTeraTermを起動し、もう一つのポートを選択。

 こうなります。
 これでもう文字を打ち込めばそのままデータが送受信されますが、その前にちょっとした下準備を。[設定]→[端末]を開きます。

 赤丸で囲った部分を、図のように変更します。
 受信した際の改行コードをCR+CLに設定することで、改行コードを読み取って改行します。また、ローカルエコーにチェックを入れることで、送信側のウインドウに、送信した内容が表示されるようになるので、使いやすくなるでしょう。
 以上で設定は終わりです。
 では、さっそくウインドウに文字を打ち込んでみます。

3.実践

 図では、COM4に接続したモジュールからもう一方のモジュールに無線信号を送り、受信したデータをCOM5から表示しています。
 応答速度は特に違和感なく、遅延などは気になりません。
 今回は同一PCで実験していますが当然別々のPCで繋いでも同様の通信が行えます。
 以上で、BeetleModuleの導入は終わりです。シンプルでわかりやすかったです。

 …ですが、導入してはい終わり、では寂しいので、この無線通信を使ってアプリを作ってみます。
C#を使って簡単なチャットアプリを作ってみました。(ソースコードをページ末尾に載せてあります)

 中身はなんてことはないただのシリアル送受信アプリですが、これを使ってちょっとした実験をば。
 どれほどの容量、速度までなら特に不都合を感じることなく通信できるのでしょう。
 アプリに、間隔を指定して連続で信号を送るボタンを作っておいたので、それで試してみます。

 まずは、0~9の数字を順番に100ミリ秒間隔で3秒間送信してみます。
 順番に値が表示され、最終的な結果はこんな感じ。0~9の数値が二回ずつと、最後は7で打ち切られ合計28字が出力されています。
 3秒間で合計30回送信しているはずなのに28字しか出力されていないのが不思議です。とりあえず少し送信速度を落として、100ミリ秒ではなく200ミリ秒間隔で3秒間送信してみます。

 出力結果は012345678901234で、合計15文字。入力と一致しています。どうやら先ほどの場合は送信速度が速すぎたようですね。
試しに、今度は70ミリ秒間隔で3秒間送信してみます。
ん……?データが表示されないぞ……
と思ったら3秒経過と同時にまとめて表示されました。(図だとわかりにくいですが…)

これはどういうことだろう。基板の挙動に注目してみます。
 上記のいくつかの入力を何度か試してみたところ、どうやら、上の写真の赤丸で囲った部分が無線通信の状態を表しているようです。データの送受信を行っている際に、送信側は左の緑と赤のランプが点灯し、受信側は黄色のランプが点灯していました。

 そこで最後の例をもう一度試して注目してみたところ、初めの数秒間は送信側の緑のランプだけが点灯し、3秒後に受信側の黄色のランプと送信側の赤のランプが点灯していました。
 製品開発部の方にお伺いしたところ、受信したデータの間隔が速すぎる場合には、受信した信号をその都度ポートに送るのではなく、ある程度バッファに溜めてから送っているそうです。
 今回の場合は、バッファの限界値に到達する前に3秒経過したために受け取ったデータが処理されシリアルポートに送られたのでしょう。
 それを確かめるために、今度はより速い50ミリ秒間隔で3秒間通信を行ってみます。

 画像だとわかりづらいですが、おおよそ10文字ずつ一気に表示され、画像の結果となっています。

 また、送信するデータを1文字ずつではなく、2文字ずつ、3文字ずつと試してみたところ、100ミリ秒間隔やそれより遅い間隔で送信しても同じような、つまり入力したデータを順次表示するのではなく、まとめて表示するようになりました。
 バッファに溜めて処理するか否かの判断は送信速度だけではなく、データの容量にもよるようです。
 
 導入も手軽で使いやすく、高速・大容量の通信にも無理なく対応していました。
他にもある様々な機能があるらしいので、とても楽しみです。

以下にテスト時に使用したソースコードを付録します。

public partial class Form1 : Form
{
    private delegate void Del();
    public Boolean portOpen = false;
    public String sendStr = "";
    public int sendInt = 0;
    public Form1()
    {
        InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        serialPort1.DataReceived += serialPort1_DataReceived;//シリアルポートの設定
    }
    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {//シリアルポートからの入力があったときの処理
        Byte[] dat = new Byte[serialPort1.BytesToRead];
        string str;//表示するテキスト
        serialPort1.Read(dat, 0, dat.GetLength(0));
        str = System.Text.Encoding.GetEncoding("UTF-8").GetString(dat);
        new Thread(new ThreadStart(delegate
        {
            Invoke((Del)delegate
            { // 匿名メソッドを Del 型にキャストし, それを呼び出す。
                textBox1.Text += str;
            });
        })).Start();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        string portName;
        portOpen = !portOpen;
        if (portOpen == true)
        {
            portName = comboBox1.SelectedItem.ToString();
            serialPort1.PortName = portName;
            serialPort1.Open();
            connection.Text = "接続中";
        }
        else
        {
            serialPort1.Close();
            connection.Text = "未接続";
        }
    }
    private void button2_Click(object sender, EventArgs e)
    {
        sendStr = textBox2.Text;
        serialPort1.Write(sendStr);
    }
    private void timer1_Tick(object sender, EventArgs e)
    {
        if (IntOrStr.Checked == true)
        {
            serialPort1.Write(sendInt.ToString());
            sendInt++;
            if (sendInt >= 10)
                sendInt = 0;
        }
        else
        {
            serialPort1.Write(sendStr);
        }
    }
    private void rush_Click(object sender, EventArgs e)
    {//連続送信ボタンを押したとき
        timer1.Interval = (int)timerInterval.Value;//送信する間隔を設定
        timer2.Interval = 1000 * (int)timerLength.Value;//送信する時間を設定
        timer1.Enabled = !timer1.Enabled;//オンオフの切り替え
        timer2.Enabled = !timer2.Enabled;//同上
        if (IntOrStr.Checked == true)//0~9の整数を順に送るとき
        {
            sendInt = 0;
            serialPort1.Write(sendInt.ToString());//整数型で
            sendInt++;
        }
        else
        {
            sendStr = textBox2.Text;//送信する文字列を設定
        }
    }
    private void timer2_Tick(object sender, EventArgs e)
    {
        timer1.Enabled = false;
        timer2.Enabled = false;
        sendInt = 0;
    }
}

0 件のコメント:

コメントを投稿