カテゴリー「AVR」の38件の記事

2009年11月 5日 (木)

Xbee電力ロガーデータのSDカード書き込み成功

 無線チップXbeeを使ったワイヤレス電力ロガーが、遂にデータをSDカードに書き込むところまで動くようになった。センサーは電流しか測っていないのでおおよその電力測定ではあるが(市販のエコワットレベル)、これで長期にわたる電気機器の電力消費を心置きなく調べることが出来る。

電力量の測定は、レーザープリンターの電源をネットを使って遠隔制御した(2008/4/9 「LAN電源制御成功」の記事)とき、プリンターの正味の電力が知りたくてCT(current transformer)電流センサーを買って以来の懸案で、Xbeeを通信販売の送料コストを下げるために買って、期せずしてプロジェクトにはずみがついた。

これまで、省電力化したセンサー部のXbee子機のハード開発と、親機のソフト開発を段階的に進め、ついに子機で収集した電力データを親機がSDカードに書き込んでログをとるところまで実現した。このあいだ(10/26記事)のステップにわけた手順では、5の「自動的にファイルに書き出す」に相当する。

親機はXbeeがまだブレッドボードに乗ったままだし、ソフトもぐちゃぐちゃでまだとても公開できるレベルではないが、とにかく電源を入れればファイルを自動的に作り、測定時刻(年月日時分秒)の記録と同時に電力量をSDカードにテキストデータで記録していく。

子機もこれから密閉ケースに実装しなればならないが、この9月から始めたXbee電力ロガープロジェクトはこれでひとつ大きな山場を越えた。以下はそのレポートである。

リチウム電池を使った子機の実装(10/30/09)Xbee
 昨日までに親機は、Xbee子機が送信したAPIフレームの内容をPCのUARTに表示するソフトがやっとのことで出来上がり、開発の先行きが見えてきた。一方、子機は、実用化に向けて最後の懸案が残っている。電源をどうするかである。現在は単3乾電池2つが電源で、このままでは基準電圧が不安定で正確な測定値を得ることが出来ない。

 正確さを言い出せばきりがないが、せめて3端子レギュレーターで定電圧化してやりたい。XbeeはVccが3.3Vなので、レギュレーターのために乾電池なら3つ以上必要だが、最近おなじみのリチウム電池ならひとつですむ(3.7V)。Olimexで作ったXbeeのピッチ変換基板の中にレギュレーターがつけられるか検討する。

 うーむ少し窮屈だが何とか入りそうだ。使っていないXbeeの2つあるピンの一方のパターンを切ってランドに流用したりして、最終的には小さな電源スイッチまでつけることが出来た。頻繁に電源を入り切りする機械ではないが、コネクターの抜き差しは、逆差しが怖いので、スイッチはあったほうが安心だ。

 リチウム電池は、LPCMプレーヤーのために、いくつか予備が買ってある。電池フォルダーも作り慣れてきた。このあいだ作った充電基板で使用したCDケースのコーナーを利用したフォルダーを作る。2つともなかなかうまくできた。

 問題はケースである。実は、リニアPCMプレーヤーのケースにこの2つはぴったり入るのだが(もともとがXbee基板はプレーヤー基板の1/2で、電池もプレーヤー用)、防滴仕様にするためのスイッチやコネクターをケースにつける余裕がない。このままでは、ケースに隙間が出来てしまう。特にコネクターは簡単に抜けないようソケットタイプにしたのでケースの上にはみ出す。どうもうまくいかない。とりあえずは名刺ケースに入れるだけで、ケースの実装は、もう少しじっくり検討することにする。

SDカードに作るログファイルの考え方(10/31/09)
 親機のソフト開発は、前の記事に書いたようにステップを細かく6つにわけて進めている。これまでにステップ2(APIフレームを表示する)まで実現した。APIフレームの中味が項目ごとに表示されて、XbeeのADCデータがぐっと身近になったような気がする。次のステップはいよいよ本格的なロガーとなる3(SDカードにデータを記録する)である。

 実際の開発の前に、ログファイルのレコードフォーマットをどうしておくか考える。昔のようにメモリや、記録装置が高価だった頃は、データをバイナリで持ち、タイムスタンプなども連続データの頭だけにしておくなど、記録容量を少なくする工夫をし、ソフトでそれを展開していたが、今はそんなことをする必要は全くない。PCのUARTに出すためにも、蓄積データはテキストデータ以外考えられない。

 今度のロガーのファイル設計もこの方針でいく。データとしては大きく重複するが、単位レコードにすべてキャラクターベースでタイムスタンプを重複して持ち、電力データを記録することにする。10秒に一回記録して1 日分とっても300Kバイト以下である。いまの記録メディアや、PCにとってはゴミのような量である。

 ファイルの管理は、年月日を自動的にファイル名にして、同じ日のログは、そのファイルに追記し、日ごとにファイルとして管理することにする。これならファイルを開けなくても中のデータが何かすぐわかる。セッションごとにファイルを作っていくと、あとの管理が大変だ。親機を複数動かす時は、ユニークな親機の番号をつければ良い。

 以上のような考え方でログファイルの仕様を次のように決めた。

ファイル名:処理系での混乱を避けるため頭にアルファベット1文字(W)をつけて、年月日2文字づつを連ねたファイル名とする。

  (例)    W091105.TXT  (2009年11月5日のデータ)

ファイル属性: テキストファイル レコード長32バイト(固定)
ファイルレコードフォーマット:

1111 09/11/05 22:25:08 0033    (セパレーターはブランク。末尾\r\a)
|              |             |       |-----------  電力データ(当面ADC値)
|              |             |----------------- 時:分:秒
|              | ------------------------- 年(西暦2桁)/月/日
|----------------------------------- センサー子機のアドレス(16進)

データ量見積もり:
  1レコード32バイト(SDカードのセクター512バイトに合わせる)
                            1時間に360レコード(10秒インタバルとして)11.25Kバイト
                            1日で270Kバイト。

RTCはすぐ出たがストリング関数がまた不調(11/3/09)
 仕様が決まったのでいよいよソフト実装である。SDカードの書き込みは例によってChaNさんのFatFSを活用させてもらうことにする。まずは、年月日などのRTCデータである。

 ChaNさんのFatFSには当然RTC(リアルタイマークロック)がついている。RTCチップとのインターフェースはI2Cだ。このI2CドライバーはこのあいだのミニLCDのライブラリに流用させてもらった。今の親機のプログラムは、このFatFSのデモプログラムがそっくり動くようになっているので、RTCを実装するのは単に数ステートメントを持ってくるだけである。

 UARTに時刻を表示する開発は5分もかからなかった。簡単に動いた。時刻の校正は、このデモプログラムのコードを利用すれば良い。ソフトウエア資産の有りがたさをかみしめる。こういうソフトはまさしく全員で共有するべき資産と言える。その意味でソフトウエアを著作権と同じ法律で縛る今のコンピューターの世界は不幸というより他はない。国民経済的に見れば、同じようなソフトを別々に独立して開発するのは人間の脳という資産を実に無駄に浪費していることになる。

 余談はさておき、前の記事の開発ステップ4は予想通り簡単に先に実現した。次はいよいよログデータの書き込みである。今度はファイル名をRTCから自動的に作らなければいけない。このFatFSでの書き込みは、LEDマトリックスの電光掲示板を作ったとき、フォントデータの変換ファイルを作るとき使った経験がある。そのときのソースを参考にコーディングして行く。

 このときはFatFSのストリング関数がどうしても動かず、原始関数のf_writeを使った覚えがある。こんどはどうするか迷ったが、時刻データなど変換するデータが多かったため、書式付のストリング関数fprintf(新版ではf_printf)を使ってみた。この関数を使えば、ファイルの書き込みが数ステップですむのが魅力だ。

 しかし、案の定と言うか、やっぱりここでもストリング関数はエラーを出して動かない。仕方がない。この前やったのと同じように、単純な書き込み関数f_writeで、バッファーにひとつひとつ書式変換したデータを移すコードに書き直す。結構手間がかかる。

ついにログデータの書き込みに成功(11/4/09)
 しかし、f_writeで書き換えたプログラムもうまく動いてくれなかった。無効なファイルオブジェクトだというエラーを吐き出して無常にも先に進まない。何度もソースを確かめる。前と全く同じような書き方をしているのに動かない。おかしい。無効なファイルオブジェクトということは、オープンして設定したオブジェクトアドレス(オープンは正常終了している)が誰かに汚されてしまっているのだろうか。確かにファイルをオープンしてから、実際にファイルを書き込むまでの間の処理が長い。

 試しに、オープンの直後、ファイルに何か書いてみる。おおー、書けた。やっぱり、どこかでデータを潰しているやつがいる。誰だ。誰だ。ソースをさらに注意深く追いかける。あ、見つけた。ループの最初のマウントコマンドだ。ソースがやっつけ仕事のため、ログ開始を設定するところと、ファイルに書き出すところは別ルーチンにし、メインループでまわしている。そのループの最初でファイルをマウントすれば、折角オープンしたファイルはすべてご破算になってファイルオブジェクトは初期化される。Xbeeconsole

 はっはっは、またお馬鹿なミスだ。マウントコマンドをメインループからはずし、めでたく子機からのデータはタイムスタンプとともにSDカードに記録された。同じ日の測定はデータが追記される仕様である。テストする。おやあ、データサイズが増えていないぞ。中味を見てみる。いけない。最初のデータをつぶして書き込んでいる。このFatFSは既存ファイルをオープンすれば追記するのではなかったのか。

 ウェブのマニュアルを調べる。あ、駄目だ。追記ではなくて最初から書き込む仕様になっている。おや、追記の方法が書いてある。f_lseekを使ってファイルポインターを最終にしておけば良いということだ。やってみる。よーし、データは見事に追記された。

 いやあ素晴らしい。出来上がったファイルをSDカードごとPCに移し、PCのエディターで開いてみる。うむ、全く問題ないテキストファイルが出来ている。ソースコードはデバッグを繰り返して、スパゲッティ状態になっておりこれから大幅な改修が必要だが、とにかくSDカードに測定データをログすることに成功した。Xbeelogdata

 残念ながら、ストリング関数は、この状態でも動かなかった。ChaNさんのコードだ。バグがあるとは考えられない。何かこちらのミスだろう。まあ、今の状態で動くのだから無理することはない。

 9月からはじめたXbeeワイヤレス電力ロガーも完成に近づいてきた。子機のケース実装が終わったら、気になる我が家の電子機器の待機電力量を片っ端から測ってみてやろう。

| | コメント (0) | トラックバック (0)

2009年10月30日 (金)

Xbee電力ロガー親機のAPIフレーム表示に苦労する

プログラムは考えたようには動かない(10/27/09)
 プログラムは考えたようには動かない、書いたようにしか動かないというのは言い古されたプログラミングの格言だが、まさしくこれを地で行くデバッグだった。Xbeeの親機の開発第2 ステップ、APIフレームの表示にえらい時間を食ってしまった。

 たいした開発量でないからと、簡単なメモを書くくらいでコーディングに入ると大抵うまくいかないものである。今度もそうだった。Xbeeから送られたAPIフレームを一旦バッファーに溜めて、画面に人間が見てすぐわかるAPIデータを表示するのが第二ステップの目的である。Apiformat

 前の第一ステップのPCのUART画面に同時にデータを表示するより構造的には、はるかに簡単だ。フレームが送り終わるのを待って、フレームフォーマットに従って、送信モジュールアドレスや、受信サンプル数、データを表示していく。造作のない話である。

 ところがこれがうまく動かないのである。コーディングを楽にするため、バッファーを文字配列にし、添字を使ってフレームからデータを抜き出すのだが、書式付の出力関数が思ったような数値を出してくれない。16進でだしたり、2バイトの整数で出したり、ビット表示だったりするので結構やっかいなのだが、出力されるのが、これが全くでたらめの値である。

 おかしいな。ChaNさんの書式付出力関数xprintfはprintfのサブセットで軽いので愛用させてもらっている。慣れているはずなのにどうしてだろう。あんまりおかしいので、元に戻って、送られてきたフレームを16進表示してみた。

 うひゃあ、これが全く似ても似つかぬAPIフレームが出力された。何だこれは。リセットしたり電源を入り切りすると、時々元の見慣れたAPIフレームが表示される時がある。何だ、何だ。ハードは何もいじっていないぞ。しかし、またすぐにおかしなデータに戻る。元のデータがこれでは、xprintfの書式どころではない。X-CTUを取り出してXbeeを確かめる。いや、何も問題ない。いつものデータを間違いなくはきだしている。

 Mega128のVccを3.3Vに落とした副作用だろうか。いや、もうひとつのファイルモニター機能は何事もなく動く、ハードの問題ではない。新しくUARTを追加したMega128のPE0,PE1ピンに何か特殊な機能があるのだろうか。いやデータシートには何もない。するとソフトか。コードを確かめる。間違いなく、Xbeeからの受信バッファーが空になるのを待ち、データ処理に入っている。暴走もしていない。データが入っているところもある。

 途方に暮れて、その日の開発はあきらめ寝床についた。次の日は仕事のない日で、朝寝坊して、うつらうつら昨夜のトラブルを思い出していた。このあいだは2つのUARTを同時に動かしたためバッファーをいくら大きくしても取りこぼした。今度はどうだ。今度は間違いがないように、受信バッファーをwhileループで監視し、空になるのを確かめて次のステップに行くようになっている。その間は別のUARTは動かしていない。

 ちょっと待て。UARTが1文字を読む時間は、いくら早くても数百マイクロ秒のオーダーだ(38.4kbpsでバイト当たり208μs)。これに対してCPUの処理速度は8Mhzで1ステップ0.125マイクロ秒。千倍以上のスピード差だ。ループの中に別のUARTが入っていないということは、このwhileループはUARTの早さに較べれば猛烈な速さで回転する。

