目次

データ圧縮

 画像データを16kバイト保存して判定するのは、MCRマシンを
 移動させた状態では、時間的余裕がないので、情報圧縮します。

 外界センサーにカメラを利用しない場合、コースに密着するタイプ
 の8ビット出力センサーを使います。

 この8ビット出力センサーと同じようにデータを保存できれば
 128ピクセルx128ラインを128バイトまで圧縮できます。

 情報圧縮の動作シーケンスを考えます。

 最初に、1ライン分のデータを2値化します。
 2値化の動作シーケンスは、以下とします。
  1. 1ラインのピクセル値取得
  2. ピクセル値の平均を求める
  3. 各ピクセル値と平均を比較し、大きければ1、そうでなければ0とする
 この処理をTcl/Tkで記述します。 ---------------------------------------------------------------------- #!/usr/local/bin/wish # genbin.tcl # open set fd_in [open "ssxx0.txt" "r"] # initlaize set sum 0 set xbuf "" # handling while { [gets $fd_in sbuf] >= 0 } { # temporary store set ssbuf $sbuf # separate foreach e $sbuf { set tmp [split $e " "] set val 0 # generate value foreach x $tmp { set val [expr 10 * $val + $x] } # summuation set sum [expr $sum + $val] } # calculate average set avr [expr $sum / 128] set sum 0 # binary code foreach e $ssbuf { set tmp [split $e " "] set val 0 # generate value foreach x $tmp { set val [expr 10 * $val + $x] } # judge set tmp 0 if { $val > $avr } { set tmp 1 } # store lappend xbuf $tmp } # show puts $xbuf # prepare next set xbuf "" } # close close $fd_in ----------------------------------------------------------------------  2値化した128個のデータを、8ビットのデータに変換するため  次のシーケンスを実行します。
  1. 16データごとに、合計値を計算
  2. 8個の合計値の平均を求める
  3. 各合計値と平均を比較し、大きければ1、そうでなければ0とする
 この処理を、先に記述したTcl/Tkのコードに加えます。 ---------------------------------------------------------------------- #!/usr/local/bin/wish # gensen.tcl # open set fd_in [open "ssxx0.txt" "r"] # initialize set sum 0 set xbuf "" # handling while { [gets $fd_in sbuf] >= 0 } { # temporary store set ssbuf $sbuf # separate foreach e $sbuf { set tmp [split $e " "] set val 0 # generate value foreach x $tmp { set val [expr 10 * $val + $x] } # summuation set sum [expr $sum + $val] } # calculate average set avr [expr $sum / 128] set sum 0 # binary code foreach e $ssbuf { set tmp [split $e " "] set val 0 # generate value foreach x $tmp { set val [expr 10 * $val + $x] } # judge set tmp 0 if { $val > $avr } { set tmp 1 } # store lappend xbuf $tmp } # calculate block summuations set sum 0 set i 0 set ybuf "" foreach e $xbuf { # add set sum [expr $sum + $e] # increment incr i # judge if { $i == 16 } { lappend ybuf $sum set sum 0 set i 0 } } # calculate block averate set sum 0 foreach e $ybuf { # add set sum [expr $sum + $e] } set avr [expr $sum / 8] # generate 8 data set xbuf "" set val 0 foreach e $ybuf { # default set tmp 0 # judge if { $e > $avr } { set tmp 1 } # calculate HEX code set val [expr $val * 2 + $tmp] # store set xbuf "$xbuf$tmp" } set xbuf "$xbuf -> [format "0x%02x" $val]" # show puts "$xbuf" # prepare next set xbuf "" set ybuf "" } # close close $fd_in ----------------------------------------------------------------------  次の画像データが得られた場合、Tcl/Tkのコードで得られるセンサー  データを調べます。  テキストファイルssxx0.txtに画像データが保存されているとき  以下のように、センサーデータを生成します。 >tclsh85 gensen.tcl > sensor.txt{enter}  作成したテキストファイルsensor.txtは、次のようになりました。  (左を2進、右を16進としてあります。) 00000000 -> 0x00 00011000 -> 0x18 00011000 -> 0x18 00011000 -> 0x18 00011000 -> 0x18 00011000 -> 0x18 00011000 -> 0x18 00011000 -> 0x18 00011000 -> 0x18 00011000 -> 0x18 00011000 -> 0x18 00011100 -> 0x1c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c 00111100 -> 0x3c  この結果より、次のシーケンスで、128ピクセルx128ラインの画像データから  ラインごとのセンサーデータを生成できます。
  1. 1ラインのピクセル値取得(128バイトのデータ)
  2. ピクセル値の平均を求める
  3. 各ピクセル値と平均を比較し、大きいなら1、そうでないなら0とする
  4. 1ラインの2値化したデータを16個ごとに、合計値を計算(8個のデータ生成)
  5. 8個の合計値の平均を求める
  6. 各合計値と平均を比較し、大きいなら1、そうでないなら0とする

