前回GPSロガー製作日記6で紹介したGPSレシーバ(まだロガーじゃないですよ!)の失敗談などを書きます。
今回のテーマは
1.tiny2313のSRAMの少なさはマジヤバイ
2.低ドロップレギュレータの出力は発振に注意
です。
1.ATtiny2313のSRAMの少なさ
ATtiny2313のプログラムメモリたるFLASH領域はデータシートのとおり2KBです。これはかなりの小ささで、プログラムのコンパイル時にはこれを超えないかどうか常にハラハラです。しかし、それを上回ってスタック・ヒープたるSRAMの大きさはさらにひどいです。いわゆるPCで言う「主記憶」の一部なわけですが、これが
128B
です。冗談じゃありません。KももちろんMも抜けてませんよ。正真正銘1byteのchar型なら128個のみのSRAMです。
実はこれに気づかないまま、位置情報の表示と、速度情報の表示を行おうとしていたのですが、どうにも意味のわからないバグが起きる。プログラムの下流のほうで式をいじると、明らかにそことは関係のない上流の処理がスキップされたりする。
かなり激しく悩んで、K氏に打ち明けたのですが、tiny2313について説明している間に、データシートのSRAMの小ささに気づき、「メモリオーバー」なる現象に見舞われていることがわかりました。
主記憶なんて、やれ「2GB」だ、やれ「4GB積んだけど、どうせ3GBしか認識しないぜ」だ、みたいな話しかしません。PC上でプログラムを長いこと組んでいますが、メモリがわずかに32MBしかなかった時代ですら、Linuxではスタック用のメモリが不足するなんて経験したことなかったのです。
char buf[ 64];
などと書こうものなら、メモリの半分を消費してしまうことについては認識不足でした。
ということでtinyなどの小規模マイコンを使うときは変数の使いすぎによるメモリオーバーに特に注意が必要です。
マイコンのメモリ構造について
勉強不足から間違ったことを書いている可能性がありますが

AVRでは低位のメモリ(メモリ番地の若い場所)から高位メモリ方向の順に
汎用レジスタ
IOレジスタ
内臓SRAM
の順で並んだメモリ空間を持っています。
そして、スタックポインタ(SP/SPL)は
「ス タ ッ ク が高位メ モ リ から低位メ モ リ へ伸長するよう に実行される」
Hiroさんの翻訳版tiny2313データシートより
とありますので、デフォルトではSPは0xDFから、スタックに積みあがるごとに低位メモリに伸びていくはずです。
つまりSRAM上でメモリオーバーを起こすと、IOレジスタや汎用レジスタが破壊されかねないということのようです。
2.低ドロップレギュレータは発振に注意
症状:
判定法:
解決法:
原因:
3端子レギュレータは不安定な高電圧電源から安定した低電圧電源を作り出す部品です。
ですが、正しい使い方をしないと、安定な電源を供給できるどころか、もとの電源にはない発振をおこしてしまいます。