あああ、これだ、これだ。このwhileループは下部のUART関数がデータをバッファーに入れている間に、あっという間にバッファーを読みつくし、余裕で抜けてしまう。そのあとはデータが読み込まれたものとして、まだ殆ど何も入っていないデータ処理バッファーを書き出す。これだ。これが目茶目茶なデータになる原因だ。

 やれやれ、わかってしまえば至極当然のことなのだが、思い込みというのは恐ろしい。最初のトラブルだったバッファーオーバーフローが頭に残っていて、UARTのデータはバッファーに溜まって行くばかりと考え、バッファーにデータが入っていることを前提にロジックを組んでいた。今度はある意味でのバッファーアンダーランである。疑ったMega128
さん、Xbeeのみなさんごめんなさい。みんなこんなソフトを書いた自分が悪いのです。

このあとも泥沼(10/29/09)Xbeeavr
 飛び起きて、朝食をとるのももどかしく開発を再開した。しかし、このあとも苦戦が続いたのである。考えてみたら、APIフォーマットでADCデータが10秒ごと(現在の設定)に送られてくるが、データの終わりを判定する条件がない。データが来た時、バッファーに溜まるまで、少し待ち時間を入れれば良いのだろうが、こういう対症療法的なロジックは一番避けたいロジックである(巷にはこういうソフトが蔓延しているが)。これまでの経験からろくなことにはならない。とりあえずは良くてもたいてい後で破綻する。是が非でもしっかりとした終了条件が欲しい。robustness(堅牢さ)というやつである。

 データフレームには、普通、そのフレームの長さのデータが入っているものである。このAPIフレームにも勿論ある。これを使えば良いのだが、データを読み始めてから終了条件をダイナミック(読んでいる間)に設定する処理が必要だ。これを安全に確実に暴走しないよう、しっかり作るのは結構神経を遣う。もし、不幸にしてデータサイズが入らなくてもハングしない構造にしなければならない。色々考える。プログラムは最初考えていたよりずっと複雑なものになりそうである。

 それにバイト配列のデータから2バイト長のデータを連続して取り出すコードがなかなかスマートに書けない。アセンブラー育ちで、ポインターとキャストを完全に使いこなせていない。試行錯誤である。

uint16_t    * ptr;         //   2バイト整数のポインター
uint8_t   Array[80];   //    1バイト配列(データバッファー)

と定義しておいて、Array[nn]のところにある2バイト長のデータをprintfなどで10進数で表示したいときは、配列のアドレス表現&を使って、

 ptr = (uint16_t *) &Array[nn];

としてキャストし2バイト整数のポインターに替え、

   printf( "%u", *ptr );

で良い筈なのだが、どうしても1バイトずれてしまう。しかもうまく行くところと行かないところが出て益々混乱する。安易にコーディングを始めたことを後悔する。よほど最初から書き直そうかと考えたが、しかしもう遅すぎる。何とかするしかない。どうしても入らないところは、ひとつづつ入れて8ビットシフトし強引に2バイト整数にする。Xbeemonitor

 少しづつ手を入れては結果を確かめ、正しく表示されるデータを増やしていく。しかしチェックサムが最後まで残った。送られてきたデータとなかなか一致しない。配列番号、アドレス、チェックサムしないデータ数、このあたりの計算はいわゆる並木算で昔からいつも悩まされてきた。紙に何度も図を描いてチェックサムの始めと終わりのアドレスを確認する。無精して++を式の中に入れたりしているので余計厄介だ。

 悪戦苦闘、数時間。データフレームにあるチェックサム値と、プログラムで計算した値がぴったり一致した時は、思わず端末の前で一人で拍手をしてしまった。思うように動かない時は、何を好んでこんなことをやっているのか、自分の不甲斐なさに情けなくなるばかりだが、出来たとなると、この充実感が何ともたまらない。実に安上がりな娯楽だ。それにしてもこんな小さなプログラミングでも、ちゃんとした計画を立て、準備を十分にしないと痛い目にあうということを今さらのように学んだ。自戒、自戒である。

| | コメント (0) | トラックバック (0)

2009年10月16日 (金)

リニアPCMプレーヤー2号機のあとかたづけとソース公開

フューズビットを甘く見てはいけない(10/12/09)
 伊豆高原にある知人の別荘に誘われて2日間ほど留守をした。家に帰って自分が明らかな電子工作依存症になっていることを実感する。工作ルームに座り、目の前の細々とした電子部品や工具を手にすると、これまでの何となくもの足らない気分が解消されて不思議に落ち着いてしまう。困ったものである。

 それはさておき、久しぶりにウェブを覗いたら、驚いた。秋月電子が今プレーヤーに使っているAVRチップMega328Pを何と¥250 で売り出したという。今までの半額である。Mega328p Mega168はこのあいだまで¥400以上していたが、これにつられて¥230である。今人気のArduinoという開発ボードでAVRが売れ出したからだろう。この価格では他のショップも大変だ。

 我が家の部品箱を見たらMega328Pはストックが切れそうだ。これは早速買ってこなければなるまい。伊豆で、出来上がったばかりのプレーヤー2号機を自慢したら、また追加注文があって嬉しい悲鳴である。

 Olimexのプリント基板は、あと2枚で行き先が決まっている。こりゃあプリント基板も追加発注しなければならないか。まあ、それはともかく、この2号機はソースコードをまだ公開していない。パラレルのLCDをI2Cを使ったミニLCDにしただけだが、ミニLCDが持っているアイコンは全く使っていない。

 余り使えそうなアイコンがなかったこともあるが、少なくともポーズの時と演奏中の区別がつかないのは不便している。何かアイコンを表示するようにしてからソースを公開しようと考えていた。

 ストックの最後のまっさらのMega328Pをブレッドボードに入れて、フューズビットの設定から準備を始める。マニュアルに書き込んである所定のフューズビットをAVRspで定義する。フューズビットは、いつもChaNさんのAVRspをDOS窓で動かし設定している。原始的だけれど簡便で使いやすい。手馴れた作業である。(FL=11100111 FH=11110111)

 事もなく設定は終わった。続いてこれまでのファームを書き込み、動作確認する。おやあ、LCDのオープニングメッセージが出ない。このブレッドボードはXbeeなどのテストベンチと共用しているので、色々手が入っている。どこかがはずれたのかと、ジャンパーの接触を確かめるが、問題ない。AVRstudioのコンパイルメッセージもNO ERRORだ。ファームの書き込みも問題ない。

 やれやれ。少し日を空けるとこれだ。何が原因か勘が働かなくなる。しようがない、UARTを入れて中を見るのが一番早い。コメントアウトしたUARTのコードを復活させてコンパイルする。端末をつなぐ。あれれ、ここも動いていない。これはもっと基本的なところだ。オシロでミニLCDとのI2C接続を見ると47Hzのパルスが出ている。何だあ、これは?

 結局、原因はフューズビットだった。ハイビットのWDTON(ウォッチドッグタイマー:通常動作=1、常時動作=0)を0にしていた。ハイビットはこれまでいじる機会が少なく、今度はEEPROMを残しておくモードにするため設定したのだが、ひとつずれていたというお粗末である。WDTONを0にするとプログラムで何もしなければ、数msごとにリセットがかかる。これがI2Cでパルスが出た原因である。フューズビットをなめてはいけない。

ミニLCDのアイコンを動かすソースコードを公開(10/16/09)
 ソースコードの改修に入る。アイコンを表示するコードを本体に入れる。ついでに、てんこ盛りに入っていたデバッグ用のステートメントを整理する。コメントアウトされたデバッグ用のステートメントは不要なようで、意外に役立つもの(特に他人のソースを見るとき)だが、ちょっと多すぎる。

 適当なアイコンがなく迷ったが、演奏中断(ポーズ)は鍵マーク、連続演奏は上下矢印(連続するので)を選んでみた。この機能の追加は10ステップ以下ですんだので、一発で動いた。うむ、これまで演奏中断がわかりにくかったが、これで使いやすくなった。Photo

 次は、EAGLEの修正である。このあいだステレオフォンジャックのフットプリントをノギスで慎重に測って正確にした(部品ライブラリは前回の記事のlbrファイルに追加して更新)。誤配線も直した。回路図は、EAGLEを使っていない人にもわかるようにPDFファイルにし画面キャプチャーでJPEGにした。

 ところが、意外なところで作業が頓挫する。回路図のオペアンプの名前が適当なディバイスを選んだので所定の型番になっていない。これを直そうと色々やったところ、基板ファイルと回路図ファイルの不整合が起きて、元へ戻らなくなった。幻のオペアンプがボードファイルに生じ、基板に2つもオペアンプが出来てしまったのである。

 基板エディターで削除しようとすると、回路図エディターで消せと怒られる。回路図エディターには、そもそも、そのオペアンプは削除されて図上にない。困った。部品名を替えるために、前のオペアンプを削除し、新しいディバイスとして別のディバイスをADDしたのだが(これが正しく入ったことは、新しいディバイスがratsnestで出現している)、前のディバイスのパッケージが残ってしまっている。

 配線が残っているからかと思ってオペアンプ周りの結線をripupしていっても駄目。ripupを続けたら、電源周りの関係ないところまでなくなってしまい青くなる。これは困った。公開しようとした基板(ボード)ファイルが目茶目茶になってしまった。Lpcm2

 EAGLEを調べている余裕はない。仕方がないので、型番が違うオペアンプになっているが、正しい(誤配線を修正、フォンジャック修正)、EAGLEのボードファイルと回路図ファイル、それにAVRstudioのソース一式をzipファイルとし、画面にはオペアンプを正しい型番にした回路図を掲示することとした。

 ついでに、SDカードリニアPCMプレーヤー2号機の仕様を以下にまとめてみた。
1号機に較べると小型化され、充電機能と演奏中断、連続演奏のアイコン表示が追加されている。

外形: 77×51×22ミリ(秋月 アクリルケース蝶番式[小] 117-TSS)

入力: SDカード(SDHCサポート)のルートディレクトリ上のWAVファイル

再生可能ファイル:16/22.05/44.1khz モノーラル/ステレオ リニアー8/16ビット

最大ファイル数: 255(カウンターを2バイトにすれば65535)

出力: ヘッドフォンステレオミニジャック、ボリュームによる音量調整

操作: スライド電源スイッチ、タクトスイッチ3ヶ(ファイルの前後選択と決定)

表示: 16字×2行 LCD(ストロベリーリナックス販売のミニLCDアイコン付き)

電源: 3.7Vリチウムバッテリー(任天堂DS-Lite 互換バッテリー)

充電: USBミニBコネクターより、USBケーブルより充電(5Vなら何でもOK)
    充電中はLEDが点灯し、満充電で消灯。充電中も使用可。

機能:

