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();