Otto-Robotは、個人的な利用であればオープンソースなので、作ってみました。
OttoのWebサイト は、https://www.ottodiy.com/です。
以下が、最初のOtto-Roboto(1号機)の製作過程です。
完成したOtto-Robot(1号機)の起動動画です。
最後は自分で転倒します。
1.Ottoのサイトを開くと、次の購入サイト画面が表示されますので、右上のXをクリックします。
(2021/01時点)

2.次のOttoサイトの画面が表示されます。

3.画面上のメニューの「Academy」をクリックします。次の画面が表示されます。

4.3Dプリントのstlファイル等の取得
正規版は、次の①のように取得しますが、後が面倒なので②の「Wikifactory」からファイルを取得します。
(1)正規版は、「Academy」画面を下にスクロールして「learn to Design」の所にある「3D CAD Source」ボタンを
クリックして取得します。但し、PCに「Fusion 360」がインストールされていることが必要です。
(2)「Wikifactory」の「Otto DIY」からstlファイルを取得します。
「Academy」画面をさらに下にスクロールして「Apply New!」を表示します。

(3)画面の「Otto"Starter"」をクリックすると、次のように「Wikifactory」の「Otto DIY」に移動します。

(4)画面中央の「Files」をクリックすると、必要なファイルが表示されます。

(5)画面下のダウンロードボタンをクリックしてダウウンロードします。
Zipファイルを解凍すると「otto-diy」フォルダーに次のファイルが入っています。

(6)「3Dprint」フォルダーには以下の3Dプリンター用のstlファイルが入っています。

(7)「Code」フォルダーにはottoを動かすスケッチプログラムが入っています。

(8)「Instruction manual」フォルダーには製作マニュアルと配線図が入っています。

配線図は、「fritzing」で描かれたものです。参考として掲示しておきます。
1.「Otto Academy」画面に戻り、「Programming Guide」の所で「Libraries+Code」をクリックします。

2.以下のottoのArduino IDE用のライブラリーがダウンロードされます。

3.このライブラリーファイルをArduino IDEにインストールします。
(1)Arduino IDEを起動し、メニューの「スケッチ」をクリックして、「ライブラリをインクルード」、
「.ZIP形式のライブラリをインストール」の順にクリックして、上記の「OttoDIYLib-master.zip」を
インストールします。

