« 2012年5月13日 - 2012年5月19日 | トップページ | 2012年6月10日 - 2012年6月16日 »

2012年5月27日 - 2012年6月2日の1件の記事

2012年5月29日 (火)

気圧計のバグつぶしと、ステッピングモーターの静音化

EEPROMストリームの一周がうまく行かない(5/18/2012)
 気圧センサーMPL115を使ったSTM32F107のグラフィック気圧計は、順調に気圧の推移を表示して稼動し始めた。嬉しくなってこの制作のきっかけとなったO-Familyさんの掲示板にも報告する。みんなが祝福してくれた。

 人は狩猟生活をしていた原始時代から、一人では生きていけない動物である。本来は孤独な電子工作だが、こういう機会を通じて沢山の同好の人と自宅に居ながらにして交流できる。こんな楽しいことはない。ネット社会の有難みをしみじみ実感する。

 稼動が2日以上になって気が付いた。気圧の表示は直近2日間だけなのに、外付けのI2CのEEPROM(24FC256)の容量は256キロビット(32KB)で1週間以上蓄積される。2日分(8KB少々必要)しか表示しないにしては大きすぎる。S_p5144879

  EEPROMのバッファーそのものは、データが一杯になれば、古いものから消していくしかけ(リングバッファー)になっているが、このままではグラフ表示が無用なデータの読み込みで遅くなってしまう。EEPROMの量を制限して、2日で廻るようにした。

 と、これが2日間のあとバッファーが折り返されるとレコードが目茶目茶な形になってグラフが表示できなくなった。折り返しのテストは、開発の初期にサイズを256バイトに縮めて何度もテストし、問題なく動くことを確認している。それなのに何故だ。

 UARTを付けてEEPROMから読んだデータを調べて、その原因はすぐわかった。 データがバッファーの最後まで書かれてオーバーラップした際、スタートポジションを1バイト余分に進めている。そうか、今までこのバッファーの使い方は、バイトストリームなので1バイト飛ばしても余り大きな問題にはならなかったのだ。データが最初に折り返すときに書き潰されるデータがひとつ増えるだけで、そのあとは問題なく折り返されていく。

 しかし、今度のアプリケーションは、32バイトのレコード単位にデータを蓄積している。このような形で、折り返しのストリームバッファーを使っている時には、この1バイトのずれは致命的である。1レコード分をすべて無効にしてアライメントを合わせてしまえば良いが、これでは解決したことにはならない。 

 しかも、今度のストリームはハードウエアがページ単位に読み書きするEEPROMで、アライメントに厳格だ。まあ、EEPROMのページサイズを考慮しないでもアクセスできる構造になっているので、レコードサイズを合わせる必要はないのだが、何となく気持ちが悪い。

簡単に修正出来ると思ったが意外に難しい(5/20/2012)
 始めは、バグのつもりで気楽に修正に取り掛かった。要するに、データがバッファーの最後まで書かれて、バッファーのトップに折り返すとき、スタートポジションを先に1つずらしてしまうのが、データが乱れる直接の原因である。

 データはまだ書かれていないので、このときにスタートポジションを移動する必要はない。次のデータが書かれるときに始めてスタートポジションを動かせば良いはずだ。これでこの問題は解決とばかり、コードを直してテストしてみた。

 しかし動かない。考えてみたら、データを読むときのEOF(End Of File ファイルの最後)の条件は、読み込むポジションがデータの最後に来た時である。データが書かれる前までスタートポジションを変えないということは、スタートとエンドが同一ポジションにあるということである。 既に読み出す前にEOF条件を満足しており、これでは先に進まない。意外や意外、難しい話になってきた。

 調べるにつれて、これは深刻な問題であることがわかった。スタートとエンドが同じポジションにあるとEOFの条件判定が極めて難しくなる。今まで、折り返しストリームバッファーがうまく動いていたのは、スタートポジションとエンドポジションが1つずれていたためなのだ。無駄なデータが必要だったのである。

 頭を抱える。メモ用紙にバッファーの図を書いて、解決法を探る。整理した結果わかったことは、データのスタートとエンドのポジションが重なると、このバッファーが、データが書かれた状態なのか、全くデータのない初期の状態なのかは、これだけで判別することは出来ないということである。

 それなら、エンドポジションの位置をスタートポジションとずらして、リングバッファーを操作すれば良いのではないか。データが全くない初期のときはデータのエンド位置をバッファーの最後に置くなどすればデータがないときと一周したときの判別が出来るはずだ。

 しかし、これも実際に動かしてみるとデータがあっても0の状態になったり、EOFが判別できなくてループになったりしてうまく動かない。いくらエンドポジションをずらしても、最後に書き込まれたデータ位置は、物理的にスタートポジションと同じなのでEOFの判定をするときは前のスタートとエンドを同一にしているときと変わらないからだ。S_p5284990

 結局、3日近くあれこれ考えた末、スタティックなポインターの位置だけでEOFを判別することは諦めた。やりたくはなかったがフラグを持ち込むことにした。スタートポジションを2回通った時に始めてEOFと判断する(1回のときはフラグを立てるだけ)ようにする。

 フラグ方式なら、beforeEOFとも言えるようなフラグを作っても良い。エンドポジションを最終データの一つ前に設定しておき、ひとつずれる形でEOFを返す。どちらが良いか迷ったが、わかりやすい前者の方式で実装することにする。

 ロジックが固まった(勿論例の擬似コードである)ので、テストに入る。EEPROMの関数を直すだけでは、テスト結果は2日かかることになるので、mainプログラムをいじって早く結果が出る(バッファーを使いきる)ようにし、テストする。

 何度かプログラムを修正して、やっとのことでデータは正しくバッファー上に記録されるようになった。これが最善の策か自信がないので、このブログに擬似コードと図を載せて、読者の方からご批評を待ちたいと思う。もっと良い方法があれば教えて下さい。

