LoginSignup
5
1

More than 5 years have passed since last update.

ETロボコン Bluetoothログ受信

Last updated at Posted at 2018-12-23

こちらの記事はケーシーエスキャロット Advent Calendar 2018の24日目の記事です。

今年度もETロボコンに参加したのですが、難所エリアに階段が加わって大変苦労しました。
階段に限らず攻略に際して、段差だったり距離だったりを計測する必要があったのですが、計測するにはログに出力して確認する必要があります。
という訳で、VB.Netを使用してBluetooth 経由でロボットからログを取得・表示するツールを作成してみたいと思います。

準備

上記で記載した通り、VB.Netを使用するので、以下をインストールします。

  • Visual Studio 2017 Community 2017

プロジェクトの生成

ファイル > 新規作成 > プロジェクトから、Visual Basicの「Windowsフォームアプリケーション(.NET Framework)」を選択して新規プロジェクトを生成します。
(プロジェクト名などは適宜変更)

フォームの配置

プロジェクト作成後、フォーム上に以下の図のようにコンポーネント群を配置します。
frm1.png

コード(VB.Net)

コンポーネントを配置したら、コードを記載していきます。

ポート情報の取得

コンピュータで使用可能なシリアルポートを列挙して、コンボボックス内に追加しています。

    ''' <summary>
    ''' 接続可能なポート番号の取得・設定
    ''' </summary>
    Private Sub initPortName()
        ' ポート番号の取得・ソート
        Dim portNames As String() = SerialPort.GetPortNames()
        Array.Sort(portNames, StringComparer.OrdinalIgnoreCase)

        With Me.cmbPort
            .Items.Clear()

            For Each port In portNames
                .Items.Add(port)
            Next

            .SelectedIndex = 0
        End With
    End Sub

ポートのオープンクローズ

先で追加したコンボボックスで選択したポートでシリアルポートをオープン・クローズする処理です。

    ''' <summary>
    ''' Bluetooth ポートオープン
    ''' </summary>
    Private Sub openBluetooth()
        Try
            With Me.spBluetooth
                'オープンするシリアルポートをコンボボックスから取り出す.
                .PortName = Me.cmbPort.SelectedItem.ToString()

                'ボーレートをコンボボックスから取り出す.
                .BaudRate = 7200

                'データビットをセットする. (データビット = 8ビット)
                .DataBits = 8

                'パリティビットをセットする. (パリティビット = なし)
                .Parity = Parity.None

                'ストップビットをセットする. (ストップビット = 1ビット)
                .StopBits = StopBits.One

                '文字コードをセットする.
                .Encoding = Encoding.UTF8

                'シリアルポートをオープンする.
                .Open()

                Me.btnConnect.Enabled = False
            End With
        Catch ex As Exception
            MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
    ''' <summary>
    ''' Bluetooth ポートクローズ
    ''' </summary>
    Private Sub closeBluetooth()
        Try
            Me.spBluetooth.Close()
        Catch ex As Exception
            MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

データの送受信

ここでは、シリアルポートから受信したデータをリストへ書き込み、また、データを送信する処理を実現しています。

    Private Delegate Sub addRecvLogDataDelegate(recv As String)

    ''' <summary>
    ''' 受信文字列の追加
    ''' </summary>
    ''' <param name="recv">受信文字列</param>
    Private Sub addRecvLogData(recv As String)
        If IsNothing(recv) Then
            Return
        End If

        Me.lstLog.Items.Add(recv)
        Me.lstLog.SelectedIndex = Me.lstLog.Items.Count - 1
    End Sub
    ''' <summary>
    ''' 指定文字列の送信
    ''' </summary>
    ''' <param name="text">送信文字列</param>
    Private Sub sendText(ByVal text As String)
        Try
            'シリアルポートからテキストを送信する.
            Me.spBluetooth.Write(text.TrimEnd())
        Catch ex As Exception
            MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

イベントハンドラ

フォーム上に追加したコンポーネント群のイベントハンドラを追加します。

    ''' <summary>
    ''' フォーム ロードハンドラ
    ''' </summary>
    Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        initPortName()
    End Sub
    ''' <summary>
    ''' 接続ボタンクリックハンドラ
    ''' </summary>
    Private Sub btnConnect_Click(sender As Object, e As EventArgs) Handles btnConnect.Click
        If Me.spBluetooth.IsOpen Then
            closeBluetooth()
        Else
            openBluetooth()
        End If
    End Sub
    ''' <summary>
    ''' 送信ボタンクリックハンドラ
    ''' </summary>
    Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
        sendText("1")
    End Sub
    ''' <summary>
    ''' シリアルポート 受信ハンドラ
    ''' </summary>
    Private Sub spBluetooth_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles spBluetooth.DataReceived
        'オープンしていない場合、処理を行わない.
        If Not Me.spBluetooth.IsOpen Then
            Return
        End If

        Try
            'メインスレッドへ受信データを渡す
            Invoke(New addRecvLogDataDelegate(AddressOf addRecvLogData), Me.spBluetooth.ReadExisting())
        Catch ex As Exception
            MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

起動確認

以上でツールは完了です。
動かして、コンボボックスをクリックすると、シリアルポートが表示されると思います。

combo.png

コード (C)

続いて、ロボット側(C)ですが、こちらはサポートサイトに記載があるので、起動開始部分とログ送信部分を抜粋するに留めます。

起動開始部分

    // Bluetooth接続
    while(!ev3_bluetooth_is_connected()){
        tslp_tsk(100);
    }

    FILE* bt = ev3_serial_open_file(EV3_SERIAL_BT);

    while (1) {
        uint8_t c = fgetc(bt);
        if (c == '1') {
           // スタート処理
           break;
        }
    }

    fclose(bt);

ログ送信部分

    const char *pMsg = "Hello EV3!";

    FILE* sp;

    sp = ev3_serial_open_file(EV3_SERIAL_DEFAULT)

    fprintf(sp, "%s\r\n", pMsg);

    fclose(sp);

動作確認

確認準備

コード部分は完了したので、ログの受信が行えます。
…が、以下の設定を行う必要があります。

  • rc.conf.ini ファイルの修正

  • ペアリングの設定

ロボット内の設定ファイル(rc.conf.ini)で以下の記載を行います。

[Bluetooth]
LocalName=xxxxxx
PinCode=xxxx
[Debug]
DefaultPort=BT

あとは、実際にロボットを起動してペアリングを行えば、準備完了です。

動作検証

ロボットおよびツールを起動します。
接続ボタンを押下して、実際に接続が完了すると、接続ボタンがDisable状態になります。
その状態から、開始ボタンを押下すると、ロボット側に「1」が送信されて、ロボット側から送られてくるログがリストボックス上に表示されます。

log.png

最後に

いかがでしょうか。
これでログの受信が行えるようになりました。
ただ、このままだと使い勝手が悪いので、受信したログをファイルに落とせるようにしたり、ログにキーワードを紐付けて、絞り込み表示にしたりすると利便性が高まると思います。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1