プロが教える店舗&オフィスのセキュリティ対策術

現在二足歩行ロボットを製作しているのですが、ボディ剛性が低いのとモーターを増やしすぎた(RC用のサーボを26個使用しています)ためか、直立状態でも姿勢が安定しないことから、姿勢の安定化のためのフィードバック用にジャイロセンサを利用しようとしたのですが、多々の問題から上手く角度が算出できずに困っています。ジャイロセンサを扱った経験のある方がいらっしゃいましたら御指導願います。
マナーが悪くて恐縮なのですが、同様の質問を下記のURLでしています。
http://oshiete1.goo.ne.jp/qa4561017.html
上記のURLでいただいたアドバイスを元に、現在はサーボ1個をジャイロを動かすために使用し、マイコンのA/Dで値を取得してexcelで計算という作業を繰り返しています。

開発環境は下記の様になります。
・ジャイロセンサ
→村田製作所製圧電振動ジャイロENC-03R(秋月電子製圧電振動ジャイロキットをそのまま使用し、オペアンプの出力をマイコンのA/Dに直結)
印加電圧:3.38V(マイコンに印加している電圧をそのままセンサに分岐)
静止時出力:約1.41V(たまたまかもしれませんが手元にある2個のジャイロキットは大体これ位出力しています)
・マイコン
→SH7144F(秋月電子製SH7144Fマイコンボード(12.5MHz))
クロック設定PΦ=25MHzシングルチップモード
・コンパイラ
→GCC

・現在行っていること
(1)SH7144のA/Dを10bit、PΦ/8で連続スキャンモードにし、CMTを8msec(センサの応答20msecの2.5倍でサンプリング)で割り込みさせてA/Dの結果をUARTでPCに出力。
(2)UART割り込みでサーボを90°回転。このときサーボ回転開始時と停止時に"S"と"E"をPCに出力し、サーボの回転時間を計算できるようにしておく。
(3)SH7144からのUART出力をPCのハイパーターミナルでテキストキャプチャして結果をexcelに入力。
(4)excelにてA/Dの結果→電圧→角速度→角度を計算。同時にサーボの回転時間と角度から平均角速度を算出して比較。

現在抱えている問題
(1)角速度計算結果について
今回使用しているジャイロキットの場合、角速度を求める式は下記の式であっているでしょうか?キットの回路は村田製作所から出ている増幅回路例と同じです。
ENC-03Rのカタログ
http://​www.murata.co.jp/catalog/s42.pdf​
角速度=(A/D出力-静止時出力)*(3.38/1024)/(感度*ローパスフィルタの増幅度)
※静止時出力=静止時のA/D出力をあらかじめメモして代入
 感度=0.00067[V/deg/sec]
 ローパスフィルタの増幅度=10[倍](カタログの回路図より直流増幅度)
参考URL
http://okwave.jp/qa3523603.html?ans_count_asc=0
http://www.hokutodenshi.co.jp/PUPPYSupportPage/s …

(2)センサーからの出力について
・他の人のホームページを見た感じのセンサの出力
        
                /\
              /    \
↑センサ出力    /       \
静止電圧___/           \
                         \/ ̄ ̄ ̄
    →時間
参考URL
http://tkstechnology.web.fc2.com/robot/system/en …
・私の持っているジャイロキットの出力
        
                /\
              /    \
↑センサ出力    /       \
静止電圧___/           \
                         \       / ̄ ̄ ̄
                           \    /
                            \  /
                             \/
    →時間

上記のような出力のせいか、積分の式が間違っているのか、または別の問題か積算していくうちに角度の計算結果が0付近に戻ってしまいます

(3)積分について
数値積分の表記は下記のようであっているでしょうか。
C風表記
kakudo = kakudo + (kakusokudo_s + kakusokudo) * (t / 2);
kakusokudo_s = kakusokudo;
(上記をタイマで繰り返す)
※kakudo:角度(初期値0)[deg]
 kakusokudo_s:一回前のサンプリング時の角速度(初期値0)[deg/sec]
 kakusokudo:サンプリングした角速度(初期値0)[deg/sec]
 t:サンプリングタイム[sec]
