これまでのような飛び飛びの描画ではなく、連続したグラフが美しく表示されるようになった。ラインを2重に引いた(座標を1つずらす)ので折れ線グラフがはっきり見えるようになった。細かいところや、枠線などがないので完璧とは言えないが、当面の心電波形の表示はこれで完成と言える。いやあ、長かったけれど何とかここまできた。このあとは、スケールを描くこと、PCコンソールではなく、ロータリーエンコーダのようなもので調整が出来るようにすること、ケースに入れることなどが残っているが峠は越した。ひっかかるところがある。表示波形のR波(一番鋭いところ)のピーク値が低いことだ。後のT波、U波と同じくらいである。したら病気なのかも知れないが、そうではなくて、サンプリングが少ない可能性の方が強い(希望的観測)。AVRとARMのUARTインターフェースで、第一バイトを識別するためデータを端折っている。残さずデータをARMに送るのは、以前、コメントでいただいた、5ビットづつの2バイト送信ロジックを検討してみるのも面白いかもしれない。いやいや、やることはまだ山ほどある。(水)心電計プロジェクト:STM32F103の心電波形表示で悪戦苦闘かれこれ半年かけた心電計プロジェクトは遅まきながらARM(STM32F103VB)で2.4インチTFT液晶に心電波形を表示するソフト開発まで進んだ。それにしても、液晶を動かすだけに大騒ぎしたり、フォトカプラーの選定に川崎まで高速カプラーを買いに行ったり、センサー部のTiny861のUARTにはまったりして、やたら脱線が多い。前の記事から20日余り、少しづつ作業を進め、やっとのことでTFT液晶から実際のグラフが表示されるようにはなった。以前、DACでオシロに出したような綺麗な心電波形はまだ出てこない。これを待っていると次の記事がいつになるかわからないので、とりあえずこのあたりで経過報告をしておくことにする。USI-UARTは動いた。送信プロトコルを決める(11/11/2014)センサー部のTiny861で動かなかったUARTは、もともとISPケーブル経由でPCとつなぐUART(ISP-UARTと勝手に命名)で、ARMへのUARTインターフェースは、最初からバッファリングの出来るUSI-UARTを予定していた。I2Cを通してDACに送っていたデータは今度はARMに送られる。このUARTの移植は問題なく終了し、プログラムは動き始めた。UARTらしい波形がオシロから出ている。念のためロジアナで出力波形を確かめた。ところが、これが全くでたらめなデータなのである。ISP-UARTに続きこれもダメかとがっくり来る。何を間違えたのだろう。気を取り直して、慎重に状況を最初から調べる。ほどなくロジアナのプロトコルアナライザーのボーレートが設定と違っていることを発見した。おお、ちゃんと正しい出力データが出てきた。やれやれ、ほっと胸をなでおろす。通ったのは良いが、ここは送信プロトコルが問題で、まだ具体的な仕様を決めていない。10ビットのバイナリ―データが2バイトでセンサー部のディジタルフィルターから送られてくる。データの時間間隔は625μsで、38400bpsのUARTなら2バイトだと、260μs(スタートストップいれて10ビット)の2倍、520μsかかるので、ほぼ連続してデータが送られることになる。何もしないで送ると、どれが第一バイトかわからなくなるので、何らかのロジックが必要である。10ビットは、1023が最大値なので、最初、第一バイト(右詰めとして)が3以下という、洒落たロジックで第一バイトを識別しようとした。0~1023の中で、それでも区別できない数値が20個近くあることがわかり(0,1,2,3,256,257,258,259など)、あきらめた。結局、採用した方式は、精度を犠牲にして連続して送るのをあきらめ、2バイトと2バイトの送出単位の間に一定の待ち時間を設け、受信側は、必ずその待ち時間だけ待ってから第一バイトを受け取る方式にした。グラフ表示が最大320ドットで長くでもスキャンは一秒間隔なので、3.3ms単位以下のデータは表示しても意味がない(前の記事の33msは間違い)。1ms程度の待ち時間を入れても大勢には影響ないはずだ。Tiny861のPCコンソールモニターでの値と、ロジアナのデータの値がほぼ一致した。待ち時間は、625μsの送出を1回休んで間隔を明ける。従って、送信頻度は、約1.25ms単位となる。ARM側のソフトが動いていないが、ロジアナの波形は正しいデータを示している。これで、AVR側のソフト開発は一段落である。ARM側のソフト開発の前にフォトカプラーの実装をすませてしまおう。フォトカプラーとインバーターをつける。インバーターは不要か(11/12/2014)センサー基板のすみに、フォトカプラーTLP512と、一緒に買って来たシングルチャネルインバーターTC7S04Fをつける。SOT23-5の極小のチップだ。持ち合わせの変換基板にハンダ付けする。フォトカプラーは論理反転するので元のUARTにするためである。SOT23-5の変換基板が結構大きく6ピンのフォトカプラーと同じくらいだ。この変換基板はもう1ノッチ小さくできるような気がする。それはともかくハンダ付けは簡単に終わった。配線を確かめて早速テストに入る。Tiny861のUART出力ピンを一つ間違えて、出ない出ないと騒いでいたが、オシロをあてて間違いを発見し、フォトカプラー経由でも問題なくUART波形が出た。テストしているうちに、このインバーターもいらないような気がしてきた。フォトカプラーの出力側を、エミッタフォロワーの形にすれば、順論理になる。しようか迷ったが、まあ、配線してしまったものを取り外すほどのことでもない。バイナリ―端末アクノリッチでUART出力が正しく出ていることを確かめた。これでAVR側は完全である。あるが、完成に向けてことが進んでいく。したハンダ付けをやっているうち、もう少し手を動かしたくなった。いうのはやりだすと止まらない。SOT23のインバーターチップを見ていて、これを汎用基板に直接ハンダ付けすれば、変換基板を使わずにもっと小型化ができる気がしてきた。DATA)がかかってAVRが幽霊動作をする現象をさけるため、かなり昔に、トランジスターのエミッタフォロワーで受けて受信側を遮断する「セパレーター」を基板の切れ端に作ったことがある。resetがかからない。この現象は今度のプロジェクトでも起きて迷惑している。このセパレーターはブレッドボード用で、こういう基板同士の接続では不便で使っていない。SOT23のチップトランジスターなら在庫がある(2SC4116)。これを使って小型化してみよう。本題が順調に進んでいないときは、こうした工作を無性にやりたくなるものだ。UARTアダプターを買ってきたところだ。こいつにもつけられるよう汎用基板の4×4の切れ端に、ピンヘッダー、チップトランジスターとチップ抵抗2つを実体顕微鏡でハンダ付けする作業に入った。ほどなく、写真のようなアダプターが完成した。抵抗やスピードアップコンデンサーはチップ部品である。38400bps程度なら問題なく動く。いやあ、こういう道草を食っているから本題がちっとも進まない。ARM(STM32F103)のUARTが2つ同時に動かない(11/18/2014)ゆるゆるとARMの開発に戻る。Tiny861からの送出データを受け取るUARTの増設だ。ねむいさんから頂いたソースコードは、複数のUARTが定義できるようになっている。始めは簡単に増やせると思っていた。これがまた難儀したのである。ソースのUARTの初期化ルーチン(conio_init(UARTn))が、どうも良くわからない。この初期化ルーチンは引数にUARTの番号を入れてやれば、それに応じたUART(この石はUARTを3つ持っている)を初期化しているので、併設が出来るものだとばかりと思っていた。2つUARTを初期化すると、2つとも動かなくなる。ソースコードを調べ直す。ふーむ、case文以外に#ifのプリプロセッサ―でUARTルーチンを制限している。調べていくうち、どうもこのコードではUARTをダブって定義できないような感じがしてきた。見かけは、引数にUART番号を入れさせて、独立してUARTが併存できるようなコードにはなっているが、2つめを定義すると動かなくなるというのは、何か変数が被っているに違いない。ARMのUARTの初期化は、GPIOピンの定義から始まってややこしくAVRのように簡単ではない。見ただけでは何が何だかわからない。仔細にコードを調べて行って遂にUARTの構造体が共通であることを発見した。こいつを独立させて(もうひとつ分ける変数があったが)、めでたく2つのUARTを動かすことに成功した。そもそも、2つ同時にUARTを動かす初期化ルーチンではなかったことに早く気付くべきだった。センサー部のTiny861とARM(STM32F103)をフォトカプラー付きUARTでつなぐ。ARMを立ち上げてPCにコンソールを出してから、センサー部の電源を入れる。よっしゃー、PCコンソールから16進表示したセンサーのデータが溢れるように出力された。UART2つが同時に動いたが、データの取り込みはうまくいかない(11/20/2014)このままではコンソールからデータが溢れて中味がわからないので、PCからのコマンドで一部だけ表示するようにソフトをいじり、中味の検証に入った。おやあ、第一バイトと第二バイトを取り違えているデータが頻々と入っている。皮肉なことに、正直に何もしないでデータを読む方がかえって間違いが少なくなる。何とも馬鹿にした話である。待ち時間がおかしいのか。コンソールデータだけではわからないのでロジアナを持ち込んで精密に波形を調べ始めた。1msだけでは区別がつかないようである。AVRに戻って、待ちの間隔を2倍にした(2回休む)。2回休むと、AVR側が2バイトづつ送らなくなったり、どうも不安定だ。コードのなかでcontinue文を使ったのが原因のようだ。愚直にif文を区分けして、このトラブルは解消したけれど、これに係っている暇はない。間隔は、データ2個分1.25msまで空いた。1msの待ちで最初のデータを識別するには十分な時間である。データは頻々と第一バイトと第二バイトを逆さまに読むケースが続出する。ARMの待ち時間がおかしいのかとGPIOピンでわざわざ時間を出してみたが正しく1msだった。うーむ、何が悪いのだろう。この方式では識別ができないのか。別の方法も考えるが、こんな簡単なロジックがうまく動かないというのが気に入らない。別の方式の検討に力が入らない。素晴らしく美しい富士をめでる(11/22/2014)ちょっと息抜きに、電子工作以外の話題をご紹介。こんなに美しい富士山の姿は、これまで見たことがなかったので、その感動のおすそわけである。知人に伊豆高原に別荘を持っている人がいて、毎年、季節の良いころに仲間で利用させてもらっている。今年は紅葉を目当てに友人と何台かの車ででかけた。伊豆は観光シーズン中は海岸沿いの道が大渋滞するので少し遠回りになるが箱根に上がって尾根伝い(天城スカイライン)に行くことが多い。箱根の山は、紅葉が中腹から美しく色づき歓声を上げながら山を登っていたが、圧巻は峠を登り切って振り返った時の富士山の姿である。十国峠からの景観が特に素晴らしい。晩秋の裾野から雪をかぶった富士山が丸ごと見える。こちら側からの富士は、宝永山の火口壁が目立って山梨側に比べると少し見劣りがするということだが、そんなことを感じさせない迫力である。この峠周りルートは、霧が出たりすると地獄になるが、こんなに晴れるのも珍しい。駿河湾から裾野、頂上にいたるまで雲一つないというのは、これまで何回もここを通っているが初めての経験だ。道行く車やツーリングのバイクもあちこちで車を止め、盛んにシャッターを切っていた。この景観がめったに見られない証拠は、帰りの道中で明らかになる。この話を聞いた海岸沿いで来た別の車の友人が、天気が良いので帰りは山に上がったのだが、靄(もや)がかかって富士山は全く見ることが出来なかったそうだ。相模湾側は青空が出ていて雲も高かったのだが山の天気というのはこういうものである。間違いなくデータを受け取れるようになった(11/25/2014)旅行から帰って電子工作に戻る。データの受け取りはまだ正確に行えない。こんなにエラーの多い状況ではグラフは曲線にはならず、散布図状態にしかならないだろう。ARMのUARTをなめてかかってえらい目にあっている。下らないことにこだわっている自分がみじめで余計気持ちが落ち込む。数日後、このトラブルはあっけなく解決した。居間から地下室のPCルームに降りる階段の途中で間違いに気が付いた。これが、電子工作の醍醐味だなどとうそぶくのも悔しい基本的なミスである。今度もわかってしまえば何でこれに気が付かなかったのだろうと思う基本的なミスだったのだが、わかるまでほぼ2日間かかった。要するに、keypressed()という関数をキーに受信データの到着時間(バッファーにデータが揃ったとき)を一生懸命測っていたのだが、実際にはデータを読まなかったため、バッファーに次々にデータが貯まり、条件が揃ったときに読むデータは、ずっと前に受信したデータだった、というオチである。これでは、何もしない方がデータが正しく読めるはずである。原因がわかってしまえば修正はあっというまだ。データが来たときは、必ず受信関数でデータを読み、バッファーを空にしておくだけである。修正に要した時間は1分もかからない。コンパイルしなおして、正しくデータが読めていることを確認する。よーし、画面一杯にデータを出しても、全く乱れはない。あっけなく治ってしまった。トラブルが解消するたびに、いつも何とかならないかとは思うが、こればっかりは仕方がない。考えたようには動かない。書いたようにしか動かないという格言をかみしめる。心電波形は出てこない(11/30/2014)いよいよ最後のステップ、得られたデータの画面表示である。枠や数字、スケールの表示はあとにするとして(これは面倒だが力仕事)、気になる数値のグラフ表示のロジックをコーディングしながらつめる(本当はおすすめしません)。以前考えた通り、出力値(0~1023)を液晶表示ドットY軸(240ドット)に正規化して、2X2ドットのピクセル(最初は赤、画面が暗くなるので黄色に変更)を打っていく。ロジックは何も難しくない。グラフはX軸の最後(320ドット)まで行くと最初に戻る。描画のとき、以前、打った値を覚えておき、表示と同時に消せば(黒で描画)、常に一つの波形が表示される理屈である。コードそのものは簡単で開発はすぐ終わった。