電源側のC1は0.1uFと小さくてよいのですが、
出力側のC2は100uFの電解コンデンサが必要のようです。
出力側の負荷が大きく大電流を流す場合は、C2はさらに低ESRでないと低ドロップタイプのレギュレータである48xxは発振してしまうようです。
部室のオシロスコープで発振していることが判明しましたが、手持ちにはアナログの電圧計しかありません。ですが、アナログ電圧計でもC2が不足しているときは平均電圧が下がる傾向にあるらしいので検知することができると思います。
ちなみに
「4805や48033など低ドロップレギュレータを使っているときにマイコンが誤作動をした」→
「レギュレータの出力が発振していないか、まず疑ってかかる」
という思考回路は、マイコン野郎の中ではかなり常識のようです。
今回のテーマは
1.tiny2313のSRAMの少なさはマジヤバイ
2.低ドロップレギュレータの出力は発振に注意
です。
1.ATtiny2313のSRAMの少なさ
ATtiny2313のプログラムメモリたるFLASH領域はデータシートのとおり2KBです。これはかなりの小ささで、プログラムのコンパイル時にはこれを超えないかどうか常にハラハラです。しかし、それを上回ってスタック・ヒープたるSRAMの大きさはさらにひどいです。いわゆるPCで言う「主記憶」の一部なわけですが、これが
128B
です。冗談じゃありません。KももちろんMも抜けてませんよ。正真正銘1byteのchar型なら128個のみのSRAMです。
実はこれに気づかないまま、位置情報の表示と、速度情報の表示を行おうとしていたのですが、どうにも意味のわからないバグが起きる。プログラムの下流のほうで式をいじると、明らかにそことは関係のない上流の処理がスキップされたりする。
かなり激しく悩んで、K氏に打ち明けたのですが、tiny2313について説明している間に、データシートのSRAMの小ささに気づき、「メモリオーバー」なる現象に見舞われていることがわかりました。
主記憶なんて、やれ「2GB」だ、やれ「4GB積んだけど、どうせ3GBしか認識しないぜ」だ、みたいな話しかしません。PC上でプログラムを長いこと組んでいますが、メモリがわずかに32MBしかなかった時代ですら、Linuxではスタック用のメモリが不足するなんて経験したことなかったのです。
char buf[ 64];
などと書こうものなら、メモリの半分を消費してしまうことについては認識不足でした。
ということでtinyなどの小規模マイコンを使うときは変数の使いすぎによるメモリオーバーに特に注意が必要です。
マイコンのメモリ構造について
勉強不足から間違ったことを書いている可能性がありますが
AVRでは低位のメモリ(メモリ番地の若い場所)から高位メモリ方向の順に
汎用レジスタ
IOレジスタ
内臓SRAM
の順で並んだメモリ空間を持っています。
そして、スタックポインタ(SP/SPL)は
「ス タ ッ ク が高位メ モ リ から低位メ モ リ へ伸長するよう に実行される」
Hiroさんの翻訳版tiny2313データシートより
つまりSRAM上でメモリオーバーを起こすと、IOレジスタや汎用レジスタが破壊されかねないということのようです。
2.低ドロップレギュレータは発振に注意
症状:
- 電流を多く使う機器を入れるとマイコンが誤作動する。
判定法:
- レギュレータの出力が規定値より低い
- レギュレータの出力をオシロスコープで見ると線がぼやける
解決法:
- レギュレータの出力側にコンデンサC2を入れる。C2はできるだけ大きくESRの少ない(つまりは新しい)電解コンデンサを用い、レギュレータに物理的に近い場所に入れるのが良い。
- 解決しない場合、レギュレータを交換する。
原因:
3端子レギュレータがレギュレーションに必要なキャパシタンスが得られず、電力供給が追いつかないため。特に入力電圧が低く、出力電流が多いときに容易に起こる。
3端子レギュレータは不安定な高電圧電源から安定した低電圧電源を作り出す部品です。
ですが、正しい使い方をしないと、安定な電源を供給できるどころか、もとの電源にはない発振をおこしてしまいます。
電源側のC1は0.1uFと小さくてよいのですが、
出力側のC2は100uFの電解コンデンサが必要のようです。
出力側の負荷が大きく大電流を流す場合は、C2はさらに低ESRでないと低ドロップタイプのレギュレータである48xxは発振してしまうようです。
部室のオシロスコープで発振していることが判明しましたが、手持ちにはアナログの電圧計しかありません。ですが、アナログ電圧計でもC2が不足しているときは平均電圧が下がる傾向にあるらしいので検知することができると思います。
ちなみに
「4805や48033など低ドロップレギュレータを使っているときにマイコンが誤作動をした」→
「レギュレータの出力が発振していないか、まず疑ってかかる」
という思考回路は、マイコン野郎の中ではかなり常識のようです。
PR
GPSレシーバとして実用的に使えるものができました!
スペックなどを書いてみます
※1
アンテナの消費電流は一度衛星をロックすると衛星補足時の65%ほどに落ちる。
※2
ENELOOP使用時
http://www.eneloop.info/home/performance-details/capacity.html
よりENELOOPの容量が1700mAhと試算
ウリは
・表示部とアンテナ部をすこーし離して、受信状態を改善←まあそれなりに重要
・4.2V駆動のLCDパネルを搭載しているにもかかわらずENELOOP2本(2.4V)で駆動←50円ケースに入れるという点では重要
前回動かなかった理由など、いろいろと失敗談を書きたいのですがそれは日記7に譲って、今回はどうしても書きたい電池の電源について書きます。
一次電池の単三2本(3.0V)や二次電池のニッケル水素なりENELOOP2本(2.4V)から5Vを作るためには昇圧が必要なのですが、
・GPSアンテナが電力食いである(入力電圧(3.8~5V)に関係せず130~200mA食いやがる)
・昇圧回路を作るのが面倒
・必要な電圧が5Vで、入力は単3電池2本がベスト。
という二つの理由から携帯の充電器をばらして使うことにしました。

