Arduino } P = 0; // https://shizenkarasuzon.hatenablog.com/entry/2019/02/16/181342 QIDI X-Smartという機種です。レビューの評価の高さと値段の手ごろさで選びました。かなりいい感じです。, ネジ2本でブレッドボードを抑えて固定している点は激ダサな上、単3電池4本はマステで仮止めのままです。この辺は追々改良したいと思っています・・・。, 今回のボディの用途は、頑丈さは特に気にしておらず、もろもろのパーツがちゃんとひとかたまりに固定できるかのみで考えます。 暇があれば、あとQiitaの使い方が分かってくれば、どこかで3Dプリンタのデータを公開するかもしれません。, たまたま手元にあったからです。 myservo2.write(90); // 後ろに傾くとpowerはプラス、前に傾くとマイナス // Arduino nanoに9V角型電池(すぐなくなる)、モーターに単3電池4本 What is going on with this article? if ( target < roll && roll < stoptheta + target) { Serial.print("I =\t"); Serial.print(I); Serial.print(",\t"); myservo2.write(90 - power); 以下にコードを載せていますが、PIDで計算したpowerを±50に制限しつつ、ちょうどいい塩梅になるようにPIDパラメータを調整している感じです。倒立はしたのでいいっちゃいいのですが、「なんだかわからんがとにかくヨシ!」感が否めません。, 多くの倒立振子挑戦者が苦しむところだと思います。そもそもPID制御の勉強から入らないとよくわからないし・・・。 タイトルにもある通り、Arduino nano(互換機)と、6軸のジャイロ・加速度センサのMPU6050(GY-521)、および連続回転サーボFS90Rで倒立振子を作ってみました。, まずは外観をご覧ください。 Arduino_Uno ブレッドボードを使って、以下の様な回路を組み立てています。, 光センサーの周りが明るい=読み取られる値が小さいと、サーボモーターへの指令値も小さくなり右回りになりました。, 反対に光センサーの周りが暗い=読み取られる値が大きいと、サーボモーターへの指令値は大きくなり左回りに動作しました。, 通常の回転し続けるモーターと違ってサーボモーターを制御できる様になると、こういった角度や位置を制御する事が可能になるので電子工作で動かすことが出来るアイデアの幅が更に広がると思います。, 次回は応用編として、複数のサーボモーターを制御する際の工夫や工作例などを紹介したいと思います。, /*****************************************************************/, // map関数で光センサの読み取り値600~1024の範囲を0~180の値に割り当てます。. さらに制御の都合上、ほとんどのサーボモーターはマイコンの制御信号で動作速度を直接コントロールする事が出来ません。メーカーのカタログなどをチェックして、あらかじめ必要な動作速度を満たしているモデルを選定する場合もあります。, Arduino SDKで用意されているサーボモーター制御コマンドについて説明します。, ヘッダーファイルの読み込みを宣言したら、制御するサーボモーターのプログラム中での名前を宣言します。, Arduinoの種類によって制御できるサーボモーターの数、ポート番号は異なります。, このプログラムを実行すると、デジタルポート5番に接続されたサーボモーターが1秒おきに90度→30度→90度→150度→90度・・・と傾く動作を繰り返します。, それでは、以前テストした光センサーを追加して、読み取った明るさをサーボモーターの傾きで示すプログラムを書いてみたいと思います。 More than 3 years have passed since last update. power = constrain(power, -50, 50); // ±50に制限 // 倒立振子 基本形 float gyro_y = gyRaw / 131.0; また、いちばん右端を0度、信号の長さが長くなる毎に反時計回りに回転して行き左端180度まで信号を送る事が出来ますが、不用意な力が外からサーボモーターに加わっても制御不能になる事がない様、通常の製品では20度から160度くらいまでの範囲で動作する様に制御して使用する事をお勧めします。, 上記の様に電気信号で簡単に角度を指定して固定する事が出来るサーボモーターですので、簡単なギミックから本格的なロボットまで色々応用する事が出来ます。 if (100 < abs(I * Ki))I = 0; // rollの計算結果のみを取得する。pitchとyawは使わない。このrollが現在の角度になる。 digitalWrite(13, LOW); ・・・真面目な理由もあります。 myservo2.attach(6); // 左車輪の信号線をD6番ピンに接続 I = 0; } ブレッドボード // Madgwickフィルターを用いて、PRY(pitch, roll, yaw)を計算 myservo1.attach(5); // 右車輪の信号線をD5番ピンに接続 厳密な解説を始めてしまうと物理の授業になってしまうので、別の機会に改めて説明したいと思います。, つまり、サーボモーターのトルクとアーム先端で動かせる物体の重さの関係を簡単な関係式で示すと, という事になります。先の5[kgf・cm]のトルクを持ったサーボモーターに2cmの長さのアームを付けた場合、アーム先端で動かすことが出来る物体の質量は5÷2=2.5kgfと、長さに反比例して小さくなって行く事が分かります。 azRaw = Wire.read() << 8 | Wire.read(); 初投稿です。 タイトルにもある通り、Arduino nano(互換機)と、6軸のジャイロ・加速度センサのMPU6050(GY-521)、および連続回転サーボFS90Rで倒立振子を作ってみました。 外観 まずは外観をご覧 … By following users and tags, you can catch up information on technical fields that you are interested in as a whole, By "stocking" the articles you like, you can search right away. 本記事はLesson 09【サーボモーター編】です。サーボモータは信号に応じて0度~N度の範囲で回転するモーターです。今回はサーボモーターの制御方法を理解します。また、サーボモーターをラジコンのステアリングのように動かしてみます。そのためポテンショメータの使い方も理解します。 myservo1.write(90 + power); タイヤはタミヤのスポーツタイヤセット(56mm径)です。, この記事にはありませんが、将来的な機能として赤外線リモコンで操作しようと考えているので、写真や動画には赤外線受光部VS1838が映り込んでいます(銀色のちっちゃい四角いLEDみたいなやつ)。今回は赤外線については触れません。うまくいってないから, 今回制作した倒立振子、電池・ブレッドボード・モータを支えているパーツや、タイヤをサーボに嵌める白いパーツは3Dプリンタで印刷したものです。, これは政府の10万円の給付金を半分くらい使って購入した3Dプリンタを活用してみることも兼ねていました。 複数のモーターをマイコンボードに直接接続すると故障の原因となりますので注意してください。 // 起動したら少し待たないと倒立しない。かといってすぐ90°になるようにすると↓ Arduino nano(互換機) // ごく単純な倒立振子。操作等はできない。 // 倒れすぎたら停止(倒れても動き続けるとうるさいし事故るから) What is going on with this article? #include // サーボモータを動かすライブラリ(ここでは連続回転サーボを使用) float Kd = 2.0; // Dゲイン 激しく動いたときのブレーキの役割をする バランスは、電池などの重いパーツをどう配置するかによるところが大きいと思います。自分はタイヤの軸のなるべく真上に単3電池4本が来るようにしています。, カルマンフィルタという手もありますが、やっぱり新しいものにすがったほうが楽でいいです。, 9V電池をVinピンに直で刺すことで電源としていますが、電池の減りが早いように感じます。別の手段を使いたいところですが、重量は増やしたくないんですよね・・・。, thingiverseで見つけたデータをちょっとアレンジして連続回転サーボの軸に嵌めこむギザギザ穴のパーツを作りましたが、この細かいギザギザは3Dプリンタで再現するには難しいということが分かりました。もちろん嵌まりはしますし、倒立振子として動かしている分には外れることはないのですが、手で引っ張ると簡単に外れるくらいにはゆるいです。事故って転倒したり、落としたりすると外れたりします。 float power = 0; // 連続回転サーボの出力(90からどれだけ動かすか) // 前に傾いたら90+x°、後ろに傾いたら90-x°の値をとる。 // https://qiita.com/coppercele/items/e4d71537a386966338d0 まずは基礎知識編として、応用的な使い方については記事を分けて行きたいと思います。, 電子工作やホビーロボットを製作している人の間ではサーボ、又はサーボモーターと言えばラジオコントロール機器の制御で使う製品の事を指します。四角い箱上の一面から回転する軸が出ている形状をした製品が多いです。 しかしDCモータの正転逆転・速度調整にはモータードライバが必要になります。 商品説明に「サーボモータに」とかかれていますけど、別にledの明るさ制御などにつかってもよさそうです。 はい。 今回はこれで複数のサーボモータの制御を試してみます。. Wire.beginTransmission(MPU_ADDRESS); // 目標角度は機体の前後の重量バランスによる。偏ると平行移動しがち。ある意味PIDパラより重要かも void loop() { 本来であれば倒立振子は角度などだけではなく、モータの回転速度も含めたPID制御が理想的ですが、連続回転サーボだとそれが難しいです。 MadgwickFilter.updateIMU(gyro_x, gyro_y, gyro_z, acc_x, acc_y, acc_z); myservo1.write(92 + power); // 92で左前方に旋回、93,94,95で右前方に旋回 write(angle) - Arduino 日本語リファレンス gxRaw = Wire.read() << 8 | Wire.read(); 当然2つ必要です。, その他、9V角型電池(006P)と電池スナップ、単三電池4本とその電池ボックス、ブレッドボード、ジャンパ線、スライドスイッチ、マスキングテープ、M3のなべネジとナットなどを使いました。 Wire.write(0x3B); // touritusinsi_test6をベースに清書 P = (target - roll) / 90; // -90~90を取るので180で割って-1.0~1.0にする 機体が安定して倒立する目標角度の設定がそもそも甘いと、PIDパラをいくら調整しても一方向に動き続け、いずれ倒れます。 Raspberry Pi でサーボモータ制御 をやってみたんですが、PWMが安定していないのが、どうしても時々プルプル震えてしまいます。というわけで、Arduinoで再チャレンジ! 公式サイトのチュートリアルを参考にして … Wire.endTransmission(false); return; myservo2.write(93 - power); // 92で右後方に旋回(早すぎ)、93で左後方に旋回 一応、自分の調べたところ、FS90Rは入力値が92~87で停止、93および86くらいの数値でゆっくりと回転し始め、106,71くらいで半分くらいの回転速度、120,57でほぼマックススピードという風に動作します(個体差も当然あると思います)。つまり速度調整できる範囲が±30くらいしかありません。おそらく狭いです。 preTime = micros(); // 処理時間を記録 float gyro_x = gxRaw / 131.0; // (度/s) if (roll < -stoptheta + target || stoptheta + target < roll) { float gyro_z = gzRaw / 131.0; https://blog.kakakikikeke.com/2016/01/arduino-with-servo-motor.html // センサーから加速度、角速度、温度を取得 Madgwick MadgwickFilter; // Madgwickフィルタのオブジェクトを設定 https://qiita.com/coppercele/items/527228e3f08c53597bd1 ←参考にさせていただいたこちらのページで紹介しているBalaCは連続回転サーボを使用しているようです。 // 積分部分が大きくなりすぎると出力が飽和するので大きくなり過ぎたら0に戻す(アンチワインドアップ) // Serialに表示 最近ではホビーロボット専用のサーボモーターも発売されていますが、これらは少々複雑な通信制御が必要になりますので、後日改めて解説したいと考えています。今回は一般的なラジオコントロール機器に用いられている信号制御方式で作られているサーボモーターについて記述していきます。, サーボモーターからは3本の電線がひとまとめになってコネクタがついているケーブルが出ています。その色は各社様々なのですが、基本的なルールとして, 黒(又は暗い色):GND(電源のマイナス) // PIDパラは倒立しうる最小の値の組み合わせがベストらしい。これは大きいかもしれない。 回路, 今回はArduinoUnoで、ラジコンサーボモーターを動かすことについてご紹介します。 // 後ろに傾いたら後ろに進んで相殺 Arduinoで学ぶ基礎からのモーター制御:基礎からのマイコンモーター制御(6):PWMを使ったサーボモーターの制御 (2/3) [今岡通博,MONOist] float acc_x = axRaw / 16384.0; //FS_SEL_0 16,384 LSB / g myservo1.write(90); 赤く光っているのがArduino nano、緑に光っているのがMPU6050モジュールGY-521です。, 以下の二つはAmazonで安く買いました。 while (Wire.available() < 14); Help us understand the problem. https://www.arduino.cc/en/Tutorial/Knob, 出来上がったコードはこんな感じ。スイッチがONの時、OFFの時、それぞれで180度、0度の位置まで回転します。, 配線図はこちら。図を描くのが面倒なので写真(^^; 右上の3本線がサーボ(SG90 MicroServo)に繋がっています。赤がVcc、黒がGND、緑(サーボ側が橙)がPWMです。. https://qiita.com/coppercele/items/e4d71537a386966338d0 ←またまた参考にさせていただいたこの方のようにいちいち書き込みしなくてもいいシステムを作っちゃう、というのもクレバーな手かと思います。 power = Kp * P + Ki * I + Kd * D; PIDパラだけここにも併記しますが、自分の場合、Kp=150,Ki=2000,Kd=2.0で倒立しました。しかしこれも更なる調整が必須かと・・・。, touritusinsi_basic.ino(クリックして展開) if (-stoptheta + target < roll && roll < target) { I += P * dt; // 偏差を積分する Serial.print("P =\t"); Serial.print(P); Serial.print(",\t"); // シリアル通信で見た限りは角度が暴れるから、うまく倒立しないかもしれない。 float P, I, D, preP; // 偏差、その微分・積分、積分記録用 信号のON/OFF時間を直接指示し、サーボモーターに制御命令として出力してみます。, モーター1個だけであればこういったやり方から拡張していっても制御できますが、複数のモーターを動作させる場合や他の処理も加えたプログラムにしようとすると、この方法では制御周期が乱れて満足にコントロール出来なくなります。, 幸いにもArduino SDKには複数のサーボモーターを制御することが出来る専用のライブラリと制御命令が用意されています。専用命令によるプログラムは最後に記述しますのでしばらくお待ちください。 touritusinsi_basic.ino void setup() { 尚、産業用のAC/DCサーボモーターと呼ばれるモーターとは制御方式が異なりますのであくまでも商品名もしくはある種類のホビーモーターの総称として覚えておいた方が良いでしょう。 float acc_y = ayRaw / 16384.0; // 100Hzだと妙に角度が暴れたりはしないけど、0°→90°になるまでちょっと計算に時間がかかるから、↓ float Ki = 2000.0; // Iゲイン バランスが崩れて全体が平行移動しだしたときに効く // 動作モードの読み出し } 連続回転サーボ FS90R axRaw = Wire.read() << 8 | Wire.read(); // Serialに表示 ソフトの方の調整も大事ですが、機体のバランスというハードの調整、それを加味した目標角度の調整も同じくらい大事です。当たり前か // タイヤはタミヤのスポーツタイヤセット(56mm径)、ボディは3Dプリンタ 本記事はLesson 26 【DCモーター編】です。DCモーターはミニ4駆やラジコンなど、おもちゃに使われています。モーターそのものですので制御回路などは組み込まれていません。本Lessonでは、DCモーターを制御することでミニ扇風機を作成します。 // 上記のPIDパラと目標角は詰めが甘いかもしれない // Arduino nano互換機、連続回転サーボ2個、GY-521(MPU6050モジュール)をブレッドボードに Arduinoでサーボモータ制御. モータにはいくつか種類がありますが、dcモータは最も単純で基礎的なものです。このdcモータの回転速度や回転方向を手軽に制御するために、dcモータの構造やhブリッジ回路、モータドライバl293dを使用した回路やプログラム、tinkercadシミュレーションについて紹介します。 PIDパラを調整して書き込み、動きから判断してさらに調整、書き込み・・・ずっとこの繰り返しでした。 gyRaw = Wire.read() << 8 | Wire.read(); D = 0; Serial.print("roll =\t"); Serial.print(roll); Serial.print(",\t"); Servo myservo1; // 右車輪を定義、ラベルはB ほかのサイトを見るとだいたいどの人も「遊びの少ないギヤードモータ」を使っていますね。 出典:双葉電子工業(株)製品紹介サイト, 動作する力は「トルク」と呼ばれています。通常は回転モーメントの事を指し[N・m(ニュートン・メートル)]が用いられますが、そんな大きな力はサーボモーターからは出せませんので、メーカーが定めるカタログなどでは[kgf・cm]で表現されています。 // 角速度値を分解能で割って角速度(degrees per sec)に変換する 赤(又は赤色系の色):Vin(電源のプラス) // 軸がぶれてたり個体差があったりするからどうしようもないかもしれない。 // 出力を計算する Why not register and get more from Qiita? Servo myservo2; // 左車輪を定義、ラベルはA Wire.write(0x00); float dt, preTime; // 処理時間 Why not register and get more from Qiita? ブログを報告する, "angle = map(angle,0,180,SERVOMIN,SERVOMAX);", "pwm.setPWM(0,0,angle); で動かすサーボの指定、角度を変数angleで指定. #include // I2C通信用ライブラリ #define MPU6050_PWR_MGMT_1 0x6B // Read and Write また、PIDパラも重要ですが、機体の重心による目標角度も重要です。 float acc_z = azRaw / 16384.0; }, draw.ioで作成しました。プログラムのフローチャートは授業の課題で作った以来なので、正しい書き方かどうかはわかりませんが、掲載します。, その場で回り続ける倒立振子… pic.twitter.com/7sQxffCL3V, いろいろ考えてますが、コロナ禍で家にいる時間が増えたので、今のうちにいろいろチャレンジしたいと思います。.