Tiny13で制御部を作って自作サーボが動いた
このままでは引き下がれない(5/2/2014)
サーボモーターをスクラッチから自作しようとして、マイコンでやれば造作のない制御部分を、こだわってロジックICだけで出来ないか模索している。前回までにNE555を使った制御ロジックを完成させたが、モーター出力が不足して、まともに動くところまで行かなかった。
サーボモーター駆動は、PWMなのだが、duty比を、ロジックICでは1/10~1/20にしかできない。何らかの方法でduty比を上げないと、モーターを快調に動かすことはできない。これは最初からわかっていたことだが、動かしてみて、やっぱり駄目だということがわかった。
自慢にもならないが、当研究所の所長は負けず嫌いでは人には負けない。かなり諦めの悪い方である。これまでにこの性格で数々の失敗をしてきた。長い目で見れば、平和な日本では我を通す人は大体嫌われる。
しかし今さらこの年齢で改める気持ちはない(直すならとっくに直している)。意地になって、マイコンを使わないで制御する方策を考えた。まあ、これが電子工作の楽しみの一つでもある。
アナログでduty比を上げる方法はともかく、デジタルっぽくやるなら、生成されたパルスの幅(最大2ms)でPWM期間(15~20ms)の後半に多数のパルスを生産すれば、duty比は稼げる。
しかし、数だけ増やすのなら出来そうだが、同じ幅のパルスでというのが難しい。CPLDやFPGAならともかく、単純なロジックICの組み合わせではとても無理な気がする。市販のサーボモーターはどうやっているのだろう。
アナログで考えられる方法は積分回路である。この回路を通せばパルスがなまって長く伸びる。スイッチングの閾値を低くしたトランジスターを介せば、長いパルスにすることができるのではないか。
ウェブには残念ながら、こういうことをやっているところは見当たらない。試しに大容量のコンデンサーを並列に入れて、強引に積分回路もどきを作ってオシロで調べてみた。ふむ、パルスがなまって後半まで引きずっている波形が現れた。
よーし、これならトランジスターの飽和域をうまく使えば、パルス幅を広げられるかもしれない。淡い期待を抱いて、ベース直列抵抗を減らしてみた。
出てきた波形は、単に、余り広がらない幅のパルスが遅れて出現しただけだった。はい、コンデンサーで幅は広がったが、立ち上がりも遅れる事に気が付きませんでした。お粗末さまでした。
さらにウェブをあれこれ、さ迷う。しかし有力な情報にはぶつからなかった。結局、ハードやロジックICでパルス幅を広げることは諦める。高電圧でパルス制御すれば良いのだろうが、モーターの定格の何倍もの電圧をかけるのは、アナログの素人にとっては、ちょっとハードルが高すぎる。
あまりこだわるのはやめよう。マイコンなら簡単なプログラムでこの程度のロジックは簡単に組み込める。そっちのほうが断然楽なはずだ。ただ、Tiny13程度の小さい石で実現できるかどうか。これはやってみるしかない。
擬似コーディングは済んだが実装にぐずぐずしている(5/5/2014)
マイコンで作れば造作がないと豪語していたが、実際にロジックを考え始めて、そう簡単ではないことを思い知らされる。Tiny13は、フラッシュがわずか1Kバイトしかないので余り複雑なロジックは組めない。
それでも何枚ものメモに擬似コーディングを書き散らしているうち、何となく構造が見えてきた。こういう繰り返し作業は、これまでに同じようなことをやっている。短いタイマーの割り込みの度に、カウンターをアップさせて、FPGAのときと同じように長いステートマシンを作ればよい。
おおよその考え方はこうだ。サーボモーターのPWMプロトコルは、周期が15~20msで、パルスの有効幅は最大でわずか2.5msである。この期間中に、サーボモーターの軸につけたポテンショメーターの電圧からその位置を特定し、入力パルスの幅との差を計算して、残りのPWM期間の12.5~17.5msの間で増幅したパルス幅をステートマシンで作ってやる。
入力パルスの立ち上がりが、この処理の最初のキーになる。チャタリングはないとして、タイマー割り込みのサンプリングで、前後の入力の状況を比較し、立ち上がりを検知する。入力パルスとパルス幅に換算したADコンバーターの値で前後進の判断と量(パルス幅)を決める。これで良いはずだ。
入力パルスと参照パルスの比較演算は簡単なロジックなのだが、実際にモーターを動かすパルスを出力するところが意外に難しい。タイマーの割り込みによって四六時中、このON/OFFするところは通過するので、確実なロジックを考えておく必要がある。
電子工作に対する意欲がこのところ減退しているので、工作室につい行きそびれる。居間でTVを見ながら擬似コーディングのメモを書き散らし、構想を練る。数日後、意を決して地下室に降り、PCの前で開発を始めた。
新しいAVRStudioのプロジェクトをおこし、コーディングにとりかかる。コーディングは一気に作業することにしている。無理をしても一息に書いた方が一番効率が良いことをこれまでに学んでいる。今回の作業時間は、夕食を挟んで数時間と言うところか。ソフトは出来上がった。
オシロを頼りにテストする(5/6/2014)
UARTはこういうタイミングがクリティカルな(PWMの最初のパルスを見逃すとおしまい)プログラムには、入れにくいので、オープニングメッセージだけにし、オシロを開発当初から入れて、プログラムをテストすることにした。
ターゲットは迷ったが、とりあえずのTiny13である。ピンの数が一杯一杯だが、この程度の制御にTiny2313あたりを使うのはちょっと抵抗がある。皮肉なことに、せっかく作ったUSIのUARTは、このTiny13では使えない。フラッシュが少ないだけでなく、Tiny13にはUSIが入っていない。
このあいだの市販サーボをテストするのに使ったTiny861のついたブレッドボードの横に、Tiny13をセットする。結線は、8ピンなので楽勝である。あっという間に終わった。ISPケーブルで動作を確認する。うん、大丈夫だ。フラッシュも1Kバイト以下に納まった(800程度)。
わくわくしながら、プログラムをロードしテストを開始する。最初は、UARTのオープニングメッセージも、所定のパルスも全く出てこなかった。えー、どうして?どこかで暴走しているのか。まさか。少し調べるがどこも悪くない。プログラムもちゃんと焼かれている。
こうなるとデバッガーか。この程度の開発でデバッガーなど持ち出すのは抵抗があるなあ。LEDをつけて確認するにしてもTiny13ではピンが足らない。パルスが出ないのはとにかく、UARTが動かないのは気に入らない。オシロを送信ラインにつないでみると、わずかにパルスが出ているのがわかった。
良かった。プログラムは動いているようだ。しかし、なぜ送信信号がこんなわずかなパルスになってしまうのだ。プルアップが必要なのか、ISPが悪さをしているのかと調べるがわからない。あちこち探し回ったあげく、UARTの初期化ステートメントがコメントアウトされているのを発見した。
最初、UARTなしのプログラムのフラッシュ量を調べるためコメントアウトしていたのを忘れている。うーむ、やきがまわったか。これを戻し何とかUARTは動いた。しかし、パルスは全くでてこない。といってUARTを挟むことは出来ない。9600bps(CRクロックなのでこれが上限)では、一文字に1ms近くかかる。有効パルス幅3msのPWM制御にはさんだら目茶目茶になる。
仕方がないので、UARTをループ100回で一回出力するようなロジックで、中の数字を出力させる。時々化けるが変数の中味は表示された。おやあ、数字がでたらめだ。数がこんなに大きくなるはずはない。
相変わらずお馬鹿なコーディングミスを続けている(5/7/2014)
プログラムを調べてすぐ原因がわかった。最初の入力パルス幅とポテンショメーター値の比較数値を符号なし変数にしていたため、引き算したときに0を挟んで最大数になってしまって止まらなくなっていた。書いているとき、どうも引っかかっていたのだが、予感が的中した。
これを直して、やっと少し動き始めた。出力線にそれらしいパルスが出てくるようになった。しかし、パルスが安定しない。所定のパルスが出てこないときがある。PWMなので、これでも動くだろうが、このままにしておくわけにはいかない。恐らくギクシャクした動きになるだろう。
オシロを良く見ると、正進ではパルスが失われ、逆進では、パルスが合体している。ここでのロジックのキーファクターは、サーボ制御のPWM入力パルスの立ち上がりである。15~20ms間隔で3ヶ所でこの入力ピンの状態を調べている。
そうかわかったぞ。ピンの状況がこのロジックを実行中に変わったらどうなるだろう。めったにないけれど、結果がおかしくなるのは当然だ。ループの最初で、状態を聞き、その値で、そのループを回すアトミックオペレーションが必要なのだ。
これを修正して、前後進ともパルスの抜けもなく、増幅された出力パルス(duty比は60%以上)が出てくるようになった。しかし、まだ少しだがパルスが息つくところがある。タイミングがUARTがコンソールにデータを出力するところなので、UARTの疑いが濃厚である。
やっぱり、最後はUARTが犯人だった。UARTをはずすとTiny13は、見事に位置を補正する前後進パルスを出力する所期の機能を実現した。フラッシュは600バイト、UARTをつけても900バイト。これならTiny13だけでもっと高度な(PID制御?)制御も実現できそうである。
モーターをつける前のテストは終了した(5/8/2014)
全く参考書なしのサーボ制御ロジックである。ウェブには一般の市販のR/C用のサーボを動かす側のプログラムは沢山あるが、サーボそのものの制御ロジックの詳細が説明されているところはどこにもない。全くの手さぐりである。
でもオシロで波形を見ている限りでは、もうちゃんと動きそうである。ただ、どうも数値がしっくりこない。タイマーの値が計算通りではない。原因究明はあとにし、とりあえず現物あわせのような形で動きを修正していく。
それぞれのボリュームを動かして、サーボ動作がうまく動くことをシミユレーションして確かめる。やってはいけないのは、モーター側のポテンショメーターの範囲が、送られてくるパルス幅より狭い時で、両端で無理な力が加わってモーターやギヤを痛めてしまうことだ。
これだけは十分数値を加減して調整する。指示側のボリュームを最小から最大まで回し、モーター側のポテンショメーターで全てモーターが逆回転して元へ戻ることを確かめる。うん大丈夫なようだ。
ここまでは、オシロでの波形を見るだけだったが、いよいよモーターをつけて実際に動くかどうか確認する段階に来た。これまでのロジックICで組んだモーター制御基板のブレッドボードを取り出す。
うーむ、モータードライバーが負論理になっている。今度のプログラムは正論理だ。プログラムを負論理に換えるか、ハードを正論理に戻すか迷う。時間も遅い。ロジックICで作り直すことはもうないだろう。ハードの結線を正論理に戻すことにする。
配線図は書いていない。このあたりの配線間違いは致命的になる恐れもあるので慎重にピンアサインを確認する。何度か検証して通電する。いかん。MP4212が急速に暖かくなってきた。貫通電流だ。あわてて結線を確かめる。間違いはない。待てよ、負論理のプルアップ抵抗がそのままだ。これは必要なのか。
夜遅くで、頭が良くまわらないが、このままでは入力ラインに何もつながなければ、両方(前後進)が1になって貫通電流のパターンだ。入れてはいけない。そう言えば正論理のときに入れていなかった。
深夜も2時を回っている。朦朧としてきているのだが、乗り掛かった舟である。止めるわけにはいかなくなってしまった。プルアップした抵抗をブレッドボードから引き抜く。周りはジャンパーで一杯だが、モーターを回すところへ遮二無二突き進む。
ついに自作サーボ動く(5/10/2014)
深夜、蜘蛛の巣のようになったブレッドボードを通して、自作サーボがやっと動いた。動きは遅いし、静止状態でもモーターがジジジと唸るし、だいたい想定より回りすぎる(一回転以上)けれど、指定側の可変抵抗器の動きに応じて、モーターは所定のところまで回り止る。
いやあ、えらい時間がかかったけれど、曲がりなりにもサーボ制御だ。嬉しい。達成感で胸がふくらむ。今回もここまで大変だった。わずか1KバイトしかないTiny13にサーボ制御のプログラムを押し込むのに苦労した。何度もソースコードを書き換えた。
最初はタイマーの割り込みで入力をチェックするプログラムの構造にしたが、誤動作を避けて、入力ピンの割り込み駆動に変更した。しかし、割り込みと外部変数を使うとフラッシュが大幅に消費されることがわかり、タイマーの割り込みの方に戻した。
さらに前後進のパルス幅を増幅するステップの変数を減らすなど(ゲートを使って出力パルスを求めていたのを単なる変数の足し算にした。これでパルスが安定)、結局ソースは3回も書き換えた。
ちまちまと、コードを工夫しては、フラッシュの削減を確かめて喜ぶ。下らないとはいえ、この箱庭に小さなジオラマを作るようなコーディングは楽しい。Arduinoのようなものでは味わえない楽しさだ。
ソースコードとモータードライバー回路図の公開(5/14/2014)
ロジックICの回路図の公開は遠慮しておこう。これで組んでもモーターは廻らないからだ。そのかわりと言うのも何だが、MP4212のモータードライバーは正論理、負論理回路ともご紹介することにする。参考にしていただければ幸いである。
ただし、アナログに素人の所長考案の回路図である。全く自信はない。そのつもりで見ていただきたい。言うまでもなく完全な無保証である(FETが焼けても知りません)。しかし少なくとも両回路とも、ここでは問題なく快調にモーターが動いている。
もっとも、このあたりは間違えると、電源をいれただけで貫通電流が流れ、FETを焼いてしまうのでくれぐれもお気を付け願いたい。最初は、ポリスイッチ(大電流で遮断され、熱がさめると導通する)や、内部抵抗の高い電源(へたりかけの乾電池を直列にする)などで防御されることをお勧めする。ソースコードは例によってAVRStudioのフォルダーの形で公開する。
| 固定リンク
「AVR」カテゴリの記事
- ソフトI2Cはクロックストレッチまで手を出してあえなく沈没(2017.09.02)
- オシロのテストどころかソフト開発で大はまり(2017.07.26)
- 超音波方式の人感センサーI2C化と新しいオシロ(2017.06.29)
- motionの動体検知はRaspi3の電源が安定しない(2017.04.16)
- 赤外線学習リモコンはデータ再現で挫折したまま進まず(2016.07.21)
「電子工作」カテゴリの記事
- 生存証明2(2022.10.19)
- 生存証明(2022.01.23)
- パソコン連動テーブルタップの修理を諦めて自作(2021.02.16)
- 半年ぶりのブログ更新に漕ぎつけた(2019.09.19)
- 研究所活動は停滞したままでCCDカメラ顕微鏡導入など(2019.02.08)
コメント
続投で申し訳ありませんが、ハイサイドのp-mosのゲート充放電について参考になればと。
http://blog.goo.ne.jp/paramako/e/a1213c1a9b06a5b9038f2702349b157f
投稿: まこと | 2014年5月17日 (土) 22時36分
まことさん、こんにちは。コメントありがとうございます。
恥を忍んで回路図を公開しているのは、こういうコメントを期待してのことです。
どんどんおかしなところをご指摘ください。アナログの世界は奥が深いので、とても参考になります。
投稿: がた老 | 2014年5月16日 (金) 15時38分
こんばんは。いつも楽しく拝見しております。
さて最後のブリッジ回路ですが、p-MOSのゲートの放電が遅くなるかと思います。
FWD=Highのとき、p-MOSはQ2とR3で比較的高速にゲートに充電されますが、FWD=LowのときにはR8とR3を経由してp-MOSのゲート電荷が抜けていきます。R8が10kΩとかなり大きな抵抗ですので、p-MOSのターンオフのキレが悪くなってしまうかと思います。
スイッチング損失が大きそうなら10kオームの抵抗をもう少し小さくするか、ゲート放電のための回路を追加する必要があるかもしれません。
pMOSのスレッショルド電圧が低いと有効ではありませんが、こんな回路を使うことで、p-MOSのターンオフを少々早くすることができます。
http://blogimg.goo.ne.jp/user_image/15/e6/7e0510f2abed58897bfffa8208b9cbbd.png
MP4212のデータシート見ましたが、Vthが結構低いので、この回路では動かないかもしれません^^;
投稿: まこと | 2014年5月16日 (金) 01時38分