ビュートローバーARM取扱説明書 には、「LPC-Link接続ポート(CN12)」というデバッグ用のポートの説明があります。

LPC-Link接続ポート(CN12)

ザックリと言えば、LPC-LINK とは以下のようなシロモノです(情報元:一人1台!全Cortex ARM マイコン対応デバッガのしくみ )。

  • JTAG/SWD (Serial Wire Debug) のプロトコルを介してターゲットボード上の CPU 動作を制御したり状態を調べたりすることができるインサーキット・デバッガのこと
  • SWD とは ARM が定めた JTAG 規格 を利用したデバッグ・インタフェースのこと

昔は NXP の評価ボードにオマケで付いてきたようですが、代替の LPC-Link2 と共に絶版 → MCU-Link に置き換わり、これがまたサポート対象に LPC1343 が入っていないのです。

JTAG/SWD をサポートしたデバッグ・プローブと呼ばれる装置なら使えるのかもしれませんが、真偽不明なため(調査中)、ここではソフトウェアで printf デバッグをする方法を紹介したいと思います。

printf デバッグ

ヴイストン社のブログ記事「【ロボコンに最適!】ビュートローバー・パソコン間で通信すると便利すぎた!【シリアル通信】」には、シリアル通信経由でホスト PC に文字を送る例が示されています(例題3から抜粋)。

char sentence[11];                  // charは文字を記録することができる
while (1) {                         // {}内を永遠に繰り返す
    for (i = 0; i < 2; i++) {       // for文 2回くりかえす
        data = ADRead(i);           // 赤外線センサの値をA/D変換してdataに代入

        // %01dにはiの値が1桁、%04にはdataの値が4桁で文字列に変換され
        // まとめてsentenceに文字列として格納される
        // \r\n(2文字)は改行を表す
        sprintf(sentence, "AN%01d=%04d\r\n", i, data);

        SciStrTx(sentence, 10);     // 変数sentenceに入った10文字をパソコンに送信
        Wait(20);                   // 0.02秒待つ
    }
    sprintf(sentence, "\033[1;1H"); // 1行目1列目にカーソルを戻すエスケープシーケンス
    SciStrTx(sentence, 6);          // エスケープシーケンス6文字を送信
    Wait(20);                       // 0.02秒待つ
}

SciStrTx() は一回の送信が64バイトに制限されてますし、文字列用バッファ sentence[] の準備や sprintf()Wati() など面倒ですよね。これを以下のように printf() 一発にすることがゴールです。

while (1) {                     // {}内を永遠に繰り返す
    for (i = 0; i < 2; i++) {   // for文 2回くりかえす
        data = ADRead(i);       // 赤外線センサの値をA/D変換してdataに代入

        // printf()一発で出力!!
        printf("AN%01d=%04d\r\n", i, data);
    }
    printf("\033[1;1H");        // 1行目1列目にカーソルを戻すエスケープシーケンスの命令
}

その方法を Wiki ページ「1.2.3 USBシリアル通信プロジェクトのインポート」にまとめたので、気に入ったらトライしてみてください。使用するのは sci.csci.h で、そのポイントは以下の通りです。

  • printf() を使うためのシステコール群を定義
  • 一回の送信量64バイトの制限なし
  • 残念ながら scanf() は使えず、代替として sciScanf() を定義
  • 最適化オプションを指定した時に動作しなくなるオリジナルの不具合を修正

赤外線センサの特性計測

ヴイストン社のブログを真似て赤外線センサの出力値を観測してみました。まず白地に引いた直線の黒ライン中央にローバーを置きます。そして次のような動作

  1. 右に振る(左センサが黒ラインに近くなり、左センサの出力値が上がる)→ 中央に戻す →
  2. 左に振り(右センサが黒ラインに近くなり、右センサの出力値が上がる)→ 再び中央に戻す

をプログラムします。この時の左右のセンサ値を printf()Tera Term に出力 → テキストをコピペして CSV ファイルとして保存 → Google スプレッドシート にアップロードしてグラフ化しました。

左右センサ値の出力特性

このグラフから次のことが分かると思います。

  • 左右センサ値の出力特性にバラツキがある(最大値が異なる)
  • 車体中心に対し、センサ出力がオフセットしている

左右センサ値のバラツキが大きい時は、振れ幅が等しくなるよう補正(キャリブレーション)をした方が良いでしょう。

そしてフォトセンサの位置が車体中心に対して左右非対称なのも気になります。車体を黒ラインの中心に置いた時のセンサ値(あるいは左右の差)がゼロになるよう、原点補正をした方が良い結果が得られると思います。

車体中心に対するフォトセンサの位置

またこの手のフォトセンサは赤外の中でも近赤外領域である 800nm 付近の波長に最大感度があり、また発光 LED 側の発光ピーク波長とも若干ずれています(参考情報:RPR-220 反射型フォトセンサ(フォトリフレクタ))。

太陽光や白熱電球はこの領域の波長をたっぷり含むため、フォトセンサの出力に影響を与えます。逆に蛍光灯や LED 電球には(電球色であっても)ほとんど含まれていません(出典:各種照明のスペクトル比較)。

次のグラフは太陽光の入る窓際で同じことをした結果です。こうなるとまともにライントレースはできなくなりますネ。

自然光の影響がある場合

まとめ

ソースコード上のおかしいところを見つけるにはインサーキット・デバッガには敵いませんが、LED やスイッチ待ちなどと組み合われば出費ゼロで出来る printf() デバッグもそれなりに役立ちます。

また Ardiono IDE の シリアルプロッタ より手間はかかりますが、センサ値を可視化してみれば、単にハードを組み上げソフトを動かすだけより勉強になるのではと思います。

そのうち走行させながらリアルタイムにデータの観測が出来るよう、無線化にもチャレンジしてみたいと思います (^.^)y