月別アーカイブ: 2014年8月

カメラ制御コード

残り4つということで、だいたい1年前のコード公開

    /*
    PB.DR.BIT.B3 CLK
    PB.DR.BIT.B2 RESET
    PB.DR.BIT.B1 START
    PF.DRL.BIT.B1 STRB
    AN0 Image DATA
    PB.DR.BIT.B16 LOAD
    PE.DRL.BIT.B15 SIN
    PE.DRL.BIT.B14 SCLK

    PFC.PAIORL.BIT.B6 = 1; 右
    PFC.PAIORL.BIT.B7 = 1; 左
    PFC.PAIORL.BIT.B8 = 1; 同期
    PFC.PAIORL.BIT.B9 = 1; 中央
    PFC.PAIORL.BIT.B10 = 1;
    PFC.PAIORL.BIT.B11 = 1;
    PFC.PAIORL.BIT.B12 = 1;
    PFC.PAIORL.BIT.B13 = 1;
    PFC.PAIORL.BIT.B14 = 1;
    PFC.PAIORL.BIT.B15 = 1;
    */

    #include <machine.h>
    #include <stdarg.h>
    #include "iodefine.h"
    #include "sci.h"
    #include "7125sio.h"

    #define CLK_H PB.DR.BIT.B3=1
    #define CLK_L PB.DR.BIT.B3=0
    #define SCLK_H PE.DRL.BIT.B14=1
    #define SCLK_L PE.DRL.BIT.B14=0
    #define WAIT for(i=0;i<1000;i++){} /*======================================*/ /* プロトタイプ宣言 */ /*======================================*/ void main(void); unsigned char dipsw_getL( void ); unsigned char dipsw_getH( void ); void setReg(unsigned char data ); /*======================================*/ /* グローバル変数の宣言 */ /*======================================*/ unsigned int watc=0; unsigned char reg[16]; unsigned int h_cnt; unsigned int adcnt; unsigned char data[256]; /************************************************************************/ /* メインプログラム */ /************************************************************************/ void main( void ) { unsigned int pri_v,pri_h; int i,j; char dif,min,max,minad,maxad,out; unsigned char rf,lf,lsh; unsigned char blevel,wlevel; char mr,ml; unsigned char digisensor; /* マイコン機能の初期化 */ init_all(); //初期化 sci1_init(38400,8,0,1); reg[ 0]=0x00;//Image Capture Mode 0 = Continuous Mode reg[ 1]=0x10;//NA reg[ 2]=0x20;//Interrupt setting reg[ 3]=0x30;//Data Rate 0 = 1/4 reg[ 4]=(0x40|(dipsw_getL()+3));//露光時間 3=285fps 2=303fps 1=323fps reg[ 5]=0x50;//露光時間 reg[ 6]=0x60;//露光時間 reg[ 7]=0x70;//露光時間 reg[ 8]=0x86;//Gain reg[ 9]=0x90;//MSB setting reg[10]=0xA0;//Black level output reg[11]=0xB0;//Offset subtraction reg[12]=0xC0;//STRB reg[13]=0xD2;//NA reg[14]=0xE0;//Power save mode reg[15]=0xFE;//NA lsh=30+dipsw_getH()*10;// 1=100 2=120 3=140 //black=30~40 RESET: digisensor = 0x00; WDT.WRITE.WTCNT = 0x5A00; PB.DR.BIT.B2=0;//リセット H -> L

    CMT0.CMCNT = 0;
    CMT.CMSTR.BIT.STR0 = 1;//cmt0 スタート
    while(CMT0.CMCNT<150){CLK_H;CLK_L;}//200us待ち CMT.CMSTR.BIT.STR0 = 0;//cmt0 停止 CLK_H; CLK_L; PB.DR.BIT.B2=1;//リセット L -> H

    CMT0.CMCNT = 0;
    CMT.CMSTR.BIT.STR0 = 1;//cmt0 スタート
    while(CMT0.CMCNT<75){CLK_H;CLK_L;}//100us待ち CMT.CMSTR.BIT.STR0 = 0;//cmt0 停止 CLK_H; CLK_L; setReg(reg[ 0]); setReg(reg[ 1]); setReg(reg[ 2]); setReg(reg[ 3]); setReg(reg[ 4]); setReg(reg[ 5]); setReg(reg[ 6]); setReg(reg[ 7]); setReg(reg[ 8]); setReg(reg[ 9]); setReg(reg[10]); setReg(reg[11]); setReg(reg[12]); setReg(reg[13]); setReg(reg[14]); setReg(reg[15]); RESTART: CLK_H; CLK_L; PB.DR.BIT.B1=1;//スタート CLK_H; PB.DR.BIT.B1=0;//スタート信号戻す 920ns リセット開始から0.5ms後 CLK_L; CLK_H; i=0; WDT.WRITE.WTCNT = 0x5A00; //2.73ms以内にクリア NEXTREAD: while(PF.DRL.BIT.B1==0){//STRBシグナル待 CLK_L; CLK_H; } AD0.ADCR.BIT.ADST = 1;//AD変換開始 if(i==0){ PA.DRL.BYTE.H = digisensor;//xxxx x001 PA.DRL.BIT.B8 = 0; //mainCPUへの同期信号クリア } CLK_L;CLK_H; CLK_L;CLK_H;//STRB -> L
    CLK_L;CLK_H;

    while(AD0.ADCSR.BIT.ADF == 0);//AD変換終了まで待つ
    data[i] = AD0.ADDR0 >> 8; //値を保存

    i++;
    if(i<128){goto NEXTREAD;} //32*5= 160 setReg(0x21);//Set STOP=1 min=-10; max= 10; minad=0; maxad=0; //ライン重心計算 for(i=1;i<29;i++){ dif=data[i+95]-data[i+96]; //96 97 if(i<24 && dif5 && dif>max){max=dif;maxad=i;} //白→黒
    }
    if(min==-10 || max==10 ||(minad>maxad)){
    out=63;
    }else{
    out=(minad+maxad);
    }
    PA.DRL.BYTE.H = out<<2; /* ラインマーカしきい値計算 */ blevel=200; for(i=65;i<=91;i++){ if(blevel>data[i]){blevel=data[i];}
    if(blevel>data[i+32]){blevel=data[i+32];}
    }
    wlevel=blevel+lsh;

    digisensor=0x01;
    //左マーカ
    if(data[ 99]>wlevel || data[ 67]>wlevel){digisensor= digisensor | 0x40;}//0100 0000

    //右マーカ
    if(data[ 89]>wlevel || data[121]>wlevel){digisensor= digisensor | 0x04;}//0000 0100

    //中心ライン
    if(data[109]>wlevel || data[110]>wlevel || data[111]>wlevel || data[78]>wlevel){
    digisensor= digisensor | 0x10;}//中央線 0001 0000

    if(data[104]>wlevel || data[ 72]>wlevel){digisensor= digisensor | 0x20;} //左中マーカ
    if(data[116]>wlevel || data[ 84]>wlevel){digisensor= digisensor | 0x08;} //右中マーカ

    PA.DRL.BIT.B9 = 1;//

    PA.DRL.BIT.B8 = 1;//同期線L->H

    goto RESTART;

    }

    /************************************************************************/
    /* ディップスイッチ値読み込み */
    /* 戻り値 スイッチ値 0~15 */
    /************************************************************************/
    unsigned char dipsw_getL( void )
    {
    unsigned char sw=0;

    if(PE.PRL.BIT.B2==0){sw+=2;}
    if(PE.PRL.BIT.B3==0){sw+=1;}

    return sw;
    }

    /************************************************************************/
    /* ディップスイッチ値読み込み */
    /* 戻り値 スイッチ値 0~15 */
    /************************************************************************/
    unsigned char dipsw_getH( void )
    {
    unsigned char sw=0;

    if(PE.PRL.BIT.B0==0){sw+=2;}
    if(PE.PRL.BIT.B1==0){sw+=1;}

    return sw;
    }

    /************************************************************************/
    /* レジスタ書き込み */
    /* */
    /************************************************************************/
    void setReg( unsigned char data )
    {
    int wt=0;
    //SCLK_Lからスタート
    //adress
    if((data&0x80)==0x80){PE.DRL.BIT.B15=1;}else{PE.DRL.BIT.B15=0;}
    SCLK_H;SCLK_L;
    if((data&0x40)==0x40){PE.DRL.BIT.B15=1;}else{PE.DRL.BIT.B15=0;}
    SCLK_H;SCLK_L;
    if((data&0x20)==0x20){PE.DRL.BIT.B15=1;}else{PE.DRL.BIT.B15=0;}
    SCLK_H;SCLK_L;
    if((data&0x10)==0x10){PE.DRL.BIT.B15=1;}else{PE.DRL.BIT.B15=0;}
    SCLK_H;SCLK_L;
    //data
    if((data&0x08)==0x08){PE.DRL.BIT.B15=1;}else{PE.DRL.BIT.B15=0;}
    SCLK_H;SCLK_L;
    if((data&0x04)==0x04){PE.DRL.BIT.B15=1;}else{PE.DRL.BIT.B15=0;}
    SCLK_H;SCLK_L;
    if((data&0x02)==0x02){PE.DRL.BIT.B15=1;}else{PE.DRL.BIT.B15=0;}
    SCLK_H;SCLK_L;
    if((data&0x01)==0x01){PE.DRL.BIT.B15=1;}else{PE.DRL.BIT.B15=0;}
    SCLK_H;
    PB.DR.BIT.B16=1;//LOAD_H
    CLK_H;
    PB.DR.BIT.B16=0;//LOAD_L
    SCLK_L;
    CLK_L;
    }