excel風表記
角度 = 1セル前の角度 + (1セル前の角速度 + 角速度) * (サンプリングタイム / 2)
(2)の問題で、時間がたつにつれて計算結果が0付近になってしまうのも問題なのですが、サンプリングタイムに0.008[sec]を代入しても、角度の値が出てこなくて困っています。

A 回答 (4件)

ANo.2,3です。


製作お疲れ様です。長文のお礼をありがとうございます。
私もいつか2足歩行ロボットに挑戦したいとは思いつつ、今の私の知識では難しいことが多く、いただいたお礼に応えられそうもありません。

ただ、お礼を読ませていただいてフト思ったことがあります。

私の場合はロボットの進行方向を制御させる上で機体が現在どの方向を向いているかを知る必要があったので、ござは承知で角速度を積分してヨー角を計算させたわけです。

ですが、質問者さんは2足歩行ロボットの姿勢制御用にジャイロを使いたいわけですよね?ロボットがふらついた時にシャンとさせる、あれですよね。

だとしますと、わざわざ回転角度の絶対値まで計算させる必要があるのかな?と思った次第です。
むしろ瞬時の角速度信号をそのまま(もちろん最適の係数はかけるとして)サーボにフィードバックしてやればよいのでは?とおもうのですが、いかがでしょう。

それでしたら、ジャイロ出力回路は回路例のままでハイパスフィルタを入れておいたほうが良いと思います。出力のドリフトや低周波ノイズもカットできますので。ANo.3は余計なアドバイスだったかも知れません。すみませんでした。

私自身には知識がありませんので、どこか参考になるサイトは無いかと探してみたところ、tks_technology と言うサイトで
  http://tkstechnology.web.fc2.com/index.html
さいとーさんという人がROBO-1出場めざして2足歩行ロボットを作っている製作日記を見つけました。回路図などの詳しい記載はありませんが、製作日記diaryの0601~0602あたりが参考になるかも知れません。

そこには、ジャイロセンサ(ムラタENC-03M)をどう使うかを悩んだあげく、
「どうやら難しく考えすぎていたようだ。
 ただ単に角速度が生じたら逆の角速度を生じさせるだけでよかった。」
とありました。なにか参考になりますでしょうか。

参考URL:http://tkstechnology.web.fc2.com/index.html

この回答への補足

毎度遅い返答にも回答いただきありがとうございます。
依然として結果を出せていないのですが、頂いたアドバイスを自分なりに理解した次第なので、合わせてご報告いたします。

>だとしますと、わざわざ回転角度の絶対値まで計算させる必要があるのかな?と思った次第です。
むしろ瞬時の角速度信号をそのまま(もちろん最適の係数はかけるとして)サーボにフィードバックしてやればよいのでは?とおもうのですが、いかがでしょう。
>「どうやら難しく考えすぎていたようだ。
 ただ単に角速度が生じたら逆の角速度を生じさせるだけでよかった。」

教えていただいたHP以外にも、サーボに角速度を直接フィードバックしている事例がいくつかあったのですが、これがどういった意味を持つのか理解できず苦しんでいたのですが、多分下記にあるような解釈だと理解しました。

→離散的処理の中では、サンプリングした角速度のデータはそのままでは角速度の瞬時値であるが、サーボのフィードバック値として使用する場合、サーボの指示角をフィードバック値で上書きしている限りサーボ指示角に対する偏差の意味合いを持つ。

・先日苦し紛れに書いたコードから上記の例を示します。
計算後サーボ指示角 = 現在のサーボ指示角 - ゲイン * 角速度のデータ
離散的処理の場合、ゲインの中には自然と時間項が含まれることになりますので角速度のデータはサーボ指示角に対する偏差として扱われると理解しました。つまり上記の式はサーボの指示角に対するP制御を行っていることとなり、実際上記の式でそれっぽい挙動を確認することができました。

現在問題となっているのは、フィードバックはされているものの、制御そのものが上手くいっていない状況です。(応答が遅すぎて姿勢の変化にサーボが追従できていない)これは、フィードバックをPIDに拡張したり、センサーの移動平均量・サンプリングタイムの見直し、制御時間の見直し(今朝確認したところ、サーボへの角度指示が20msecなのに対し、フィードバック制御は42msecで行っていました。これでは制御になりませんね(泣))等々で、何とかなるような気がします。