・通常演奏
ディレクトリの最初から、タクトスイッチでファイル名を前後スクロールさせて表示し、決定ボタンにより演奏開始。SDカード10個までの選択ファイルの位置を記憶し、カードを替えても常にその位置から表示(ファイルを書き換えると最初に戻る)。

・連続演奏
タクトスイッチの前後ボタンの同時押しにより、選択時のWAVファイルから連続再生し、ディレクトリの最後まで行くと最初に戻って演奏を続ける。中止は、再生中の決定ボタン長押し(1秒以上)。連続演奏時は「上下矢印」のアイコンが表示される。

・演奏中断
再生中に決定ボタン押下。再開は同じボタン押下。中断中は「錠前」のアイコン表示

・演奏中止
再生中に決定ボタン長押し(0.5秒以上)。ファイル表示は次のファイルに行く。

ここに、ソースコードの入ったAVRstudioのフォルダーmLPCM328V3と、EAGLEの基板図ファイル(.brd)、回路図ファイル(.sch)をひとまとめにしたzipファイルを置きます。いつものように、メインのファイル名は変わっていませんので注意してください。フォルダーの中には、デバッグ用のUART関係のファイルも入っています。コメントをはずして所定のソースファイル、ヘッダーファイルをAVRstudioにとりこめば、UARTの使用が可能になります。

「mLPCM2.zip」をダウンロード

| | コメント (3) | トラックバック (0)

2009年7月28日 (火)

2号機開発がなかなか進まない

 このところ電子工作以外のことに時間をとられたこともあるが、LPCMプレーヤーの2号機の開発は殆ど進展していない。気分が乗るときは夢中になるのだが、波がある。Olimexの休みの話を聞いて出鼻をくじかれたのと、EAGLEのパーツ作りが思うように行かず、ちょっとスランプ状態に入ったようだ。

 それでも、手を動かしていないと落ち着かない性分になってしまったので、2号機の実装に必要な機能のテストを少しづつやっている。

ソフトパワースイッチの落とし穴(7/23/09)
 擬似コーディングでソフトパワースイッチの骨格はできた。しかし、このときに使うsleepのパワーダウンモード(セーブモードよりもっと節電)を実際に動かしたことはまだ一度もない。がた老AVR研究所では、初期の頃の電池からDCアダプターを電源に使うようになって、節電に余り気を使わないようになっていた。これまで使っていたsleepはすべてアイドルモードである。正式に組み込む前にこのパワーダウンモードが動くか確かめておいたほうが良い。

 最近のAVRプロセッサーで名前の末尾がPで終わるチップは、Pがピコワットの頭文字であるように、これまで以上の省電力をうたっている。データシートを見てみるとMega168Pのパワーダウンモード時の消費電流は何と0.1μAである。ボタン電池あたりの自己放電電流の1/10である。これなら大威張りでソフトパワースイッチに出来るというものだ。Mega168

 ソフトパワースイッチを組み込む対象のLPCMプレーヤーはブレッドボード上に一式残っているが、いきなり入れて混乱するのを避け、実装は直近のミニLCDのテストプログラムで行うことにした。

 データシートには丁寧な解説があるし、そんなに難しい処理があるわけでもない。最初は気楽に考えて実装に入った。しかし、考えていたことを実際に動くようにすることはやっぱりそう簡単ではなかった。しかも大きな考え落ちを見つけて気分が重い。

 周辺のタイマーも全て止まっているパワーダウンモードからCPUが目覚めるのは外部割込みだけである。外部割込みは周波数カウンターや、初期のTinyなどで何度も経験済みだ。これまでのプログラムからコードをとりだし、レジスターをMega168用に取り替える。鼻歌交じりでブレッドボードにタクトスイッチをつける。ものの1時間もかからない。簡単に動くと思った。しかし、これが動かないのである。

 仕方がない。モニターにUARTメッセージを出すステートメントを入れて(いわゆるprintf)デバッグに入る。おやあ、スイッチを押しても割り込みルーチンに処理が来ていないぞ。割込みそのものが起きていない。データシートをもう一度見直す。やれやれ「データシートは穴が開くほど見よ」である。データシートに明記してあった。パワーダウンモードは確かに外部割込みでsleepから目覚めるが、目覚めるのは「外部割込みのレベル割込み」だけなのだ。こちらはスイッチの「立下り」を一生懸命待っていた。

 あわてて割込み条件を「Lowレベル」にする。と、今度は、スイッチが押されている間中割り込みが入り、長押しの時間を測るどころではない。うーむ、困った。まさしく考えたようにコンピューターは動かない。書いたようにしか動かない。

 これで良いのかどうかわからないが、割り込みが来れば、割り込み条件をただちにレベル割り込みから立下り割り込みに換え(このあとの制御に使うため)、割り込みリクエストをクリアし、次のパワーダウンsleepに入る前にもう一度レベル割込みに戻すコードを付け加える。よーし、2秒長押しで電源が入った。今度は電源断のルーチンだ。でもその前にどれくらいの消費電流になっているか調べてみよう。テスターを取り出す。

 まず実行時で6mA程度。電源をOFF/ONしパワーダウンモードにする。何い、パワーダウンしても3mA以上流れているぞ、LEDか?いやそんなものつけていない。LCDか。しまった。CPUはパワーダウンしてもLCDの電源は入ったままだ。これはいかん。こいつの電源もCPUで制御しないとソフトパワースイッチにならない。これは大きな考え落ちだ。

 それはとにかく、LCDをブレッドボードからはずす。何と、電流が変わらない。この電流はLCDではない。プルアップ抵抗?まさか。はずしてみる。変化なし。とすると、あとはPCとつないでいるISPケーブルしかない。このテストプログラムは、ISPを利用したUARTをモニターにしている。ええー、こんなところに電流が流れるの?PCの端末プログラムは動かしていない。

 電流の主はやっぱりISPケーブルだった。こいつをはずすと、150μAに激減した。LCDをはずすと0.4μA。やれやれやっとスペック(0.1μA)に近い消費電流に落ちた。あとはプルダウン抵抗を通してCPUやLCDに流れ込む電流だろう。ミニLCDの消費電流の150μAは優秀だけど、これを流しっぱなしにするわけにはいかない。

 LCDの電源をパワーダウンモードと同時に切る必要が出てきた。いくらCPUがμA以下でも、周辺機器に150μAも流れれば何にもならない。FETか何かで切る必要がある。しかし、今度の2号機はもうスペースがない。やっぱりスライドスイッチを使うのか。

 次の日、電源断のロジックも入れてソフトパワースイッチのテストプログラムは完動した。2号機にソフトパワースイッチを実装するかは微妙になってきた。周辺機器の電源制御は結構厄介で、下手な制御をすると、予期しないところに電流が流れて誤動作したり、ひどいときにはCPUそのものをこわしてしまったりする(どちらも経験済みだ)。スライドスイッチはケースの上蓋や、余裕のある半田面のケース側につけようと思えばつけられる。

 それに「でんし研」のTADさんからのコメントで、プリント基板発注のOlimexが8月一杯夏休みで注文を受け付けてくれないということがわかった。これは計画を大幅に作り直す必要がでてきた。流れはスライドスイッチを入れた手配線版を実装する方向に傾きつつある。

いつのまにか動いたミニLCD(7/24/09)
 2号機のLCDの換装のテストをした。ブレッドボードにあるLPCMプレーヤーから秋月の「超小型」LCDとDC-DCコンバータをはずし、さらに小さいストロベリーリナックスのミニLCDをセットする。ハードはいたって簡単。インタフェースはI2Cなので、これまでのパラレルのデータ4本、制御線3本、それに電源、グランド合わせて9本のケーブルに対して、信号線2本、電源も含めて4本をつなぐだけである。ずいぶんすっきりした。A7282092

 ソフトのほうは先に公開したミニLCDのライブラリを入れて、メインのLCD関数をミニLCDのものに換える。たいした手間ではない。テストに入る。全く反応なし。まあ、こういうのには慣れている。コードをもう一度見直す。どこも間違っていない。それでも動かない。段々頭に血が昇ってくる。いかん、いかん。落ち着いて最初から見直そう。

 基本的なところからチェック。電源は入っている。暴走はしていない。スイッチは反応して音楽は通常に演奏する。それではと、こういうときのためのUARTを復活させる。ありゃ、やっぱり初期化でエラーが出ている。ロジアナを持ち出す。いやちゃんとI2Cは動いている。

 こうなったらデバッグステートメントてんこもりだ。I2CのsendコマンドにUARTの出力をぶちこむ。盛大に送信データとリターンコードがPCに流れる。おやあ、正常終了だぞ。あ、画面が出ている。何も他に変えていない。UARTでI2Cコマンドのタイミングが遅くなったので動いたのか。デバグステートメントをはずしてみる。何と何と、正常に表示するではないか。原因がわからずに動いてしまった。気分が悪い。

 日を空けて原因究明にとりかかる。このライブラリは公開しているので責任がある。いつのまにか動くということは、また、いつのまにか動かなくなるということを意味する。放っておくわけにはいかない。自慢にもならないが、こういうときの粘着質には人には負けない自信がある。気分を落ち着けて、動くまでのひとつひとつの工程を思い出し、手順を戻してテストしていった。

 その結果、LCDのリセットピンを浮かしたまま、リセットをしないモードで動かすと、LCDが動かなくなることを確かめた。リセットをしないのなら、このピンは確実にHigh(Vcc直結)にしておく必要があるが、最初の頃は確かに何も接続していなかった。

 UARTを入れたりするデバッグの最中、リセットピンもついでに配線してリセットありでコンパイルした記憶がある。このときはUARTの初期化を間違えて端末にメッセージが出なかったため、すぐコンパイルし直したが、LCDの方は確認していなかった。

 恐らくこのときに動いたのだろう。リセットをするか、リセットピンをinactive(High)にしてどちらも動作することを確かめ問題は解決した。いやいや慌てることはデバッグの一番の敵である。

 ミニLCDの印象である。文字は小さいが視認性は悪くない。1行目のアイコン表示のところに何も表示されないので、少し間が抜けているが、アンテナや電池などのアイコンはどうも今回のプレーヤーには役に立ちそうにない。採用は見送ることにする。