携帯の充電器のいいところは
・電池の電圧が低く(ニッケル水素の2.4V)でも安定して5Vを供給する
・もともと電源用のためかなりの電流を流せる(5V側200mA、電池側470mAで電圧も下がってませんでした)
・上のような大電流を流しても高効率89%!
・電池ボックス付き
逆に悪いところは
・入力、出力電圧を変えるためにはICの解析が必要
・あまり安くはない(700円はする)
100円SHOPとかで売ってたら一番なんですが、昇圧用ICが高いのでダイソーではおいてませんね。ダイソーにおいてある携帯電話充電器はすべて電池4本(6V)から携帯電池の電源の5Vに落とすものばかりでした。
たぶんレギュレータが入っているだけなんでしょう。
あーでも300円ぐらいでおいてないかなぁ。
スペックなどを書いてみます
重量 | 195g |
電源 | 単三アルカリ電池×2 or 単三ニッケル水素電池×2 |
消費電力 | 0.89~1.1W※1 |
電池持続時間 | 3.6~4.6h※2 |
GPSアンテナ | GT-720F |
精度 | 位置 CEP5m 速度 0.1m/s |
表示 | 0.5Hzで以下を表示 緯度(0.0001分) 経度(0.0001分) 速度(0.1km/h) 移動方向 |
コスト | GT-720F 3500 SC1602BS 550 TINY2313 370 その他 計 5500円程度 |
アンテナの消費電流は一度衛星をロックすると衛星補足時の65%ほどに落ちる。
※2
ENELOOP使用時
http://www.eneloop.info/home/performance-details/capacity.html
よりENELOOPの容量が1700mAhと試算
ウリは
・表示部とアンテナ部をすこーし離して、受信状態を改善←まあそれなりに重要
・4.2V駆動のLCDパネルを搭載しているにもかかわらずENELOOP2本(2.4V)で駆動←50円ケースに入れるという点では重要
前回動かなかった理由など、いろいろと失敗談を書きたいのですがそれは日記7に譲って、今回はどうしても書きたい電池の電源について書きます。
一次電池の単三2本(3.0V)や二次電池のニッケル水素なりENELOOP2本(2.4V)から5Vを作るためには昇圧が必要なのですが、
・GPSアンテナが電力食いである(入力電圧(3.8~5V)に関係せず130~200mA食いやがる)
・昇圧回路を作るのが面倒
・必要な電圧が5Vで、入力は単3電池2本がベスト。
という二つの理由から携帯の充電器をばらして使うことにしました。
携帯の充電器のいいところは
・電池の電圧が低く(ニッケル水素の2.4V)でも安定して5Vを供給する
・もともと電源用のためかなりの電流を流せる(5V側200mA、電池側470mAで電圧も下がってませんでした)
・上のような大電流を流しても高効率89%!
・電池ボックス付き
逆に悪いところは
・入力、出力電圧を変えるためにはICの解析が必要
・あまり安くはない(700円はする)
100円SHOPとかで売ってたら一番なんですが、昇圧用ICが高いのでダイソーではおいてませんね。ダイソーにおいてある携帯電話充電器はすべて電池4本(6V)から携帯電池の電源の5Vに落とすものばかりでした。
たぶんレギュレータが入っているだけなんでしょう。
あーでも300円ぐらいでおいてないかなぁ。
うまくいかない~
GPSレシーバは見通しがよく、きちんとした姿勢でおかれないと安定して受信ができないとわかってきたので、表示部やAVR本体から離せるようにすることを考えました。
UART通信の信号線を3芯シールド線で離したのは良かったのですが、そこからなぜか表示がまたバグりはじめた・・・
とりあえず
1.前回同様、UARTのタイミングがうまく取れていない。
2.信号が劣化している
3.線の抵抗値が大きすぎて、信号をAVRがうまく拾えない。
などを考えてみています。
あと、レギュレータの出力電圧がかなり低いです。
4805なので出力は5Vになるべきなのですが、4V付近まで落ちてしまっている。
原因ですが、あまり良くわかりません。200mAを食うGPSレシーバをはずしてみたらちゃんと5Vになります。
レギュレータは電圧差分を熱エネルギーに変えているので、感覚的には熱の問題さえなければちゃんと降圧してくれそうな感じなのですが。
GPSレシーバは見通しがよく、きちんとした姿勢でおかれないと安定して受信ができないとわかってきたので、表示部やAVR本体から離せるようにすることを考えました。
UART通信の信号線を3芯シールド線で離したのは良かったのですが、そこからなぜか表示がまたバグりはじめた・・・
とりあえず
1.前回同様、UARTのタイミングがうまく取れていない。
2.信号が劣化している
3.線の抵抗値が大きすぎて、信号をAVRがうまく拾えない。
などを考えてみています。
あと、レギュレータの出力電圧がかなり低いです。
4805なので出力は5Vになるべきなのですが、4V付近まで落ちてしまっている。
原因ですが、あまり良くわかりません。200mAを食うGPSレシーバをはずしてみたらちゃんと5Vになります。
レギュレータは電圧差分を熱エネルギーに変えているので、感覚的には熱の問題さえなければちゃんと降圧してくれそうな感じなのですが。
前回「ヒューズ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
昨日はRS-232C経由でPCと接続しGT-720Fの動作確認をしたので、今日は本命のLVTTL側の端子を使ってマイコンでデータを扱うことに挑戦。
実は今回のGT-720Fを使う前に、一度秋月からGPS-52を購入し、同じようなGPSロガーを作ろうとしていました。
しかし端子を逆差ししてしまい、GPS-52はあえなくご臨終。4800円が一瞬で吹き飛びました(泣)
今回はそのテストに使っていた回路を再利用してGPS-52のテストを行うことにしました。
GPSモジュールから受け取るプロトコルはNMEA-0183で同じなので、プログラムもほとんどそのまま再利用。
GT-720からの出力を液晶モジュールSC1602にそのまま出力する安直なプログラムです。
とりあえずつないでみよう。えいっ。
・・・文字化け。
テストパターンの”Hello, world!"はちゃんと出力されるから、LCDへの出力プログラムミスではないらしい。となるとUARTがうまく受信できていないらしい。
とりあえずGT-720(9600bps出力)からの信号にうまく同期できていないのだろう、と当たりを付けて、
・baud rateはちゃんと9600bpsになっているか。
・1byte=8bitの受信になっているか。
ということを確認。問題なし。
・・・困った。UARTを扱うのが初めてだからどう対処すべきかわからない。
UARTはクロックにうるさいとどこかで聞いたので、内臓クロックを使ってるのがまずいのかと思って内臓クロックの精度を見てみた。
tiny2313のデータシートによると、
内臓RC発振器:誤差2%
UARTの精度は5%絶対必要でできれば3%といっているので結構大きい。面倒くさがらず、外部クロックにしよう。
買ってあったまま使っていない8MHzセラロックを使う。
これまた使うのは初めてなので、極性がないこととか、ちゃんと調べながらw
回路図上の記号が対称だから、極性なんてないとは思っていたけど、やっぱりないようですねw