上記の修正を加えたEEPROMのライブラリをzipに固めたものを下に置きます。以前公開したコードでは折り返しで1バイトずれます。また、気圧計全体のロジックの参考のため、main.cも入っています。ただしこれだけでは動きませんのでご注意。

「5_28_2012eeprom_lib.zip」をダウンロード

自動巻き機のマイクロステップ制御の勉強を続ける(5/21/2012)
 時計の自動巻き機の工作の話である。ステッピングモーターを静かに回すための方策、マイクロステップ制御の検討を続けている。前回記事にマイクロステップ制御には4つもPWMチャネルが必要だと書いたら、コメントでhiraさんがバイポーラなら2本のPWMで出来ることを教えてくださった。

 ユニポーラモーターでも、バイポーラにして使うことが可能なようだが、モータードライバーには、逆転が必要なため、フルブリッジのドライバーが2つもいる。PWMを2つにしたいのは、Tiny13などの8ピンのAVRがPWMを2つしか持っていないためで、Tiny45も、調べたらPWMを4つ持っているのにPWM出力は不思議なことに3本しか出すことができない。

 とはいえ、8ピンのAVRで実装しなければならない必然性は殆どない。AVRチップ最安値(秋月で¥100)のTiny2313は、余裕で4本のPWMが使える。それに、こちらには、Xbeeラジコンのときに間違えて買ったステッピングモーター用のFETモジュールMP4401が5つもある。早くこいつを消化したい気持ちもある。ここはとりあえず2313で実験を進めることにする。

ただ、2313ではタイマーを全て使い切るので、運転制御のためのタイマーがPWMのタイマーと併用できるか心配である。ウェブを見ていると、バイポーラのマイクロステップ制御のICが数多く売られている。それだけ需要があるということなのだろう。

マイクロステップ制御の仕様を固める(5/23/2012)
 だいぶ煮詰まってきたので、細かい仕様を決めていくことにする。クロックの計算をする。波形は、一番ポピュラーな正弦波にすることにした。これを分割して近似波形の0から255 までのテーブルを作る。PWMサイクルは20kHz(5ms)、分解能は8ビットで十分だろう。回転は恐らく、1分20回転もする必要がない。正弦波は、どの部分を使うのだろう。 

 最初はモーターを動かさずにLEDとオシロで実際に波形が出るかどうかを確かめれば良さそうだ。偉そうなことを言っているが、実は、がた老AVR研究所はまともなPWMは始めての経験である(ゼロクロスのトライアックで真似ごとのPWMはやったが)。

 波形はサインカーブをEXCELで作り、1/2π分を32分割で作る。分割の数は良くわからないで適当に決めた。これをテーブルに入れ、PWMカウンターのオーバーフロー割り込みの度にデータを移していけばPWMが出来るはずである。

 さらに、4相のモータードライブ単位に、PWMを設定していく。モーターの1サイクルは全体を少し大きな(ステップ数の多い)ステートマシンで動かせばよい。まずは1チャンネル分のPWMを作り、LEDとオシロで確認することにする。

 久しぶりのAVRの開発である。この前のステッピングモーターのAVRStudioプロジェクトをコピーして、新しいソースコードを起こす。色んなことを忘れている。何かの手違いか、全く同じソースを持ってきたはずなのにビルド出来ない。エラーで帰ってくる。

 こういう統合開発環境の不具合は厄介だ。先を急いでいるので、深追いせずこのプロジェクトをさっさと諦め、もういちど別のプロジェクトを起こしなおす。よーし、動いた。何が悪かったのか追求しても始まらない。ソフト開発の世界はこういう見切りも結構重要な要素のような気もする。

 PWMといっても難しいところがあるわけではない。やたらにタイマーの定義が複雑なだけだ。でもARMに較べれば、AVRのタイマーの定義など可愛いものだ。8ビット高速PWM、コンペアレジスター2つで、2つのPWM波形がとれる。とりあえずタイマーひとつだけに実装し、LEDが人間の目で蛍のように瞬く時間にプリスケールを定義して、簡単にソースコードが書けた。

