前回「ヒューズDE☆封印」してしまったtiny2313の代わりも買ってきて、ようやく製作再開です。
素直にmega644使えばよかったような気もします。
UARTについて
前回までではUARTが失敗していたのですが、ようやく成功しました。
自戒をこめて、間違った原因などを記しておきます。
UARTで失敗して困っている人の役に立てばと思います。
間違えていた原因は、オシレータの周波数が8MHzばかり気にしていて、クロックの8分周を忘れていたということ。実効クロックは1MHzでした。気づいてみればあまりにばかばかしくて、書くのも恥ずかしいです。
8分周をはずすには、あのヒューズビットを書き換えなければなりません。速度的にも困ってないので、いろいろとトラウマのあるヒューズビットは書き換えたくないw。
プログラムだけで書き換えたいなぁと思って、1MHzのままUARTの分周比だけを変えてしまえと、baud rateから分周比Nを求める式を
N = 8000000/16/9600 -1
から
N = 1000000/16/9600 -1
に変えたところ、やっぱり動きませんでした。
原因は今度こそ精度のようです。
2番目の式ではN=5.51・・・となり誤差が8~10%にも及びます。
このためクロック1MHzでbaud rate9600bpsのときはうまくいく分周比がないのです。
9600bpsを扱いたいときは8MHz(N=51.08・・・/誤差0.16%)や10MHz(N=64.10・・・/誤差0.16%)などを使わなければいけないようです。
あと、前回気づかなかったのですが、
秋月で買ったときについていた説明書(紙切れ一枚)には
9600bps 8 N 1
と書いてあったのですが、CanMoreのデータシート(見た目はしっかり)には
4800bps 8 N 1
と書いてありました。
前回の製作日記を読んでいただいた方には、どっちが正解かということはもはや自明ですね。
GT-720Fのデータシート間違い3ヶ所目
もう勘弁してくれ。CanMoreのデータシートはまず疑ってかからねば。
あ、ちなみにbaud rateをまちがえるとデータの送受信はできません。GPSモジュールがGPSモジュールとして働いてくれません。
最後に前回書いた恥ずかしい間違いなどの訂正と、正しい原因にいたるまでの過程でわかったことなどを。
前回の記事で「内部8MHzRC発振では精度が悪いのではないか」ということですが、baud rateが直ってから内部にもう一度切り替えてみたところ、問題なく通信できました。
ということで、内部RC発振器でも外部セラロック発信器でもどちらでも9600bpsUARTは可能。ということがわかりました。
また、部室のオシロスコープでGT-720Fの出力を見てみたら5V与えているにもかかわらず4V程度しか出ていませんでした。これをうまく読み取れていないのではないかという仮説もたてて、間に74ICを挟んでCMOSレベルにしてからAVRに入力させてみたのですが、結果から言えばこれも無駄でした。
AVRのVcc=5Vのときに、4V程度の入力ならちゃんとHとして読んでくれるようです。今は74ICは抜いて実験中です。また不具合が出ればそのときにでも報告します。
LCDとUART
UARTのタイミングについて
ようやくGPSレシーバの出力をうまくUARTで受け取れるようになりましたが、今度は位置情報をLCDに表示しようと思ってもうまく表示できませんでした。
ところで、GT-720Fから出力されるフォーマットはNMEA-0183のVersion 3.01です。
NMEA-0183と一言に行っても、いろいろなフォーマットがあります。
このうち位置情報と速度情報だけでほかの要らない情報を含まないフォーマットがRMC(RECOMMANDED MINIMUM SPECIFIC GPS/TRANSIT DATA)です。GT-720Fはほかにも衛星情報を含むGGAやGLLを吐いてくれるのですが、今回はそれらの情報は見捨ててRMCを使うことにしました。
RMCのフォーマットは
$GPRMC,<時刻>,<測位の可否>,<緯度>,<N/S>,<経度>,<E/W>,<速度>,<速度の方向>,<日付>,その他いろいろ<CR><LF>
とほしい情報だけ並んでいます。
で、まずはGT-720Fからどんどん送られてくる文字列から、"$GPRMC"を捕まえたあと、コンマを3回数えて緯度情報を送られてくる一文字ずつ出力させました。つまり、
char ch;
/*GPRMCを捕まえたてコンマを3回数えた後*/
for(;;){
ch = GetCharFromGPS(); //UARTでGT-720Fから文字を受け取る。
LCDPutChar( ch ); //LCDに出力
if( ch == ',' ) break; //コンマなら「緯度」のセクションは終わり
}
としたのですが、うまくいかない。変な文字列ばかり表示される。
この原因は受け取った文字をLCDへ逐一出力させたことにありました。LCDへの出力はLCDモジュールの処理完了を待つためかなり時間がかかります。それに対し、UARTは9600bpsで動作しているため、途切れなく文字が届いた場合、1秒に1000文字くらい送られてくる計算になります。AVRのUARTでは文字をためておくバッファが2つしかないため、UDRを読みにいく間隔が1msよりも大幅に遅すぎるとどんどん読み落としを作ってしまいます。
つまりUARTでほしいデータを読み取っているときは、重い処理を同時に行うことは危険なのです。今回LCDモジュールの余裕を見て1文字出力するたびに2msほどwaitしていたのでこのようなことが起こりました。
いったん文字列をバッファリングして、RMCのデータを読み終わったあと、じっくりとLCDに出力することで解決しました。
最後にtiny2313で快調にプログラムを組んでいたら、AVRWRTから「プログラムのサイズがでかすぎてAVRのフラッシュに入りきらないよ!」って言われました。
マイコンで組んでいれば本当によくあることです。
ちなみにtiny2313の2KBフラッシュしかもたないAVRでは、小数を扱うと大きくファイルサイズが増大します。
つまり
・float,doubleで変数を宣言する
だけではなく
・float,doubleで型キャストして、小数計算させる
などが1箇所でもあると、小数計算ライブラリを読み込むようです。AVRの小数計算ライブラリが馬鹿でかいらしく、hexファイルが5KBほど増えます。この量は大体の場合tiny2313のFLASHのサイズを超えさせてしまうようです。
ということでtiny2313では工夫して整数のみで計算を行いましょう。
まあ、これも常識なのでしょうかw。まだマイコン工作が2作目の私にとってはかなりの衝撃なのですが。
ということで、数々の教訓を残してGPSレシーバちゃんは元気に動いております。
常時130mAを食いながらw
素直にmega644使えばよかったような気もします。
UARTについて
前回までではUARTが失敗していたのですが、ようやく成功しました。
自戒をこめて、間違った原因などを記しておきます。
UARTで失敗して困っている人の役に立てばと思います。
間違えていた原因は、オシレータの周波数が8MHzばかり気にしていて、クロックの8分周を忘れていたということ。実効クロックは1MHzでした。気づいてみればあまりにばかばかしくて、書くのも恥ずかしいです。
8分周をはずすには、あのヒューズビットを書き換えなければなりません。速度的にも困ってないので、いろいろとトラウマのあるヒューズビットは書き換えたくないw。
プログラムだけで書き換えたいなぁと思って、1MHzのままUARTの分周比だけを変えてしまえと、baud rateから分周比Nを求める式を
N = 8000000/16/9600 -1
から
N = 1000000/16/9600 -1
に変えたところ、やっぱり動きませんでした。
原因は今度こそ精度のようです。
2番目の式ではN=5.51・・・となり誤差が8~10%にも及びます。
このためクロック1MHzでbaud rate9600bpsのときはうまくいく分周比がないのです。
9600bpsを扱いたいときは8MHz(N=51.08・・・/誤差0.16%)や10MHz(N=64.10・・・/誤差0.16%)などを使わなければいけないようです。
あと、前回気づかなかったのですが、
秋月で買ったときについていた説明書(紙切れ一枚)には
9600bps 8 N 1
と書いてあったのですが、CanMoreのデータシート(見た目はしっかり)には
4800bps 8 N 1
と書いてありました。
前回の製作日記を読んでいただいた方には、どっちが正解かということはもはや自明ですね。
GT-720Fのデータシート間違い3ヶ所目
もう勘弁してくれ。CanMoreのデータシートはまず疑ってかからねば。
あ、ちなみにbaud rateをまちがえるとデータの送受信はできません。GPSモジュールがGPSモジュールとして働いてくれません。
最後に前回書いた恥ずかしい間違いなどの訂正と、正しい原因にいたるまでの過程でわかったことなどを。
前回の記事で「内部8MHzRC発振では精度が悪いのではないか」ということですが、baud rateが直ってから内部にもう一度切り替えてみたところ、問題なく通信できました。
ということで、内部RC発振器でも外部セラロック発信器でもどちらでも9600bpsUARTは可能。ということがわかりました。
また、部室のオシロスコープでGT-720Fの出力を見てみたら5V与えているにもかかわらず4V程度しか出ていませんでした。これをうまく読み取れていないのではないかという仮説もたてて、間に74ICを挟んでCMOSレベルにしてからAVRに入力させてみたのですが、結果から言えばこれも無駄でした。
AVRのVcc=5Vのときに、4V程度の入力ならちゃんとHとして読んでくれるようです。今は74ICは抜いて実験中です。また不具合が出ればそのときにでも報告します。
LCDとUART
UARTのタイミングについて
ようやくGPSレシーバの出力をうまくUARTで受け取れるようになりましたが、今度は位置情報をLCDに表示しようと思ってもうまく表示できませんでした。
ところで、GT-720Fから出力されるフォーマットはNMEA-0183のVersion 3.01です。
NMEA-0183と一言に行っても、いろいろなフォーマットがあります。
このうち位置情報と速度情報だけでほかの要らない情報を含まないフォーマットがRMC(RECOMMANDED MINIMUM SPECIFIC GPS/TRANSIT DATA)です。GT-720Fはほかにも衛星情報を含むGGAやGLLを吐いてくれるのですが、今回はそれらの情報は見捨ててRMCを使うことにしました。
RMCのフォーマットは
$GPRMC,<時刻>,<測位の可否>,<緯度>,<N/S>,<経度>,<E/W>,<速度>,<速度の方向>,<日付>,その他いろいろ<CR><LF>
とほしい情報だけ並んでいます。
で、まずはGT-720Fからどんどん送られてくる文字列から、"$GPRMC"を捕まえたあと、コンマを3回数えて緯度情報を送られてくる一文字ずつ出力させました。つまり、
char ch;
/*GPRMCを捕まえたてコンマを3回数えた後*/
for(;;){
ch = GetCharFromGPS(); //UARTでGT-720Fから文字を受け取る。
LCDPutChar( ch ); //LCDに出力
if( ch == ',' ) break; //コンマなら「緯度」のセクションは終わり
}
としたのですが、うまくいかない。変な文字列ばかり表示される。
この原因は受け取った文字をLCDへ逐一出力させたことにありました。LCDへの出力はLCDモジュールの処理完了を待つためかなり時間がかかります。それに対し、UARTは9600bpsで動作しているため、途切れなく文字が届いた場合、1秒に1000文字くらい送られてくる計算になります。AVRのUARTでは文字をためておくバッファが2つしかないため、UDRを読みにいく間隔が1msよりも大幅に遅すぎるとどんどん読み落としを作ってしまいます。
つまりUARTでほしいデータを読み取っているときは、重い処理を同時に行うことは危険なのです。今回LCDモジュールの余裕を見て1文字出力するたびに2msほどwaitしていたのでこのようなことが起こりました。
いったん文字列をバッファリングして、RMCのデータを読み終わったあと、じっくりとLCDに出力することで解決しました。
最後にtiny2313で快調にプログラムを組んでいたら、AVRWRTから「プログラムのサイズがでかすぎてAVRのフラッシュに入りきらないよ!」って言われました。
マイコンで組んでいれば本当によくあることです。
ちなみにtiny2313の2KBフラッシュしかもたないAVRでは、小数を扱うと大きくファイルサイズが増大します。
つまり
・float,doubleで変数を宣言する
だけではなく
・float,doubleで型キャストして、小数計算させる
などが1箇所でもあると、小数計算ライブラリを読み込むようです。AVRの小数計算ライブラリが馬鹿でかいらしく、hexファイルが5KBほど増えます。この量は大体の場合tiny2313のFLASHのサイズを超えさせてしまうようです。
ということでtiny2313では工夫して整数のみで計算を行いましょう。
まあ、これも常識なのでしょうかw。まだマイコン工作が2作目の私にとってはかなりの衝撃なのですが。
ということで、数々の教訓を残してGPSレシーバちゃんは元気に動いております。
常時130mAを食いながらw
PR
トラックバック
トラックバックURL: