マイコンカーラリー用センサボードのテスト(続続)

マイコンカーラリー用センサボードのテスト(続)の続きです。

入力回路に100pFのコンデンサを取り付けて波形を見てみました。
多少波形がなまっていますが1mSのサイクルのLED ON/OFF切り替えになんとか間に合っているように見えます。

R8CのAD変換結果をグラフ表示したのが次の図です。
波形の変化はLED ON/OFFではなく白と黒の境目でセンサーを左右に振った結果です。
センサー裏面には2mmのスペーサーを張り付けています。
デジタルセンサとして見ると2mm以下の隙間であれば問題ないでしょう、アナログセンサとしての使い方では横に4mmの移動で信号レベルの上端から下端に変化します。

次に照明をあててセンサの出力変化を確認するために強力な白色LEDライトを照射してみました。

明るさは6360ルクスで日の出1~2時間後の屋外相当の明るさです。
(参考)照度と明るさの目安

ライン検出のためのアナログセンサは可視光カットフィルターのついた赤外域を使ったセンサのため白色LED照明の外乱に対しては非常に強くなっています。
下の図はセンサの位置は動かさずに照明の光を手で繰り返し遮った状態で、
グラフが多少波打っているのがLED照明の影響によるものです。

室内照明には有効な赤外センサですが太陽光にはかなり影響を受けます。
下の図はブラインド越しに漏れる太陽光を上と同じように手で遮ってみたものです。
明るさはLED照明の方が遥かに明るいのですが太陽光には赤外成分が含まれているため大きく影響を受けている様子がわかります。
ただ、オレンジ色の差分のグラフは殆ど揺れていないことからLED ON/OFFの結果から差分を取るノイズ対処法が有効であることが判ります。

一方、前方を見るスタートバーセンサの方はLED照明に負けてしまいました。
スタートバーに見立てたティッシュBOXの裏面に当たるLED照明の光を手で遮ってみたものですが光があたるとLED ON/OFFの両方ともAD変換値がほぼゼロに近づいてしまいスタートバーの検出が出来なくなっています。
実際にはこれほど強い照明が直接スタートバーに当たることは無いでしょうが安全のためにスタートバー検出用のセンサも赤外タイプに変更することにします。

 

マイコンカーラリー用センサボードのテスト(続)

マイコンカーラリー用センサボードのテストで紹介したプログラムでLEDをON/OFFしてアナログセンサの信号を観測したのが下の写真です。
アナログセンサと白色面の距離は2㎜くらいで出力がほぼ0まで振り切れます。
デジタルセンサとして使うにはこの状態がベストと思われますがステアリング制御用アナログセンサとしてはもう少し距離を長くしてセンサの視野を広げたほうが良いような気がします。

横軸は400uS/divなので約500uSで出力がON/OFFを繰り返しているのが判ります。

上図がドライブボードのアナログセンサ入力回路です。
コンデンサの値は100pFに変更しますが観測したのは最速の応答を見るためにコンデンサを外した状態の信号です。
アナログクロックを遅くしたのでコンデンサなしでもそれほど大きなノイズは発生していません。

マイコンカーラリー用センサボードのテスト

センサーボードの裏面には実装部品はありません、ケーブル、スタートバー用部品ののハンダ付け部分以外は突起がないのでクラッシュ時にコースの角などで擦ってもダメージを最小限に抑えられるようになっています。(下の写真)

基板上面にはセンサと電流制限用の抵抗だけがあります、センサ出力のプルアップ抵抗はドライブボード側に付きます。(下の写真)

A/D変換のシーケンス

アナログセンサはP70~P77に接続されていて、ステアリングVR等のアナログ信号入力をP0に割り当てています。
センサの応答時間を1mSにするためにTRAを使った249uS間隔の割り込みの中で次のシーケンスでA/Dをおこないます。

1.P7 8chのA/D変換結果をadP7OFF[]に保存(LED OFF時の値)
  センサーボードのLEDをON
  P0 6chのA/D変換開始

2.P0 6chのA/D変換結果をadP6[]に保存
  p7 8chのA/D変換開始

3.p7 8chのA/D変換結果をadP7ON[]に保存 (LED ON時の値)
  センサーボードLEDをOFF
  p0 6chのA/D変換開始

4.1.に戻って繰り返す。(1mS 弱で1サイクル)