scan_files( )の機能を落とす(7/27/09)
 機嫌よく、ブレッドボードの2号機用のLPCMプレーヤーを鳴らしてテストするうち、1枚のSDカードで暴走しシステムリセットがかかるようになった。TinyFatFSでは問題がなかったカードである。今度のFatFSのバージョンアップによる不具合であることは明らかだ。

 しかし、このカードで動かなくなる原因には心当たりがある。ディレクトリがあるカードである。現在のLPCMプレーヤーはルートディレクトリ上のWAVファイルしか演奏対象にせず、ディレクトリ以下のファイルは無視しているが、レジューム機能のときにSDカードを特定するため、ファイルサイズとファイル数をChaNさんのFatFSの内部関数scan_files( )を使ってサブディレクトリ下のファイルまで全部数え上げている。

 scan_files( )の仕様が変わったのだろうか。ディレクトリのアトリビュートにロングファイルネームのオプションが入ったのが気になる。ソースコードを調べる。全く変わっていない。UARTを入れてシステムリセットがかかる原因を調べていく。

 予想通り、scan_filesで暴走していることが確かめられた。UARTをさらに奥深く入れて検証する。おやあ、このディレクトリはさらに下にまだディレクトリを持っているぞ。あああ、わかった。スタック領域がSRAMを潰しているのが原因にちがいない。このscan_files(  )は自分で自分を呼ぶ、再帰構造になっており、これは大量のスタックデータを消費する。

 TinyFatFSからFatFSに上げてSRAMが残り少なくなっていた(90%)のが気になっていたが、やっぱり駄目だったか。試しに、このディレクトリの構造を一段少なくすると暴走しなくなった。これが原因であることは間違いない。

 ルートディレクトリのファイルしか見ていないのに、scan_files( )で全部のファイルを調べる必要はない。過剰品質である。しかし、見事な美しい作りなのでオリジナルを生かしたままにしておいたのが仇になった。泣く泣く、scan_files( )に手を入れて、ルートディレクトリだけのファイルを数えることにする。これでどんなに複雑なディレクトリ構造のカードでも暴走はしないはずである。

 2号機に向けてのソフト開発はこれで一段落したようだ。今回はソフトパワースイッチは実装を見送ることにする。残るは、手配線に着手するか、EAGLEをさらに攻めるかである。

 上記トラブルは、ディレクトリのないSDカードでは発生しません。もしディレクトリがあるSDカードで、ディレクトリの階層が深い(3段以上)ときは、メインファイル(SDPCM328V3.c)の193行目にある、scan_files(char* path)の以下のステートメント4行をコメントアウトしてください。これでscan_filesはルート上のファイル、ディレクトリしか数えませんが実用上は全く問題ありません。

            if (finfo.fattrib & AM_DIR) {
                acc_dirs++;
//                *(path+i) = '/'; strcpy(path+i+1, &finfo.fname[0]);
//                res = scan_files(path);
//                *(path+i) = '\0';
//                if (res != FR_OK) break;
                                          } else { .........

(以上)

| | コメント (0) | トラックバック (0)

2009年7月10日 (金)

ストロベリーリナックスのミニLCDのライブラリ公開

(7/10/09)Mlcd
 最近、売り出した低電圧で動くI2Cを使ったストロベリーリナックスの液晶ディスプレイのドライバーがやっと公開できるレベルに達した。このLCD、小さいが2行16文字が表示でき、低電圧(2.7Vまで)で動くのが嬉しい。昇圧用のDC-DCコンバーターなどが要らない。ただインタフェースがI2Cなので知らない人にはとっつきにくいだろう。

 今度公開するライブラリは、標準のTWI(I2CのことをAVRではこう呼ぶ。ライセンスの関係らしい)を持っているAVRチップ(Megaシリーズ)だけでなく、持っていないチップ(Tinyシリーズなど)でも、GPIO(普通のIOピン)を使って、簡単な関数呼び出しだけで文字、アイコンを、このミニLCDに自由に出すことが出来る。I2Cに関する知識は要らない。ライブラリだけならフラッシュサイズは1Kバイトそこそこで入る。

 ソフトウエアで実現するI2Cは当研究所では、ずっと前にTiny26でUSIインターフェースを使ったドライバー(マスター・スレーブとも)を完成させている。当初はこれを組み込んで、TWIとの二本立てと考えていたが、途中で気が変わった。USIインターフェースそのものがTinyシリーズでしか実装しておらず、しかもピンが固定されている。MegaシリーズでもI2Cを2チャンネル使いたい時もある。GPIOを使ったI2Cの方が汎用性が高い。

 それなら、このあいだのChaNさんのFatFSの中にあるAVR用のRTCドライバーである。この前FatFSを使った時、このソースを読み、I2Cインターフェースを実に軽妙にソフトで実現しているのに感動した覚えがある。

 このときはフラッシュサイズを縮めるためこのRTC.cをそのまま使わず、TWIに替えたので、実際にはこのコードは使ったことがない。ちょうど良い機会だ、これを使わせてもらおう。早速FatFSのライブラリのRTC.cから必要なコードを取り出し、#ifでソースを入れ込んでいく。

 気が抜けるくらい余りにも少ないコードでI2Cを実現している。1バイトを送信するだけなら、RTC.c全体の1/3くらいしかない。たいしたもんだ。これで本当に動くのか半信半疑でテストに入る。悪い予想があたってGPIOのI2Cはエラーを大量に吐き出してつながらなかった。

 オシロではそれらしい波形が見えたのに、ロジアナでは全く反応がない。実はこのコードにはもともとよく理解できないところがある。GPIOピンを上下にドライブするのに、DDRという入出力指定レジスターだけを叩いている。これがどうもよくわからない。

(オリジナル)
#define SCL_LOW()    DDRE |=    0x04         /* SCL = LOW */
#define SCL_HIGH()    DDRE &=    0xFB        /* SCL = High-Z */
 (DDREはポートEのDDRレジスター、PE2(0x04)がSCL)

 ChaNさんが書いたコードだ。ぬかりがあるわけはない。どこかに何かを設定するとこれで動くのだろう。しかし、それが何なのか見つけられない。色々いじったが事態は全く好転しない。どうもおかしい。オシロで見えて、ロジアナで見えないというのが何か気になる。臭い。しかしこうなるとハードの問題で、これ以上はちょっと手が出せない。

 悩んだ挙句、強引だがこのDDRレジスター以外に、PORTもドライブするコードを入れてテストしてみた。
(変更したもの)
#define SCL_LOW() {mLCD_DDDR|=(1<<mLCD_SCL); mLCD_DPORT&=~(1<<mLCD_SCL);}while(0)    /* SCL = LOW */
#define SCL_HIGH() mLCD_DDDR &=  ~(1<<mLCD_SCL)    /* SCL = High-Z */
(mLCD_DPORTはSCLのポート番号、mLCD_SCLはSCLピン)

 スイッチを入れる。おおお、ロジアナにそれらしい波形が戻った。ちゃんとスタートコンディションを作っている。立派、立派。しかし、依然としてLCDは動かない。 Gpio_iicでも、ここまで来れば光が見えてきた。

 printfメッセージを沢山出してコードを追う。どうもC言語のBOOL変数はわかりにくい。こちらはアセンブラー育ちなので、等しいとき、正常終了のときはリターンコード0という観念からぬけられない。C言語のTRUE=1 FALSE=0というのがどうにもなじめない。特にif文の中で式なしで使われると大混乱する。やっぱりいくつか勘違いが見つかり修正する。

 #ifを使って分離したTWIのコードとあわせてリターンコードを揃え、祈る気持ちで電源ON。やった。Welcome画面がLCDに出た。これでGPIOのI2CでもLCDが動いた。#defineを設定し直してTWIに戻してみる。動かない!今までの苦労は水の泡か。頭から血が引いていく。はっはっは、ハード接続を替えていなかった。ジャンパーコードを差し込みなおして問題なく稼動。慌ててはいけない。

 アイコンの表示と消去がちょっと難しかったけれど、このあとの開発は順調に進み、だいたいこれでミニLCDのライブラリは完成した。アイコンも関数ひとつで任意の絵柄を表示/消去できる。コントラストもコマンドで調整できる。そろそろ公開できるレベルのようだ。

 これで少しはストロベリーリナックスさんにも顔が立った。前回の記事で営業妨害で訴えられる心配もないだろう。このライブラリでLCDが沢山売れることを願っている。

以下に、AVRstudioのプロジェクトファイルの形でソースコードとヘッダーファイルを置きます。mLCD168はライブラリmLCD.cをテストするためのやっつけのモニターです。10以上を1文字で入力する時は、;、:、などを入れてください。詳しくはフォルダー内の、mLCD_readme.txtを見てください。

7/10に公開したソースコードにはgoposにバグがありました。以下のものは修正されたものです。コメントにあるような変更もしてあります。コードは80バイト近く減っています。前のmLCD.lzhをダウンロードした方はダウンロードしなおし、前のソースは破棄してください。

「mLCD168_712.lzh」をダウンロード

| | コメント (5) | トラックバック (0)

2009年7月 7日 (火)

LPCMプレーヤー2号機の開発

アクセス急増の反動でもないが別の工作へ(6/30/09)
 BeagleBoardの記事を載せてからアクセスが急激に増えた。これまでは多くても精々一日に300アクセス程度だったのだが、このところ400を越える日が増えている。ページ単位のアクセスもBeagle関係が多い。みんなの関心が高いようだ。

 前にも書いたようにBeagleBoardはこれまで色々楽しんできた電子工作とは異質の世界である。ARMと言っても最近始めた、Cortex-M3とかLPC2388とは数ランク上のプロセッサーで、ハードは勿論のこと、ソフトもすでに素人がソースレベルで気楽にいじれる規模ではない。日本語表示が出来て次のステップは日本語入力機能なのだが、あまり気が進まない。日本語が入力できたからといって何か次の目的があるわけではない。それにソフトパッケージをダウンロードしてきました。インストールしました。動きました、だけでは何となく面白くない。

 まあ、BeagleBoardに関してはすべてこれしかやっていないので偉そうなことは言えない。しかし何か、こう、どきどきわくわくするところが欲しい。自分の創意、工夫が役に立って、既定の機能と違う動きをしたり、別の働きをするところが見たい。人間とは贅沢なものである。Photo

 そんなこともあって、Beagleはちょっと横に置いて、このあいだのDS-Liteのバッテリーの充電基板を作ってみた。これは基板を作るだけが目的でなく、LPCMプレーヤー2号機を念頭に置いた、電池フォルダー制作の練習を兼ねている。もしプレーヤーを量産するとなったらより簡便な手順で電池フォルダーが作れないと効率が悪い。

 1号機で苦労したのが電池接点を支える天板の固定である。電池は接点にかなり強い力で接している必要がありその強度が問題になる。基板にピンヘッダーの接触ピンをハンダ付けし、それに基板をボンドで固定するという手の込んだ方法で天板の強度を確保しているが、ここはもっと簡単に作れるよう改善しておきたい。
Photo_2
 そこで思い当たったのが、CDケースである。スペースを節約するためCDケースは最近薄いケースを使うようになって、初期の頃の厚いケースがごろごろ余っている。このケースの高さが電池の高さとぴったり合うことを発見した。アクリルのケースを適当にルーターで切り取り、天板付のマザー基板にすることにした。ユニバーサル基板を小さく切ってボンドで接着して接点基板にし、配線用の基板を横に載せる。 Ltc4054

 充電用のIC、LTC4054はこれまでの変換基板では大きすぎるので、サンハヤトの変換シール基板と秋月の8X8のミニ基板(10 ヶ¥100)を活用して実装した。このシール基板はサンハヤトの製品にしては、お買い得で一枚(¥770)に24個のSOTチップ(一ヶあたり¥32、秋月のミニ基板をつけても¥42)をつけることが出来る。このシール基板は結構銅面が多く、データシートによる最小面積50平方mmを満足し、600 mA まで流せそうだ(外気35°C)。基板にジャンパーピンをつけて充電電流の実測が簡単に出来るようにし、充電電流を決める制御抵抗は用心のため半固定の可変抵抗にして調整できるようにする。

 うむ、なかなか具合の良い充電基板が出来た。充電も順調だ。しかしこのCDケースを応用した電池フォルダーは、プレーヤーの方のケースの高さが足らなくて、今度の2号機には使えないことがわかった。残念。充電機能も内蔵しようと当初考えていたが、これもDCアダプターが大きすぎて、とても入りそうにない。充電機能がないとなると、電池交換がすぐ出来るようにしなければならない。

ストロベリーリナックスから小さいLCDが送られてきたので部品あわせをしてみる。いやいや、これは、これまで以上に大変だ。しかし全く不可能と言うわけでもないので悩ましい。何とか納まりそうだが、やっぱり手配線では無理か。そろそろプリント配線に挑戦する時期に来ているのかもしれない。

FatFSのバージョンアップ(7/3/09)2
 LPCMプレーヤー2号機のためのソフトウエアの整備もやり始めた。電源スイッチを入れる場所がないので、スイッチ長押しのソフトパワースイッチを実装する必要がある。ちょうど良い機会なので、これまでの不満なところや、2GB以上のSDカードのサポートをしようと考えた。

 ソフトパワースイッチは、データシートを確かめて驚いた。最も節電できるPowerDownモードだと、Mega88クラス(Mega328など)で1μA、Mega128クラスでも5μAしか流れない。電池の自己放電と言えば、多いほうのニッケル水銀電池では数百μA、少ないリチウム電池でも数μAというからこの消費電流は優秀なものだ。食わず嫌いをしていたようだ。2号機はソフトパワースイッチで決まりだ。

 もうひとつの現在のソフトの不満と言えば、SDカード読み取りの途中でエラーが起きると、そこでスタックしてしまい、電源のOFF/ONをしない限り正常に戻らないという不具合である。まあスイッチを入り切りすれば元へ戻るからそう目くじら立てることもないのだが、設計上はカードを読み直して復帰するはずなのにそれがうまく動いていない。

 これはソースリストをもういちど注意深く読んで不具合があちこちで見つかった。まずマウントは、FatFSではソフト的にしか行っていないので、下位ルーチンのdisk_initializeという関数を呼ぶ必要があった。そのほかのルーチンも初期化をさぼっていて変数がそのままになり元へ戻れないことがわかる(要するにserially reusableでなかった)。これらの修正の結果、プレーヤーはSDカードを途中で差し替えても、電池の瞬断で演奏が止まっても、何かスイッチを押すと最初の状態に戻って正しく動くようになった。

 うむ、大分丈夫になった。これでソフトパワースイッチの実装の環境に不安はない。いよいよ最後のTinyFatFSから、SDHCをサポートするFatFSのバージョンアップにとりかかる。

 ChaNさんのサイトから最新のFatFS(0.07c)をダウンロードさせてもらい移植を開始する。このファイルシステムは着実に進化を続けており、このあいだのバージョンでは遂にWindowsのロングファイルネームをサポートするようになっている。海外のサイトでもFatFSの導入例を時々見る。日本の組み込みOS、TOPPERSにも採用されている。こういうソフトを無償で気前良く提供し、なおかつ改良を怠らない姿勢には頭が下がるばかりである。

 おや、TinyFatFSはどこへ行った? リリースノートを見る。ありゃあ、最新版の最初のバージョン(0.07a)ですでに標準のFatFSに吸収されてしまっている。えー、TinyFatFSは前から、FAT32をサポートしていたんだ。何だSDHCが使えるのか。知らなかった。身の不明を恥じる。それにしてもこのバージョン番号、未だに0.1以下にすることはないんじゃないでしょうか(こんなに進んでいるのに)。もう1以上を名乗って何の問題もないと思いますがね。

 フラッシュサイズはどうだ。うーん、少し大きくなっているようである。R/Oの最小サイズは、TinyFatFSの時の、2524バイトから、3824バイトに上がった。しかしこちらは今、32KBもあるMega328を使っているから全く問題はない。それにTinyFatFSはなくなったけれど、小さいチップ用のプチFatFSが用意されている。さすがやることにぬかりがない。

 I/Oディバイス依存のmmc.cは替えないで良いはずだが、まあ用心のため新しいmmc.cを入れてこちらの環境に合わせる。コンパイルする。いくつかの未定義エラーが出る。あれ、これもバージョンアップしたはずだがとソースを見ると標準のdiskio.hではなく、サンプルプログラムのSDカード用のdiskio.hが必要とわかる。 

 とりあえずコンパイルは通ったので動かしてみる。動かない。Welcome画面から先に進まない。やれやれ2行のLCDの表示だけではどうしようもない。デバッグ用のUARTを入れなおしてすこしづつ確かめていく。本当はテスト環境を作るべきなのだが、不精してプレーヤーにいきなりぶちこんだのが良くなかった。かえって手間がかかっている。

 ディスクの初期化はうまくいっているようだ。エラーは出ていない。しかしファイルの表示が出ない。あちこちにprintfを入れてデバッグする。ファイルサイズがおかしい。おやあ、ちゃんと動くSDカードがあるぞ。演奏も問題ない。これは困った。ハードも影響しているのか。

 あちこち調べまわった結果、やっと原因がわかった。不具合の原因は、ファイル名の小文字だった。LFN(ロングファイル名)をサポートしたので、ファイル名のupper case化がされていないのだ。WAVという拡張子を調べてそれ以外のファイルは再生の対象からはずしていた。正常に動いたSDカードはどういうわけか最初から大文字だった。

 wavという小文字の拡張子も再生リストに入れることにして解決。またしても大山鳴動ネズミ一匹的な騒動だった。フラッシュサイズはこれまでの13KBから1KBほど大きくなっているが、まあ問題ないレベルだ。速さはどうだろう。ロジアナを引っ張り出す。うーむ、速度も少し遅くなった。これまでより12%程度遅くなったか。ま、これも許容範囲だ。

ストロベリーリナックスの低電圧ミニLCDを動かす(7/5/09)

 最近売り出されたばかりの3Vで動く小さなLCDモジュールである。小さいけれど、生意気に2行16文字が表示できる。画面は最上行に携帯電話用らしいアイコンを表示する少し余計な機能があるが、今計画しているLPCMプレーヤー2号機にはぴったりの表示装置である。3Vの低電圧で動くのでDC-DCコンバータも不要だ。3ヶも買ってある。

 インターフェースは、パラレルでなくてI2C(AVRではTWI)である。I2Cは、がた老AVR研究所では発足以来すぐ、秋月のRTC(リアルタイマークロック)とのインターフェースや、Tiny26などI2CのないチップのUSIインターフェースでソフトI2C(マスター・スレーブ)を開発したりして経験を積んでおり実装には問題ない。ショップのページには、液晶コントローラのデータシートも、アプリケーションノートも、サンプルプログラムもダウンロードできるようになっていて、開発に不安はなさそうだ。

 FatFSのバージョンアップが一段落したので、2号機に向けての次のステップとして、早速動作確認をすることにした。さすがに現用のブレッドボードにあるLPCMプレーヤーを使うことは止め、別のブレッドボードに新しくCPUチップ(Mega168)を乗せて専用のテストベンチを作る。配線そのものはCPU周りを準備(ISPまわりとXtal)すればI2Cは2線インターフェースなのでプルアップ抵抗を入れて5分もかからない。

 しかし、ちゃんと動くまでには意外に時間がかかった。日曜日を丸々一日使ってしまった。負け惜しみを言うようだが、沢山あるように見えた資料が問題だった。まず、ショップの提供するデータシートが英語であることはともかく、パラレルとシリアルそれにI2Cの3種類のインタフェース共通のデータシートでとてもわかりづらい。I2Cの項の最初には「I2Cでは書き込みしかできない」と明記してあるのに、後半には、読み込みが出来ないと使えないBusyFlagの説明が出ていたりして混乱する。一般的なI2Cの説明と、このコントローラ特有のビットの説明が混ざっているので余計わかりにくい。

 日本語のアプリケーションノートも、どうも端折って書いてあってこれまた全貌がつかめない。I2Cについてある程度知識があれば類推が効くが、そうでないと理解するのに苦労するだろう。データシートからの引用のチャートは肝心のCOビットの説明文が省略されているので何のことか良くわからない。特にファンクションセットのあたりは省略が激しい。

 結局、データシートと、アプリケーションノート、それにソースコードの3つを同時に見て、それぞれ確認していかないと開発が進まない。各コマンドのあとには必ず30μs程度のwaitが必要なようで、I2Cとしてはシビアな環境ではない。しかもI2Cインターフェースの多いRTCとは違って読み込み処理はなく、一方的に書くだけだ。

 割り切って、スタートコンディション、マスター書き込み宣言、コマンド、データ、ストップコンディションというI2CシーケンスとLCDシーケンスの順番を単純に繰り返す手順を解説するだけで、LCDはとりあえず動くはずなのだが、そういう書き方ではなく色々な方法を紹介したりするものだから余計わかりにくくなっている。

 ソースコードがまた難物であった。余り悪口は言いたくないが、構造化言語であるCの文法を全く無視したアセンブラー的なコーディング(switch文にgotoと、returnが入ると訳がわからなくなる)で、読むのに大苦労である。こういう通信関係のエラーによる中断の多いプログラムは構造化しにくい処理の代表格だが、もうすこし整理の仕方があるだろう。それにこんなに綿密にエラー処理をしたりリトライしてもあまり意味がない。近接した液晶とCPUの間で一旦エラーが起きたら回復する可能性は殆どない。先の見通しがないときエラーで帰ってきても無意味である。

 これまでのI2Cを使ったプロジェクトからソースをとりつくろいUARTからLCDを操作するテストプログラムを作る。久しぶりのAVRの本格的な開発である。用心のため、xprintf(ChaNさんのFatFSについているもの)を沢山仕込み、デバッグに備える。

 動かしてみた。全く動かない。まあこういうのには慣れている。xprintfを初期化から入れて動きを確認していく。あれえ、最初からリセットしている。なんだなんだ。変数を表示するxprintfのところで暴走している。原因はわからないがとにかくxprintfがおかしい。デバッグのために入れたステートメントで暴走するなんて洒落にもならない。

 xprintfをやめ自前のUART出力関数などでデバッグを進める。おやあ、ちゃんと正常終了のフラグを出しているぞ。あっ、ifの中の論理が逆だ。これを正しく直す。おお、画面に何かが出た。なーんだ。I2Cは動いていたのだ。正常なのにエラー終了していた。

 そりゃそうだ。このへんのI2Cの関数はすべて動作確認済みだ。ただ、文字は出たが、表記が目茶目茶である。しかし、ここまでくれば大分近づいた。ソースコードを点検する。コマンドのビットが1ビットずれているのを発見する。Mlcd

 これを修正し、めでたく低電圧ミニLCDは動くようになった。しかし、クリアや、コントラストの変更ができない。これはアプリケーションノートが端折ったところで、ファンクションセットに2種類あり、コマンドを出す前にはそれに応じたファンクションセットをしてからでないと動かないことがわかった。これを修正してUARTから自由にクリアとコントラストが調整できるようになる。

 日曜一日で何とか動くようになった。xprintfが動かなかった原因は次の日、事務所に行く途中で気がついた。xprintfの内部ルーチンのxitoaの行き先を指定するのを忘れていた。これでは暴走するはずである。情けない。

 ストロベリーリナックスさんには相当悪態をついたけれど、今回のソースコードはライブラリ化して近く公開し、少しでもこのディバイスが沢山の人に使われるようにしたいと思っている。こういうお洒落なディバイスをアマチュアに提供してくれるショップは大事にしないといけないし、オープンソースではこれまで沢山の人のお世話になっているのでせめてもの恩返しだ。

| | コメント (2) | トラックバック (0)

2009年2月26日 (木)

SDカードプレーヤーの実装はケースが小さすぎて難航

勉強することがまだ山ほどある(2/19/09)
 SDカードプレーヤーの実装は、秋月電子で手頃な小さなプラケース(92×64×22 ポリカーボネート製 ¥100)を手に入れたが、どういうわけかあんまり進んでいない。ちょっとスランプに入ったようだ。意欲が前ほどわかなくなってしまった。アナログ回路を改善しようと色々手を加えたが、ことごとくうまく行かなかったのが原因かもしれない。

 まず、音量調整をボルテージフォロワの前でやろうとVRを前段に持ってきたのだが、VRを回すと猛烈なノイズが出てうまく調整できない。VRを少しまともなものに換えてみても同じ。原因は良く分からない。どうもオペアンプの直流のところで可変抵抗を入れるとノイズが出るようだ。ACにしようとするとカプリングコンデンサーを増やさなければならないし、音質や実装のことを考えるとこれはやりたくない。

 それでも、ウェブを見ていたらACのボルテージフォロワの回路があったので試しに動かしてみた。しかしこれは全く動かなかった。良く回路を見てみたらオペアンプの反転入力側がグランドになっている。そうかこれは両電源用の回路だ。単電源の回路にするには、ACが入ってくるのだから、また中位電圧を作ってやる必要がある。ここには大容量のパスコンが必要だ。また部品が増える。

 電源電圧を下げて、音が割れる理由もわからない。DACの出力は、Vccの1/2がACの0V地点で、上下にデコードされて0からVccがダイナミックレンジになる。DACのVccとオペアンプのVccは同じである。電圧が変っても違いはないはずだ。何故Vccを下げると歪んで聞こえるのだろうか。オペアンプの電圧の低いところは直線性が悪いからなのか。オシロで方形波でも見ればわかるのだろうか。準備が面倒なのでどうも今ひとつやる気が起こらない。

 DACのBU9480Fのデータシートで出力段に入っているCR直列回路も良く分からなかった。ウェブ上の回路例などではDACのあとに時々入っているときがある。負荷とは並列に入っているのでフィルターの働きはしない。これは何だろうと首を傾げていたら、別のところで同じような回路を見つけた。出力アンプの終段についていることが多い。この回路はZobelフィルター/ネットワークと言って、高周波数域での負荷インピーダンスを下げて出力側を保護するものらしい。しかし定数がかけ離れている。zobelは抵抗が10Ω程度、コンデンサーは0.1μF前後だが、BU9480Fについているのは、10KΩと1μFと大きい。

BU9480Fの出力インピーダンスは10KΩなので、理論的にはこの抵抗値と1μFで16Khz以上(カットオフ周波数)の出力に対してインピーダンスを一定にする働きがあるようだが、これも良く分からない。ブレッドボードに入れて試してみたが、音は全く変わらなかった。DACからオペアンプをつないでいる直列抵抗も10KΩ以外にすると音が割れたりノイズが出たりする。音は皮肉なことに少なくとも今の状態が一番音が良い。アナログは残念ながら、まだまだ手探り状態だ。勉強することが山ほどある。Photo

 ケースへの実装は、ほんの少し進んだ。電池フォルダーの端子処理が一番の課題だったが、これは端子側に接する板に穴を2つづつあけ、0.5ミリの燐青銅線をそこに入れるようにして端子にするとうまくいきそうである。実際にドリルで基板に0.8ミリの穴を1ミリ離して2つ開けてU字に曲げた線を入れて電池を押さえてみた。うむ、これなら立派な端子になりそうだ。

 ケースに必要な部品をレイアウトしてみた。欲張ってかなり小さめのケースを選んだため、予想したとおり、これまでにない高い密度になりそうだ。まあ、折角の実装だ。挑戦してみよう。

Beagle Boardに興奮(2/23/09)
 アナログの資料集めにウェブをさまよっていたら、とんでもないハードウエアを発見して興奮している。7センチ(3インチ)四方のボードに、ARMの最新プロセッサーと、グラフィックチップを内蔵したCPUに、映像出力、シリアル、SDカード、USBが付いて、値段がたったの149ドルである。イーサネットはUSB経由で動く。輸入パーツショップを通して既に日本でも¥17000程度で手に入るらしい。実際に動かしている人のレポートがある。

 このあいだ、Linuxを動かすためにSHの評価ボードを\8000で買おうかと考えていたが、こんどのボードはこの2倍の価格と言っても、中身が全然違う。OpenGLという3Dをサポートするグラフィックエンジンがはいった本格的なビデオチップが内蔵されている。これは驚いた。このボードだけでちょっとしたノートPCが出来てしまう。USBがついているのでペリフェラルは全く気にする必要がない。電源は5V単電源だけで動く。しかも自分でいじれる。Beagleboard

 モバイル業界で最近騒がれている、Googleの携帯端末のエンジン部分らしいが、何と言っても一番すごいところは、この上で動く、OS、ミドルウエア、アプリがすべてオープンソースということだ。もちろんLinuxも動く。組み込み系の世界でも革命が始まったようである。ソフトもさることながら、ハードとしてみてもこれは破格の値段である。これだけのCPUパワーを持ったボードは雑誌の広告で見る限り、これまで10万以上はしていたし、こんなに豊富なインターフェースのついたボードはこれまで見たことがない。なにしろビデオインタフェース内蔵なのだ。ウェブの情報の中で印象的だったのはYouTubeの動画だ。このボードの威力が良く分かる。説明は英語だがわかりやすい。

 今日は秋葉に寄って、PCMプレーヤーの部品を買ってきたのだけれど、暫く手に付かず、珍しくウェブにかじりついて情報収集に夢中になっていた。現在のbeagleボードはまだ完全でなく、この春リリースされる予定のリビジョンCというのが良いらしい。がた老AVR研究所としては、ハイエンド組み込みシステムの研究のため是非一台手に入れたいものだ。遅れがちな実装がこんなことでまた進まない。

果たして入るのか心配(2/24/09)
 SDカードプレーヤーの実装に必要な部品がほぼそろった。まず、SDカードソケットは秋月の廉価版の\150のものを使う予定だったが、これは安いけれどプッシュイン・プッシュアウト(押してセット、再び押してエジェクト)でないので、SDカードをケースからかなり出す必要があり持ち運びに不便だ。千石で定番のヒロセのものを買った。これはサンハヤトの変換基板や、このあいだの雑誌付録のSTARMにつけたものと同じタイプで、千石の方がこの前買った店よりかなり安い(\210)。隣にマイクロSDのソケットがあったのでこれも買う(\160)。Sd

こいつは小さくて今度の実装には使えると喜んでいたのだが、帰って調べてみると、やはり小さすぎて手配線でしっかり固定するのは難しそうだ。ソケットは普通の部品と違って力がかかる。しっかり固定する必要がある。基板でもおこして接続ピンをすべて固定するならともかく、汎用基板では空中配線になってしまい、2箇所の固定ピンのハンダ付けしか強度がない。これではどうも自信がない。

 使用する基板は両面基板である。これはSDカードソケットを表につけて高さを稼ぐためと、SDカードが裏返して装填されるのを嫌ったためである。変なところにこだわりがある。今日は、久しぶりに工作台をだして基板の加工を始めた。基板がケースに入るよう2辺を切り落として整形し、予定した部品の実物を置いてレイアウトしてみる。

 これは厳しい。電池がケースの1/3を占めるので、圧倒的にランドが足らない。それにヒロセのSDカードソケットが秋月の安いものよりかなり大きく、オーディオジャックや可変抵抗器などかさの大きい部品が載るので全部が入りきるか心配になってきた。Sdplay2

 タクトスイッチのスペースはとても基板上には確保できない。前にやったように別の小さな基板を上蓋に固定してそこへまとめることにする。これはスイッチのストロークが上側ケースに足らなくてどうしようかと考えていたところなのでちょうど良かった。

 何とか入りそうだ。LCDは上蓋に固定しない。ピンヘッダーでベースの基板に固定する。これでケーブルを減らせる。高さが微妙だが、いざとなったらピンヘッダーソケットを削っても良い。これはうまく行きそうだ。方眼の拡大図をつくってアートワークに着手する。

 ブレッドボードのプレーヤーは快調に音を出している。秋葉で1枚¥350で買った2GのSDカードに今度はベートーベンのピアノ協奏曲「皇帝」を入れて見る。うむ、大編成のオーケストラが良く鳴っている。これは実用になりそうだ。

 ご機嫌で、今までのSDカードの整理をして選曲していたときバグを見つけた。一番最後までリストを見にいって逆戻りすると最初の数曲が見えなくなるバグである。あわててUARTを復活させて変数を全部表示させ、バグを追う。やはりファイルリストの最後の処理が間違っていた。これはいけない。ソースを公開した後である。

 テストしていたSDカードのWAVファイルの数が、たまたまファイルリストの数の倍数だったので発見が遅れていた。典型的なテストケース不足である。

前回公開したソースリストに次の修正をあててください。
バグ修正(2/26/09):
現象: 最後のWAVファイルがファイルリストの途中にあると表示が不正確になる。
修正ファイル: SDPLAY328.C 
場所: 行ナンバー338付近(行ナンバー表示はTeraPadが便利)

スイッチCを見てリストを進めるところの以下のステートメント

if(ls_top+2 > crnt_end ) の部分を

if(ls_top+1 > crnt_end && !(crnt_end+1 == crnt_eof))
に修正してください。

| | コメント (1) | トラックバック (0)

2009年2月16日 (月)

ブレッドボード上のLCD版SDカードPCMプレーヤー完成

LCDを動かすのにまた一苦労(2/13/09)
 実装に必要な部品をすべてブレッドボードに載せたリニアPCMのプレーヤーが遂に完成した。2行づつ表示するロジックは結構難しかったが、それより時間と手間がかかったのはタクトスイッチの制御の方であった。中々安定しない。試行錯誤の末、押したスイッチが完全に離れるまでスイッチルーチンから処理を外に出さないようにすると、これまでのおかしな現象はピタリと止まった。最初からこうすれば良かったのである。人間相手の制御は、下手な小細工をするより無骨にやるほうが良さそうだ。特にピンチェンジ割込みは立ち上がりエッジでも立下りエッジでも割込みが起きる。管理が難しい。

 LCDへの換装にかかる。Mega328のI/Oピンはもう連続したピンが空いていない。ピンが連続していなくても動くLCDライブラリーをこのあいだ開発したばかりだが、ばらばらにアサインするとあとの確認が大変なので、タクトスイッチに割り当てていたところを引越し、データピンくらいは連続するようにする。クロック20Mhz用にWAITループ(初期設定時はビジーフラグが動かないので)を調整し、9本のケーブルを接続する。ここはいつも接続間違いをするところで慎重に何度も確かめながらブレッドボードに結線。よし出来た。

 とりあえずスタート表示だけをLCD出力に換え、電源オン。LCDは何の反応も示さない。あれえ何処がおかしいのだ、と電源を確かめて愕然となる。このあいだ実装に向けレベルシフターをはずして、全部3V駆動にしたのを忘れていた。しまった、負電源はまだ組んでいない。LT1144を組めばすぐ出来るのだけど、必要な10μFがちょうど切れている。50とか100μFはごろごろあるのだが、何故か10μFだけがない。50μFでも問題ないとは思うがスペック外だ。気持ちが悪い。

 こういうときの非常手段、電池に頼る。実験用のLCD基板には幸いコントラスト調整用のVRがついている。ボタン電池のソケットを急遽、基板にハンダ付けしコントラスト端子に接続する。うむ、-2Vに出来る。ブレッドボードにサイド接続する。おーし、LCDに、なにやらゴミキャラクターが出たぞ。しかし、表示のところでハングアップして先に進まない。

 何度も接続を確かめる、間違いない。しかしこの現象はデータラインの接続違いの疑いが強い。この前もそうだった。最初に作った色別のコードのデータライン図と何度も確認するが間違っていない。MCUのピンの順番が逆順になっていることもあるのでこれも確かめる。うーむ、間違っていない。これはどうしたことかと思いあぐねていたとき、ふと基板を裏返して見た。Lcdpcmplayer1

 何と、何と、表の接続コードと色が違うではないか。こちらはハンダ付けされていて換えようがないが、接続コードの先はピンヘッダーなので差し替え可能である。そう言えば思い出した。この前、やっぱり接続間違いがあって、ピンヘッダーの方を移動させたまま、元へ戻していなかったのである。またもお馬鹿な間違いで時間を無駄にしてしまった。

 正しく接続すると事もなくLCDは表示された。胸をなでおろす。これまでUARTに出していたxatoiの関数をすべてLCDに移し、細かい調整を行って、ついにLCD版の実装が完成した。2行でもそこそこ流れがわかるし、逐次演奏にはこれで十分である。リチウム電池をブレッドボードに移し、写真をとる。電池駆動なので持ち運びが出来る。ブレッドボードを居間に持ち込み家族に自慢する。音が良いことだけは感心してくれた。まるで苦心の工作が出来た小学生のはしゃぎようと変わらない。やれやれ。Lcd_pcmplayer

 久しぶりの成功の余韻に浸る。この前、フィルムコンデンサーを買ってきて、LPFにしたら(2000pF カットオフ周波数8khz)、格段に音が良くなっている。これまでの緊張感のある、とげとげした音が、まろやかな穏やかな音に換わった。小さなスピーカーでは殆ど分からないが、ヘッドフォンだとその差が良く分かる。聴いていて気持ちが良い。

部品箱を漁っていたら、この前のイーサネットドライバーの予備の部品袋からタンタル10μFが2つ見つかった。早速、LT1144を組み込む。簡単に負電圧が出た。電流を測る。0.46mA。こいつにとってはゴミみたいな電流だろう。少しもったいないか。音には全く影響がない。オシロで確かめる。立派な直流だ。

 今のところ音で気になるのが電池駆動のとき、ごくわずかだがビート音がするときがある。決まった曲(ファイル)だけ(5Vのときはしない)なので余り気にならないが、いずれは直さないといけない。それと3Vでは明らかに音の大きいところが歪みはじめた。今は出力直前にVRを入れているがオペアンプ前に入れて、もう少し本格的なLPFを入れてやる必要がある。さあ、いよいよケースに組み込む本当の実装が待っている。

連続演奏機能は簡単だった(2/14/09)
 こういうプレーヤーでは定番の連続演奏や、ランダム演奏などの付加機能である。最初は、全く別のコードを書いて、この機能を作るつもりだったが、閃いた。折角オブジェクト指向とか言って、凝ったプログラムにしたのだ。今のままで、次々に曲のファイル番号をそこへ与えていけば連続演奏になるのではないか。調べてみたら簡単に出来そうだ。スイッチの押されるのを待つところで、番号を増やし、スイッチ待ちをバイパスしてやれば良い。

 うまく行った。再生中に連続演奏である表示まで含めて、10ステップ要しないで出来た。この機能の実現でプレーヤーは急に実用的なレベルに近づいた感じがする。オブジェクト指向のとき分けたブロックBとブロックCはメインルーチンに吸収したが、これも分けて関数などにしたほうがもっと合理的で、今度の追加機能開発もさらに楽になることがわかった。

 ケースへの実装に入る前に、現在の仕様をまとめてみた。

SDカード非圧縮PCMプレーヤーLCD版

  • 入力:         SDカードに入ったWAVファイル(SDHC可能)
  • 再生可能WAVファイル: 16/22.05/44.1khz モノーラル/ステレオ 8/16ビット
  • 最大フアイル数:    255(カウンターを2バイトにすれば65535)
  • 出力:         ヘッドフォンステレオミニジャック
  • 操作:         電源スイッチ、タクトスイッチ3ヶ
  • 表示:        16字×2行 LCD
  • 電源:        3.7Vリチウムイオンバッテリー
  • 機能:

・通常演奏_ディレクトリの最初から、タクトスイッチでファイル名を上下スクロールさせて表示し、決定ボタンにより演奏開始。

・連続演奏_タクトスイッチの上下ボタンの同時押しにより、選択時のWAVファイルから連続再生し、ディレクトリの最後まで行くと最初に戻って演奏を続ける。中止は、再生中の決定ボタン長押し(1秒以上)。

・演奏中断_  再生中に決定ボタン押下。再開は同じボタン押下。

・演奏中止_  再生中に決定ボタン長押し(0.5秒以上)

・ランダム演奏_ (計画中)

 SDカードのI/Oエラーは発生すると、エラー表示して一旦止まり、スイッチを押すとディスクのマウントから再開することにして電源監視は入れないことにする。入れるとDAC再生中にも10msの割込みをかけておかねばならず再生に影響が出そうなためである。

アナログの方はボルテージフォロワーの入力に2000pFのフィルムコンデンサーを入れ、LPFもどきになっているだけで、もう少しまともなLPFにすることが必要だ。音が割れるのは、オペアンプ前にVRをつければ解決するはずだ。現在のVRは千石で売っていた¥80の安物の平型2連のもので、左右のバランスが悪く、動かすたびに左右が振れる。これも換えてやる必要がある。Vr10k

 オペアンプの出力のところだけは、このあいだ音響用の無極電解コンデンサー(MUSE)をカプリングコンデンサーにした。気のせいか、これで音が良くなったような気がする。電圧が低下したときのビート音も解消してやる必要がある。アナログはまだまだ改善するところが沢山ありそうだ。

 ケースは秋月の一番小さいケースが良いように思うが、これに全部入るかが課題である。電池の充電は外でやるので、簡単に電池が取り外せるようにしないといけない。今度は工作の腕が問われる。

 ランダム演奏機能は実装するか迷っている。自分が余り使ったことがないのと、まともにやろうとすると最大曲数を255とした場合、メモリが足らなくなる。と、ここまで書いてまた閃いた。EEPROMを活用すれば、何か出来るのではないか。Mega328なのでフラッシュならまだ有り余るほどあるし、1KBもあるEEPROMは全く使っていない。これは面白くなってきた。

 それはともかく、ケースへの実装は時間がかかりそうなので、ここでとりあえずLCD版のソースコードと回路図を公開することにする。回路図のアナログの部分はこの前公開したものと殆ど変っておらず全く自信がないが、ソースコードの方は参考になるかもしれない。Sd_pcm_player_lcd

オブジェクト指向などと言っていた割には、単にファイルリストを作る部分だけが独立しているだけじゃないかとお叱りを受けるかもしれないが、開発はコンセプトが大事なので、要はデバッグしやすい構造になっていれば良いのだ。と、まあこんな書き方をするのは年寄りの負け惜しみで、素直に白状すれば最初の意気込みどおり書けなかっただけのことである。

公開した回路図で動くソースコードをAVRstudioのプロジェクトファイルとして以下に置きます。解凍したフォルダーをこのままAVRstudioで起動させればコンパイル可能です。

「SDPLAY328.zip」をダウンロード



| | コメント (0) | トラックバック (0)

2009年2月12日 (木)

LCD版SDカードPCMプレーヤーの開発

DC-DCコンバーターはもう準備してある(2/5/09)
 ポータブルの実装化でのもうひとつの課題が、5V駆動のLCDを3Vリチウムバッテリーでどうやって動かすかという問題がある。3VではLCDのコントローラーが動いても液晶のコントラストが出ないのだ。しかし、これは当がた老AVR研究所では以前検討して準備済みである。DC-DCコンバータを買ってあるのだ。最初に手がけた温度ロガーにLCDを付けようと計画したとき、秋月電子で入手した小電流用のDC-DCコンバーターLTC1144である。¥300もしたがそのときは高いと思わなかった。データシートには最大電流が記載されていないが、50mAくらいまで流せそうだ。LCDの消費電流は1mA以下なので全く問題ない。追加部品も電解コンデンサー2つですむ。Ltc1144

 その後、情報を集めているうち、インバーターで簡易に負電圧を得る方法が見つかってこれも試したくなった。ChaNさんのホームページにも詳しく載っている。原理はどちらもチャージポンプ方式。アナログ回路があるのでノイズが気になるが、音源装置にも使っている人もいるし、発振周波数をあげれば影響はあまりないだろう。

 手元にインバーターがあったので早速ブレッドボードに組んでみた。うむ、リチウムバッテリーの3.7Vでも、-3.5Vが出る。これはすごい。ただ、無負荷なのでこのまま使えるわけではない。LCDは1mA程度で動くことなので、LEDを負荷にしてみる。3mAも流すと、-0.5Vまで下がってしまう。電圧の調整が難しそうだ。それと部品点数がLTC1144がコンデンサー2つで済むのに較べると少し多すぎる(6点)。どちらにするか迷ったが、LTC1144を遊ばせておくのも何なので、こんどの実装にはこちらを使うことにする。

 肝心のソフトの方である。オブジェクト指向的設計でだいたいの骨格が見えたが、まだ検討するところが多くてなかなか実際のコーディングに入れない。タクトスイッチの制御が結構難しい。ロジアナやオシロで見ると、マイクロスイッチなどに較べるとチャタリングは殆ど起きないことが確認された。とはいえ、ないという前提でプログラムを組むのは不安だ。それと連続再生を指示するのに2つのスイッチの同時押しでやろうと考えているが、スイッチが2つ押されたことを確実に検知するのに単にスイッチのピンをループして見ているだけで出来るのか、これも自信がない。

 それと電池駆動なのでなるべく消費電力を抑えたい。sleepを使って割込み駆動にしたいが、タイマーも併用しないと正確なスイッチ状態の確認ができない。メモ用紙を何枚も使って簡便な方法を模索する。それとファイルのアクセスでのエラー処理をどうするかも大事な問題である。SDカードは時たまI/Oエラーが起きる(特に起動時)のでそのたびにリセットするのも芸がない。

 プログラムをLCD版に作り直す前に、スイッチ制御の練習のつもりで現在のソースに、タクトスイッチで演奏中のpauseと中止する機能を組み込んだ。これが結構手こずって正確に動くまで半日かかった。一応動くのだがミスが多い。タクトスイッチのチャタリングはないと思っていたが、やっぱり時たま起きるようである。それぞれのタイミングで少しづつ待ち時間をとり状態を確認することでやっと安定するようになった。

 1秒長押しで中止にする機能には、既にファイルアクセスのために組み込んである10msのタイマーを利用してこれは一発で通った。スイッチのハンドリングは色々な方法があるが、ここは演奏中の処理なので気を遣う。余り人のソースを見たくないので、まあ自己流である。それにしてもスイッチの制御は人間の感覚と、マイコンの速度がかけ離れているので正確に押したことを確認するのは手間がかかるものだ。

ソフトの開発に予想外に苦戦
(2/9/09)
 LCD版のコーディングにえらい時間がかかっている。ディレクトリを少しづつ読み込み、出来上がったメモリ上のファイルリストを元にスイッチで表示する範囲を上下させる機構が思ったようにすっきり作れない。擬似コーディングのレベルに落とすのにメモを書き散らす。A4用紙(印刷の裏紙)で5枚以上になった。SDカードにはWAVファイル以外のファイルや、ディレクトリが入る可能性がある。これを除きながらWAVファイルだけの中でファイルリストを処理するのは思ったより面倒である。特に最後のWAVファイルと、本来のディレクトリの最後のファイルが違うときどうするかなど、最後の処理が難しい。

 ファイル名を選ぶのだったら、常に頭からディレクトリを読んで数だけ読み飛ばしていけばそのファイル名を知ることが出来るが、何か無駄なことをやっているようだし、これだけでは余りにも面白みがない。というので画面のスクロールのようにバッファーに入れ、上下端でディレクトリファイルを読み直すなどの凝った仕掛けにしたが、これが仇になっている。

 どうもプログラムに懲りすぎる傾向がある。まあ、これがアマチュアの特権でもあるのだが、生産性から言えばとても昔、職業プログラマーをしていたと自慢できるレベルではない。ただ、これまでの経験から言えば、始めに時間をかければかけるほど、プログラムの完成度は上がるし、バグも取りやすい。適当にコーディングを始めてどうしてもバグがとれず、結局そのソースを放棄し作り直したことは何度もある。

 新しくプロジェクトファイルを起こすのでなく、これまでのプログラムに追加していく。念入りに擬似コーディングをしたおかげで、実際のコーディング作業はそれほど時間はかからなかった。コンパイルしてテストに入ったが、これがまた全く思うように動かない。考え違いが沢山見つかる。ディレクトリを読み進むときは問題ないのだが、表示範囲が戻って前のディレクトリを読み戻す処理が難しい。

 悪戦苦闘の末、コマンドプロンプトに数字を入れると、SDカードに入っているWAVファイルを頭から数え、そのあとのファイル名が所定のファイルリストに入る仕掛けが出来上がった。前のオブジェクト指向設計で3つに分けた、ブロックA「ディレクトリを命じられたところから一定数読み出しメモリに入れる」のところである。これだけで2日もかかってしまった。

 次の、B「そのメモリにあるディレクトリから、指示に基づき一部をLCDに表示する」ブロックとC「スイッチが押されたことを検知して意味を解釈しその指示を出力する」ブロックは、合わせてメインルーチンに吸収し一緒に開発する。これがロジックもさることながら、前にテストしたはずのタクトスイッチが思うように動作しない。

 今度のスイッチロジックは、あとで機能に加えたい連続再生やランダム再生のモード切替えにスイッチの同時押しを考えて作ってある。これを単なるWAITではなく、省電力化のためピンチェンジ割込みを使った本格的な構造にしたのだが、想定どおり動かないのである。

 始め作ったロジックでは全く同時押しを検知できなかった。ロジアナで調べてみて理由が良く分かった。人間の二重押しは、どんなに同時に押したと思っていても5ms以上の差ができる。普通の感覚で二重押しをすると20~40ms位は平気で違う。片やマイコンの処理はマイクロセカンドオーダーである。最初の待ち時間が短すぎた(数ms)。ファイルアクセスに使う10ms単位の待ち時間をたっぷりつかって(50ms)やっと同時押しを認識できるようになった。

ピンチェンジ割込みの落とし穴(2/11/09)
 スイッチでファイルリストを2行づつ表示するテストに入る。sleepをいれた本格的な割込み駆動のスイッチルーチンである。これが順送りは上手く行くのだが、逆戻りが動かない。スイッチのレスポンスはあるのだが一部表示しただけで次に行かない。ロジックを何度も見返す。テストステートメントをいくつも挿入する。それでも解決しない。途方に暮れた。

 結局、原因はまた別のところにあった。このピンのピンチェンジ割込み許可が抜けていたのである。Megaや新世代のAVRマイコンは、ピンチェンジ割り込みはピン毎に設定できるが、そのマスク記号の番号はピンの番号と違う。確かめたはずなのだが、動かないピンの設定がされていなかった。動いているように見えたのは、本来マスクされているピンの割り込みでsleepが抜けたことである。どうもピンチェンジ割り込みはグループ単位で割込みを制御しているので割込み禁止にしていても割り込みが起きているようだ。正しく設定し直して何の問題もなくスイッチは機能し、逆戻り表示が出来た。Sdpcm_lcd

 これで、UART上でLCDで動かす基本部分の開発が終わった。想定どおりの表示がUARTに出る。やれやれである。設計に5日、コーディングに3日かかっている。一段落してこれまで盛大にいれたテストステートメントを削除し、ソースを整理しようとしたときである。今度は突然コンパイルエラーがでた。最後の }(波カッコ)がないというエラーである。試しに最後に }を追加するとエラーがなくなる。

 このままコンパイルすると、当然のようにプログラムは動かない。これは困った。ソースはもう600ステップ近くある。ここから探し出すのは大変な作業である。見つける手立てがない。テストステートメントを入れて少しづつ先に進め、コンパイルしては動いているところを探っていく。やっとのことでif文のおしりの }が抜けているところを発見した。テストステートメントを消去するときにバックスペースキーが勢い余って上の行にはみ出し、}を消してしまったらしい。ソースの単位を余り大きくしてはいけないという教訓である。

 次の日、ソースを大幅に組み替え、すべての入力をタクトスイッチで行い、LCD表示の部分だけをUARTに出すソースがほぼ完成した。あとはUARTに出している表示をLCDに移し換えるだけである。残る課題は、電源が入っているときSDカードを交換するとおかしくなる不具合解消と、演奏中のカウント表示や、連続再生機能など付加機能の開発である。Mega328のI/OピンはLCDをつけてほぼ使い果たし、SDカードの抜き差し検知のピンが入るかどうか微妙なところである。まあ、そのときはテスト用のUARTのピンを外せばよい。

 それにしても、次から次にやりたいことが増えていく。がた老AVR研の電子工作の冒険には終わりがない。(2/12/09)