ファームウエアでの実現

 移動しながら、カメラから送られてくる画像データをセンサーデータ  に変換しなければ、ライントレーサを実現できません。  カメラから画像データが送られてきた時点で、2値化できれば、次の  シーケンスで、センサーデータに変換できます。
  1. ピクセル値取得
  2. ピクセル値と平均を比較し、大きいなら1、そうでないなら0とする
  3. 2値化したデータを16個ごとに、合計値を計算(8個のデータ生成)
  4. 8個の合計値の平均を求める
  5. 各合計値と平均を比較し、大きいなら1、そうでないなら0とする
  6. 1バイトのデータとする
 センサーデータに変換するときに、平均が必要になります。  この平均を、予めスレショルド(しきい値)として、走り始める前に求めます。  画像データ入力時、フラグでスレショルドを求めるか、1バイトずつシリアルで  転送するかを選べるように、関数get_imgを定義します。 #define MAX_SIZE 16384 UWORD img_cnt ; UBYTE threshold ; void get_img(UBYTE x) { UWORD result ; UBYTE tmp ; UWORD max ; UWORD min ; /* send start */ send_start(); /* READ data */ img_cnt = 0 ; max = 0 ; min = 0 ; while ( img_cnt < MAX_SIZE ) { /* impress XCK:H */ set_xck(ON); /* impress XCK:L */ set_xck(OFF) ; /* judge */ tmp = PINA ; if ( tmp & 2 ) { /* start conversion */ start_adc() ; /* wait */ wai_adc() ; /* get data */ result = (ADCH << 8) | ADCL ; result >>= 2 ; /* threshold */ if ( x == ON ) { max += result ; min += result ; } /* uart handling */ if ( x == OFF ) { /* show */ show_value( result ); /* new line */ if ( (img_cnt % 16) == 15 ) { crlf() ; } } /* increment */ img_cnt++ ; } } /* calculate threshold */ if ( x == ON ) { max >>= 2 ; min >>= 2 ; threshold = (UBYTE)((max+min) >> 1) ; } }  スレショルドを求められたならば、走行中にカメラでのコース  撮影と同時にセンサーデータ(128バイト)を生成できます。  GBCでは、露光時間が過ぎると、内部メモリに画像データを格納しています。  内部メモリからデータを取得するタイミングは、マイコン主導でよいので  画像データからセンサーデータへの変換に、時間がかかっても問題ありません。 UBYTE rdat[8] ; UBYTE sdat[128] ; void get_sensor(void) { UWORD result ; UBYTE index ; UBYTE res ; UBYTE i ; UBYTE sensor ; UBYTE avr ; /* send start */ send_start(); /* READ data */ img_cnt = 0 ; index = 0 ; i = 0 ; res = 0 ; while ( img_cnt < MAX_SIZE ) { /* impress XCK:H */ set_xck(ON); /* impress XCK:L */ set_xck(OFF) ; /* judge */ if ( PINA & 2 ) { /* start conversion */ start_adc() ; /* wait */ wai_adc() ; /* get data */ result = (ADCH << 8) + ADCL ; result >>= 2 ; /* judge */ if ( result > threshold ) { res++ ; } /* generate line code */ if ( (img_cnt % 16) == 15 ) { *(rdat+index) = res ; res = 0 ; index++ ; index %= 8 ; } /* generate sensor data */ if ( (img_cnt % 128) == 127 ) { /* average */ avr = 0 ; avr += *(rdat+0) ; avr += *(rdat+1) ; avr += *(rdat+2) ; avr += *(rdat+3) ; avr += *(rdat+4) ; avr += *(rdat+5) ; avr += *(rdat+6) ; avr += *(rdat+7) ; avr >>= 3 ; /* compare */ sensor = 0 ; if ( *(rdat+0) > avr ) { sensor |= 0x80 ; } if ( *(rdat+1) > avr ) { sensor |= 0x40 ; } if ( *(rdat+2) > avr ) { sensor |= 0x20 ; } if ( *(rdat+3) > avr ) { sensor |= 0x10 ; } if ( *(rdat+4) > avr ) { sensor |= 0x08 ; } if ( *(rdat+5) > avr ) { sensor |= 0x04 ; } if ( *(rdat+6) > avr ) { sensor |= 0x02 ; } if ( *(rdat+7) > avr ) { sensor |= 0x01 ; } /* store */ *(sdat+i) = sensor ; /* increment */ i++ ; } /* increment */ img_cnt++ ; } } }
目次

inserted by FC2 system