2009年6月アーカイブ

2009-06-29-001.JPG  本番用に買った SD1602 を接続。一発で動く。当たり前か (^^;

 ケースといっしょに買ったコネクターを使って SC1602 を接続するケーブルもいっしょに作ったので今日はここで時間いっぱい。

 明日はバックライトを点けよう。明るさの設定をどうするか...。

----
 ちなみにケーブルは、昔 PC8001 で遊んでいたときのもの。ものは捨ててはいけません (^^
011.JPG010.JPG  デジタルタコメータ本番用の LCD  SD1602HUOB(-XA-G-R)を秋月から買ったのだが、「超」小型という割には、実装面積は SC1602BS-B(-SO-GS-K) と比べてあまり小さいとは思えない。表示部は確かに小さそうだが...。

 それよりも問題はケースへの固定方法。 SC1602 の方はケースに LCD の枠ぎりぎりの穴をあけ、接着剤で固定すれば何とかなりそうなのだが、SD1602 は、きちんとやるにはパネルを2重するぐらいの手間ががかかりそう。

 面倒くさいから SC1602 を使って仕上げてしまうか?
009.JPG  デジタルタコメータ本番用の LCD を秋月に注文したついでに、せっかく送料を払うのだからと色々と注文。

 USB - シリアル変換は今のメインマシンで H8 に書き込むときに必要、ピンセットは前々から欲しいと思っていたけど、それ以外は使うことがあるのか...。
 2-3日前にちょっとがんばってやったらそれからやる気がおきない。まぁ、届いた LCD をケースに入れるのが難しいというのが一番の理由なのだが....。

 明日ケースを買いにいくか。

 昨日、完全 ROM 化してエージングをかけていると不具合発生。15分程度動かしていると、強制的に’under'状態になり、表示がちらつく感じ。
 調べてみると、プログラム内部の基準クロックにしていた、TimerA の割り込みで 31.25ms ごとに更新される 16bit のフリーランカウンタの扱いに問題があった。
 16bit の符号無し整数でボローが出たときの処理が、x86 の gcc と違うような気がするのだが気のせいか?

-----
 一晩エージングしたが、特に問題はないよう。

  • ごく希に、一瞬だけ 'under' を表示する
  • data セグメントの定数にうまくアクセスできない
という不具合はすでに判明しているのだが、どちらもタチが悪そうなので今回は目をつぶる (^^;
回路図-1 LCD-1-4.PNG いつまでもタコメータばかりやっているわけにもいかないので、一日一時間の枠を取っ払って仕上げにかかる。

 リセットスイッチ、FLASH 書き込みモード切替スイッチ、電圧測定用の分圧回路を組み込む。イグニッションパルスの入力回路は、ブレッドボードを使ってカットアンドトライをしたが、手持ちに丁度いいコンデンサがなかったので保留。

 電圧計測の AD変換はあっさり動いたので組み込むことに。簡単なオープニング画面を表示させて、いよいよ完全 ROM 化。

 Makefile に rom.mot を作るルールを追加、rom から起動するプログラム用のスタートアップルーチンとリンカスクリプトを持ってきて、コンパイル。
 リンカスクリプトの変更(1,2)を忘れていて多少手こずったが、CPU へのヘキサの書き込みは一発で動く。

 先に ROM 化したプログラムとあわせてヘキサが2本(H8OS も入れると3本)、メモリマップも奇々怪々。機会があれば一本化したほうがいいかも。

 あとは、注文した LCD をケースに入れて、ステラから信号を引っ張り出して...。

----
 エージングしていたんだが、表示がおかしい。正常な信号が入っているのに under と判断しているようだ。

 やっぱり、簡単にはいかないか。

 
 今使っている LCD はジャンク箱をひっくり返して見つけたもので、バックライトがないのでそのままでは使えない(車に積んだら夜は見えない)。
 ということで、オレンジ色のバックライト付の LCD を注文。オレンジを選択したのは、ステラのメーター証明がオレンジ色のため。小さいのを選択したのは、いままで使っている LCD が意外と大きく、ケースがかなり大振りになるため。

----
 ここから先はケース加工やら ECU から信号線を引き出しやら、面倒くさい仕事が待っている。完成まで持っていけるか??
回路図-1 LCD-1-2.PNG 昨日はちょいと無茶をして眠れなくなったので、久しぶりに夜中の3時にプログラミング。すぐオーバーレブしてしまう原因は、発信器のリニアリティの問題 -- ほんのちょっとボリュームをまわすと周波数が跳ね上がってしまうことが原因らしい。

 ということで、タコメータの機能的にはプログラムは完成。あとはちょっとお化粧して全体を ROM 化するとソフトウェアは全部おしまい。電圧計も入れたいのだが、そろそろプロジェクトを完結させたいし...。
-----
 今日は点火パルスをアナログ系の回路を考えてみる。ネットにあるのはイグニッションコイルの 12V ラインから取ってくるようなものが多く、ダイレクトイグニッションのステラにそのまま使えそうなものは見当たらない。

 やっぱり車の横にオシロを持っていって実測するしかないか...。
-----
 昨日は街に出たついでに、部品を少々買ってきた。プログラム書き込み・実行切り替え用のスライドスイッチ、リセットスイッチに使うタクトスイッチ、5V のツェナー2本、電圧測定用の分圧抵抗2本。

 そろそろ本番用の LCD も注文せねば。
 今日は異常時というか、停止や over rev などの状態表示を追加。なぜかすぐ over rev してしまう不安定な動作。車両エミュレーターの問題か?少し調べてみよう。

 一応これで使えるようにはなった。あとは秋月に本番用の LCD を注文して、今日はケースを見て、時間があれば電圧計も実装したい。

 今月中に完成できるか?
090617003.JPG  今日はすでに ROM 化してある TimeW のルーチンをチェック後、全部の動作を組み合わせてみた。ようやくそれらしく動いた (^^
 今日はここまで 30分。のこり 30分は...。結局コード圧縮に勤しむ。全部の関数を main に入れたり、2進->10進変換に H8OS API を使ったりで 256byte ほど圧縮。

  あとは、正常動作、回転数高すぎ、回転数低すぎ、エンジン停止の状態を作ればプログラムは一応完成。作ること自体は難しくないのだが、メモリが足りない...。
  RAM 上で動作チェックはやめて、いきなり ROM で動かすことにしようか?
-----
  ちなみに、自分で作った H8+GCC 向けの「吐き出されるオブジェクトの小さい2進->10進変換」のソースはこちら。10分かそこらで作ったたいしたコードではないのだが、記念に残しておこう (^^;

    short i,ptr,n,m;
    ptr = 19;
    for (i = 0;i < 4;i++) {
//    while(x > 0) {
        n = x / 10;
        m = x - n * 10;
        LcdRam[ptr--] = m + '0';
        x = n;
    }
 今日は今、RAM で動いている関数を二つ、ROM に移動した。作業ははかどったが、機能的には何の変化もないわけで、時間の無駄使い。

 こんなことをしているからいつまでたっても完成しない。

----
 今日作業を始めようとすると、あるべきはずファイルがない。昨日マシンが立ち上がらなくなって、Windows が何度か再起動していたのだがそのせいか?幸い、古いソースのあるディレクトリに似たようなファイルがあったのでそこからコピー・修正して事なきを得た。
 で、今日はあわてて Project 4 全体のディレクトリを iTunes サーバーへバックアップ。

 やばいやばい。
 今日は LCD アクセスルーチンの ROM 化。の前に、昨日作業を終えてから気がついた TimerW アクセスルーチンの<del>バグ</del>不具合を直して動作確認。

 そのあと、LCD アクセスルーチンを ROM 化し、テストプログラムを書いたのだが、あっという間にコードが膨れ上がり RAM 容量の壁にぶち当たる。

----
 このプロジェクトを始めてから、早一月半。LCD アクセスルーチンのファイルのタイムスタンプは丁度一ヶ月前。いくらなんでも2ヶ月以内に完成させたいと、今日の作業時間は2時間。
 予想外のところに時間を吸い取られていく...。
----
 H8+gcc は異様にコード効率が悪い。

struct sLcdFont {
    unsigned char code;
    unsigned char *dat;
};
void    lcd_font_set_up(void)
{
    int    i;
    struct sLcdFont buf;

    for (i = 0;i < 6;i++) {
        buf.code = i;
        buf.dat = font[i];
        func_tbl[SetLcdFont]((int)&buf);
    }
}
SetLcdFont は定数。

 この関数が 92byte。

void    put_disp(unsigned short x)
{
    disp_bar(x);
    disp_number(x);
    func_tbl[RewriteLcd](0);
}
RewriteLcd は定数
 この関数が 50byte

 ちなみにコンパイルオプションは -O。引数のレジスタ渡しとかしないのだろうか?

 開発中のコードに使える RAM 領域は 1kbyte 強ある。これだけあれば何とかなると思っていたのだが、全然足りなくなってきた。



 昨日に引き続いて TimerW アクセスルーチンを ROM化。測定した周期の読み出しは

func_tbl[GetPeriodW](0)

 なのだが、print の引数に

func_tbl[GetPeriodW]

 と書いてしまって、アドレスが返ってきてしまい一瞬あせる。すぐにアドレスが返っていると気づいて事なきを得たが、気がつかなければかなりハマるところだった。

-----
 「関数のポインタの配列へのポインタ」の値を読み出す部分だが、気になったので見直しをかけて、結局以下の形にした。

#define func_tbl_ptr (*(int (***)(int))0x5800)

 もう何がなんだか...。ちなみに、

#define func_tbl_ptr (*(int (**[])(int))0x5800)

 は、読み出した値を代入するところで形が合わないとワーニングになった。

-----
 今日はここで時間切れ。明日は LCD アクセスルーチンの ROM化だ。


 昨日作った ROM化した TimerA アクセスルーチンを使うためのプログラムを作る。

 「関数のポインタの配列へのポインタ」をアクセスするのに悩んだが、なんとか一発で動く。

 ROM にある関数のアクセスはこんな感じ。

enum {dummy,InitTimerA,GetTimerA_Counter};
#define func_tbl_ptr (int (**)(int))(*(volatile unsigned long *)0x5800)
int (**func_tbl)(int);
func_tbl = func_tbl_ptr;
func_tbl[InitTimerA](0);

 このあと、二つの *.mot ファイルを CPU の FLASH に書き込むのに手間取るが(結局二本の *.mot をエディターで結合した)、ROM 化した関数のアクセス・動作は問題なく成功。

 明日は TIimerW アクセスルーチンの ROM 化だ。



 部屋を整理していて出てきた昔のノートを開いたら、作りかけのプログラムが書いてあった。よく見るとタコメータ。さらによく見るとラフスケッチの回路図があって、使っているのが Z80CPU + Z80PIO (^^;

 ざっと20年、いやそれ以上前か。

 この20年進歩がない?いやいや、20年来の夢がもう少しでかなう (^^
 プログラム全体のサイズが H8OS/3664 の RAM 領域で開発できる範囲を大きく超えることが明らかになったので、今まで作ったルーチンを少しずつ ROM 化していくことにした。
 最初はサイズが小さく機能も少ない TimerA 割り込み関連の処理から。H8OS 本体のリンカスクリプトを見ながら専用のリンカスクリプトを作る。関数ベクタテーブルの ROM 化に手間取ったがとりあえずそれらしい *.mot ファイルが完成。

 しかし、こういうのは最近の組み込みの範疇に入るのだろうか?いや、入るのだろうが、おそらく「プリミティブ」なごく一部な領域になるのだろう。

 今日はここで time up。明日は呼び出す側のプログラム作成、ROM への書き込み、そして debug だ。

----
 関数へのポインタの配列を定数化にするのに、少し悩む。

const int (*func_tbl[])(int) = {main,...};
 だと、const int を返す関数のポインタへの配列になってしまう。

int (* const func_tbl[])(int) = {main,...};
 正解はこちら。やっぱりポインタは難関だ。
----
 gcc は(同じファイルにない)外部関数のアドレスを引っ張ってこれる。以前使っていた 8/16bit の C コンパイラではこれが出来なくて苦労した記憶がある。
----
 今日、ヘキサファイルを眺めていて気付いたが、H8 の gcc はポインタが 4byte もある。コードがでかくなるわけだ。

 昨日少し調べたが、H8 CPU は 16bit レジスタが 16本もある。なるほど、C で割り込みハンドラを書くとスタックを馬鹿食いたくさん使うわけだ。


 昨日に引き続いて、タイマW のソースにタイマA を組み込むとうまく動かない不具合の調査。色々やっていくうちに、スタックがコードを食い荒らしているのではなかろうかと考え H8OS のメモリダンプやらメモリクリアを使って見て行くと、確かにスタックがコードまでは行かなくても bbs 領域まで侵食した跡が見える。

 割り込みハンドラの終わり方を間違ってスタックを食い続けているか、いや、ハンドラの管理は H8OS だし。CPU の data sheet を見ても特殊な「お約束」があるようにも見えないし...。

 あれこれやった結果、割り込みを使うとその分スタック使用量が増えて、H8OS のユーザーRAM 領域にまで入り込むらしいことがわかった。これなら使わないソースを組み込んだだけで動作がおかしくなるのも納得がいく。

 今日はここまでで 20分のオーバー。つまらないことで一日半も使ったと思うと悔しいが、2時間と思えば、そうでもない。

-----
 これ以上は RAM 上での開発は無理。ここから先は毎回フラッシュに焼いていかなくてはならない。CPU の書き込み制限 100回以内に完成させられるか?

----
 それにしても、H8 のメモリ利用率は、8086/Z80 に比べて異様に悪い気がする。気のせいなのか、いまどきの CPU はこんなものなのか?
001.JPG  昨日接続した車両エミュレータと開発ボードを使って周期測定ルーチンのデバッグ開始...。あっさり動いた (^^;。
 ここは手こずると思っていたのでうれしい。

 時間が余ったので何をしようかと悩んだが、周期測定テストプログラム(タイマW使用)にタイマA テストプログラムを合体させることにした。が、ここでハマる。
 タイマA 関連を別ファイルにしてコンパイルしたのだが、動かず。まぁ、割り込み関係だし、とタイマA 関連の関数をコメントアウトして周期測定プログラムを元に戻してコンパイルするも動かず。まさか...。Makefile からタイマA のソースを外すと動く。リンカの問題?タイマA のソースを周期測定プログラムに持ってきて...、それでも同じ。コードが入るだけで(呼び出さなくても)動かない。なぜ??

 今日はこれで 10分オーバー。

 人間、運の総量は決まっているのだろうか、やっぱり。
発振器 7-400Hz-2.PNG 固定抵抗を 1kΩ->470Ω に変更すると、周波数が 426.7 Hz まで上がるようになった。この状態で開発ボードと接続。
 ブレッドボード上のボリュームは不安定なので当面 1kΩの固定抵抗で代用。このときの発信周波数は 117Hz。ということは 50kΩのボリュームのほんの 2% だけを使って 300Hz の幅を調整しなくてはならないのか...。もうひとつ用意したほうがいいかも。

 さて、明日からはタイマW周りのデバッグ。見えないところをやるのは気が重いが...、いかんいかん、がんばって完成させねば。
003.JPG ようやく見つけた 555 を使ってブレッドボード上に車両エミュレータを作成。ブレッドボードを使うのは初体験。慣れないせいもあってか、これぐらいの回路なら半田付けしてつくるのと時間的にあまり変わらない感じ。
 このあとあっちこっち引っ掻き回して泥縄的に電源と周波数カウンターを引っ張り出し、念のためにオシロまで準備したが、あっさり一発で動いた。
 ただし、周波数可変範囲が 2.9-258.9Hz。7-400Hz を狙っていたので上の方が全然足りない。色々考えたが、1KΩ の固定抵抗を 470Ωに変更すれば...、と考えたところですでに時間を 30分オーバー。続きは明日。

-----
 今日、周波数カウンターと比べて、オシロの時間軸が 5% 早いことに気がついた。そういえば UNCAL の LED が点灯しない。まぁ、ヤフオクで安く買った年代ものだしね。仕方ないか。

25年物の 555

| | トラックバック(0)
002.trim.JPG デジタルタコメーター車両エミュレータ(単なんる矩形波発信器)を作るために家の中で 555 を探した。秋月でまとめ買いしたのがあったはずだと探していたら、ガラクタ箱の中から 555 をひとつ発見。足が中に曲がっていたが半田付けの跡はなし。何とか使えそうだと思ってよく見ると、生産時期が 8440。1984年の40週?25年前??。

 いやぁ、これでまたジャンクが捨てられなくなった (^^;
 今日は予定を変更して回転数測定部のコーディング。表示は H8OS の機能を使用。まずはこれはこれでテストしよう。

 いよいよ車両エミュレータを作らねば。555 が何個かあるはずなんだが、探し出せるか?なければこないだ見つけた 4011 を使おう。

 
 今日は朝から頭が痛いが、こういうときこそウォーミングアップの意味がある。
-----
 表示の更新周期 100ms を得るためにタイマwを使おうと思ったが、面倒くさいのでタイマAを使って更新周期を 125ms とする。時間をかければ 100ms を得られるのだが、Project 4 もすでに始まってから一ヶ月以上。あまり長引くと完成する前に飽きてしまう (^^;

 タイマAはあっさり動く。31.25 ms の割込み4発で 125ms を得る目処が立つ。

 タイマwを使って周期を得るところもコーディングは終わり。

 これで部品はすべてそろったので組み合わせようとすると...、最初の部品(周期から周波数への変換)の中身を忘れている。

 今日はここで時間切れ。明日はメモリサイズを考えずに全体をまとめてみたい。
 昨日考えたアルゴリズムを基にコード書く。100行近いコードを書いて、コンパイルエラーになったのは ';' を ':' と typo した一箇所だけ。幸先よい?

 LCD の更新周期の 100ms もタイマW を使って得るつもりだったが、桁^H ビット数が足りない。ちょっと悩みどころ。

 10000rpm まで 1rpm 単位で計測するには、カウンターは、4MHz を入力して 18bit 必要になる。残念ながら H8/3664 のカウンターは 16bit しかないので 2bit をソフトで何とかしなくてはならない。
 単純に 16bit のカウンタがオーバーフローしたところでソフトが管理するカウンタをインクリメントするだけだと、オーバーフローとインプットキャプチャーのタイミングが重なったところで誤動作してしまう。計算すると 16bit のカウンターがオーバーフローするあたりの回転数は、3662rpm。 対策をしないと良く使うエンジン回転数でときたま表示がちらつくという非常にいやらしい不具合になりそうだ。

 同じような仕様のこちらコードを見ると、きちんと対策は打ってあるが H8 と AVR の割り込みコントローラーの仕様の違いからこのままでは使えない。頭を捻ってアウトプットキャプチャーを二本使うロジックを考える。

 今日はここでタイムアップ。明日は今日考えたロジックの検証だ。
 
 今日は H8-3664 のタイマの動作確認。フリーランで走らせて、オーバーフロー割り込みでカウンタをインクリメントさせてみた。あっさり成功。30分も時間が余った。

 こういう状況は考えていなかったので、次にやることが思いつかない (^^;。余った時間で H8OS ドキュメントの 3664 版との正誤表をちょっと作ってみた。

P4:下調べ

| | トラックバック(0)
 タイマ W を使った周期測定のために、タイマ W を使うための下調べ。

 H8OS 3.51 のソースに timer.c というファイルがあって、それを見ると関数 sleep はタイマVを使っていることになっている。ということはタイマV をいじって行けば sleep の動きに変化があるはず、とやっていくが思ったとおりの変化が得られない。タイマVのカウンタを直接読み出してもカウントしているようには見えない。一体なぜ...。

 よくよくソースを追って行くと 3664 版の H8OS は timer.c をリンクしていない orz。内部で H8_3664 の define も使っているのに...。
 H8OS のソースを sleep で grep すると、misc.c にも sleep 関数の定義があり、そちらではただの for の loop。

 少し調べた限りではタイマW もまったく使っていない模様。これはこれでありがたいが、ドキュメントを見ると、H8OS が 16bit カウンタを使っているとも書いてある。
 H8OS 3.51 のドキュメントはあまり当てにしないほうが良いか。フリーの、何年も前のソフトに文句も言えんし。

----
 今日はここで時間切れ。
 
 今日は実際の動作をイメージした LCD表示ルーチンの作成。バーグラフ表示は出来ているし、自前の 10進変換を作れば良いだけのはずだったのだが...。

 現在、表示の時間待ちに H8OS の sleep を使っているのだが、最短の待ち時間が少々長い。ソースを見ると タイマー V を使っているので、パラメータを変更して入力クロックを 1/128 から 1/32 にしようとレジスタを直接アクセスしたのだが...、動かない。2-30分ほどやってみたが原因不明。
 ここでハマって入るわけにもいかないので、途中であきらめ 10進変換ルーチンを作成開始。と、「メモリが足りない」のメッセージが。どうやら 変数÷変数 を実行すると演算ライブラリがリンクされて 200byte 程度コードが増えるようだ。変数÷定数だとリンクされないのだが...。
 アルゴリズムを変え、使っていない LCD アクセスの関数削除したりして何とか動くようになったが、ゼロサプレスが入りそうもない。

 予想外のところに時間をとられて今日は1時間オーバー。

-----
 表示周りはとりあえずここまでにして、明日からは周期測定部に入ろう。まずは車両エミュレーターの作成か。