(2)ライブラリーをインストール後、ライブラリの「contributedライブラリ」の中に「OttoDIYLib」が
入っていればOKです。
これでottoを起動する準備が出来ました。
1.全てのサーボは、90°の位置に設定しておきます。
2.組立手順は、「Instruction manual」フォルダーに入っている「OttoDIY_Manual_V10.pdf」を
参照して組み立ててください。
3.今回は、電源として単3電池4本を使わないで、006P形ニッケル水素充電池8.4V(NiMH)を使用しました。
したがって、NANO用の拡張ボード「ナノV3.0ナノプロトタイプシールドi/o拡張ボード」
(Aliexpressで購入)のVin端子にスイッチを通して電池を接続しました。
1.ottoの電源スイッチはoffにしておいて、NANOとパソコンをUSBコードで接続し、
「Code」フォルダーの「Otto_allmoves_V9」にあるスケッチ「Otto_allmoves_V9.ino」を
起動してください。
2.Arduino IDEで、ボードとシリアルポートを選択し、スケッチを書き込んでください。Ottoが起動します。
確認ができたらUSBコードを外してottoの電源スイッチをONにして起動してみます。
3.「Otto_allmoves_V9.ino」は、ottoの全ての動きがプログラムされています。最後は、自分で転倒します。
参考として「Otto9.h」における関数の全容は以下の通りです。
ちなみに使用方法は、次のようにします。
#include <Otto9.h> Otto9 Otto; //This is Otto! ・・・・・・・・・・・・・・・・・・・ Otto.init(PIN_YL, PIN_YR, PIN_RL, PIN_RR, true, A6, PIN_Buzzer, PIN_Trigger, PIN_Echo); Otto.sing(S_connection); Otto.home(); ・・・・・・・・・・・・・・ Otto.walk(2,1000,1);
「Otto9.h」における関数
Otto9::initDC(int NoiseSensor, int Buzzer, int USTrigger, int USEcho)
Otto9::initMATRIX(int DIN, int CS, int CLK, int rotate)
Otto9::matrixIntensity(int intensity)
Otto9::initBatLevel(int batteryPIN)
Otto9::attachServos()
Otto9::detachServos()
Otto9::setTrims(int YL, int YR, int RL, int RR)
Otto9::saveTrimsOnEEPROM()
Otto9::_moveServos(int time, int servo_target[])
Otto9::_moveSingle(int position, int servo_number)
Otto9::oscillateServos(int A[4], int O[4], int T, double phase_diff[4], float cycle=1)
Otto9::_execute(int A[4], int O[4], int T, double phase_diff[4], float steps = 1.0)
Otto9::home()
Otto9::getRestState()
Otto9::setRestState(bool state)
Otto9::jump(float steps, int T)
//---------------------------------------------------------
//-- Otto movement: Jump
//-- Parameters:
//-- steps: Number of steps
//-- T: Period
//---------------------------------------------------------
Otto9::walk(float steps, int T, int dir)
/---------------------------------------------------------
//-- Otto gait: Walking (forward or backward)
//-- Parameters:
//-- * steps: Number of steps
//-- * T : Period
//-- * Dir: Direction: FORWARD / BACKWARD
//---------------------------------------------------------
Otto9::turn(float steps, int T, int dir)
/---------------------------------------------------------
//-- Otto gait: Turning (left or right)
//-- Parameters:
//-- * Steps: Number of steps
//-- * T: Period
//-- * Dir: Direction: LEFT / RIGHT
//---------------------------------------------------------
Otto9::bend (int steps, int T, int dir)
/---------------------------------------------------------
//-- Otto gait: Lateral bend
//-- Parameters:
//-- steps: Number of bends
//-- T: Period of one bend
//-- dir: RIGHT=Right bend LEFT=Left bend
//---------------------------------------------------------
Otto9::shakeLeg (int steps,int T,int dir)
/---------------------------------------------------------
//-- Otto gait: Shake a leg
//-- Parameters:
//-- steps: Number of shakes
//-- T: Period of one shake
//-- dir: RIGHT=Right leg LEFT=Left leg
//---------------------------------------------------------
Otto9::updown(float steps, int T, int h)
/---------------------------------------------------------
//-- Otto movement: up & down
//-- Parameters:
//-- * steps: Number of jumps
//-- * T: Period
//-- * h: Jump height: SMALL / MEDIUM / BIG
//-- (or a number in degrees 0 - 90)
//---------------------------------------------------------
Otto9::swing(float steps, int T, int h)
/---------------------------------------------------------
//-- Otto movement: swinging side to side
//-- Parameters:
//-- steps: Number of steps
//-- T : Period
//-- h : Amount of swing (from 0 to 50 aprox)
//---------------------------------------------------------
Otto9::tiptoeSwing(float steps, int T, int h)
/---------------------------------------------------------
//-- Otto movement: swinging side to side without touching the floor with the heel
//-- Parameters:
//-- steps: Number of steps
//-- T : Period
//-- h : Amount of swing (from 0 to 50 aprox)
//---------------------------------------------------------
Otto9::jitter(float steps, int T, int h)
/---------------------------------------------------------
//-- Otto gait: Jitter
//-- Parameters:
//-- steps: Number of jitters
//-- T: Period of one jitter
//-- h: height (Values between 5 - 25)
//---------------------------------------------------------
Otto9::ascendingTurn(float steps, int T, int h)
/---------------------------------------------------------
//-- Otto gait: Ascending & turn (Jitter while up & down)
//-- Parameters:
//-- steps: Number of bends
//-- T: Period of one bend
//-- h: height (Values between 5 - 15)
//---------------------------------------------------------
Otto9::moonwalker(float steps, int T, int h, int dir)
/---------------------------------------------------------
//-- Otto gait: Moonwalker. Otto moves like Michael Jackson
//-- Parameters:
//-- Steps: Number of steps
//-- T: Period
//-- h: Height. Typical valures between 15 and 40
//-- dir: Direction: LEFT / RIGHT
//---------------------------------------------------------
Otto9::crusaito(float steps, int T, int h, int dir)
/---------------------------------------------------------
//-- Otto gait: Crusaito. A mixture between moonwalker and walk
//-- Parameters:
//-- steps: Number of steps
//-- T: Period
//-- h: height (Values between 20 - 50)
//-- dir: Direction: LEFT / RIGHT
//-----------------------------------------------------------
Otto9::flapping(float steps, int T, int h, int dir)
/---------------------------------------------------------
//-- Otto gait: Flapping
//-- Parameters:
//-- steps: Number of steps
//-- T: Period
//-- h: height (Values between 10 - 30)
//-- dir: direction: FOREWARD, BACKWARD
//---------------------------------------------------------
Otto9::getDistance()
//-- Otto getDistance: return Otto's ultrasonic sensor measure
//---------------------------------------------------------
Otto9::getNoise()
//-- Otto getNoise: return Otto's noise sensor measure
//---------------------------------------------------------
Otto9::getBatteryLevel()
//-- Otto getBatteryLevel: return battery voltage percent
//---------------------------------------------------------
Otto9::getBatteryVoltage()
//The first read of the batery is often a wrong reading, so we will discard this value.
//////////////////////////////////////////////////////////////////
//-- MOUTHS & ANIMATIONS ----------------------------------------//
///////////////////////////////////////////////////////////////////
Otto9::setLed(byte X, byte Y, byte value)
// EXAMPLE putAnimationMouth(dreamMouth,0)
Otto9::putAnimationMouth(unsigned long int aniMouth, int index)
//EXAMPLE putMouth(smile);
Otto9::putMouth(unsigned long int mouth, bool predefined)
Otto9::clearMouth()
Otto9::writeText(const char * s, byte scrollspeed)
///////////////////////////////////////////////////////////////////
//-- SOUNDS -----------------------------------------------------//
///////////////////////////////////////////////////////////////////
Otto9::_tone (float noteFrequency, long noteDuration, int silentDuration)
// tone(10,261,500);
// delay(500);
Otto9::bendTones (float initFrequency, float finalFrequency, float prop, long noteDuration, int silentDuration)
//Examples:
// bendTones (880, 2093, 1.02, 18, 1);
// bendTones (note_A5, note_C7, 1.02, 18, 0);
Otto9::sing(int songName)
case S_connection:
_tone(note_E5,50,30);
_tone(note_E6,55,25);
_tone(note_A6,60,10);
case S_disconnection:
_tone(note_E5,50,30);
_tone(note_A6,55,25);
_tone(note_E6,50,10);
case S_buttonPushed:
bendTones (note_E6, note_G6, 1.03, 20, 2);
delay(30);
bendTones (note_E6, note_D7, 1.04, 10, 2);
case S_mode1:
bendTones (note_E6, note_A6, 1.02, 30, 10); //1318.51 to 1760
case S_mode2:
bendTones (note_G6, note_D7, 1.03, 30, 10); //1567.98 to 2349.32
case S_mode3:
_tone(note_E6,50,100); //D6
_tone(note_G6,50,80); //E6
_tone(note_D7,300,0); //G6
case S_surprise:
bendTones(800, 2150, 1.02, 10, 1);
bendTones(2149, 800, 1.03, 7, 1);
case S_OhOoh:
bendTones(880, 2000, 1.04, 8, 3); //A5 = 880
delay(200);
for (int i=880; i<2000; i=i*1.04) {
_tone(note_B5,5,10);
}
case S_OhOoh2:
bendTones(1880, 3000, 1.03, 8, 3);
delay(200);
for (int i=1880; i<3000; i=i*1.03) {
_tone(note_C6,10,10);
}
case S_cuddly:
bendTones(700, 900, 1.03, 16, 4);
bendTones(899, 650, 1.01, 18, 7);
case S_sleeping:
bendTones(100, 500, 1.04, 10, 10);
delay(500);
bendTones(400, 100, 1.04, 10, 1);
case S_happy:
bendTones(1500, 2500, 1.05, 20, 8);
bendTones(2499, 1500, 1.05, 25, 8);
case S_superHappy:
bendTones(2000, 6000, 1.05, 8, 3);
delay(50);
bendTones(5999, 2000, 1.05, 13, 2);
case S_happy_short:
bendTones(1500, 2000, 1.05, 15, 8);
delay(100);
bendTones(1900, 2500, 1.05, 10, 8);
case S_sad:
bendTones(880, 669, 1.02, 20, 200);
case S_confused:
bendTones(1000, 1700, 1.03, 8, 2);
bendTones(1699, 500, 1.04, 8, 3);
bendTones(1000, 1700, 1.05, 9, 10);
case S_fart1:
bendTones(1600, 3000, 1.02, 2, 15);
case S_fart2:
bendTones(2000, 6000, 1.02, 2, 20);
case S_fart3:
bendTones(1600, 4000, 1.02, 2, 20);
bendTones(4000, 3000, 1.02, 2, 20);
//////////////////////////////////////////////////////////////////
//-- GESTURES ---------------------------------------------------//
///////////////////////////////////////////////////////////////////
Otto9::playGesture(int gesture)
case OttoHappy:
_tone(note_E5,50,30);
putMouth(smile);
sing(S_happy_short);
swing(1,800,20);
sing(S_happy_short);
home();
putMouth(happyOpen);
case OttoSuperHappy:
putMouth(happyOpen);
sing(S_happy);
putMouth(happyClosed);
tiptoeSwing(1,500,20);
putMouth(happyOpen);
sing(S_superHappy);
putMouth(happyClosed);
tiptoeSwing(1,500,20);
home();
putMouth(happyOpen);
case OttoSad:
putMouth(sad);
gesturePOSITION[0] = 110;//int sadPos[6]= {110, 70, 20, 160};
gesturePOSITION[1] = 70;
gesturePOSITION[2] = 20;
gesturePOSITION[3] = 160;
_moveServos(700, gesturePOSITION);
bendTones(880, 830, 1.02, 20, 200);
putMouth(sadClosed);
bendTones(830, 790, 1.02, 20, 200);
putMouth(sadOpen);
bendTones(790, 740, 1.02, 20, 200);
putMouth(sadClosed);
bendTones(740, 700, 1.02, 20, 200);
putMouth(sadOpen);
bendTones(700, 669, 1.02, 20, 200);
putMouth(sad);
delay(500);
home();
delay(300);
putMouth(happyOpen);
case OttoSleeping:
gesturePOSITION[0] = 100;//int bedPos[6]= {100, 80, 60, 120};
gesturePOSITION[1] = 80;
gesturePOSITION[2] = 60;
gesturePOSITION[3] = 120;
_moveServos(700, gesturePOSITION);
for(int i=0; i<4;i++){
putAnimationMouth(dreamMouth,0);
bendTones (100, 200, 1.04, 10, 10);
putAnimationMouth(dreamMouth,1);
bendTones (200, 300, 1.04, 10, 10);
putAnimationMouth(dreamMouth,2);
bendTones (300, 500, 1.04, 10, 10);
delay(500);
putAnimationMouth(dreamMouth,1);
bendTones (400, 250, 1.04, 10, 1);
putAnimationMouth(dreamMouth,0);
bendTones (250, 100, 1.04, 10, 1);
delay(500);
}
putMouth(lineMouth);
sing(S_cuddly);
home();
putMouth(happyOpen);
case OttoFart:
gesturePOSITION[0] = 90;// int fartPos_1[6]= {90, 90, 145, 122};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 145;
gesturePOSITION[3] = 122;
_moveServos(500,gesturePOSITION);
delay(300);
putMouth(lineMouth);
sing(S_fart1);
putMouth(tongueOut);
delay(250);
gesturePOSITION[0] = 90;// int fartPos_2[6]= {90, 90, 80, 122};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 80;
gesturePOSITION[3] = 122;
_moveServos(500,gesturePOSITION);
delay(300);
putMouth(lineMouth);
sing(S_fart2);
putMouth(tongueOut);
delay(250);
gesturePOSITION[0] = 90;// int fartPos_3[6]= {90, 90, 145, 80};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 145;
gesturePOSITION[3] = 80;
_moveServos(500,gesturePOSITION);
delay(300);
putMouth(lineMouth);
sing(S_fart3);
putMouth(tongueOut);
delay(300);
home();
delay(500);
putMouth(happyOpen);
case OttoConfused:
gesturePOSITION[0] = 110;//int confusedPos[6]= {110, 70, 90, 90};
gesturePOSITION[1] = 70;
gesturePOSITION[2] = 90;
gesturePOSITION[3] = 90;
_moveServos(300, gesturePOSITION);
putMouth(confused);
sing(S_confused);
delay(500);
home();
putMouth(happyOpen);
case OttoLove:
putMouth(heart);
sing(S_cuddly);
crusaito(2,1500,15,1);
home();
sing(S_happy_short);
putMouth(happyOpen);
case OttoAngry:
gesturePOSITION[0] = 90;//int angryPos[6]= {90, 90, 70, 110};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 70;
gesturePOSITION[3] = 110;
_moveServos(300, gesturePOSITION);
putMouth(angry);
_tone(note_A5,100,30);
bendTones(note_A5, note_D6, 1.02, 7, 4);
bendTones(note_D6, note_G6, 1.02, 10, 1);
bendTones(note_G6, note_A5, 1.02, 10, 1);
delay(15);
bendTones(note_A5, note_E5, 1.02, 20, 4);
delay(400);
gesturePOSITION[0] = 110;//int headLeft[6]= {110, 110, 90, 90};
gesturePOSITION[1] = 110;
gesturePOSITION[2] = 90;
gesturePOSITION[3] = 90;
_moveServos(200, gesturePOSITION);
bendTones(note_A5, note_D6, 1.02, 20, 4);
gesturePOSITION[0] = 70;//int headRight[6]= {70, 70, 90, 90};
gesturePOSITION[1] = 70;
gesturePOSITION[2] = 90;
gesturePOSITION[3] = 90;
_moveServos(200, gesturePOSITION);
bendTones(note_A5, note_E5, 1.02, 20, 4);
home();
putMouth(happyOpen);
case OttoFretful:
putMouth(angry);
bendTones(note_A5, note_D6, 1.02, 20, 4);
bendTones(note_A5, note_E5, 1.02, 20, 4);
delay(300);
putMouth(lineMouth);
for(int i=0; i<4; i++){
gesturePOSITION[0] = 90;//int fretfulPos[6]= {90, 90, 90, 110};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 90;
gesturePOSITION[3] = 110;
_moveServos(100, gesturePOSITION);
home();
}
putMouth(angry);
delay(500);
home();
putMouth(happyOpen);
case OttoMagic:
//Initial note frecuency = 400
//Final note frecuency = 1000
// Reproduce the animation four times
for(int i = 0; i<4; i++){
int noteM = 400;
for(int index = 0; index<6; index++){
putAnimationMouth(adivinawi,index);
bendTones(noteM, noteM+100, 1.04, 10, 10); //400 -> 1000
noteM+=100;
}
clearMouth();
bendTones(noteM-100, noteM+100, 1.04, 10, 10); //900 -> 1100
for(int index = 0; index<6; index++){
putAnimationMouth(adivinawi,index);
bendTones(noteM, noteM+100, 1.04, 10, 10); //1000 -> 400
noteM-=100;
}
}
delay(300);
putMouth(happyOpen);
case OttoWave:
// Reproduce the animation four times
for(int i = 0; i<2; i++){
int noteW = 500;
for(int index = 0; index<10; index++){
putAnimationMouth(wave,index);
bendTones(noteW, noteW+100, 1.02, 10, 10);
noteW+=101;
}
for(int index = 0; index<10; index++){
putAnimationMouth(wave,index);
bendTones(noteW, noteW+100, 1.02, 10, 10);
noteW+=101;
}
for(int index = 0; index<10; index++){
putAnimationMouth(wave,index);
bendTones(noteW, noteW-100, 1.02, 10, 10);
noteW-=101;
}
for(int index = 0; index<10; index++){
putAnimationMouth(wave,index);
bendTones(noteW, noteW-100, 1.02, 10, 10);
noteW-=101;
}
}
clearMouth();
delay(100);
putMouth(happyOpen);
case OttoVictory:
putMouth(smallSurprise);
//final pos = {90,90,150,30}
for (int i = 0; i < 60; ++i){
int pos[]={90,90,90+i,90-i};
_moveServos(10,pos);
_tone(1600+i*20,15,1);
}
putMouth(bigSurprise);
//final pos = {90,90,90,90}
for (int i = 0; i < 60; ++i){
int pos[]={90,90,150-i,30+i};
_moveServos(10,pos);
_tone(2800+i*20,15,1);
}
putMouth(happyOpen);
//SUPER HAPPY
//-----
tiptoeSwing(1,500,20);
sing(S_superHappy);
putMouth(happyClosed);
tiptoeSwing(1,500,20);
//-----
home();
clearMouth();
putMouth(happyOpen);
case OttoFail:
putMouth(sadOpen);
gesturePOSITION[0] = 90;//int bendPos_1[6]= {90, 90, 70, 35};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 70;
gesturePOSITION[3] = 35;
_moveServos(300,gesturePOSITION);
_tone(900,200,1);
putMouth(sadClosed);
gesturePOSITION[0] = 90;//int bendPos_2[6]= {90, 90, 55, 35};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 55;
gesturePOSITION[3] = 35;
_moveServos(300,gesturePOSITION);
_tone(600,200,1);
putMouth(confused);
gesturePOSITION[0] = 90;//int bendPos_3[6]= {90, 90, 42, 35};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 42;
gesturePOSITION[3] = 35;
_moveServos(300,gesturePOSITION);
_tone(300,200,1);
gesturePOSITION[0] = 90;//int bendPos_4[6]= {90, 90, 34, 35};
gesturePOSITION[1] = 90;
gesturePOSITION[2] = 34;
gesturePOSITION[3] = 35;
_moveServos(300,gesturePOSITION);
putMouth(xMouth);
detachServos();
_tone(150,2200,1);
delay(600);
clearMouth();
putMouth(happyOpen);
home();