KITtyBot:Arduino Pro Mini・サーボ・IRリモコン・電源内蔵のDIYスマートロボットキット
部品と材料
| SparkFun Arduino Pro Mini 328 - 5V/16MHz | ×1 | |
| サーボ (Tower Pro MG996R) | SG-90や同フォームファクタの9gサーボでも可 | ×12 |
| Adafruit UBEC DC/DC 降圧コンバーター - 5V @ 3A出力 | ×1 | |
| Adafruit ミニリモコン | もちろん他のリモコンでも可。IRLibライブラリと相性が良かったため採用 | ×1 |
| Adafruit IR受信センサー - TSOP38238 | ×1 | |
| 抵抗 1kΩ | ×1 | |
| 抵抗 2.2kΩ | ×1 | |
| 7.4V / 500mAh LiPoバッテリー | ラジコンホビー用でこの容量程度のものなら何でも可 | ×1 |
必要な工具と機械
| 3Dプリンター(汎用) | |
| ハンダごて(汎用) | ブレッドボード版ならハンダ付け不要の場合も |
アプリとオンラインサービス
| Arduino IDE |
このプロジェクトについて
はじめに
「クモ」や「昆虫」タイプではなく、「哺乳類」スタイルの四足歩行ロボットを作りたくなりました。ボストン・ダイナミクスのロボットや他の四足研究ロボットからインスピレーションを得ました。体の中心に足があり重心が高いため、簡単に転倒してしまうなど、このタイプのロボット制作はかなり困難です。
目標は、Arduinoと低コストマイクロサーボで安価なロボットを作ること。もちろん限界はありますが、動画で示す歩行動作を実現できるレベルまで複数台製作できました。限られた予算で最高の成果を出すのは、潤沢な資金のある研究プロジェクトでは味わえない挑戦です :)
早期に逆運動学(IK)の学習が必要と判明しました。コードには、目標足位置から関節角度を計算する方程式セットが含まれ、これを用いてボディ移動(全足を逆方向に動かす)や完全な足動作(持ち上げ→指定方向移動→着地)などの繰り返しタスクを関数化しています。
次の課題は歩容(ガイト)の研究。ロボットがどう歩き、どう曲がるかをボディ・足の動きで定義します。私のロボットは常に静的安定歩容を使用します。一度に1本の足を持ち上げて新位置に置き、残り3本の足で支えます。重心がこの3点で形成される三脚台内に留まる限り転倒しません。前進、後退、左旋回、右旋回の4つの標準歩容を開発し、足・ボディ移動関数を組み合わせて完全なシーケンスを構成しました。
また、複数サーボが設定時間内に異なるストロークを行う場合に同期させる関数も実装。滑らかな動作には必須です。
完全無保護のLiPoバッテリーを使用していますが、リスクもあります。主な危険は過放電と過大電流放電。後者は誤って短絡させない限り回避可能(一般的なRCバッテリーは25C放電率で本ケースでは12Aまで可能だが、UBECが2Aに制限)。前者はソフトウェア監視機能で防止:アナログピンで電圧を測定し、7.0V未満になるとロボットを休止させます。
バッテリーは専用充電器で充電し、充電中は放置しないでください。ロボットから取り外し(ベルクロ固定推奨)、防火バッグ内または可燃物から離れた安全な場所で充電・保管してください。LiPoバッテリーに不慣れな方は、地元のRCホビーショップでバッテリーと充電器、防火バッグ/容器をセットで購入し、警告表示をよく読んで自分の判断で扱ってください :)
ロボットの組み立て
同梱ファイルに従ってパーツをプリント。写真を見ながら組み立て手順をイメージしてから開始してください。私はスカンジナビア出身ですが、この説明書はIKEAやLEGOの説明書レベルではありません :)
まず股関節を組み立てます。品質の良い両面テープでパーツを接合(接着剤でも可だが、修理時に分解不能になるため非推奨)。
サーボサポートを1つのサーボ底面に、作動軸と一直線になるよう取り付け。もう1つのサーボを軸が垂直になるよう接合。下図はフロント右とリア左の股関節。他の2隅はミラー対称で作ります。

