半日で作る倒立振子

254,128

33

191

Introduction: 半日で作る倒立振子

arduinoを使った工作を幾つかやった後、倒立振子の作成を思い立ちました。今回の方針は次の2つです。

  • 極力シンプルな構成
  • 自力で作る(webの先人に頼らない)


立たせるのにまるまる1週間以上かかりましたが、なんとか当初の方針を守りながら、上の写真の倒立ロボットを作りました(下の動画は動作のデモです)。

(*1)制御の方程式とジャイロのトラブルシュートはwebを参照しました
(*2)動画では9V電池に代えてUSB出力のバッテリでarduinoに給電してます

この倒立ロボットですが、構造、電装、スケッチ(プログラム)ともにとても簡素です。使用するセンサは1つだけ(200~400円)で、モータは普通に手に入る一番安いヤツでOKです。なのでarduinoでLEDを点滅させたことがあれば、あとは材料とプログラムさえ揃えば、半日もかからずに作ることができると思います。

それで作成後の感想ですが、倒立振子の作成は、ちょっと難しいパズルを解くのに似ているように思います。答えが分かってしまえば簡単、というかパズルの意味がないので、そこに注意して話を進めます。

*An English version of this instructable is available.

** 日本語版では幾つかのコンテンツ(※)が表示されないようです。その場合、ブラウザのアドレスバーに表示されているURLの末尾「?lang=ja」を削除して画面を更新してください。それでも上手く表示されない場合は、英語版をご覧ください。
(※:各ステップの代表写真下の参考写真、PDFファイルのアイコン等)

*** ジャイロをSTマイクロ社製のデジタル出力センサに代えた新バージョン「もう一つの倒立振子(デジタル版)※」と、これらの倒立ロボットを用いた「倒立振子の研究」をアップしました(2014年9月)。それに伴い、本バージョン(オリジナル版)の最後にステップ12を追加し、これの記事で使うスケッチのリンクを添付しています。(※Step.2の微細なはんだ付けが不要です)

Step 1: 材料をそろえる

(1)躯体

 タミヤの「楽しい工作シリーズ」を使用します。


