« 2009年1月 | トップページ | 2009年3月 »

2009年2月の4件の記事

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))
に修正してください。

| | コメント (2) | トラックバック (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)

« 2009年1月 | トップページ | 2009年3月 »