セラロックをつけたところ。
コネクタは赤いコネクタから右回りに、電源、ISP、GPSモジュール、LCD。
外部クロックに切り替えようとヒューズビットを書き込んだところ。
まったく入力を受け付けなくなりました。
お約束ですね~
間違ったヒューズビットを焼いてしまったようです。
AVRはヒューズビットという、電源が切れてもAVR自身の設定を覚えておくビットがあります。
クロックの部分やリセットの条件についてなど、AVR動く条件がそのヒューズビットで決められています。
ですので、意図しないヒューズビットを書き込んでしまった場合、AVRを動かしてやれる条件を満たすことができず、AVRは動きません。
AVRが動かないとヒューズビットの書き換えもできないので、誤ったヒューズビットを書き込んでしまうと、手持ちの機材ではAVRは一切動いてくれなくなる、という地雷のような設定があるのです。
今回はその地雷を見事に踏み抜いてしまったらしいです。
ATtiny2313のヒューズビットはクロック選択の部分だけ抜き出すと、
となっているようなのですが、誤って0110を焼いてしまったようなのです。(今となっては確認すらできません)
表によれば128kHz内部発振器が働くはずなのですが、SPIでプログラミングできません。これまたよくわかりません。
使っているプログラマはディジットのAVR WRTなので高電圧プログラミングによるヒューズビットの書き換えもできず、お手上げです。
クロック周りの設定は気をつけなければならないとわかってはいたのですが、今回は外部発振器を持っていたので楽観していました。
油断大敵です。
ということで、ATtiny2313を一つ封印してしまいました。1個100円なのでたいしたことはないですが、予備が一個もないので今日は作業中止。
結局UARTがうまく働かなかったのは、内臓クロックを使ったせいなのかどうかも検証できずじまいでした。ヒューズビットを直すか、新しい2313で成功したら、内臓クロックでも試してみたいです。
実は今回のGT-720Fを使う前に、一度秋月からGPS-52を購入し、同じようなGPSロガーを作ろうとしていました。
しかし端子を逆差ししてしまい、GPS-52はあえなくご臨終。4800円が一瞬で吹き飛びました(泣)
今回はそのテストに使っていた回路を再利用してGPS-52のテストを行うことにしました。
GPSモジュールから受け取るプロトコルはNMEA-0183で同じなので、プログラムもほとんどそのまま再利用。
GT-720からの出力を液晶モジュールSC1602にそのまま出力する安直なプログラムです。
とりあえずつないでみよう。えいっ。
・・・文字化け。
テストパターンの”Hello, world!"はちゃんと出力されるから、LCDへの出力プログラムミスではないらしい。となるとUARTがうまく受信できていないらしい。
とりあえずGT-720(9600bps出力)からの信号にうまく同期できていないのだろう、と当たりを付けて、
・baud rateはちゃんと9600bpsになっているか。
・1byte=8bitの受信になっているか。
ということを確認。問題なし。
・・・困った。UARTを扱うのが初めてだからどう対処すべきかわからない。
UARTはクロックにうるさいとどこかで聞いたので、内臓クロックを使ってるのがまずいのかと思って内臓クロックの精度を見てみた。
tiny2313のデータシートによると、
内臓RC発振器:誤差2%
UARTの精度は5%絶対必要でできれば3%といっているので結構大きい。面倒くさがらず、外部クロックにしよう。
これまた使うのは初めてなので、極性がないこととか、ちゃんと調べながらw
回路図上の記号が対称だから、極性なんてないとは思っていたけど、やっぱりないようですねw
セラロックをつけたところ。
コネクタは赤いコネクタから右回りに、電源、ISP、GPSモジュール、LCD。
外部クロックに切り替えようとヒューズビットを書き込んだところ。
まったく入力を受け付けなくなりました。
お約束ですね~
間違ったヒューズビットを焼いてしまったようです。
AVRはヒューズビットという、電源が切れてもAVR自身の設定を覚えておくビットがあります。
クロックの部分やリセットの条件についてなど、AVR動く条件がそのヒューズビットで決められています。
ですので、意図しないヒューズビットを書き込んでしまった場合、AVRを動かしてやれる条件を満たすことができず、AVRは動きません。
AVRが動かないとヒューズビットの書き換えもできないので、誤ったヒューズビットを書き込んでしまうと、手持ちの機材ではAVRは一切動いてくれなくなる、という地雷のような設定があるのです。
今回はその地雷を見事に踏み抜いてしまったらしいです。
ATtiny2313のヒューズビットはクロック選択の部分だけ抜き出すと、
外部クリスタル/セラミック発振子 | 1111~1000 |
128kHz内部(WDT)発振器 | 0110 |
8MHz校正付き内蔵RC発振器 | 0100 |
4MHz校正付き内蔵RC発振器 | 0010 |
外部クロック信号 | 0000 |
(予約) | 0xx1 |
となっているようなのですが、誤って0110を焼いてしまったようなのです。(今となっては確認すらできません)
表によれば128kHz内部発振器が働くはずなのですが、SPIでプログラミングできません。これまたよくわかりません。
使っているプログラマはディジットのAVR WRTなので高電圧プログラミングによるヒューズビットの書き換えもできず、お手上げです。
クロック周りの設定は気をつけなければならないとわかってはいたのですが、今回は外部発振器を持っていたので楽観していました。
油断大敵です。
ということで、ATtiny2313を一つ封印してしまいました。1個100円なのでたいしたことはないですが、予備が一個もないので今日は作業中止。
結局UARTがうまく働かなかったのは、内臓クロックを使ったせいなのかどうかも検証できずじまいでした。ヒューズビットを直すか、新しい2313で成功したら、内臓クロックでも試してみたいです。