続き

・エッジ検出によるライン位置推定
・CPU間用パラレル通信

#define LED 13
#define AO A0
#define SI 11
#define CLK 12

#define BIT_7 9
#define BIT_6 8
#define BIT_5 7
#define BIT_4 6
#define BIT_3 5
#define BIT_2 4
#define BIT_1 3
#define BIT_0 2

//エッジ検出閾値
#define MIN_EDGE 3
unsigned char data[32];

void setup() {
// put your setup code here, to run once:
pinMode(LED, OUTPUT);

digitalWrite(SI, LOW);
pinMode(SI, OUTPUT);
digitalWrite(CLK, LOW);
pinMode(CLK, OUTPUT);

ADCSRA = ADCSRA & 0xfd;//Division Factor 128->32

pinMode(BIT_7, OUTPUT);
pinMode(BIT_6, OUTPUT);
pinMode(BIT_5, OUTPUT);
pinMode(BIT_4, OUTPUT);
pinMode(BIT_3, OUTPUT);
pinMode(BIT_2, OUTPUT);
pinMode(BIT_1, OUTPUT);
pinMode(BIT_0, OUTPUT);

Serial.begin(9600);
while (!Serial);
}

void loop() {
// put your main code here, to run repeatedly:
signed char min,max,dif;
unsigned char maxad,minad,out;

delay(500);

while(1)
{
digitalWrite(BIT_7, LOW);
digitalWrite(SI, HIGH);
digitalWrite(CLK, HIGH);
digitalWrite(SI, LOW);
delayMicroseconds(10);
digitalWrite(CLK, LOW);
for (int j = 0; j <32; j++){
 data[j]=analogRead(A0)/4;
 digitalWrite(CLK, HIGH);
 digitalWrite(CLK, LOW);
 digitalWrite(CLK, HIGH);
 digitalWrite(CLK, LOW);
 digitalWrite(CLK, HIGH);
 digitalWrite(CLK, LOW);
 digitalWrite(CLK, HIGH);
 digitalWrite(CLK, LOW);
}

min=-MIN_EDGE;
max= MIN_EDGE;
minad=0;
maxad=0;
for(char j=0;j<31;j++){
 dif=data[j]-data[j+1];
 if(j<30 && dif<min){min=dif;minad=j;} //黒→白エッジ検出
 if(j>1  && dif>max){max=dif;maxad=j;} //白→黒エッジ検出
}
if(min==-MIN_EDGE || max==MIN_EDGE ||(minad>maxad)){
 out=63;
 //63:検出エラー
}else{
 out=(minad+maxad);
 //out=31位が中心に白線がある状態 15~45位の範囲で横ズレ量を示す
}
Serial.println (out);
if(out>=32){digitalWrite(BIT_5, HIGH);out=out-32;}else{digitalWrite(BIT_5, LOW);}
if(out>=16){digitalWrite(BIT_4, HIGH);out=out-16;}else{digitalWrite(BIT_4, LOW);}
if(out>= 8){digitalWrite(BIT_3, HIGH);out=out- 8;}else{digitalWrite(BIT_3, LOW);}
if(out>= 4){digitalWrite(BIT_2, HIGH);out=out- 4;}else{digitalWrite(BIT_2, LOW);}
if(out>= 2){digitalWrite(BIT_1, HIGH);out=out- 2;}else{digitalWrite(BIT_1, LOW);}
if(out>= 1){digitalWrite(BIT_0, HIGH); }else{digitalWrite(BIT_0, LOW);}
digitalWrite(BIT_7, HIGH);

delay(10);//露光時間
}
}

ラインカメラをArduino Nanoで動かす


カメラ誘導マシンでよく使われているTSL1401をArduinoで動かしてみる
とりあえず128画素を読んでみると

1フレームの読み込みに15.4ms程度かかっている。遅すぎる。
ので、高速化を検討。
まず、128画素も使わないので4画素に1回のみ取り込むことにしてAD変換の回数を1/4にする。
ライントレースに使うデータとしては、32画素もあれば十分だろう。

4.38ms位になった。これで、露光時間を含めると150fps~160fps位になりそう。
でも、Advanceのセンサ置き換えには、もう少し欲しいところ。

遅い画素の読み取り(AD変換)に手をつける。
analogRead()を早くしたい。
garretlabさんを参照すると
Arduinoの初期化関数init()内でADCの変換時間を決めるADCSRレジスタを設定しているようだ。
早速、hardware/arduino/avr/cores/arduino/wiring.cを覗くと

と書いてある。Arduino Nanoは16MHzなので、ADCSR=0b111(分周比128)になってそうである。
ので、スケッチに戻り、void setup()に下記コードを追記して分周比を32に変更する。
ADCSRA = ADCSRA & 0xfd;//Division Factor 128->32
と、

1.892msとなった。露光時間が2msなら 250fps相当になる。

#define LED 13
#define AO A0
#define SI 11
#define CLK 12

unsigned char data[32];