先に進む前に、全12個のサーボがセンタリングされているか確認を推奨。PCB(またはブレッドボード、後述)を組み立て、全サーボを接続してコードを書き込むと、Arduino起動時に全サーボがセンター位置(指令信号90度)に移動します。ロボット組み立て後に再度微調整が必要です。
次に「太もも」パーツ(脚上肢)を取り付け。このパーツにはサーボ付属のホーンが嵌まるリセスがあります。ホーンをリセスに接着。3Dプリント素材とナイロン製ホーンの両方に効く接着剤を使用(グルーガンはOK、瞬間接着剤は銘柄により可否あり)。
太ももは股関節に対して60度の角度で接合。サーボがセンター位置のときにこの角度に近づくよう調整し、付属の短いネジでホーンをサーボスプラインに固定。以下は組み立て後の太ももと股関節(ホーンは省略)。


脚下部(下肢)も組み立て。サーボをネジで脚パーツに固定(サーボ付属の長めの「木ネジ」2本を使用)。

脚をボディに取り付け。前後に「バンパー」パーツがあり(車のバンパーのような位置)、太ももと同様にホーン用リセスがあります。ホーンを接着し、上肢のサーボサポートをボディの対応する穴にスライドさせます。両側完了後、バンパーで固定。脚が約12度外側を向くよう調整(脚先で20mmのトーアウト)。バンパーは余った長いサーボネジでボディに固定。
最後に下肢を取り付け。太ももと逆方向に角度を付け、足先が各脚の股関節真下に来るようにします。
これでロボット本体は完成。下図のようになります。トップ画像や動画とは設計が若干変更されています(ボディをシンプルかつ堅牢に再設計、股関節のサーボサポートとホーンの位置を入れ替え)。3D画像に従って組み立て、写真/動画に惑わされないよう注意。

各関節の角度を理想値に正確に合わせるのは困難です。SG-90サーボのスプライン数は21で、1ステップ約17度。機械的には±10〜20度の誤差が生じます。残りはコード側のニュートラル位置補正で吸収します(後述)。一度全サーボを接続してArduinoを起動し、ニュートラル位置を確認、必要なら機械的に調整(スプライン1〜2段ずらす)すると良いでしょう。作業中に誤ってサーボを回してしまうことがよくあるため。
電子回路の接続
選択肢は2つ:すべてを1つのブレッドボードに収めるか、付属のFritzingファイルでPCBを製作するか。ブレッドボードではサーボの電源・GND配線に注意しないと電圧降下で不安定になることがあります(最悪ケースで1サーボ600mA消費)。PCB版は電源ラインが太い銅パターンなので、正しくハンダ付けすれば安定します。
電源スイッチはありません。バッテリーの着脱でON/OFFします。スイッチを付けるならバッテリーコネクタ直後、ArduinoとUBECへの7.4V供給を遮断する位置に。
ブレッドボード版
ハーフサイズブレッドボード1枚にPro Mini、サーボ用コネクタ、その他電子部品を収められます。下図は回路図。特に5V電源とGNDのサーボ接続には短いジャンパーワイヤーを使用。サーボコネクタはロングピンヘッダを3ピンずつ切り出してブレッドボードに差し込むだけ。
図にないもの:バッテリーとUBEC。バッテリーコネクタに合わせて多少ハンダ付けが必要。コネクタから2本のジャンパーワイヤーをブレッドボード下側「パワーレール」に繋ぎ、Pro MiniのRAWとGNDに給電。また、7.4VラインからA0ピンへ分圧用抵抗2本を接続:プラス側から2.2kΩ、マイナス側から1kΩ。満充電時8V超えを5V以下に分圧してアナログピンで測定可能にします。
UBEC出力側はサーボコネクタ形状。ブレッドボード上側「パワーレール」中央付近に2ピンヘッダを立てて接続すると、サーボへの電力分配がバランスよくなります。
IR受信機はA1ピンに接続し5V給電。ピンが長いためブレッドボードに直接差し込み可能。
下記に回路図と完成ブレッドボードの写真を掲載。写真は旧バージョン(ピン配置・接続が異なる)ですが、ジャンパーワイヤーとサーボコネクタの配線イメージとして参考になります。


ブレッドボードは裏面粘着シートでボディに固定。D3〜D5ピンのコネクタがあるコーナー(回路図右上)がロボットのフロント左コーナーになるよう配置し、ボディ中央にセンタリング(重心位置が重要)。
PCB版
Fritzingファイルを同梱。Fritzingの基板製造サービスで発注、または製造用データをエクスポートして外部発注可能。このPCBは本ロボット専用設計で、全サーボコネクタ、IR、電圧測定用コネクタを備え、残りピンも拡張用にブレークアウトしています。
ボディにPCB四隅が嵌まる小さな「パッド」があります。ここでもD3〜D5コネクタコーナーをフロント左に。PCBに取り付け穴がありますが、両面テープでボディに固定するだけでズレません。




