目次
前
次
データ圧縮
画像データを16kバイト保存して判定するのは、MCRマシンを
移動させた状態では、時間的余裕がないので、情報圧縮します。
外界センサーにカメラを利用しない場合、コースに密着するタイプ
の8ビット出力センサーを使います。
この8ビット出力センサーと同じようにデータを保存できれば
128ピクセルx128ラインを128バイトまで圧縮できます。
情報圧縮の動作シーケンスを考えます。
最初に、1ライン分のデータを2値化します。
2値化の動作シーケンスは、以下とします。
- 1ラインのピクセル値取得
- ピクセル値の平均を求める
- 各ピクセル値と平均を比較し、大きければ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ビットのデータに変換するため
次のシーケンスを実行します。
- 16データごとに、合計値を計算
- 8個の合計値の平均を求める
- 各合計値と平均を比較し、大きければ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ラインのピクセル値取得(128バイトのデータ)
- ピクセル値の平均を求める
- 各ピクセル値と平均を比較し、大きいなら1、そうでないなら0とする
- 1ラインの2値化したデータを16個ごとに、合計値を計算(8個のデータ生成)
- 8個の合計値の平均を求める
- 各合計値と平均を比較し、大きいなら1、そうでないなら0とする
ファームウエアでの実現
移動しながら、カメラから送られてくる画像データをセンサーデータ
に変換しなければ、ライントレーサを実現できません。
カメラから画像データが送られてきた時点で、2値化できれば、次の
シーケンスで、センサーデータに変換できます。
- ピクセル値取得
- ピクセル値と平均を比較し、大きいなら1、そうでないなら0とする
- 2値化したデータを16個ごとに、合計値を計算(8個のデータ生成)
- 8個の合計値の平均を求める
- 各合計値と平均を比較し、大きいなら1、そうでないなら0とする
- 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++ ;
}
}
}
目次
前
次