| | コメント (0) | トラックバック (0)

2009年2月 3日 (火)

LCDをつけた実装版PCMプレーヤーの設計

LCDにリスト表示する検討に入る(1/27/09)
 サンプリング周波数44.1khzの音楽CDの非圧縮(リニアー)PCMの再生に成功して少し気が抜けた。ブレッドボードはロジアナのプローブケーブルも加えてうず高い配線の山がボードの2/3を占めている。このまましておくわけにもいかない。といって、これを解体すれば今までの苦労の成果は消えてなくなる。まあ消えるわけではないが、もう一度作り直すのは大変だ。

 となると、やっぱり実装して残すしかない。そういえば、このあいだ携帯のリチウムバッテリーの実験をして、バッテリーの使い途を考えていたところである。バッテリーをこの試作版につけて動かし、消費電流を測ってみた。待機のときが30mA、再生時は60mA程度だった。バッテリーの容量は830mAh、連続再生でも10時間は持つ。うむ、これを電池に小さいPCMプレーヤーを作ってやろうか。少し制作意欲がでてきた。

 レイアウトしてみる。LCDは秋月の超小型と称する16 字2 行のものが、何かのときにと思って買ってある(¥800)。バックライトがついているが、なくても視認性は悪くない。電池やLCDが小さいので、DIP版のMega328に、LCDをつけても、かなり薄く、定期入れサイズくらいに小型化できそうである。858pcm