バッテリー
バッテリーはボディ底面の平らな専用スペースにベルクロで固定。7.4V/500mAh LiPoの一般的なフォームファクタ(約55×30×10mm)がちょうど収まります。

最後にサーボ配線を束ねて整理。歩行時に配線が絡まるのを防ぎ、四足生物らしく見える見栄えにもなります :)

仕上げ
使用前にセンター位置を微調整。コード内の配列 servodeg0 を編集:
const float servodeg0[12] = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90};
順序は α、β、γ × フロント左、リア左、フロント右、リア右。例:フロント右のβは8番目(インデックス7)。
回転方向を定義する配列 servodir もあります:
const int servodir[12] = { +1, +1, -1, -1, -1, +1, -1, -1, -1, +1, +1, +1 };
// 正はサーボ反時計回り
使用サーボは0〜180度で反時計回り。逆方向のサーボを使う場合は全符号を反転。
Arduino起動後、全サーボの角度を測定・確認。すべて真っ直ぐで対称になっているかチェック。距離と角度は下図の通り。

ミリ単位の精度は難しく、cmオーダーで合っていれば合格。必要な修正を servodeg0 に加減算。数回の反復で完了します。最終的には以下のような配列になります(私のロボットの実例):
const float servodeg0[12] = {80, 95, 100, 100, 110, 90, 100, 115, 100, 80, 80, 100};
これで四本足で真っ直ぐ立つロボットが完成。お楽しみください!
いくつかヒント:
- サーボは経年でセンター位置がズレることがあります。定期的にアライメントを確認してください。
- 正しく組んでも転倒する場合は重心をチェック。バッテリー位置をベルクロでずらして調整可能です。
- 繰り返しになりますが、LiPoバッテリーは慎重に扱ってください。
今後の改良案
このロボットを公開することで、設計の改良(機能追加、レイアウト変更、大型化・小型化、カッコよくする等)を皆さんに呼びかけています。コードは少し異なるレイアウト/サイズのロボットでも再利用可能です。下図はコード内の各種定数と座標定義(xが前進方向)。