RMCR2014

140825
競技では運よく部門優勝と総合2位を頂きました。

ロボマガの記事の紹介をさせて頂いたプレゼンでは、長い上に分かり難く申し訳ない状態でしたが、Amazonの在庫がもう少しで無くなりそうなことから、ある程度は興味を持って頂けたのだと思っています。

技術交流会では、某チームが車体重量を測ってまわっていたり(次は横Gコンテストを期待)、モータを長持ちさせるノウハウを聞きに言ったら逆の回答がきたり、RXマイコン用のライブラリの情報を頂いたり。

参加者の皆様や大会を運営してくださったルネサスの皆様。ありがとうございました。

走り収め


福工にて最終調整。来週末はガンバロー。
変更点
・車線変更区間の終了直後に操舵が暴れる
 車線変更復帰後のオフセット走行の解除が雑
 段階的にオフセットを減らすように変更
・高速で直線からコーナへの進入するとコーナ中盤でアンダー
 コーナ進入直後の減速不足
 前輪でも若干のブレーキを掛ける
 後輪が滑り出したので後輪のブレーキを弱める
・コーナ終盤でのアンダーステア
 前輪の駆動力を弱める
・コーナ終盤でのオーバーステア
 後輪外輪の駆動力を弱める。代わりに後輪内輪の駆動力を強める