これくらいなら市販のプレーヤーと並べて恥ずかしくなるほど大きくはなるまい。こちらは何と言ってもMP3などと違うリニアーの非圧縮オーディオなのだ。格が違う。SDカードソケットをマイクロSD用のものに換えればもっと小さくできる。よーし、これに決めた。

 プロジェクトの方向が見えたので、以前の記事(12/27/08)の計画で、(3)LCDで操作を考える段階に入った。今度はそう簡単ではない。表示をUARTからLCDに換えるだけではない。入力ディバイスも必然的にタクトスイッチなどにしなければならない。しかも表示はたったの2行である。これでSDカードに入っている沢山のWAVファイルを表示させて選択し、再生の指示をしなければならない。好い加減な設計では、あとで苦労することが見えている。

とは言え、フラッシュサイズはふんだんにある。16KBでも十分なのに32KBもある。連続再生や、ランダム再生、経過時間表示など考えられることは大抵実装できるだろう。しかし、表示が2行32文字しかないのが一番の難関である。余り機能を盛り込みすぎると、昔買った、S○○yのHIMDレコーダーのように、使い物にならない操作性になってしまう。

 課題はやはり、わずか2行の表示スペース内で再生するたくさんのファイル名をいかにわかりやすく表示するかである。SDカードに入っているWAVファイルの数に制限は作りたくない。限られたSRAMスペースに、SDカードの全部のファイル名をどうやって収容するか、タクトスイッチによる上下のスクロールをいかにスムーズに行うか。スイッチの機能をいかに整理して操作しやすくするか。これは完全にロジックの世界である。久しぶりのソフト開発に腕が鳴る。段々気分が盛り上がってきた(それにしても安い娯楽だ)。

 擬似コーディング(ソースコードを自然語で書いていく方法)で、簡単に出来上がる規模ではない。メモリ上に一部だけ読んだディレクトリのファイル名リストを作り、タクトスイッチに応じて表示する行を上下させる必要がある。メモリは無限にとれないので、リストの最後に来れば次のファイル名をディレクトリから読み取りディレクトリの最後までこれを繰り返す必要がある。少しづつディレクトリを読み取ることで、無限のディレクトリに対応できるが、ファイル名をスクロールさせようとすると、処理は急に複雑になり、垂れ流しのUARTのように単純には行かない。簡単な機能を作りこれを発展させていく方法では無理である。

 オブジェクト指向的設計の出番である。これは私が勝手に名をつけている方法で、オブジェクト指向というように、オブジェクト指向のコンセプトを使った全体設計手法である。機能をオブジェクトとして分割し、その間を最初は抽象的なメッセージ(データを貰う、ボタンを押すなど)でつなぎ、全体の動作を確認した後、オブジェクトを関数などに置き換えていく。こうしておくと機能が独立し、このあとの設計が格段に楽になる。

 オブジェクト指向というと、機能継承とか多態性とかクラス、インヘリタンスなどの専門用語が飛び交う何か異次元のプログラミングと思われがちだが、コンセプトそのものは、実は30年も前から汎用機やUNIXなどのOSの開発ではごく当たり前の開発手法だったように思う。

 開発したコードの寿命を長くして結果として全体の開発コストを下げるには、機能に絞り、なるべく他と影響がない丈夫なコードを作っていく必要がある。それには自分の中の情報は外にださず、他との関係をなるべく抽象的にしておくのが良い(カプセル化でデータまで入れてしまえば本当のオブジェクト指向に近づく)。

 その意味では、C言語は実は使いにくい。内部関数を作れないからだ。関数は全部外に見えてしまう。従って、外に出したくない変数も全部、外部変数にしなければならない。昔私が使っていたPASCALはその点、内部関数が階層的にいくらでも定義でき、情報を隠蔽化するのに苦労しなかった。Cはその点とても気を遣う。内部の繰り返し処理のために気楽に関数を作れない。変数を全部、引数にするか、外部変数を使わないといけない。

 昔話はさておき、開発に戻ろう。今度のLCDへの表示機能をまとめる。タクトスイッチは、ファミコンのように上下の移動ボタンと、決定ボタンの3つで決まりだ。全体をいくつかの機能に分割し、それぞれがメッセージに基づいて動くように、何枚もメモに機能図を書き散らして、おおよその構成を作っていった。