LEDで実験に入る(5/24/2012)
 ブレッドボードにLEDを差して、早速実験に入る。LEDが点いた。しかし、変な瞬きである。ギクシャクしているし、完全に消えないところがある。オシロを接続して出力波形を見る。ふむ、何となくPWMっぽい波形だが、あちこちにパルスが出て(これがLEDの消えない理由)、しかも綺麗な波形ではない。

 デバッグに入る。ヒゲが出るわけは判明した。スタックを減らしてプログラムを小さくするため割り込みではフラグを立てるだけで、主な処理はすべてメインルーチンに引き込んでいる。ステートマシンの番号でフェーズを判定し、コンペアマッチレジスターを0にしているが、タイマーはCPUの動きとは無関係に動き続けるので、この差の分だけヒゲになるのだ。

 そういうことなら、これを割り込みルーチンで直接やれば良い。これでヒゲはなくなるはずだ。おやあ、まだ残る。何故だ。そうか、高速PWMではカウンターがオーバーフローすると出力は1にトグルされるが、オーバーフローしてから、このユーザープロセスの割り込みルーチンに来る時間は0ではなく必ず少し遅れる。

 CPUクロックとのプリスケールが8程度では、8ステップ以内にコンペアレジスターを0にしなければならず、割り込みでうかうかレジスターの退避などしていては間に合わない。このグリッチはクロックを上げてプリスケールを増やせばなくなるのだろうが、何となく対症療法的でしゃくである。

 データシートを眺めているうち気がついた。意味が良くわからないが「位相基準」PWMというのは、コンペアマッチする場所とオーバーフローするところが違うようだ。PWM周波数は1/2になってしまうが、これならグリッチは出ないのではないか。

 早速、確かめる。タイマーのレジスター設定で「位相基準」PWMに替えて動かしてみる。ビンゴ!だった。全くグリッチはなくなり、LEDも完全に消えるところが出来てホタルらしく点滅する。よーし良いぞ。ただPWMで調整している光の動きがどうもギクシャクしているような気がする。S_p5264894

 出力ピンに4KΩと、1μF程度のLPFをかませてオシロで見てみた。思ったより綺麗なサインカーブが現れた。おやあ、カーブが最大になったあと、少し欠けて次の下降カーブになっている。ちょうど、LPCMプレーヤーでバッファーアンダーランを見つけたときのようなカーブだ。綺麗なサインカーブが一部欠けているところが見つかったのである。

 ソースコードを調べる。すると、カウンターの増やし方を間違えているところが発見された。これを直して動かしてみる。やった、やった。完全なサインカーブがオシロの上で観測できた。いやあ、オシロを買っておいて良かった。これはロジアナではなかなか発見できなかっただろう。

モーターは完全に静かになった。大成功(5/26/2012)
 マイクロステッピング制御でモーターを動かせる環境が少しづつ整って、完成の期待が段々高まってきた。1つだけのPWMチャネルを4つに拡張する。ブレッドボード上にあり合わせのLEDを差して、それぞれホタルのように次々に点滅する様子を暫く楽しんでから、いよいよモータードライバーを接続する。

 さきほどの簡易LPFをさらに3組増やす。ブレッドボードは林のように部品が乱立するがそれにかまっている場合ではない。配線が済んだ。さあ、どうだ。コンパイルはARMと違ってフラッシュが2KBもないのであっという間に終わる。さあ実行である。緊張の一瞬。「ゆけー」という掛け声とともに電源ON。

 しかし、モーターは、「ンゴゴゴ...」と言ったまま、廻る気配はない。ふーむ、配線を間違えたか。試しに一部を反転させてみる。廻り始めた。おおお、全く音がしない。手に持っているとわずかな振動が感じられるが、導電スポンジの上に置くと、余程耳を近づけないとモーター音が聞こえない。

 大成功だ。LPFの部分を少しいじってみる。意外なことに、コンデンサーをはずすとモーター音は更に小さくなった。手で持っていても、この状態だと殆ど振動を感じない。ただし、モーターを机の上に直に置くと、PWM周波数(およそ2Khz)の「ピルルル」という音がはっきり聞こえる。ひところの電車のモーター音のようで面白い。

S_p5284991

 コンデンサーをつけるとこの高周波音は小さくなるが、モーターの振動は明らかに増える。抵抗は入れてあるほうが静かになる。エッジがなまるからであろうか。パルス制御で言えば一相制御にあたるのでトルクの低下を懸念したが、手で止めることが出来ないくらい力は十分で、時計を回すくらいなら全く問題がない。

 いやあ嬉しい。あれだけゴーゴーとうるさかったステッピングモーターが、全く無音になったのである。同じモーターとは思えないほどだ。PCの横で動かせば、PCのファンの音で、モーターが廻っている音は完全に消える。ただ、長時間動かすとモーターは2相パルス駆動のときより明らかに発熱する。

 2時間連続で動かしても、少し暖かいなという程度なので、これからのアプリケーションには全く問題がないが、やっぱりモーターには少し負担がかかっているのかもしれない。一方、MP4401は全く変化がない。この程度のPWM制御は全く問題がないようだ。

 これで自動巻き機のソフト開発は峠を越えた。これだけ音が静かになったのだ。大威張りで巻き機だと自慢できる。残るは、マイクロステップ駆動の逆転である。これ結構面倒くさそうである。

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

« 2012年5月13日 - 2012年5月19日 | トップページ | 2012年6月10日 - 2012年6月16日 »