リモコンの未使用ボタンに機能を割り当てる(ダンスや特定動作シーケンス等)のも面白いでしょう。
私はアナログ入力での制御、旋回しながら歩く歩容(ジャイロ/コンパスでコース修正)、超音波センサーによる自律回避行動などを実験中。現在はスマホからアナログ制御と自律を統合制御するプロジェクトに取り組んでいます(Blynk、ESP8266、デバイス間シリアル通信等を習得中)。洗練版を公開できるか、あるいはもっと腕の良い誰かが先を越すか、楽しみです :)
コード
KITtyBot2用コード Arduino
Arduino Miniにアップロード
/* IR制御版 KITtyBot 2。Arduino Pro Miniと自作PCB基板(Fritzing: Kittybotmini.fzz)を使用。
先代のKITtyBot、KITtyBot miniをベースに、IRリモコンでロボットを制御。
NEC(Adafruit)リモコンとIRLib2ライブラリを使用。https://github.com/cyborg5/IRLib2
IRLib2ライブラリをリポジトリからダウンロードし、指示に従ってインストール。
一般寸法はオリジナルKITtyBotと類似だが、γ軸とα軸の間に12mmの変位あり(サーボを上下に重ねたため)
歩行と旋回の歩容を継続的に調整したが、現状これが最も安定していると判断。
Created by Staffan Ek 2017 */
#include <IRLibRecv.h>
#include <Servo.h>
#include <IRLibDecodeBase.h>
#include <IRLib_P01_NEC.h>
#define MY_PROTOCOL NEC
long Previous;
IRrecv My_Receiver(A1);
IRdecodeNEC My_Decoder;
const int servonum = 12;
Servo servo[servonum];
const float servodeg0[12] = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90};
float servodegnew[servonum];
float servodegold[servonum];
const int servodir[12] = { +1, +1, -1, -1, -1, +1, -1, -1, -1, +1, +1, +1 };
const float pi = 3.1416;
const float alfa0 = pi / 6;
const float beta0 = pi / 3;
const float jointlength = 50;
const float width = 120;
const float leng = 120;
const float distag = 12;
const float toeout0 = 20;
const float leglength0 = 2 * jointlength * cos(alfa0);
const float gamma0 = asin(toeout0 / (leglength0 + distag));
const float bodyradius = sqrt(pow((width / 2), 2) + pow((leng / 2), 2));
const float phi0 = atan(width / leng);
const float height0 = sqrt(pow(leglength0 + distag, 2) - pow(toeout0, 2));
float leglength[4] = {sqrt(pow(height0, 2) + pow(toeout0, 2)), sqrt(pow(height0, 2) + pow(toeout0, 2)), sqrt(pow(height0, 2) + pow(toeout0, 2)), sqrt(pow(height0, 2) + pow(toeout0, 2))};
unsigned long timestep = 500;
int steplength = 40;
float phi = 20;
float footpos[12];
float stepturn[12] = {0};
const float jointangle0[12] = {alfa0, beta0, 0, alfa0, beta0, 0, alfa0, beta0, 0, alfa0, beta0, 0};
float jointangle[12];
const int voltagepin = A0;
int lowvolt = 0;
int mode = 0;
void setup() {
Serial.begin(9600);
Serial.println("KITtyBot mini");
Serial.print("Gamma0: "); Serial.println(gamma0);
Serial.print("Leglength0: "); Serial.println(leglength0);
Serial.print("Bodyradius: "); Serial.println(bodyradius);
Serial.print("Phi0: "); Serial.println(phi0);
Serial.print("Height0: "); Serial.println(height0);
servo[0].attach(3); servo[1].attach(4); servo[2].attach(5);
servo[3].attach(6); servo[4].attach(7); servo[5].attach(8);
servo[6].attach(2); servo[7].attach(A3); servo[8].attach(12);
servo[9].attach(11); servo[10].attach(10); servo[11].attach(9);
for (int i = 0; i < servonum; i++) {
servodegnew[i] = servodeg0[i];
servodegold[i] = servodegnew[i];
servo[i].write(servodegnew[i]);
}
delay(5000);
My_Receiver.enableIRIn();
}
void loop() {
voltmeasure();
while (lowvolt == 0) {
bodyxyz(0, 0, 0);
servomove();
mode = 0;
IRread();
Serial.print("Mode: "); Serial.println(mode);
switch (mode) {
case 1: forwardcreep(); break;
case 2: reversecreep(); break;
case 3: leftturn(); break;
case 4: rightturn(); break;
}
voltmeasure();
delay(500);
}
if (lowvolt == 1) {
bodyxyz(0, 0, -30);
servomove();
}
}
// 以下、IK計算、歩容生成、サーボ同期制御、電圧監視、IR受信などの関数が続く(原文通り)
// 詳細はGitHub参照
カスタムパーツとエンクロージャ
- ボディ:PCBとバッテリーを搭載
- バンパー:ボディ前後に配置(車のバンパーのような役割)。2個必要
- 股関節サポート:股関節を支える。4個プリント
- 太もも:脚の上肢。4個プリント
- 下肢(足):脚の下肢。4個プリント
- 全パーツ組み立て図:プリント用ではない
回路図
PCB製造用Fritzingファイル。Fritzing経由で発注、または適切なフォーマットでエクスポートして外部発注可能。
kittybotmini_XKZYltyQVJ.fzz
製造プロセス
- Raspberry Pi 2からAzure Event HubsへAdafruit 10DOF IMUデータを送信(Windows 10 IoT Core)
- Adafruit 60 LED NeoPixelリングとArduinoで作るスタイリッシュな壁掛け時計
- UnifiedWater v1 - 完全なArduino水質センサーキット
- 3DプリンターとArduinoで作るアイアンマン ヘルメット&アークリアクター完全ガイド
- GSM接続対応ポータブル投票システム「Mobile Vote Box」
- Arduino 101 BLE + Blynk:スマホで操作するBluetooth戦車ロボット
- Arduino 101とtinyTILE BLEでスマートマッチングサングラスを作る
- Arduino Portenta H7で作る高性能エッジAIカメラ:OpenMV + TensorFlow Lite
- モダンジュークボックス:Raspberry Pi & Arduino LEDミュージックプレーヤー
- DIY Arduino スマートウォッチ — Apple Watch 風腕時計を自作
- 礼儀正しいドライバーに感謝を伝える - Arduino MKR1000で作る車載メッセージ表示システム