その結果、機能は、
A「ディレクトリを命じられたところから一定数読み出しメモリに入れる」ブロック
B「そのメモリにあるディレクトリから、指示に基づき一部をLCDに表示する」ブロック
C「スイッチが押されたことを検知して意味を解釈しその指示を出力する」ブロック

の3つに分けられた。LCDは2行しかないので、読み出したディレクトリの最後に来たときは、(MORE)などの表示をし、そこで決定ボタンを押せば、次のディレクトリのグループが読み出され選択できるようにする。前のグループに戻るには、そのグループのトップにいる(UP)表示のところで決定ボタンを押し、前にもどる。863

 決定ボタンを押せば、表示された先頭ファイルの再生とみなしてDACへデータを送り始める。再生が終了すれば、前の位置のファイル名の表示をして次の入力を待つ。中断や中止は、再生中に決定ボタンを短く押すと「中断」、長く押すと「中止」とする。うむ、大体の動きはこれで良いようだ。こんどはこれをもう少し具体的にしていく作業に入ることにする。

汎用WAVデータの再生とUART版ソースの公開(2/2/09)
 毎年続けている北海道スキー合宿に今年も行ってきた。空港からスキー場までのバス往復(2 時間はかかる)で、これまで考えていたLCD表示ロジックを色々考える。この種の思考にはこういう閉鎖空間で何も出来ないときが向いているようだ。

 このあいだは、(MORE)の表示を作って、ここで決定ボタンを押せば次に行くようにしていたが、わざわざそれをするまでもなく表示がスムーズに出来る方法を思いついた。ダブルバッファーにすれば良いのだ。こうしておけばファイルの切れ目でディレクトリを頻繁に読み直す必要がなくなる。隣接した部分ではファイルアクセスをせず、沢山移動させたときに始めてディレクトリファイルを読み直す。