次のリストはタイマRAとADコンバータの初期化関数です。
R8CのAD変換には最短で44サイクル必要なので、ADクロックに20MHzを使った場合1/20*44uS=2.2uS/CHとなり、17.6uSで8CH の変換が終わります。
ADクロックが速ければAD変換が速くなる反面AD入力に接続するセンサのインピーダンスも低いこと(4.4KΩ)が要求されます。
アナログセンサのフォトトランジスタ出力は100KΩでプルアップあるのでそのままではAD変換時にひげのようなノイズが発生しAD変換誤差となります。
それを防ぐためにプルアップ抵抗と共に1000pのコンデンサが接続してあるのですがこのコンデンサのせいで入力の応答が遅くなるという副作用が発生します。
250uS毎の変換をするためには1000pのコンデンサではセンサの応答が少し遅すぎるので100pのコンデンサに変更することにしました。
ADクロックを遅くすればAD入力のインピーダンスが高くなるので最大の分周比1/8を選択して20/8=2.5Mhzにしています。
この時のAD変換時間は 最短で0.4 × 44 × 8 =140.8uS となり250uSサイクルの処理に間に合う計算となります。  

/************************************************************************/
/* ADの初期化                                                           */
/************************************************************************/
void init_adc( void )
{
    /* タイマRAの設定 */
    /* 割り込み周期 = 1 / 20[MHz]   * (TRBPRE+1) * (TRBPR+1)
                    = 1 / (20*10^6) * 1   * 256 * 19
                    = 0.0002432 = 0.2432[ms]
    */
    tramr  = 0x00;                      /* タイマモード、カウントソースf8 */
    trapre = 19-1;                       /* プリスケーラレジスタ         */
    traic  = 0x07;                      /* 割り込み優先レベル設定       */
    tracr  = 0x01;                      /* カウント開始                 */

    /* A/Dコンバータの設定 */
    adcon0  = 0x00;      /* A/D変換ストップ              */
    asm(" nop ");        /* φADの1サイクルウエイト入れる*/
	/* ADClkが遅いほど入力インピーダンスが高く出来る */
    admod   = 0x20;      /* 単掃引モードに設定 AD Clk f/8 -> 150uS/8ch   */
//  adinsel = 0x90;      /* 入力端子P7の4端子を選択      */
    adinsel = 0xb0;      /* 入力端子P7の8端子を選択      */
    adcon1  = 0x30;      /* A/D動作可能                  */
	p8_7 = 1;            /*  センサ基板LEDOFF */
	pd8_7 = 1;           /*  センサ基板LEDポート出力設定 */    
}

下のリストはAD変換をおこなう割り込み関数です。
スタートバーセンサ用のフォトトランジスタは応答が遅いので走行開始前はON/OFFの間隔を10倍にして、走行中は1mS サイクルでセンサデータを取得します。

/************************************************************************/
/* タイマRA 割り込み処理                                                */
/************************************************************************/
#pragma interrupt intTRA(vect=22)
void intTRA( void )
{
    static int sel=0; // 0:P0  1:P7
    static int led=0; // 0:LEDOFF  1:LEDON
    static int t;
	
	if( !iRunFlag ){
	//if( dipsw1() ){  // for test
		// スタートバーセンサのために走行開始前はLEDON/OFF間隔を長くする
		if( t++ < 10) return;
		t = 0;
	}
    //p4_5 = 1;
    switch(sel){
      case 0: // P7の結果を保存してP0変換スタート
        //adcon0 = 0x00;    // AD stop
		if( led ){
            adP7ON[0] = ad0;
            adP7ON[1] = ad1;
            adP7ON[2] = ad2;
            adP7ON[3] = ad3;
            adP7ON[4] = ad4;
            adP7ON[5] = ad5;
            adP7ON[6] = ad6;
            adP7ON[7] = ad7;
			led = 0;
		}else{
            adP7OFF[0] = ad0;
            adP7OFF[1] = ad1;
            adP7OFF[2] = ad2;
            adP7OFF[3] = ad3;
            adP7OFF[4] = ad4;
            adP7OFF[5] = ad5;
            adP7OFF[6] = ad6;
            adP7OFF[7] = ad7;
			led = 1;
		}
 		p8_7 = !led;      // 
        adinsel = 0x20;  // P0 6端子 Gyro,nc,nc,Steer VR, Steer VR(option)
    	asm(" nop ");                       /* φADの1サイクルウエイト入れる*/
        adcon0 = 0x01;    // AD start
        sel = 1;
        break;
      case 1: // P0の結果を保存してP7変換スタート
        //adcon0 = 0x00;    // AD stop
        adP0[0] = ad0;
        adP0[1] = ad1;
        adP0[2] = ad2;
        adP0[3] = ad3;
        adinsel = 0xb0;   // P7 8端子 Sensor L1, R1, L2, R2, L3, R3, Center, Start
     	asm(" nop ");     /* φADの1サイクルウエイト入れる*/
       	adcon0 = 0x01;    // AD start
        sel = 0;
        break;
      default:
        sel = 0;
    }
// p4_5 = 0;
}