最後にひとつ質問がありますので、まだご観覧していただけていたら、御教授頂けると幸いです。

>それでしたら、ジャイロ出力回路は回路例のままでハイパスフィルタを入れておいたほうが良いと思います。

手持ちの回路がこれ以上手を入れると壊れそうなので試せていないのですが、ハイパスフィルタを入れると以前のように微分回路の影響でセンサーの出力波形が崩れ、そのままフィードバックすると振動に繋がる印象があるのですが、その辺どうなんでしょうか。
よろしくお願いいたします。

補足日時:2009/01/18 11:44
    • good
    • 0
この回答へのお礼

依然回路面での問題が解決できずにいますが、センサーの取り扱いに関しては大まかな方向が固まってきたので、質問を締め切ろうと思います。ありがとうございました。

お礼日時:2009/01/27 17:27

ANo.2です。

補足させていただきます。

> (2)センサーからの出力について

についてですが、質問者さんのジャイロキットのセンサ出力電圧がいったん山になって次に谷になった後にゼロに戻っていますね。これは変です。

これの原因として最初に思いついたのは、センサの振り角がきれいにステップ状になっていないのでは?つまり、目標角度を通り過ぎてから戻るような動きをしているのでは?ということでしたが、ENC-C3Rのカタログを見てみると、
 (貼り付けたURLはエラーのため見られませんでしたので、
  http://www.murata.co.jp/products/catalog/pdf/s42 … を探し出しました)
回路例にはハイパスフィルタが入っていますね。

この回路通りに作っているとすると、これのために出力の直流成分がカットされた結果、問題の出力波形になるのではないか?と思われますが、いかがでしょうか。

ハイパスフィルタの部分を外してみることをお薦めします。

この回答への補足

御教授ありがとうございます。
文字数の関係で補足で失礼します。
返信が遅くなり申し訳ありませんでした。
返信が遅くなったのは、やっぱり納得できる結果が出てないせいです。(泣)

> (2)センサーからの出力について
御指摘の通りハイパスフィルタをはずしたところ、出力の谷が消え、角度の計算ができるようになりました。ありがとうございます。

しかし、依然としていくつかの問題が解決できず困っています。
(1)回路の出力が??
現在の回路構成を下記に示します。
   +3V
   │ENC-03R             OPアンプ1
   │┏━┓4            ┏━━┓     
  3├┨  ┠────────┨+   ┠┬ ─ ──→ AD
  C ┃  ┃1          ┌─┨-   ┃│
  2├┨  ┠─┐       │  ┗━━┛│
   │┗━┛  │      ├── R2 ─-┤
   │     │  ┌  R1 ┴── C1 -┘
   │     │   │   OPアンプ2
   ┷      │   └────────┐
  GND     │        ┏━━┓   │
          VR←──-─┨+   ┠┬┘
          │      ┌┨-   ┃│
          │      │┗━━┛│
          ┷       └────┘
R1:91k
R2:91k
C1:1800p
OPアンプ1:NJM2115D
OPアンプ2:LM324
(VR、OPアンプ2、R2は別基板で、キットの100k抵抗のVref側からバイパスしてVRに入力、R2の出力をOPアンプ1の-側にバイパス)
上記の回路構成にしたのは、ジャイロキットを2枚使って3軸構成にしているのですが、当初ハイパスフィルタをはずしたところENC-03RD-R側の出力が出ませんでした(このときのR2は10k=増幅度9.1倍)。ENC-03RD-RのVoutを確認したところ1.2V位だったことと、ローパスフィルタの回路は差動増幅の形を取っていることから、Vrefを調整できるようにしました。すると今度はENC-03RC-R側の出力が3V位まで振り切ってしまいました(この時点でも増幅度は9.1倍)。このときのENC-03RC-RのVoutが1.6V位であったので、増幅度の問題だと思い、R2を91k(増幅度1倍)にしました。
こうして、現在の回路構成になったのですが、ENC-03RC-R側の出力が1.8V位~3.3Vでしか可変できない状態です。増幅度が1倍なら、0V近くまで可変してもいいと思うのですが、回路の解釈が間違っているのでしょうか。現在は一応静止電圧2Vに調整して、Voutもジャイロの回転に従って変化しているので、使えてはいるのですがいまいち納得できない状態です。
(2)ジャイロセンサーの出力自体が??
現在のジャイロセンサーの静止時出力を下記に示します。3軸構成なので3個分です。
         Vout     Vref
ENC-03RC-R(1):1.58V  1.35V
ENC-03RD-R: 1.44V  1.36V
ENC-03RC-R(1):1.58V  1.35V
ENC-03RD-Rの静止時出力が(1)で書いていたのと違うじゃん!と思われるかもしれませんが、実際こんなんなんです。何度か測っていたのですが、1.2Vを示したのは最初の1回だけで、回路を作ってみたあとは1.35Vを下回ることはありませんでした。温度ドリフト?なんですかね。
なので、現在の回路の静止時出力は3軸とも1.8V位~3.3Vでしか可変できない状態です。なんか納得できない(泣)。
(3)結構温度ドリフト無視できない
最初静止時の出力を定数で書いていたのですが、暖房つけたり消したりしながらコードを書いていると、いつまでたっても出力のオフセットが消えない。仕方がないので、スタートアップ時にセンサの静止出力の平均を取って、それを使っています。コードをNo.2に示しますので、参照いただければ幸いです。
(4)CW時の感度とCCW時の感度が違う
単純に感度が違うだけなら良いのですが、温度ドリフトや線形性の問題も重なってか、毎回微妙に角度が違います(泣)。

結果としては、±90°の回転を繰り返すと、一回90°回すたびに3°位ずれていく感じ+時々はいるノイズの積算で、5回位動かすと+20°か-20°位でずれて、その後は繰り返すたびにだんだん±どっちかに発散という感じです。また何かアドバイスor突っ込みがありましたら、大歓迎ですのでよろしくお願いいたします。

補足日時:2009/01/08 11:36
    • good
    • 0

以前、左右2輪駆動式の自立移動ロボットを試作した時に、機体の水平回転角を検出するために電子ジャイロ(HS-EG3ツカサ21)を使ったことがあります。

マイコンはH8/3048Fを使いました。

だいぶ前のことなので細かいところは忘れてしまってますが、だいたい次のようにしてうまくいきましたのでご参考までに。

角速度センサの出力Vout(V)から回転角ψ(deg)を求めるには下記のような式を使いました。

角速度瞬時値dωを
 dω=(Vout-V0)*1000/Rg
  ただし
   Vout:角速度センサの出力、
   V0:ゼロ点オフセット(=2.48V),
   Rg:ジャイロ出力係数(=25mV/deg/sec)
として求め、計測のサンプリングタイムdtを乗じた値を前回までの総和に加えて、

 ψ= Σdω*dt (deg)

として回転角ψ(deg)を算出します。

実際のプログラムの一部を下に示します。10ms毎に実行する割込ルーチンの中で現在角度を計算させて逐次グローバル変数に格納し、メインルーチンの中で必要に応じてこの変数を読み出すようにしました。
 なおここでは
 TURN_ANG:角度値(グローバル変数)
 GYR:ジャイロセンサ出力をADCで取り込んだ数値
 d_rotat_deg:微少機体回転角
としています。D_Tは割り込みタイミング(10ms)です。

=============(タイマ割込ルーチン)=================

/*---------機体回転角算出------------------*/
/* d_rotat_deg=GYR*VREF*1000/ADC_RATE/GYRO_RATE - V0*1000/GYRO_RATE */
d_rotat_deg = (float)GYR * 0.196 - 99.2;
TURN_ANG = TURN_ANG + d_rotat_deg * D_T;

=====================================================

検定は、ジャイロをサーボモーター軸に取り付け、サーボを指定角度で水平に回転させて行いました。

添付した左の図は、計算プログラムの確認のために、2degの回転を与えた時のジャイロ出力電圧Vout(V)と算出回転角度ψ(deg)を記録した例です。

右の図は、ジャイロ出力の検定を行ったものです。横軸が実際に回転させたサーボ軸角度、縦軸がジャイロ出力の算出値です。まずまずの直線性が確認できました。

なお精度はさほど必要なかったので、積分誤差の蓄積などは考慮していません。
質問者さんが試みていることのほうが私のやったことよりずっとレベルが高いようなので、上記がはたして参考になるかどうか自信がありませんが……。
2足歩行ロボット製作の成功を祈ります。
「ジャイロセンサを用いた角度の算出について」の回答画像2

この回答への補足

御教授ありがとうございます。
文字数の関係で補足で失礼します。
No.3で頂いたアドバイスを含めて、コードを書き直してみたので、ご報告いたします。
結果としては、No.3の補足にも記載させていただきましたが、±90°回転を繰り返した時の繰り返し精度は、1回当り、+もしくは-3°位ずれていく状態です。
角度算出の式に関してはアドバイスいただいて申し訳ないのですが、一応台形測で計算して、サンプリング時間を8msec→20msecに変更という形をとってみました。

adc0_buffer_sum:移動平均計算時の合計を入れるバッファ
adc0_buffer:平均値計算時のバッファ
data_adc0:角速度用変数
adc0_ave:静止時センサー出力用変数
data_adc0i:角度用変数

void int_cmi0(void)
{
short int i, j = 0;

for(i = 0; i < 50; i++)//20回の合計を求めます
{
for(j = 0; j < 3; j++)
{
adc0_buffer_sum[j] = adc0_buffer_sum[j] + adc0_buffer[i][j];
}
}
for(i = 0; i < 3; i++)
{
data_adc0[i] = (double)adc0_buffer_sum[i] / 50;//平均を求めます
data_adc0[i] = data_adc0[i] - adc0_ave[i];//静止時のセンサー出力を引きます
data_adc0[i] = (int)data_adc0[i] >> 1;//上の計算結果の小数点切捨て+下1桁をマスク
data_adc0[i] = (int)data_adc0[i] << 1;
}
for(i = 0; i < 3; i++)//A/D→digを計算(ジャイロの増幅度=1)
{
if(data_adc0[i] > 0)//CW時の計算
{
data_adc0[i] = data_adc0[i] * 5.25;//((3.3V/1024)/(0.67*10^-3))*1.09←CW時の係数
}
else//CCW時の計算
{
data_adc0[i] = data_adc0[i] * 4.74;//((3.3V/1024)/(0.67*10^-3))*0.98←CCW時の係数
}
}
for(i = 0; i < 3; i++)//角度計算(サンプリング時間20msec)
{
data_adc0i[i] =data_adc0i[i] + (adc0_buffer_s[i] + data_adc0[i]) * (0.02 / 2);
adc0_buffer_s[i] = data_adc0[i];
}

for(i = 0; i < 49; i++)//adc0_buffer内の値を1個ずらします
{
for(j = 0; j < 3; j++)
{
adc0_buffer[i][j] = adc0_buffer[i + 1][j];
}
}
for(i = 0; i < 3; i++)//合計値を初期化します
{
adc0_buffer_sum[i] = 0;
}
adc0_buffer[49][0] = AD0.ADDR0.WORD >> 6;//配列の最後に新しい値を代入します
adc0_buffer[49][1] = AD0.ADDR1.WORD >> 6;
adc0_buffer[49][2] = AD0.ADDR2.WORD >> 6;
  CMT0.CMCSR.BIT.CMF = 0;//コンペアマッチフラグをクリア
}
main()にて
wait(); //センサ出力が安定するまで待ち

initIO(); //IO~ADC、SCIまでをイニシャライズ+駆動
initINT();
initADC();
initSCI();

for(x = 0; x < 50; x++) //移動平均用の初期値を取り込み
{
adc0_buffer[x][0] = AD0.ADDR0.WORD >> 6;
adc0_buffer[x][1] = AD0.ADDR1.WORD >> 6;
adc0_buffer[x][2] = AD0.ADDR2.WORD >> 6;
}

for(x = 0; x < 3000; x++)  //静止時センサ出力を計算
{
adc0_ave_sum[0] = adc0_ave_sum[0] + (AD0.ADDR0.WORD >> 6);
adc0_ave_sum[1] = adc0_ave_sum[1] + (AD0.ADDR1.WORD >> 6);
adc0_ave_sum[2] = adc0_ave_sum[2] + (AD0.ADDR2.WORD >> 6);
}
for(x = 0; x < 3; x++)
{
adc0_ave[x] = (double)adc0_ave_sum[x] / 3000;
adc0_ave_sum[x] = 0;
}
initCMT();
 initMTU();
CMT.CMSTR.BIT.STR0 = 1;//CMT0カウント開始

補足日時:2009/01/08 12:26
    • good
    • 0

こちらでもこんばんは。



> (1)角速度計算結果について
> 角速度=(A/D出力-静止時出力)*(3.38/1024)/(感度*ローパスフィルタの増幅度)

ローパスフィルタは増幅してくれないので、OPアンプの増幅率ですよね。
増幅率は回路図から見ると10倍で良いと思います。でも、CPUに供給している電源電圧が3.38Vというのは、なぜ3.3Vではないのですか?

> (2)センサーからの出力について

90度回して止めたのであれば、センサの出力が静止時の電圧より低く出るのは明らかにおかしいですよね。

> (3)積分について

台形積分をしたいのなら、それで正しいと思います。ですが、サンプリング時間が8msなら十分短時間ですから、
(今回の角度)=(前回の角度)+(今回の角速度)×(サンプリング時間)
で十分な気がします。

それから、ジャイロの「応答性(周波数特性)」は「周波数をもった入力に対してセンサ出力の位相角が90°遅れる周波数」ですから、ENC-03Rの応答性が50Hzであることとサンプリング時間にはあまり関係がないのではないかと思います。

> 上記のような出力のせいか、積分の式が間違っているのか、または別の問題か

問題を切り分けて、一つずつ確認していきましょう。
まずはオシロスコープでジャイロセンサの出力電圧を観察するところから。
    • good
    • 1
この回答へのお礼

御教授ありがとうございます。
回答が遅くなり申し訳ありません。
いまだに納得のいく結果が得られず苦しんでいます(泣)。
No.3さんのアドバイスから、何とか値は出るようになってきました。
繰り返し精度ですが、No.2、No.3の補足にも記載させていただきましたが、±90°回転を繰り返した時の繰り返し精度は、1回当り、+もしくは-3°位ずれていく状態です。

>増幅率は回路図から見ると10倍で良いと思います。でも、CPUに供給している電源電圧が3.38Vというのは、なぜ3.3Vではないのですか?

ロボットに積んでいる電源回路は、トランジスタ技術2008年10月号に付属していたDC-DCコンバーターにVRを付けているものです。VRで電圧を決めているので、ちょっとずれているんです。

>台形積分をしたいのなら、それで正しいと思います。ですが、サンプリング時間が8msなら十分短時間ですから、
(今回の角度)=(前回の角度)+(今回の角速度)×(サンプリング時間)
で十分な気がします。
>それから、ジャイロの「応答性(周波数特性)」は「周波数をもった入力に対してセンサ出力の位相角が90°遅れる周波数」ですから、ENC-03Rの応答性が50Hzであることとサンプリング時間にはあまり関係がないのではないかと思います。

コード面に関してはNo.2に示していますが、上記のアドバイスから、逆に台形則を使用して、サンプリング時間を長くとってみました。

繰り返し誤差に関しては、実際の開発現場からみていかがでしょうか。
No.2さんのグラフを見ると、自分の結果に満足できないところです。

改善方針としては、コードよりも回路を優先と感じていますが、現在までに回路をいじりまくった結果、回路のランドがそろそろ限界なんで、大きな変更に踏み切れない感じです。良いアドバイスがありましたらよろしくお願いいたします。最悪キットを買いなおして、1から作り直そうと思います。

以上の状況を踏まえまして、現在は加速度センサーを実装して、静止時の傾斜角を補正するようにも動いていますが、できればもっとジャイロを詰めたいので、良いアドバイスがありましたらよろしくお願いいたします。

お礼日時:2009/01/08 12:59

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!