センサーボードの裏面には実装部品はありません、ケーブル、スタートバー用部品ののハンダ付け部分以外は突起がないのでクラッシュ時にコースの角などで擦ってもダメージを最小限に抑えられるようになっています。(下の写真)
基板上面にはセンサと電流制限用の抵抗だけがあります、センサ出力のプルアップ抵抗はドライブボード側に付きます。(下の写真)
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;
}