コーナ進入時の減速は最大でも精々0.6G程、そんなに荷重移動も起きないはずなのだけど、毎回毎回梃子摺るのは何か思い違いしているような気がする

ROBOCON Magazine 9月号

140810
Tさんの記事が読めるのはロボコンマガジンだけ。
前回に引き続きいて今回はソフトウェア編。
実際のソースコードと共にカメラの使い方と、その画像からのトレースライン+マーカの検出方、そしてライントレースのやり方を紹介しています。

IRカットフィルターをためす

14080901
セラテックジャパンのWEBカタログで赤外線カットフィルタを購入する
物としては1cm角のガラス薄板になるが、それに対して梱包はかなり厳重にされていた。
抜き取り検査時と思われる測定データも同梱されている。
個人では入手しにくい赤外カットフィルタを少数・低価格で提供してくれるのは有難い

購入したのは[IRカットフィルター2]で、カメラM64285FPの分光感度のうち
白色LEDの発光色外である650nm以上をカットするようにした。
IR取り付けるべき向きは分からないので、とりあえずIR面をコース側にして取り付ける

なにがやりたいかと言うと
様々な光環境下でもカメラの出力がサチらないようにするために
太陽光のスペクトルを検出して絵が明るくなりすぎないようにしたい
よって、LED照明だけの時の絵の明るさから、変化が小さいほど良い。

フィルター無しが↓で、
14080902
IRカットフィルタを付けると↓になる。
14080903
ちなみに、以前購入した太陽熱カットフィルムが↓
14080904
微妙に絵が暗くなるけれど、それ以外の差は分からない。
曇天(時折雨交じり)だったため太陽光が弱く、
赤外のスペクトルが低くなる傾向もあるようなので、
その辺の影響か?

//////////////////////
遅れていた参加手続きも完了。

コーナの曲がり方

14080201
画像右下の直線から左コーナに進入するとする。
最初は、直線からコーナに進入する区間で
減速をしながらコーナーに進入して行くことになる。
この区間でアンダーステアが発生する場合
前輪の過度なブレーキによるタイヤロックや
直線での速度の出しすぎによるヨー回転の立ち上がり遅延が原因になる
前者の場合には前輪のブレーキを弱くして対処する。
コーナ進入時のブレーキは殆ど後輪だけで十分である。
後者の場合、直線の速度を遅くするかセンサーアームを長くして操舵速度を緩やかにする
または、素早い操舵でも車体の応答がついて行くように、前輪のグリップをあげる(かホールベースを延長する)
前輪のグリップは、フロントヘビーに車体をデザインするが、減速により前輪への荷重を増やして実現する
その他、ライントレースの追従性が低い場合にもアンダーステアのような軌道で走ることもある

14080202
減速が終わり走行速度が目標値付近になる区間
減速から加速に移る時に急なパワーコントロールをすると姿勢を崩す。
前の区間での減速により後輪の荷重が減っているため、
後輪駆動車がここで急にパワーを掛けると直ぐにスピンに陥る。
ヨー回転の立ち上りが終わっていない場合、前輪のパワーを上げるとアンダーステアになる。
また、公転による遠心力が発生しだす区間でもあるため、
走行速度が早すぎる場合には負担の大きいタイヤから滑り出しはじめる。
静止荷重の大きいタイヤほど負担が大きくなるため、フロントヘビーの車はこの区間以降でアンダーステアが出やすくなる

14080203
ヨー軸の加速も終わり、走行速度も一定となった後に定常旋回を行う区間になる。
如何に綺麗な姿勢でこの区間にたどり着くかが大事となる。
車体の加減速によるステア特性の調整ができないため、
車体の基本特性を各タイヤのパワーコントロールで押さえ込んでニュートラルステアを保つことになる
前後のタイヤのうち負担の大きい方が滑りやすく、また、パワーを掛けすぎたタイヤから滑り出す。
この区間ではタイヤの限界を確認しながら、どのタイヤにパワーを掛けるかを調整して行く。