良いアイデアが浮かんで、それが可能なことが確認できたときの快感は、最近TVに良く出てくる「AHA」体験と言うのだそうだが、これはプログラミングの醍醐味のひとつだ。忘れないように揺れるバスの中で、メモにまとめた。

 LCD操作機能の設計が進んできたが、その前にやることがある。WAV再生の汎用化である。それにUART版のソースコードでも、DAC再生の事例として公開すれば何かの役に立つかもしれない。多種のWAVデータが再生できるようにしてから公開することにする。

 そもそもWAVファイルというのは、汎用的な音楽ファイルフォーマットの規格で、ヘッダーで多種多様の音楽ファイルが収容できる。リニアーPCMといっても種類を間違えると強烈なノイズになって機械は壊れないにしても精神衛生上良くない。少なくともサンプリングは44.1khz、22.05khz、データ長は16、8ビット、モードはステレオとモノ、これくらいは何もしなくても自動認識して再生できるようにしておきたい。

 このロジックは簡単に出来た。BU9480Fは、モノーラルの時、Lチャンネルだけにデータを送れば出力が両方に出るということなので、モノーラルのときはRチャンネルを空振りするようにし、16ビットと8 ビットは処理を別にすれば、上記のWAVデータは全部再生できるはずだ(サンプリングの違いは最初のタイマーの設定で分けられる)。chaNさんのxatoiのように、関数のエントリーポイントを振り分ける手法をとらずに、デコードの度にブランチさせても時間的には余裕がありそうである。まあ、これはテストしてみればわかる。幸い、バッファーとSDカードアクセスの時間的余裕はかなりある。

 スキーから帰った翌日、久しぶりに地下のオーディオルームで、CDからリッピングしたお気に入りのモーツアルトのクラリネット協奏曲をプレーヤーから再生しながら、上機嫌でプログラム開発をする。ロジックは大分前に考えてあったのでコーディングは簡単に済んだ。再生してみる。ははは、ほとんどの曲が超スロー再生になってしまっている。サンプリング周波数がおかしい。16ビットと8ビットの振り分け、モノとステレオはうまく行っているようだ。スロー再生は思い当たることがある。タイマーのプリスケールの指定をORでやっているので正しいプリスケールになっていない疑いが強い。

 (1<<CS21)とか_BV(CS21)というAtmel社推奨のビットハンドリングはこういうとき意外に使いにくい。1にするときは簡単だが、0にするには反転してANDにしなければならない。混在するときは決め打ちするしかない。今度もそうした(誰か他に良い方法があれば教えてください)。ここの処理はデコード前なのでいくらでも増やせる。ついでにサンプリング周波数16khzのレコードも再生できるようにする。プログラムを修正し動かしてみた。Sd_pcm_player_2

 以前の22khz8ビットのファイルも正しく再生できるようになった。今まで音になっていなかった44khz16ビットモノーラルのゲームソフトの女性の声もちゃんと出る。単純に嬉しい。これでソースの公開の準備が整った。回路図も用意することにする。アナログの部分は単純なボルテージバッファーしかないので参考程度だが、強みはこれで今動いていることである。何かの手がかりになれば幸いである。

UARTのシリアルコンソールからSDカードのファイルリストを出して、再生する曲の指定ができるPCMプレーヤーのソースコードをAVRstudioのプロジェクトファイルの形でここに置きます。16/22.05/44.1khz、8/16ビット、モノ/ステレオのリニアPCMオーディオが再生できます。なお、UARTはTTLベースなので適当な変換(秋月のUSBアダプターなど)を通して接続してください。 boud rateは38400bps.8ビットノンパリティです。   

修正:回路図に誤りがありました。レベルシフターが当初の図では74HC126になっていましたが、正しくは74VHC126です。(2/9/09)

「SDPCM328.lzh」をダウンロード

| | コメント (3) | トラックバック (0)

その他のカテゴリー

ARM | AVR | EAGLE | Xbee | 電子工作