void setup() {
// put your setup code here, to run once:
pinMode(LED, OUTPUT);

digitalWrite(SI, LOW);
pinMode(SI, OUTPUT);
digitalWrite(CLK, LOW);
pinMode(CLK, OUTPUT);

ADCSRA = ADCSRA & 0xfd;//Division Factor 128->32

Serial.begin(9600);
while (!Serial);
}

void loop() {
// put your main code here, to run repeatedly:
delay(500);

while(1)
{

digitalWrite(SI, HIGH);
digitalWrite(CLK, HIGH);
digitalWrite(SI, LOW);
delayMicroseconds(10);
digitalWrite(LED, HIGH);
digitalWrite(CLK, LOW);
for (int j = 0; j < 32; j++){
data[j]=analogRead(A0)/4;
digitalWrite(CLK, HIGH);
digitalWrite(CLK, LOW);
digitalWrite(CLK, HIGH);
digitalWrite(CLK, LOW);
digitalWrite(CLK, HIGH);
digitalWrite(CLK, LOW);
digitalWrite(CLK, HIGH);
digitalWrite(CLK, LOW);
}
digitalWrite(LED, LOW);
Serial.println (data[15]);
delay(5);
}

}

RMCR2017春

逆境からのスタートでしたが、その後は幸運に恵まれ
予選、部門とトーナメント優勝できました。
皆様の助言と、各所で、調整させて頂いたおかげです。
ありがとうございました。

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

東海大学 Challenge Cup 2017


東海大学熊本キャンパスで行われた東海大学 Challenge Cup 2017に参加してきた。
参加台数が90を超える大きなイベントとなっていた。


N氏のカメラ誘導マシン。アッカーマンに進化していた


小中学生によるマイコンレーサーの走行回。

大会は
前日試走から色々やらかすもギリギリ部門優勝。
しかしタイムで適わず。エキシビジョンでも追いつけない。

大会を開催して下さった東海大学の皆様、熊本の先生の皆様、お疲れ様でした。

マイコンカーラリー技術交流会

神戸市立科学技術高等学校にて開催されたマイコンカーラリー技術交流会

大会の様子

コース清掃マシン。清掃用ローラは2自由度のリンクで固定され、良い感じに動く

画処理クラス決勝T

賞品とはっさく。
・前日試走は室温が狭く、タイヤグリップは期待できない状態。
・試しにバッテリをづっと使ってるニカドからづっと放置していたニッ水に変えるとタイムが伸びた
・当日は室温も上がり、タイヤのグリップは十分に
・グリップしすぎて、レーンチェンジの入り口側の柱に当たる→入りのオフセット走行を減らす+進入速度アップで合わせる
・決勝Tで、予備のニカドに変えたらタイムが伸びた

みなさま。おつかれさまでした。

こつこつ


作ったけど、これを繋ぐモータドライブ基板Ver5と車体が無い。

ついでに回路も眺める。

GR-PEACHとモータドライブ基板Ver5を接続するとき、?。
まず、LED側
VCC=5Vだと、LEDのVf=1.7V付近で、RZのポートには3.3Vがかかる。
VCCはGR-PEACHの5Vピンから供給ならば、バッテリ電圧-0.4V程度。
バッテリ電圧が高いと、少しスペックを超えそう。
モータドライブ基板Ver5のLEDは青色とかVfが高い物に変えたい。
次にプッシュスイッチ
VCC(バッテリ電圧-0.4V)がRZのポートにかかる。
R13は未接続にして、GR-PEACH側の3.3VからのPUに変えたい。

つれづれ


トレースラインを検出するセンサについて、
センサで得た情報を何に使うかで制御方法を考える

①モータ制御量を決定する
 標準プログラムのアナログセンサみたいなヤツ
 センサから得たズレ量を、操舵モータに印加する電圧に変換する
 トレース制御のためには、センサからの情報はリアルタイムに更新される必要がある。

②モータ速度を決定する
 センサから得たズレ量から、操舵モータの速度目標値を決定する
 制御モータの速度制御は別のFBが行う
 これもリアルタイム性は必要。

③操舵角度を決定する
 センサから得たズレ量(とか)から、操舵角度目標値を決定する
 操舵モータの角度制御は別のFBが行う
 この辺から、センサからのデータの更新速度の重要性は、目標値の設定の正確さによって変わってくる。正確に目標値を設定できれば、センサからの情報は、あるていど離散的でもなんとかなる。
 Basicの構成はコレ?

④操舵計画を決定する
 センサから得たズレ量(とか)から時間/距離毎の操舵角度のシナリオをつくる。
 センサからの情報は、シナリオの修正に使用される。

件のライントレース制御は③の構成。これは、画処理マシンの作り始め頃に30fps以下のカメラでの滑らかなトレースするために使用していたのが続いている。当時の画処理マシンのトレンドだったのもある。
今の450fpsとかのカメラでは①の構成でも行けそうだし、他の画処理マシンではその構成も普通のようだ。
NTFCカメラでのトレースしようとすると、③以上の制御が必要になる。突き詰めて行って④が実現できれば楽しそうに思う。