(2)電装

  • arduino UNO
  • ブレッドボード(小)
  • ジャンパ・ケーブル(20本ほど)
  • モータ・ドライバIC(TOSHIBA TA7291P)を2個
  • ジャイロ・モジュール(秋月電子 K-04912
  • 単3電池を4本
  • 9V電池(006P形)
  • 電池ホルダ(単3×4本用)
  • 電池スナップを2個
  • 輪ゴム(数本)


材料紹介の動画(Step.1)


<補足>
ジャイロ・モジュールは個体のばらつきがあるようなので、2~3個買っておいた方が良いかもしれません。また最後に簡単に紹介しますが、モジュールを2つ使うと、倒立振子の動作が安定する気がします。

Step 2: 電装の準備

電装部品にピンとワイヤを取りつけます。

  1. モータにリード線を取り付ける(はんだ付け)
  2. ブレッドボード用のジャンパ・ケーブル(4本)を2つに切る
  3. モータと電池スナップのリード線(全部で8本)に、この切断したケーブルをはんだ付けする
  4. はんだ付けした箇所をテープで覆う(絶縁処理)
  5. 秋月電子製のジャイロ・モジュールにピンをはんだ付けする
  6. このモジュールのコンデンサ(C6)の両端を細いワイヤでつなぐ(はんだ付け)


作業の解説動画(Step.2)


■解説(1)
使用するジャイロ・モジュールは、村田製作所のジャイロ・センサ(ENC-03R)を2つ実装しています。今回使うのはこの内1つだけです。このセンサは単位角速度(1deg/sec)あたり0.67mVを出力(Vo)し、モジュールのオペアンプ(NJM2155)でこれを10倍に増幅して1番ピンから出力します(6.7mV/dig/sec)。

問題は、このモジュールに付けられた2つのフィルタの高い方(HPF)で、これが角速度の変化率(角加速度)を混入させます。そこでこのフィルタを無効にするため、モジュールのコンデンサ(C6:4.7uF)の両端をショートさせて角加速度の混入を回避します。
(*1)参考サイト1
(*2)参考サイト2

Step 3: 躯体の組み立て

タミヤの「楽しい工作シリーズ」を使って車体部分を組み立てます。

  1. ユニバーサルプレートにV字の切れ込みを作る(2か所)
  2. ユニバーサルアームセットのL字アングル(4個)をユニバーサルプレートに取り付ける
  3. ダブルギヤボックスを組み立てる(ギア比は114.7:1
  4. ダブルギヤボックスに付属モータ(2個)を取り付ける
  5. ダブルギヤボックスをユニバーサルプレートに取り付ける
  6. スリムタイヤセットの大径ホイールを組み立てる
  7. スリムタイヤをダブルギアボックスに取り付ける


作業の解説動画(Step.3)

Step 4: 電装の組み立て

電装部品を組み立てて、躯体に取り付けます。

  1. ブレッドボードにモータ・ドライバIC(2個)とジャイロ・モジュールを写真の通りに取り付ける
  2. ブレッドボードに輪ゴムを巻き、躯体のL字アングル(下の方)に取り付ける
  3. 上の配線図を見ながらブレッドボードにジャンパ・ケーブルを刺していく
  4. 配線図を見ながらブレッドボードに電池スナップ(単3ホルダに接続する方)のピン(2本)を刺す
  5. arduinoに輪ゴムを巻き、躯体のL字アングル(上の方)に取り付ける
  6. 配線図を見ながらarduinoにジャンパ・ケーブルを刺し、ブレッドボードと接続する
  7. 電池ホルダーに電池(4本)を入れる
  8. 躯体に輪ゴムを巻き、電池ホルダを取り付ける


作業の解説動画(Step.4)


■解説(2)
ここで作った倒立ロボットにはスイッチが付いていません。電源のON/OFFは電池スナップの接続/取り外しで行ってください。

Step 5: プログラムの書き込み

IDEを使ってarduinoにスケッチ(プログラム)を書き込みます。

  1. IDEに「MsTimer2」が見当たらない場合(上の写真参照)、ダウンロードしてインストールする(*追記:タイマを使わない簡素版(ver.2.0)を追加しました(2014/06/06)。こちらを使用する場合、MsTimer2は不要です) 
  2. arduinoとPCをUSBケーブルでつなぐ
  3. 電池ホルダに接続した電池スナップを外しておく
  4. 躯体を寝かせて静止状態にする
  5. 本ステップの最後にある「■サンプル・スケッチ(プログラム)」以下の内容を読む
  6. サンプル・スケッチを収めたpdfファイル「invertedRobot.pdf」(もしくは「invertedRobot_v20_noTimer.pdf」)をPCに保存して(*)、その内容を全てコピーし、IDEでarduinoに書き込む (* ブラウザで開いてコピーすると、スケッチの体裁が乱れて上手くいきません)


■解説(3)
倒立振子の制御は、モータの回転力の調整で行います。この調整は、振子の状態を表す4つの変数を使った簡単な数式で表されます。
モータの回転力= k1 × 躯体の傾き(角度)
          +k2 × 躯体の傾きの変化率(角速度)
          +k3 × 車輪軸の移動速度
          +k4 × 車輪軸の移動距離

ここでk1~k4は、これら4つの変数の重視の程度を表す定数です。末尾のpdfファイルのプログラムでは、72行目の長い式がこの調整式に相当します。倒立振子を立てるには、これら4つの変数を適切に評価するとともに、これらに掛る4つの係数の値を上手く決める必要があります。

ジャイロ・センサは、この式の2番目の変数(躯体の傾きの変化率)を計測し、これを電圧の高低で出力します。そして、この出力値をarduinoが積算することで1番目の変数(躯体の傾き)を評価します。

一方、3つ目の変数と4つ目の変数の評価は、モータもしくは車輪の回転速度を計測して行うのが標準的です。このため、ジャイロ・センサとは別のセンサ(回転計)か物理的なメータ(電流計やステッピング・モータ)を用います。

しかしここで作ったロボットは、ジャイロ・センサしか使っていないので、3番目と4番目の変数の評価が問題になります。末尾のpdfファイルのプログラムでは、76行目と77行目の式で、これら2つの変数の評価するのですが、とりあえずパズルとして空白にしています。

■解説(4)
もし、ここで紹介したジャイロ・モジュール以外のモジュールを使う場合、k1およびk2に相当する係数(プログラムの10行目と11行目)の値を変えてください。例えば、オペアンプ(NJM2155)をつけずにセンサ(ENC-03R)単独で使う場合、arduinoへの入力値は1/10になるので、係数k1とk2は10倍の値に変える必要があります。

■サンプル・スケッチ(プログラム)
まず下の「invertedRobot.pdf」もしくは「invertedRobot_v20_noTimer.pdf(*5)」をPCに保存し、これをadobe Reader等のアプリで開いてください。次にその中身(全部で3ページ)を全てコピーしてIDEに張り付け、下記の注記のようなミスプリを修正した上でarduinoに書き込んでください。

(*1)ファイルをブラウザで開いてコピーすると、スケッチの体裁が乱れます。必ずダウンロードしてからコピーしてください
(*2)72行目が切れている場合、次に置き換えてください
powerScale = ( kAngle * thetaI / 200 ) + ( kOmega * omegaI / 78 ) + ( kSpeed * vE5 / 1000 ) + ( kDistance * xE5 / 1000 ); //72
(*3)IDEやエディタにコピーすると、「//」の間にスペースが入る(「/ /」)ことがあるので修正してください
(*4)気温により動作が不安定になる可能性があります。夏期にバランスが上手くとれない場合、10~12行目の係数の値(45、85、57)を、それぞれ「52、95、53」あたりに変えてみてください(2014/06/06:追記)
(*5)「invertedRobot_v20_noTimer.pdf」はタイマ(MsTimer2)を使わない簡素版です。安定性も改善しているはずです(2014/06/06:追加)

(*6)Copyright (C) 2014 ArduinoDeXXX All Rights Reserved.

Step 6: 動作の確認

振子(倒立ロボット)の動作を確認します。

  1. プログラムの書き込みが終わったら、5秒ほど静止状態で放置する(写真①)
  2. その後、躯体を起こして電池スナップを接続する(写真②)
  3. 車輪が回転を始めるので、両手でその回転を止める
  4. 車輪を床に接地させ、躯体重心が車輪軸上に乗るあたりで、躯体が動かないように静止させる(写真③)
  5. ロボットが静止を確認すると、モーターの回転が緩み、「ミー」という小さなノイズがモータから出る
  6. そっと手を離し(写真④)、ロボットの上端を指で軽く押さえる
  7. この指を前後させ、ロボットが追従して動くことを確認する
  8. 押さえていた指を離すと、ロボットが少しバランスを取ろうとした後、転倒するのを確認する


作業の解説動画(Step.5~6)


■解説(5)
使用したジャイロ・センサは、躯体が動かない状態(角速度=ゼロ)での出力値が決まっていません。このためarduinoの電源を入れた後(もしくはリセット・ボタンを押した後)、躯体を寝かせたまま5秒ほど放置してください。この間に静止状態での出力値を評価します。

■解説(6)
解説(5)の後、躯体を起こすと角度の変化を感知して車輪が回転し始めます。そこでロボットに、倒立時の標準的な姿勢(角度)を覚えさせる必要があります。このロボットは、躯体が0.05秒間静止していたら、その時の角度を標準とするようプログラムされています。

したがって、躯体を起こして車輪が回り始めたら、両手でロボットの下部を持って車輪の回転を強制的に止め、Step.6の4段目以降の操作を実行してください。

なお、しばらく静止させてもモーターの回転が緩まない場合、解説(5)の評価が上手くいっていない可能性があります。この場合、arduinoのリセット・ボタンを押して車輪の回転を止め、躯体を寝かせて静止させた後、再度リセット・ボタンを押してからStep.6を再実行してください。

■トラブルシューティング(1)
躯体を起こしても車輪が回転しない場合、もっとも疑われるのは配線の誤りです。Step.4に戻って慎重に確認して下さい。あと考えられるのはジャイロ・モジュールの不良です。私が最初に使ったモジュールはVccとGNDが短絡しており、配線をつなぐたびにarduinoとPCの接続が切れました。

また、車輪は回っても指の動きに追従しない場合、もっとも疑われるのは、モータのリード線もしくはジャイロ・モジュールの配置が逆になっているケースです。さらに、モータ・ドライバICとarduinoのデジタル・ピンの配線に誤りがあるケースもこれに準じます。Step.4に戻って慎重に確認してください。

Step 7: パズルを解く

転倒振子から倒立振子になるための壁をスケッチ(プログラム)の修正でクリアします。

  1. ロボットが転倒する理由を考える
  2. Step.5のプログラムに修正を加えて、転倒が防げるかどうか試す
  3. 試行錯誤が上手くいけば、転倒振子から倒立振子に脱皮して完成! (おめでとうございます)
  4. 完成したらStep.8を覗いた後、Step.9のロボット操作を試してみる
  5. 試行錯誤が上手くいかなかったら、「1.」に戻るかStep.8(解答案)を見るかどうか悩む

Step 8: パズルの解答案

プログラムを修正して、振子を倒立させます。

  • Step.5のプログラムの76行目と77行目を次の3行に書き換える(上書きする)

vE5 = sumPower; //76a
xE5 = sumSumP / 1000; //77a
// Copyright (C) 2014 ArduinoDeXXX All Rights Reserved.

  • Step.6を実行する(8行目以降の指による支持は不要)
  • 手で静止させた状態で躯体の重心が車輪の軸上に近いところにあれば、ロボット(振子)は前後に少し往復した後で倒立状態に移行する
  • 振子がバランスをとりながら倒れないことを確認する
  • 振子がバランスを取りながら、少しずつ移動していく場合、74行目の「power」の後に、適当な数値(1~5程度の整数)を足し引きしてみる


作業の解説動画(Step.8)


■トラブルシューティング(2)
Step.6をクリアしたにもかかわらず、振子が倒立せずに倒れてしまう場合、まず電池(単3×4本)を新しいものに換えてみてください。それで解決しない場合、Step.5のプログラムの10行目から13行目の数値を変えてみてください。この内、最も効果があるのはたぶん12行目の数値だと思います。

Step 9: シリアル・モニタを使った振子の操縦

シリアル・モニタを使って、振子の向きと前進/後退の操縦を行います。

  1. Step.8で修正したプログラムに後述の修正(4か所)を追加する
  2. 追加修正したプログラムをIDEでarduinoに書き込む
  3. 書き込みが終了したら、IDEからシリアル・モニタを起動する
  4. シリアル・モニタの右下を確認し「LFのみ」「115200 baud」に変更する
  5. 5秒ほど振子を放置する
  6. Step.6を実行して振子を倒立させる(8行目以降の指による支持は不要)
  7. シリアル・モニタの上部の入力窓に、0〜3の数字を入力して送信ボタン(もしくはEnterキー)を押す
  8. 振子の姿勢や動作が変わることを確認する


作業の解説動画(Step.9)


■解説(7)
シリアルモニタを使って、振子を回転させたり前後に移動させたりします。例えば、「00」と入力すると、「0」を2回入力したことになり回転幅が大きくなります。
・右回転・・・「0」を入力
・左回転・・・「1」を入力
・前進・・・「2」を連続して入力すると前方向に加速します
・後退・・・「3」を連続して入力すると後方向に加速します

■スケッチ(プログラム)の追加修正(4か所)

(1)Step.8で修正したプログラムの17行目と18行目(*)の間に、次の5行を追加(コピー)する (*行番号は、Step.5のpdfファイルで各行右側に付記している行番号(//xx)に準じます)

volatile int drct = 0;
volatile boolean right = false;
volatile boolean left = false;
volatile int fwdBck = 0;
// Copyright (C) 2014 ArduinoDeXXX All Rights Reserved.


(2)さらに元のプラグラムの32行目を削除し、代わりに次の26行を追加(コピー)する

if ( Serial.available() ) {
drct = Serial.read();
Serial.println(drct);
}
if( drct == 48 ) { right = true; }
else if ( drct == 49 ) { left = true; }
else if (drct == 50 ) { fwdBck++; drct = 0; }
else if (drct == 51 ) { fwdBck--; drct = 0; }
if ( right == true ) {
analogWrite( 6, 140 );
digitalWrite( 4, HIGH );
digitalWrite( 5, LOW );
analogWrite( 9, 140 );
digitalWrite( 7, LOW );
digitalWrite( 8, HIGH );
delay(40);
} else if ( left == true ) {
analogWrite( 6, 140 );
digitalWrite( 4, LOW );
digitalWrite( 5, HIGH );
analogWrite( 9, 140 );
digitalWrite( 7, HIGH );
digitalWrite( 8, LOW );
delay(40);
} else if ( power > 0 ) {
// Copyright (C) 2014 ArduinoDeXXX All Rights Reserved.

(3)さらに元のプラグラムの55行目と56行目の間に、次の4行を追加(コピー)する

drct = 0;
right = false;
left = false;
// Copyright (C) 2014 ArduinoDeXXX All Rights Reserved.

(4)最後に元のプラグラムの74行目を削除し、代わりに次の2行を追加(コピー)する

sumPower = sumPower + power + fwdBck * 4; // 74a
// Copyright (C) 2014 ArduinoDeXXX All Rights Reserved.

Step 10: USBケーブルの切り離し

arduinoの電源を電池に代えて、倒立振子を完成させます。

  1. arduinoからUSBケーブルを抜く
  2. 2つ目の電池スナップに9V電池を接続する
  3. この電池をロボットの背部に、電池ホルダと共に輪ゴムで取り付ける
  4. この電池スナップのプラス側の線をarduinoのVinピンに刺す
  5. この電池スナップのマイナス側の線をarduinoのGNDピンに刺す
  6. 電池ホルダー(単3×4本)に1つ目の電池スナップが接続されていれば、車輪が回転し始める
  7. Step.6を実行して振子を倒立させる(完全な自立)
  8. 完成


作業の解説動画(Step.10)

Step 11: 発展

完成したロボット(倒立振子)を改良してみましょう。(二つ目の改良まで半日で行うのは、さすがに難しいと思います)

(1)ジャイロ・モジュールを追加

ジャイロ・モジュールをもう一つ追加して、倒立の姿勢や操縦の安定が改善するか確認します。

確認動画(Step.11-1)



(2)無線で倒立ロボットを遠隔操作

部品点数を増やさないようにテレビの赤外線リモコンを使います。

操縦動画(Step.11-2)



(3)Excelでシミュレーション

振子を車輪と胴体と頭の3つに簡略化して考えると、高校物理の範囲で運動方程式が書けます。これもパズル感覚ですが、運動方程式が書ければ、Excelでシミュレータを作れます。Step.5の2つの係数(k1とk2)の大きさは、これで概略あたりを付けることができます。

Step 12: 「もう一つの倒立振子(デジタル版)」と「倒立振子の研究」の資料

使用するジャイロ・モジュールとモータ・ドライバーICを変更した別バージョン(改良版)を、別のインストラクタブルとして追加しました(2014年9月)。そのステップ5で用いる2つのスケッチを収めたpdfファイルを添付します。

  • invertedRobot_v20d_noTimer.pdf
  • digtlGYRO_L3GD20_SPI_recover.pdf


さらに同月、これらの倒立ロボットの動作を分析し、PC上で「仮想振子」を描く方法を、「倒立振子の研究」のタイトルで別途投稿しました。そのステップ3ステップ9で用いる2つのケッチを収めたpdfファイルも併せて添付します。

  • virtualPendulum_processing.pdf ・・・ Processingのスケッチ
  • invertedRobot_v21d_crrnt_accl.pdf ・・・ Arduinoのスケッチ

なお、これらpdfファイルのアイコンが表示されない場合、アドレス・バーのURLの末尾の「?lang=ja」を削除して、ページを更新してください。

1 Person Made This Project!

Recommendations

  • Maps Challenge

    Maps Challenge
  • Summer Fun: Student Design Challenge

    Summer Fun: Student Design Challenge
  • First Time Author Contest

    First Time Author Contest

191 Comments

0
pikapikamunyu5
pikapikamunyu5

5 months ago

しばらくこの記事について、いろいろ実験をしたり調べたりしてわかったことを書いていこうと思います。
matsumoto81さんと同じく、ジャイロモジュールの「角加速度成分の混入」についての疑問があったので、次のような実験を行いました。ジャイロモジュールとarduinoをモーターに取り付けて一定角速度で回転させ、そのときのセンサ出力を調べました。通常のモジュール(HPFが有効)とコンデンサーC6を短絡させたモジュール(HPFが無効)で↓のグラフのような違いが現れました。モーターは一定の回転速度であるから、センサが角速度を検出しているのであれば0以外の値で一定となるはずですが、ほぼ0付近で振動していることがわかります。しかし、HPFを無効にすることで角速度を検出できていると言えそうです。つまり、このモジュールは「角加速度を強く検出してしまっている状態」にあるということがわかりました。おそらくHPFが除去したカットオフ周波数帯に、角速度に関連する周波数帯が含まれていたのではないでしょうか。(続く)

HPF.pngHPF無効.png
0
pikapikamunyu5
pikapikamunyu5

Reply 5 months ago

またロボットを作る際、なかなかうまくいかない状況が続いたため、センサ出力に問題があると考え調べたところ、matsumoto81さんと同じように、C6短絡後のセンサ出力が大きく落ちてしまっていることが確認できました。「説明通りに作ったのに倒立する係数が見つからない」という人はおそらくこれが原因ではないかと思います。出力電圧を調べるときのスケッチは次の通りです。また、そのときの配線図も載せておきます。

float g1,v_1;

void setup()
{
  Serial.begin(9600) ;
}
void loop()
{
  g1 = analogRead(A1);
  v_1 = g1/1023*5;

Serial.println(v_1);
delay(100) ;
}

このスケッチによりセンサG1についての出力電圧を調べることができます。シリアルモニタのビットレートを9600にして確認します。C6を短絡させてない状態だと、1.35~1.45[V]くらいの値をとりますが、短絡させた後は電圧が下がることがほとんどだと思います。私がロボットを倒立できたのは最低でも0.6Vくらいでした。これより低いと倒立が難しいと思われます。半田付けの仕方によって電圧はかなり変わってきます。きれいにできたと思っても低くなったりします(私は結局モジュールを8個くらい購入しました)。0.8VくらいのモジュールではkAngle=56,kOmega=178,kSpeed=53で倒立できました。また無効にしたHPFには周囲の温度変化の影響を除去する役割があるので、C6短絡後は温度変化に敏感になります(呼気をかけただけで大きく変化しました)。寒い部屋では電圧がどんどん下がっていくので、空調のもとで係数決定をおこなった方がよいと思います。また、同じモジュールでも日を跨ぐと電圧が変わっていることがあるので昨日倒立できたのに今日はできない、的なことがありました。ちょくちょく電圧チェックを行うのがおすすめです。
 この記事は大変興味深く、楽しい経験をさせていただきました。筆者に多大なる感謝をして、研究を終わろうと思います。ありがとうございました。

配線.png
0
ArduinoDeXXX
ArduinoDeXXX

Reply 5 months ago

こんにちは
丁寧な分析の御投稿、ありがとうございます。
拝読いたしましたが、こうして見るとアナログの機材はやはり面白いですね。

0
pikapikamunyu5
pikapikamunyu5

8 months ago

こんにちは。楽しく記事を拝見させていただきました。
step11で紹介されている画像のように、角度や角速度のデータをExcelで表示してありますが、これはSerial.print()で通信し、シリアルモニタに表示させたものを貼り付けているのでしょうか?
また、角度とモーターの回転の関係を探るべく、角度をモニタやプロッタで確認しようとしたところ、値の桁数が角度のものではなく困惑しました。Serial.print(thetaI);とコードに加えたのですがこの方法は間違っているのでしょうか。
素人質問で大変申し訳ありませんが、よろしくお願いします。

0
ArduinoDeXXX
ArduinoDeXXX

Reply 7 months ago

こんにちは
本記事Step11の冒頭にあるExcelのキャプチャ画像ですが、これは同ステップの(3)の運動方程式のシミュレーションを実行している様子です。
実際のセンサの計測値や各種変数の評価値の取得方法については、別の記事「倒立振子の研究」で解説しています。同記事のStep2~4を参照してください。
なお、同記事のStep3では3つの方法を紹介しています。そこに示した条件をクリアできるなら、PLX-DAQが使い勝手が良いと思います。
あと、角度の評価変数は「thetaI」ですが、単位はアドホックです。標準的な角度への変換については、使用しているジャイロモジュールの仕様書を参照してください。

0
pikapikamunyu5
pikapikamunyu5

Reply 7 months ago

返信遅くなりました。ありがとうございます!!

0
rk.ngym
rk.ngym

Question 10 months ago

初めまして。制御工学の勉学のため本サイトを参考にさせていただき工作を始めました。
Step6をトライした結果STEP6-3にて電池スナップ取り付けるとモータが回転するのですが、本体を立たせても回転をやめません。たまに回転をやめますが倒立動作はしません。手で本体をもって揺さぶるとその動作に反応するようにタイヤが回転します。
ジャイロの初期化の問題と思い、Analog Read(A5)のデジタル値を確認したところ静止中常に1010という値(ほぼ5V上限値)が表示されます。
一方もう一つジャイロセンサがあったので同じようにトライしましたが電池スナップ取り付け後に本体を立たせてもタイヤが回転しません。ただし手で本体を持ち空中で揺さぶるとタイヤが回転します。Analog Readは5という値(ほぼ0V)でした。
ジャイロの個体差とC6のはんだ付けの仕方が原因かと思われますがここまで違ってくるものなのかと不思議に思っています。工作を前進させるために大変恐れ入りますがご教示いただければ幸いです。

0
ArduinoDeXXX
ArduinoDeXXX

Answer 10 months ago

こんにちは
お話を伺う限り、ジャイロモジュールの動作不良のようですね。そうすると、同じモジュールを改めて購入する、もしくは、他のモジュールを購入するしかないと思います。
予算に余裕があれば、同じモジュールとデジタル出力のモジュールを2~3個ずつ購入すればいろいろ安心だと思います。なお、デジタル出力のモジュールは、私の別投稿の記事のモジュールを使えば、同記事で使い方を参照できます。
あと、同じモジュールを再購入する場合、まずはC6を無効化する前にモジュールの動作確認をすることをお勧めします。動作確認の方法は、本記事におけるmatsumoto81さん、tokumikatuさんのコメントを参照してください(後者のコメントを見るには、最下段の「More Comments」をクリックしてください)。

0
rk.ngym
rk.ngym

Reply 10 months ago

ご回答いただきありがとうございます。別の工作でジャイロを使用したとき293のデジタル値(約1.35V)を出力できていたためC6短絡時のはんだ付けの仕方が問題かと思います。ご紹介いただいたL3GD20Hを使用した工作にシフトして進めていきたいと思います。ありがとうございました。

0
tosihide333
tosihide333

Question 1 year ago

こんにちは。
私はこちらのサイトを参考に倒立振子を製作させてもらっています。
一つお聞きしたいことがあるので、質問してもよろしいでしょうか。

プログラムを入れて電池スナップを接続し躯体の上を押さえるとしっかりと追従して立とうとしてくれているのは伝わってくるのですが、タイヤの回転が速すぎて手を離した瞬間に自分でバランスをとろうとせずすぐに転倒してしまいます。プログラムの数値を変えたりして何度試しても転倒してしまいます。何が原因か分かりません。原因は何だと思いますか。

ちなみにジャイロセンサはショートさせたものが壊れてしまい今使用しているものはショートさせていません。

教えて頂けるとありがたいです。

0
ArduinoDeXXX
ArduinoDeXXX

Reply 1 year ago

ここで使用しているジャイロ・モジュールは、角加速度が混入するのでコンデンサのショートは必須です。詳しくは先にコメント頂いたmatsumoto81さんとのやりとりを参照してください。

なお、ジャイロ・モジュールをデジタル出力のセンサに代えた別バージョンも紹介しているので、コンデンサのショートが面倒ならば、こちらを参照してください。

0
matsumoto81
matsumoto81

1 year ago

このサイトを参考にさせていただき、無事に倒立振子を製作することができました。ありがとうございました。
製作に当たっての私の感想などを投稿いたします。
◯ハード:使用部品は全てこの記事と同じ。
◯使用スケッチ:invertedRobot_v20_noTimer.pdf
◯k1~k4の値:
10行目〜13行目
 kAngle = 50;//10
 kOmega = 90;//11
 kSpeed = 58;//12
 kDistance = 60;//13
このサイトの記事に魅了され、今年初めに1台作りました。当初自分にできるのか自信がなかったので、できる限りハードやスケッチを記事通りに製作することを心掛けました。また、スケッチもできるだけ自分なりにかみ砕いて理解するよう努めました。その結果、一ヶ月ほどでなんとか倒立できました。しかし、偶然倒立した感がぬぐえず、再度作っても倒立させる自信がありませんでした。そこで高校生たちと一緒に同じものを作り、自分の疑問をその中で解決することにしました。その結果、その後6台製作し全て倒立させることができました。この時はやっと確実に倒立させる自信がつきました。この時の私の疑問とそれを解決したデータを投稿します。
私の最大の疑問は今回の中心部品であるジャイロモジュールについてでした。
ジャイロに関する一つ目の疑問はジャイロセンサ(ENC-03R)のC6を短絡しないときのジャイロの静止状態の出力電圧が約1.45v(電源電圧5v)ですが、C6短絡時に静止状態の出力電圧が12個のサンプルで(0.02v、0.02v、0.87v、1.45v、2.08v、2.39v、2.42v、2.55v、2.68v、2.91v、3.37v、3.75v)のように異なる値になり、これらの電圧で倒立振子ができるのかということ。
結論からいうと0.02vのジャイロは上への変動はあったが下への変動がなく倒立できませんでした。0.8vから3.75vでは上下とも変動があり倒立できました。ただし、何故静止状態の電圧が一定の値でなく個々に異なる値になるのかは最後まで不明なままです。
ジャイロに関する二つ目の疑問は記事の中でジャイロセンサ(ENC-03R)のコンデンサC6を短絡させて角加速度の混入を回避するとありましたが、角加速度の混入がどういう状態なのかということ。
これを定量的に把握したかったので本サイトの過去ログを全て拝見しました。
その中でArduinoDeXXXさんがIWAOKOさんやtokumikatuさんと対話した記事が参考になりました。この記事をもとにC6短絡無しとC6短絡有りの2つのモジュールを同一ボード上に配置して、縦向きジャイロの角速度をarduinoで同時に測定し、それをexcelでグラフ化し比較しました。(グラフを添付しました)
その結果、C6短絡有りのモジュールは「後傾→停止」で山が、「前傾→停止」で谷がきれいに描かれました。一方、C6短絡無しのモジュールは常に谷と山が混在し出力が不安定な様子が描かれました。これが角速度の中に角加速度が混入している状態だと理解できました。結論として、C6を正確に短絡し静止状態の電圧が0.8vから3.75vとなっても、グラフのような特性が得られれば確実に倒立できることがわかりました。なお、C6短絡無しのモジュールで実際に倒立を何度か試みましたが、(HPFの影響で角加速度が混入し)倒立はできませんでした。
自分なりの解釈と考察で間違っているところがあるかもしれません。ご指摘頂けるとありがたいです。よろしくお願いします。

Image2.jpg
0
ArduinoDeXXX
ArduinoDeXXX

Reply 1 year ago

こんにちは
詳細な報告ありがとうございます。高校生と一緒にいろいろ試すの良いですね。
秋月さんのジャイロ・モジュール(K-04912)は発売が8年以上前なので結構扱いにくかったりします。
(今や9軸のデジタル・センサ・モジュールが800円で売られていますし)
秋月さんのサイトのデータ・シートを見ると、モジュールのHPFは村田のジャイロ・センサの温度ドリフトを除去する役割があるようです。なので、HPFをキャンセルする前の静止時出力を見てみてはいかがでしょうか。
秋月さんの資料では、静止時の出力は1.35Vとのこと。なので、これとの乖離が大きいようなら、モジュールもしくはセンサの不良を疑う、と言うことになりそうですね。
あと添付のグラフですが、横軸の630~670あたりが分かり易いと思います。上のグラフの各速度は谷になっていますが、下のグラフでは、動き始めに下方スパイク、停止時に上方スパイクが見られます。これは各加速度の混入に拠るものと考えられます。

0
matsumoto81
matsumoto81

Reply 1 year ago

ご意見ありがとうございました。今回はこのサイトの記事通りできるだけ忠実に製作することを心掛けました。ジャイロモジュールを初めて扱ったのでいろいろ勉強になりました。今後はこれに改造を加えて発展させていきたいと思っています。このような機会を提供していただき感謝しております。

0
hana2018
hana2018

2 years ago

こんにちは,こちらのサイトを参考にさせていただき倒立振子を制作しました.
無事に倒立振子は立ってくれたのですが
プログラムの処理で数箇所よくわからない点があったので質問してもよろしいでしょうか

1.積分処理
thetaI = thetaI + omegaI; や sumPower = sumPower + power;
となっているのですが,例えば簡単な矩形の掛け算で
thetaI = thetaI + omegaI*サンプリング時間
としなくても良いのは何故なんでしょうか
omegaIが既に角度情報として取得されているのでしょうか

2.recOmegaIの取得タイミング
recOmegaI[0]は
recOmegaI[0] = omegaI;で取得していることがわかるのですが
recOmega[i] (i=1,2...9)はどの箇所で取得されるんでしょうか

3. recOmegaの役割
2.の質問に関連するかもしれませんが,recOmegaの役割がよくわかっていません
chkAndCtl内でomegaIを保存するような変数かなと思っているのですが...

宜しくおねがいします

0
ArduinoDeXXX
ArduinoDeXXX

Reply 2 years ago

こんにちは
ご質問、Step5の「invertedRobot_v20_noTimer.pdf」に基づいて回答しますね。

1.積分処理
角速度の離散サンプリングで、i回目とi+1回目の経過時間をΔT_iとすると次のような角度の評価値を考えることができます。
・角度の評価値θ=初期値θ_initial+Σ(過去の角速度の評価値ω_i × ΔT_i)
この時、初期値θ_initial=0で、ΔT_iの値がiによらず安定している(ΔT_i=ΔT)としたら、このθは次のように書けます。
・角度の評価値θ=ΔT×Σ(過去の角速度の評価値ω_i )
一方、Step5の「解説(3)」の制御の方程式では、この角度の評価値θに対して適当な係数k1が乗じられます。サンプル・コードでは、72行目のkAngle/200が、k1×ΔTに相当します。

2.recOmegaIの取得タイミング
角速度の評価履歴はサンプル・コードの71行目で更新しています。

3. recOmegaの役割
倒立振子が良いバランスを取ると、角速度はゼロもしくはゼロに近い数値になります。サンプル・コードではこの状態の角度評価値θをゼロにリセットして、誤差の累積による評価ドリフトをキャンセルしています。この時、角速度の評価値にノイズがなければ評価履歴は不要ですが、ノイズがあると一定のフィルタリングが必要になります。サンプル・コードでは、これらの機能は60行目から70行目で実装されています。

0
hana2018
hana2018

Reply 2 years ago

返信ありがとうございました
できる限りブラックボックスを作りたくなかったので助かりました
もう少しプログラムを眺めてじっくり考えてみたいと思います

0
MichiK2
MichiK2

3 years ago

ArduinoDeXXXさま、

このサイトを参考にさせていただき、10秒〜2分程度の倒立振子を製作することができました。感動しました。ありがとうございました。

製作に当たっての私の場合のテータなどを投稿いたします。

◯ハード:使用部品は全てこのページのものと一緒。

◯ハード変更箇所:9vの電池を、単3電池の上に並べて取り付けた。また、Step 11 のように ジャイロ・モジュール(秋月電子 K-04912)を2つ使用した。

◯使用スケッチ:invertedRobot_v20_noTimer.pdf

◯スケッチ変更箇所1:

10行目〜12行目(実験時の気温22度、湿度22%)

 kAngle = 60;//10

 kOmega = 166;//11

 kSpeed = 60;//12 (結果的に元の値と同じ)

 kDistance = 60;//13 (ここは一切触らなかった)

上記の値は ±1 違っても上手く行きませんでした。また、各値(65〜69行目)をリセットする時間など、いろんな所をいじりましたが、結局初期のスケッチが一番安定的でした。

◯スケッチ変更箇所2:

51行目 zeroOmegaI = zeroOmegaI + (analogRead(A5) - analogRead(A4))/2 ;

58行目 omegaI = omegaI + (analogRead(A5) - analogRead(A4))/2 - zeroOmegaI;//NL5

◯ジャイロ・モジュール(秋月電子 K-04912)を2つ使用した理由

1つでは残念ながら、値をどういじっても倒立できませんでした。(2〜3往復ぐらいで倒れた)

そこでシリアルモニタで確認しながら調整を試みたところ、ジャイロ・モジュール(秋月電子 K-04912)からの値 analogRead(A5) が全く触らない状態で zeroOmegaIから+2ずれるという原因不明の現象(おそらくarduino側の問題?)に遭遇しました。

( omegaI = omegaI +analogRead(A5) - zeroOmegaI;//NL5 の omegaI の値が静止状態で 2 の値を取る)

このズレを解消する(相殺する)ために、Step 11 のように逆向きにもう一つ取り付けました。

◯その他の不具合・発見など

1.何度も何度も倒れた衝撃で、ジャイロモジュールが片方の角速度にしか反応しなくなってしまった。

2.電池の減りがとても早い。1週間、立たせるために試行錯誤しただけでなくなってしまった(元々1.6v → 1週間後1.2v)。そしてこれも立たない原因の一つであった。

3.フローリングよりもカーペットの上のほうが安定する(私の心も)。

長々と書かせていただきましたが、とりあえず今後製作される方の参考になれば幸いです。

とりあえず、購入の際はジャイロ・モジュール(秋月電子 K-04912)は4つぐらい、電池は大量に買っておいたほうがいいかもしれませんね。

この「半日で作る倒立振子」はとても素晴らしい記事です。私のfacebookで紹介させていただきました。今後も面白い作品紹介をぜひよろしくお願いします。

IMG_3670.JPG
0
ArduinoDeXXX
ArduinoDeXXX

Reply 3 years ago

詳細な情報ありがとうございます。ご案内の諸点、その通りだと思います。

・ジャイロ・センサを2つにすると安定が高まる(センサ出力のノイズやバイアスを緩和できるので)

・フローリング床よりカーペット上の方が安定する(極端な話、砂や粘土の上に強く押し付けると、電池なしでも直立します。押したら倒れますが)

・電池が弱ると安定性が悪化する(いろいろ試すなら、エネループなどの充電可能な電池の方が割安だと思います)

・ジャイロ・モジュールは4つほど買っておくと便利だし安心

あと、「 omegaI = omegaI +analogRead(A5) - zeroOmegaI;//NL5 の omegaI の値が静止状態で 2 の値を取る」のは不思議ですね。ジャイロ・センサの出力にはバイアスがあるので、それを zeroOmegaI で評価して引き算でキャンセルしています。ArduinoのA5ピンに何らかのバイアスがあるなら、同ピンをGNDを繋いだプルダウン時の出力で確認できると思います。(zeroOmegaIに2を加えるという対症療法もありますが)

なお続編が2つありますのでよろしければご参照ください。

0
km-mental
km-mental

3 years ago

こんにちは。

サイトを参考に倒立振子ロボットを作らせて頂きました。

プログラムのことで、気になったところがあったので、この度コメントさせて頂きました。

プログラムの中にいくつか書かれている「delay」はどういった意味(効果)があり、入れられているものなのでしょうか?

Arduinoはおろか、電子回路初心者なため、わかっておりません。

ぜひ、ご教授お願いできないでしょうか?

よろしくお願いします。