テレビのリモコンで操作するOTTOヒューマノイドロボットとダンス
私は最近知ったのですが、だいぶ前からこのロボットが作られていたようです。
3Dプリンターで何か面白いものが無いか、ネットを捜していたらこのロボットに出会いました。元々作るのが趣味なので、面白そうだなと思って作ってみたらハマりました。
前回作ったものに、パーツを追加して作ったものです。

色々とトラブルありましたが、なんとか完成させることができました。
しかし、電源問題でバッテリーからの動作が落ちてしまい改良の余地があるので進めていこうかと思っています。またバラして作るのって面倒なんですけどね。
取り敢えず、USB給電でダンス動画を作りました。音ズレして、つたないダンス動画になっていますが、笑って貰えれば幸いです。
参考までに、接続図とプログラムを公開しますので、興味ありましたら参考に作ってみてください。
製作にあたっては、自己責任でお願いします。
-----ロボットのショートダンス-----
-----今回のロボット製作動画-----
FreeCADでSTLデータを一部加工して製作するTVリモコンで動くOTTO Humaanoid ROBOT
https://youtu.be/oYtIF_jio4o
----- 前回ロボット製作動画 -----
https://www.youtube.com/watch?v=ODE9FRg-qT4&t=45s
3DプリンターデータURL
Otto Biped
Humanoid Expansion

// OTTO humanoid ROBOT 動作確認用
// 2026.2.7 konan0119
#include <IRremote.hpp>
#include <Otto.h>
Otto Otto;//Ottoロボット宣言(クラス、オブジェクト)
#include <PlayRtttl.hpp>
#include <Servo.h>
Servo AL, AR;
int adj[]={ 0, 0,};
int pos[]={ 90,90};
int shift = 60;
int shift_inc = 10;
int shift_delay = 50;
const char data[] = "VARIABLE#";
unsigned long int matrix;
#define LeftLeg 2 //左足
#define RightLeg 3//右足
#define LeftFoot 4 //左足首
#define RightFoot 5 //右足首
#define Buzzer 13 //ブザー
#define PIN_AL 6 // 左腕
#define PIN_AR 7 // 右腕
void move_servo(){ AL.write(pos[1]+adj[1]); AR.write(pos[2]+adj[2]);}
// ---- 8x8 LED Matrix ----
#define DIN A3 // Data In pin
#define CS A2 // Chip Select pin
#define CLK A1 // Clock pin
// 8x8 LED Matrix orientation Top = 1, Bottom = 2, Left = 3, Right = 4
#define Orientation 2
// ---- 超音波モジュール端子 ----
#define TRIG_PIN 8
#define ECHO_PIN 9
long duration;
int distance;
// ---- 赤外線受信端子 ----
const int IR_RECEIVE_PIN = 12;
//超音波距離測定
long ultrasound_distance_simple() {//longは大きな整数を扱うための型
long duration, distance;
digitalWrite(8,LOW);//超音波を1回発射
delayMicroseconds(2);
digitalWrite(8, HIGH);
delayMicroseconds(10);
digitalWrite(8, LOW);
duration = pulseIn(9, HIGH);//超音波が戻る往復時間
distance = duration/58;//58「往復時間をcmに変換する定数」
return distance;//値を関数の外に渡す
}
bool chk() {//void関数は値を返せないのでboolを使う
distance = ultrasound_distance_simple();
Serial.print("Distance: ");
Serial.println(distance);
if (distance < 15) {//15cm以下なら
Otto.sing(S_buttonPushed);
Otto.walk(2.5, 1000, -1);//後退
Otto.home();
delay(500);
IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK);//LED フィードバックを無効化
return true;//前方距離不足
}
return false;//前方距離問題なし
}
void setup() {
Otto.init(LeftLeg, RightLeg, LeftFoot, RightFoot, true, Buzzer); //端子セット
Otto.home();
AL.attach(PIN_AR);
AR.attach(PIN_AL);
move_servo();
delay(100);
Otto.initMATRIX( DIN, CS, CLK, Orientation);
Otto.clearMouth();
Otto.writeText ( "I AM OTTO",80);
Otto.playGesture(OttoSuperHappy);
AL.write(90);
AR.write(90);
Otto.home();
delay(shift_delay);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
Serial.begin(115200);
delay(200);
IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK);//LED フィードバックを無効化
Serial.println("Press the SONY remote control key");
}
void loop() {
if (IrReceiver.decode()) {
// 受信データが正しいプロトコルか確認する
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
IrReceiver.resume();
return;
}
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
// ノイズなので無視
IrReceiver.resume();
return;
}
// ここから先は「正しい信号だけ」
IrReceiver.printIRResultShort(&Serial);
uint32_t raw = IrReceiver.decodedIRData.decodedRawData;
switch (raw) { //リモコンキー押下げによる処理先
case 0x80:Serial.println("1番キー"); demo1(); break;
case 0x81:Serial.println("2番キー"); demo2(); break;
case 0x82:Serial.println("3番キー"); demo3(); break;
case 0x83:Serial.println("4番キー"); demo4(); break;
case 0x84:Serial.println("5番キー"); demo5(); break;
case 0x85:Serial.println("6番キー"); demo6(); break;
case 0x86:Serial.println("7番キー"); demo7(); break;
case 0x87:Serial.println("8番キー"); demo8(); break;
case 0x88:Serial.println("9番キー"); demo9(); break;
case 0x89:Serial.println("10番キー");demo10(); break;
case 0x8A:Serial.println("11番キー");demo11(); break;
case 0x8B:Serial.println("12番キー");demo12(); break;
//前方距離不足の場合はreturnでloop始めに戻る
case 0xF4:Serial.println("↑キー前進");if (chk()) return; demo13(); break;
case 0xF5:Serial.println("↓キー後退"); demo14(); break;
case 0xB4:Serial.println("←キー左に進む");if (chk()) return; demo15(); break;
case 0xB3:Serial.println("→キー右に進む");if (chk()) return; demo16(); break;
default:
Serial.println("未割り当てのキー"); break;
}
IrReceiver.resume();// 次の受信に備える
}
}
int time_ = 1000;
void buz2(){//終了確認音
delay(500);tone(Buzzer,1000,100);delay(200);noTone(Buzzer);tone(Buzzer,3100,100);delay(200);noTone(Buzzer);
Otto.home();IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK);}
void demo1() { AL.write(160);delay(500);AR.write(20);delay(500);AL.write(90);delay(500);AR.write(90); buz2();}//両手を上げ戻す
void demo2() { AL.write(20);delay(500);AR.write(160); buz2();}//両手を下げる
void demo3() { Serial.println("ハッピー"); Otto.playGesture(OttoSuperHappy); buz2();}//ハッピー
void demo4() { Serial.println("ハッピー2"); Otto.playGesture(OttoHappy); buz2();}//ハッピー2
void demo5() { Serial.println("悲しい"); Otto.playGesture(OttoSad); buz2();}//悲しい }
void demo6() { Serial.println("ねむり"); Otto.playGesture(OttoSleeping); buz2();}//ねむり}
void demo7() { Serial.println("混乱"); Otto.playGesture(OttoConfused); buz2();}//混乱 }
void demo8() { Serial.println("気が重い"); Otto.playGesture(OttoFretful); buz2();}//気が重い}
void demo9() { Serial.println("愛"); Otto.playGesture(OttoLove); buz2();}//愛}
void demo10(){ Serial.println("いかり"); Otto.playGesture(OttoAngry); buz2();}//いかり}
void demo11(){ Serial.println("マジック"); Otto.playGesture(OttoMagic); buz2();}//マジック}
void demo12(){ Serial.println("ウェーブ"); Otto.playGesture(OttoWave); buz2();}//ウェーブ}
void demo13(){ Otto.walk(3,800,1); Otto.home();} // 前進 ↑キー
void demo14(){ Otto.walk(3,800,-1); Otto.home();} // 後退 ↓キー
void demo15(){ Otto.turn(3,800,1); Otto.home();} // 右に曲がる ←キー
void demo16(){ Otto.turn(3,800,-1); Otto.home();} // 左に曲がる →キー
/*
---------動作コード設定一覧--------
ダンス(回数,速度,動作,左右)
速度:ノーマル1000 スロー2000 ベリースロー3000 速い750 高速500 超高速250
動作:ノーマル25 小さく10 大きく40
Otto.walk(3,800,1);Otto.walk(3,800,-1); //前進後退
Otto.turn(3,800,1);Otto.turn(3,800,-1); //左右ターン
Otto.bend(1,700,1); Otto.bend(1,800,-1); // 左傾 右傾
Otto.shakeLeg(1,800,-1); Otto.shakeLeg(1,1000,1); //左ゆら右ゆら
Otto.moonwalker(2.5, 800, 25, 1); Otto.moonwalker(2.7, 800, 25, -1); //ムーンウォーカー
Otto.crusaito(3, 1000, 25, 1); delay(500);Otto.crusaito(3.1, 1000, 25, -1); //クロッシング
Otto.flapping(3, 1000, 25, 1);delay(500); Otto.flapping(3.8, 1000, 25, -1); //フラッピング
実行(回数,速度,動作)
速度:ノーマル1000 スロー2000 ベリースロー3000 速い750 高速500 超高速250
動作:ノーマル25 小さく10 大きく40
Otto.swing(1, 1000, 25);
Otto.updown(1, 1000, 25);
Otto.tiptoeSwing(1, 1000, 25);
Otto.jitter(1, 1000, 25);
Otto.ascendingTurn(1, 1000, 25);
Otto.setTrims(0,0,0,0);//キャリブレーション
Otto_moveLegs(200,90,90,90,90);//動く(速度、足左、足右、足首左、足首右角度)
サーボ2ピンに接続の場合
servo_2.write(90);delay(100);//サーボを回す(ピン番号、角度)
servo_2.writeMicroseconds(1500);//サーボを回す(ピン番号、マイクロ秒)
servo_2.detach();//離す (ピン)()無し
servo_2.attach(2);//付ける (ピン)
setServo(0,90);//(ピン、角度)
AR.write(90);//右手を戻す
AR.write(20);//右手を上げる
AR.write(160);//右手を下げる
AL.write(90);//左手を戻す
AL.write(20);//左手を下げる
AL.write(160);//左手を上げる
ジェスチャー+8x8LEDで口の表示
Serial.println("ハッピー"); Otto.playGesture(OttoSuperHappy);//ハッピー
Serial.println("ハッピー2"); Otto.playGesture(OttoHappy);//ハッピー2
Serial.println("悲しい"); Otto.playGesture(OttoSad);//悲しい
Serial.println("ねむり"); Otto.playGesture(OttoSleeping);//ねむり
Serial.println("混乱"); Otto.playGesture(OttoConfused);//混乱
Serial.println("気が重い"); Otto.playGesture(OttoFretful);//気が重い
Serial.println("愛"); Otto.playGesture(OttoLove);//愛
Serial.println("/いかり"); Otto.playGesture(OttoAngry);//いかり
Serial.println("マジック"); Otto.playGesture(OttoMagic);//マジック
Serial.println("ウェーブ"); Otto.playGesture(OttoWave);//ウェーブ
Serial.println("勝利"); Otto.playGesture(OttoVictory);//勝利
Serial.println("失敗 倒れる"); Otto.playGesture(OttoFail);//失敗 倒れる
Serial.println("おなら"); Otto.playGesture(OttoFart); //おなら
8x8LED表示
Serial.println("ハッピー1"); Otto.putMouth(happyOpen); delay(time_);//ハッピー1
Serial.println("ハッピー2"); Otto.putMouth(happyClosed); delay(time_);//ハッピー2
Serial.println("笑顔"); Otto.putMouth(smile); delay(time_);//笑顔
Serial.println("悲しい1"); Otto.putMouth(23); delay(time_);//悲しい1
Serial.println("悲しい2"); Otto.putMouth(24); delay(time_);//悲しい2
Serial.println("おどろいた1"); Otto.putMouth(smallSurprise); delay(time_);//おどろいた1
Serial.println("おどろいた2"); Otto.putMouth(bigSurprise); delay(time_);//おどろいた2
Serial.println("混乱"); Otto.putMouth(confused); delay(time_);//混乱
Serial.println("べろ"); Otto.putMouth(tongueOut); delay(time_);//べろ
Serial.println("ばか"); Otto.putMouth(culito); delay(time_);//ばか
Serial.println("まじめ"); Otto.putMouth(lineMouth); delay(time_);//まじめ
Serial.println("動揺"); Otto.putMouth(21); delay(time_);//動揺
Serial.println("ハート"); Otto.putMouth(heart); delay(time_);//ハート
Serial.println("v1"); Otto.putMouth(vamp1); delay(time_);//"v1
Serial.println("v2"); Otto.putMouth(vamp2); delay(time_);//v2
Serial.println("ノー"); Otto.putMouth(xMouth); delay(time_);//ノー
Serial.println("オッケー"); Otto.putMouth(okMouth); delay(time_);//オッケー
Serial.println("はてな"); Otto.putMouth(27); delay(time_);//はてな
Serial.println("雷"); Otto.putMouth(thunder); delay(time_);//雷
Serial.println("zero"); Otto.putMouth(zero); delay(time_);//zero
Serial.println("(one"); Otto.putMouth(one); delay(time_);//
Serial.println("two"); Otto.putMouth(two); delay(time_);//
Serial.println("three"); Otto.putMouth(three); delay(time_);//
Serial.println("four"); Otto.putMouth(four); delay(time_);//
Serial.println("five"); Otto.putMouth(five); delay(time_);//
Serial.println("6"); Otto.putMouth(6); delay(time_);//
Serial.println("7"); Otto.putMouth(7); delay(time_);//
Serial.println("8"); Otto.putMouth(8); delay(time_);//
Serial.println("9"); Otto.putMouth(9); delay(time_);//
Serial.println("smile"); Otto.putMouth(smile); delay(time_);//
Serial.println("happyOpen"); Otto.putMouth(happyOpen); delay(time_);//
Serial.println("happyClosed"); Otto.putMouth(happyClosed); delay(time_);//
Serial.println("heart"); Otto.putMouth(heart); delay(time_);//
Serial.println("angry"); Otto.putMouth(angry); delay(time_);//
Serial.println("smallSurprise"); Otto.putMouth(smallSurprise); delay(time_);//
Serial.println("bigSurprise"); Otto.putMouth(bigSurprise); delay(time_);//
Serial.println("tongueOut"); Otto.putMouth(tongueOut); delay(time_);//
Serial.println("confused"); Otto.putMouth(confused); delay(time_);//
Serial.println("21"); Otto.putMouth(21); delay(time_);//
Serial.println("27"); Otto.putMouth(27); delay(time_);//
Serial.println("23"); Otto.putMouth(23); delay(time_);//
Serial.println("24"); Otto.putMouth(24); delay(time_);//
Serial.println("vamp1"); Otto.putMouth(vamp1); delay(time_);//
Serial.println("vamp2"); Otto.putMouth(vamp2); delay(time_);//
Serial.println("xMouth"); Otto.putMouth(xMouth); delay(time_);//
Serial.println("okMouth"); Otto.putMouth(okMouth); delay(time_);//
Serial.println("thunder"); Otto.putMouth(thunder); delay(time_);//
Serial.println("lineMouth"); Otto.putMouth(lineMouth); delay(time_);//
Serial.println("culito"); Otto.putMouth(culito); delay(time_); //
Serial.println("littleUuh"); Otto.putAnimationMouth(littleUuh, 0); delay(time_);//
Serial.println("dreamMouth"); Otto.putAnimationMouth(dreamMouth, 0); delay(time_);//
Serial.println("dreamMouth, 1"); Otto.putAnimationMouth(dreamMouth, 1); delay(time_);//
Serial.println("dreamMouth, 2"); Otto.putAnimationMouth(dreamMouth, 2); delay(time_);//
音 (ピン、周波数、長さミリ秒)
Otto._tone(Buzzer, 3, 1);
音(初期周波数、最終周波数、音のステップ、音長、無音時間)
Otto.bendTones (100, 200, 1.04, 10, 10);
曲データ33曲(PlayRtttl.hpp要) 全試聴はメモリ不足で書き込み不可
Serial.println("1"); playRtttlBlockingPGM(13,(char*)StarWars);
Serial.println("2"); playRtttlBlockingPGM(13,(char*)MahnaMahna);
Serial.println("3"); playRtttlBlockingPGM(13,(char*)LeisureSuit);
Serial.println("4"); playRtttlBlockingPGM(13,(char*)MissionImp);
Serial.println("5"); playRtttlBlockingPGM(13,(char*)Entertainer);
Serial.println("6"); playRtttlBlockingPGM(13,(char*)Muppets);
Serial.println("7"); playRtttlBlockingPGM(13,(char*)Flinstones);
Serial.println("8"); playRtttlBlockingPGM(13,(char*)YMCA);
Serial.println("9"); playRtttlBlockingPGM(13,(char*)Simpsons);
Serial.println("10"); playRtttlBlockingPGM(13,(char*)Indiana);
Serial.println("11"); playRtttlBlockingPGM(13,(char*)TakeOnMe);
Serial.println("12"); playRtttlBlockingPGM(13,(char*)Looney);
Serial.println("13"); playRtttlBlockingPGM(13,(char*)_20thCenFox);
Serial.println("14"); playRtttlBlockingPGM(13,(char*)Bond);
Serial.println("15"); playRtttlBlockingPGM(13,(char*)GoodBad);
Serial.println("16"); playRtttlBlockingPGM(13,(char*)PinkPanther);
Serial.println("17"); playRtttlBlockingPGM(13,(char*)A_Team);
Serial.println("18"); playRtttlBlockingPGM(13,(char*)Jeopardy);
Serial.println("19"); playRtttlBlockingPGM(13,(char*)Gadget);
Serial.println("20"); playRtttlBlockingPGM(13,(char*)Smurfs);
Serial.println("21"); playRtttlBlockingPGM(13,(char*)Toccata);
Serial.println("22"); playRtttlBlockingPGM(13,(char*)Short);
Serial.println("23"); playRtttlBlockingPGM(13,(char*)JingleBell);
Serial.println("24"); playRtttlBlockingPGM(13,(char*)Rudolph);
Serial.println("25"); playRtttlBlockingPGM(13,(char*)WeWishYou);
Serial.println("26"); playRtttlBlockingPGM(13,(char*)WinterWonderland);
Serial.println("27"); playRtttlBlockingPGM(13,(char*)OhDennenboom);
Serial.println("28"); playRtttlBlockingPGM(13,(char*)LetItSnow);
Serial.println("29"); playRtttlBlockingPGM(13,(char*)Frosty);
Serial.println("30"); playRtttlBlockingPGM(13,(char*)SilentNight);
Serial.println("31"); playRtttlBlockingPGM(13,(char*)LastChristmas);
Serial.println("32"); playRtttlBlockingPGM(13,(char*)AllIWant);
Serial.println("33"); playRtttlBlockingPGM(13,(char*)AmazingGrace);
Serial.println("S_cuddly"); Otto.sing(S_cuddly);
Serial.println("S_OhOoh"); Otto.sing(S_OhOoh);
Serial.println("S_OhOoh2"); Otto.sing(S_OhOoh2);
Serial.println("S_surprise"); Otto.sing(S_surprise);
Serial.println("S_buttonPushed"); Otto.sing(S_buttonPushed);
Serial.println("S_mode1"); Otto.sing(S_mode1);
Serial.println("S_mode2"); Otto.sing(S_mode2);
Serial.println("S_mode3"); Otto.sing(S_mode3);
Serial.println("S_sleeping"); Otto.sing(S_sleeping);
Serial.println("S_fart1"); Otto.sing(S_fart1);
Serial.println("S_fart2"); Otto.sing(S_fart2);
Serial.println("S_fart3"); Otto.sing(S_fart3);
Serial.println("S_happy"); Otto.sing(S_happy);
Serial.println("S_happy_short"); Otto.sing(S_happy_short);
Serial.println("S_superHappy"); Otto.sing(S_superHappy);
Serial.println("S_sad"); Otto.sing(S_sad);
Serial.println("S_confused"); Otto.sing(S_confused);
Serial.println("S_disconnection");Otto.sing(S_disconnection);
*/