134128| 6
|
[教程] 给你的Arduino加上"耳朵"和"嘴巴"之二:OTTO机器人蓝牙功能详解 |
做好了基础的OTTO机器人之后,很多朋友都想和这个萌宠互动,可是对于很多新手来讲,蓝牙模块的烧录以及程序文件的调试都是个麻烦事。其实,即使你不是学硬件和软件专业出身也同样可以玩转Arduino;只是,估计很多朋友跟我一样都是在业余时间玩,没有更多的时间查找资料和翻译英文文档,所以这里就给出大家一个简明的OTTO蓝牙模块教程。 1. 硬件连接如图: 2. 蓝牙模块可以选择HC-05或者HC-06,如果你想修改蓝牙模块默认的名称、密码和波特率就需要烧录。烧录代码如下: [mw_shl_code=c,true]/* http://giltesa.com/?p=11738 09/08/2012 (CC) BY-NC-SA: giltesa.com Modified by Pablo García pabloeweb@gmail.com for Otto DIY robot ConfigBluetooth HC-06 from Arduino. Change name, password and baud using serial port, with no user interaction. 1.- Upload this code to Arduino nano (no bluetooth module connected) 2.- unplug USB 3.- Connect HC-06 4.- Power arduino from external power. 5.- Wait for the Arduino´s onboard led to start blinking 6.- Disconnect power. Everything is done. After upload code you have 10 seconds to connect the module BT ---- Arduino TX ----> RX RX <---- TX Once the LED off configuration will start and at the end LED will blink After this you can pair your module */ // Options: int ArduLED=13; //Internal Arduino´s LED char ssid[10] = "Zowi"; // Name for Bluetooth. char baudios = '8'; // 1=>1200 baudios, 2=>2400, 3=>4800, 4=>9600 (default), 5=>19200, 6=>38400, 7=>57600, 8=>115200 char password[10] = "1234"; // Password for pairing void setup() { Serial.begin(9600); //9600bauds is the deafult baudrate for these modules. //if it´s not working try changing this baudrate to match your HC-06 initial setup // Waiting time (10 seconds) onboard LED is ON: pinMode(ArduLED,OUTPUT); digitalWrite(ArduLED,HIGH); delay(10000); digitalWrite(ArduLED,LOW); Serial.print("AT"); delay(1000); // Now configuration start Serial.print("AT+NAME"); Serial.print(ssid); delay(1000); // Change Name of BT Serial.print("AT+BAUD"); Serial.print(baudios); delay(1000); // Change Baud Serial.print("AT+PIN"); Serial.print(password); delay(1000); // Change Password } void loop() { // After programing bluetooth, onboard LED will Blink. digitalWrite(ArduLED, !digitalRead(ArduLED)); delay(500); } [/mw_shl_code] 我翻译一下烧录过程: (1)上传这段代码(HC05_BT_config.ino或HC06_BT_config.ino)至Arduino nano(注意这时不要连接蓝牙模块); (2)拔下USB线; (3)连接HC-05或者HC-06模块; (4)用外接电源给Arduino通电; (5)等待Arduino板的LED灯直到开始闪烁; (6)拔下电源,就一切OK了。 另外,默认设置是Arduino板等待10秒开始烧录,接线方式如下: BT ---- Arduino TX ----> RX RX <---- TX 当然还需要连接电源线。Arduino板上LED灯灭的时候配置开始,配置结束后LED灯开始闪烁,这时你就可以使用你的蓝牙模块了。 3. Arduino nano板上的烧录。Otto官网上的例子很多,我用的是smooth_criminal,注意需要把Oscillator文件夹拷贝到你的Arduino IDE里的libraries文件夹下(同时需要重新启动IDE,不然会提示找不到库文件)。 此外,smooth_criminal里没有整合蓝牙功能,所以需要加入蓝牙模块的控制代码,你可以从otto官网上的代码中获取灵感,也可以直接使用下面的代码烧录: [mw_shl_code=c,true]//---------------------------------------------------------------- //-- OTTO Dance smooth criminal //-- Released under a GPL licencse //-- Originally made for Zowi project remake for Otto //-- Authors: Javier Isabel: javier.isabel@bq.com //-- Juan Gonzalez (obijuan): juan.gonzalez@bq.com //----------------------------------------------------------------- #include <Servo.h> #include <Oscillator.h> #include <EEPROM.h> #include <SoftwareSerial.h> #define N_SERVOS 4 //-- First step: Configure the pins where the servos are attached /* --------------- | O O | |---------------| YR 3==> | | <== YL 2 --------------- || || || || RR 5==> ----- ------ <== RL 4 |----- ------| */ #define EEPROM_TRIM false // Activate to take callibration data from internal memory #define TRIM_RR 7 #define TRIM_RL 4 #define TRIM_YR 4 #define TRIM_YL -7 //OTTO.setTrims(-7,-4,-4,7); #define PIN_RR 5 #define PIN_RL 4 #define PIN_YR 3 #define PIN_YL 2 #define INTERVALTIME 10.0 SoftwareSerial BT(6, 7); //新建对象,接收脚为6,发送脚为7 char val; //存储接收的变量 String string; char command; Oscillator servo[N_SERVOS]; void goingUp(int tempo); void drunk (int tempo); void noGravity(int tempo); void kickLeft(int tempo); void kickRight(int tempo); void run(int steps, int T=500); void walk(int steps, int T=1000); void backyard(int steps, int T=3000); void backyardSlow(int steps, int T=5000); void turnLeft(int steps, int T=3000); void turnRight(int steps, int T=3000); void moonWalkLeft(int steps, int T=1000); void moonWalkRight(int steps, int T=1000); void crusaito(int steps, int T=1000); void swing(int steps, int T=1000); void upDown(int steps, int T=1000); void flapping(int steps, int T=1000); void setup() { Serial.begin(19200); BT.begin(115200); //设置波特率 servo[0].attach(PIN_RR); servo[1].attach(PIN_RL); servo[2].attach(PIN_YR); servo[3].attach(PIN_YL); //EEPROM.write(0,TRIM_RR); //EEPROM.write(1,TRIM_RL); //EEPROM.write(2,TRIM_YR); //EEPROM.write(3,TRIM_YL); int trim; if(EEPROM_TRIM){ for(int x=0;x<4;x++){ trim=EEPROM.read(x); if(trim>128)trim=trim-256; Serial.print("TRIM "); Serial.print(x); Serial.print(" en "); Serial.println(trim); servo[x].SetTrim(trim); } } else{ servo[0].SetTrim(TRIM_RR); servo[1].SetTrim(TRIM_RL); servo[2].SetTrim(TRIM_YR); servo[3].SetTrim(TRIM_YL); } for(int i=0;i<4;i++) servo.SetPosition(90); } // TEMPO: 121 BPM int t=495; double pause=0; void loop() { if (BT.available() > 0) {string = "";} while(BT.available() > 0) { command = ((byte)BT.read()); if(command == ':') { break; } else { string += command; } delay(1); } if(string == "TO") { dance(); } if(string =="TF") { for(int i=0;i<4;i++) servo.SetPosition(90); } for(int i=0;i<4;i++) servo.SetPosition(90); } void dance(){ //primera_parte(); segunda_parte(); moonWalkLeft(4,t*2); moonWalkRight(4,t*2); moonWalkLeft(4,t*2); moonWalkRight(4,t*2); primera_parte(); crusaito(1,t*8); crusaito(1,t*7); for (int i=0; i<16; i++){ flapping(1,t/4); delay(3*t/4); } moonWalkRight(4,t*2); moonWalkLeft(4,t*2); moonWalkRight(4,t*2); moonWalkLeft(4,t*2); drunk(t*4); drunk(t*4); drunk(t*4); drunk(t*4); kickLeft(t); kickRight(t); drunk(t*8); drunk(t*4); drunk(t/2); delay(t*4); drunk(t/2); delay(t*4); walk(2,t*2); backyard(2,t*2); goingUp(t*2); goingUp(t*1); noGravity(t*2); crusaito(1,t*2); crusaito(1,t*8); crusaito(1,t*2); crusaito(1,t*8); crusaito(1,t*2); crusaito(1,t*3); delay(t); primera_parte(); for (int i=0; i<32; i++){ flapping(1,t/2); delay(t/2); } for(int i=0;i<4;i++) servo.SetPosition(90); } //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////FUNCIONES DE CONTROL////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// void oscillate(int A[N_SERVOS], int O[N_SERVOS], int T, double phase_diff[N_SERVOS]){ for (int i=0; i<4; i++) { servo.SetO(O); servo.SetA(A); servo.SetT(T); servo.SetPh(phase_diff); } double ref=millis(); for (double x=ref; x<T+ref; x=millis()){ for (int i=0; i<4; i++){ servo.refresh(); } } } unsigned long final_time; unsigned long interval_time; int oneTime; int iteration; float increment[N_SERVOS]; int oldPosition[]={90,90,90,90}; void moveNServos(int time, int newPosition[]){ for(int i=0;i<N_SERVOS;i++) increment = ((newPosition)-oldPosition)/(time/INTERVALTIME); final_time = millis() + time; iteration = 1; while(millis() < final_time){ //Javi del futuro cambia esto interval_time = millis()+INTERVALTIME; oneTime=0; while(millis()<interval_time){ if(oneTime<1){ for(int i=0;i<N_SERVOS;i++){ servo.SetPosition(oldPosition + (iteration * increment)); } iteration++; oneTime++; } } } for(int i=0;i<N_SERVOS;i++){ oldPosition = newPosition; } } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////PASOS DE BAILE//////////////////////////////// ////////////////////////////////////////////////////////////////////////////// void goingUp(int tempo){ pause=millis(); for(int i=0;i<4;i++) servo.SetPosition(90); delay(tempo); servo[0].SetPosition(80); servo[1].SetPosition(100); delay(tempo); servo[0].SetPosition(70); servo[1].SetPosition(110); delay(tempo); servo[0].SetPosition(60); servo[1].SetPosition(120); delay(tempo); servo[0].SetPosition(50); servo[1].SetPosition(130); delay(tempo); servo[0].SetPosition(40); servo[1].SetPosition(140); delay(tempo); servo[0].SetPosition(30); servo[1].SetPosition(150); delay(tempo); servo[0].SetPosition(20); servo[1].SetPosition(160); delay(tempo); while(millis()<pause+8*t); } void primera_parte(){ int move1[4] = {60,120,90,90}; int move2[4] = {90,90,90,90}; int move3[4] = {40,140,90,90}; for(int x=0; x<3; x++){ for(int i=0; i<3; i++){ lateral_fuerte(1,t/2); lateral_fuerte(0,t/4); lateral_fuerte(1,t/4); delay(t); } pause=millis(); for(int i=0;i<4;i++) servo.SetPosition(90); moveNServos(t*0.4,move1); moveNServos(t*0.4,move2); while(millis()<(pause+t*2)); } for(int i=0; i<2; i++){ lateral_fuerte(1,t/2); lateral_fuerte(0,t/4); lateral_fuerte(1,t/4); delay(t); } pause=millis(); for(int i=0;i<4;i++) servo.SetPosition(90); crusaito(1,t*1.4); moveNServos(t*1,move3); for(int i=0;i<4;i++) servo.SetPosition(90); while(millis()<(pause+t*4)); } void segunda_parte(){ int move1[4] = {90,90,80,100}; int move2[4] = {90,90,100,80}; int move3[4] = {90,90,80,100}; int move4[4] = {90,90,100,80}; int move5[4] = {40,140,80,100}; int move6[4] = {40,140,100,80}; int move7[4] = {90,90,80,100}; int move8[4] = {90,90,100,80}; int move9[4] = {40,140,80,100}; int move10[4] = {40,140,100,80}; int move11[4] = {90,90,80,100}; int move12[4] = {90,90,100,80}; for(int x=0; x<7; x++){ for(int i=0; i<3; i++){ pause=millis(); moveNServos(t*0.15,move1); moveNServos(t*0.15,move2); moveNServos(t*0.15,move3); moveNServos(t*0.15,move4); while(millis()<(pause+t)); } pause=millis(); moveNServos(t*0.15,move5); moveNServos(t*0.15,move6); moveNServos(t*0.15,move7); moveNServos(t*0.15,move8); while(millis()<(pause+t)); } for(int i=0; i<3; i++){ pause=millis(); moveNServos(t*0.15,move9); moveNServos(t*0.15,move10); moveNServos(t*0.15,move11); moveNServos(t*0.15,move12); while(millis()<(pause+t)); } } void lateral_fuerte(boolean side, int tempo){ for(int i=0;i<4;i++) servo.SetPosition(90); if (side) servo[0].SetPosition(40); else servo[1].SetPosition(140); delay(tempo/2); servo[0].SetPosition(90); servo[1].SetPosition(90); delay(tempo/2); } void drunk (int tempo){ pause=millis(); int move1[] = {60,70,90,90}; int move2[] = {110,120,90,90}; int move3[] = {60,70,90,90}; int move4[] = {110,120,90,90}; moveNServos(tempo*0.235,move1); moveNServos(tempo*0.235,move2); moveNServos(tempo*0.235,move3); moveNServos(tempo*0.235,move4); while(millis()<(pause+tempo)); } void noGravity(int tempo){ int move1[4] = {120,140,90,90}; int move2[4] = {140,140,90,90}; int move3[4] = {120,140,90,90}; int move4[4] = {90,90,90,90}; for(int i=0;i<4;i++) servo.SetPosition(90); for(int i=0;i<N_SERVOS;i++) oldPosition=90; moveNServos(tempo*2,move1); moveNServos(tempo*2,move2); delay(tempo*2); moveNServos(tempo*2,move3); moveNServos(tempo*2,move4); } void kickLeft(int tempo){ for(int i=0;i<4;i++) servo.SetPosition(90); delay(tempo); servo[0].SetPosition(50); //pie derecho servo[1].SetPosition(70); //pie izquiero delay(tempo); servo[0].SetPosition(80); //pie derecho servo[1].SetPosition(70); //pie izquiero delay(tempo/4); servo[0].SetPosition(30); //pie derecho servo[1].SetPosition(70); //pie izquiero delay(tempo/4); servo[0].SetPosition(80); //pie derecho servo[1].SetPosition(70); //pie izquiero delay(tempo/4); servo[0].SetPosition(30); //pie derecho servo[1].SetPosition(70); //pie izquiero delay(tempo/4); servo[0].SetPosition(80); //pie derecho servo[1].SetPosition(70); //pie izquiero delay(tempo); } void kickRight(int tempo){ for(int i=0;i<4;i++) servo.SetPosition(90); delay(tempo); servo[0].SetPosition(110); //pie derecho servo[1].SetPosition(130); //pie izquiero delay(tempo); servo[0].SetPosition(110); //pie derecho servo[1].SetPosition(100); //pie izquiero delay(tempo/4); servo[0].SetPosition(110); //pie derecho servo[1].SetPosition(150); //pie izquiero delay(tempo/4); servo[0].SetPosition(110); //pie derecho servo[1].SetPosition(80); //pie izquiero delay(tempo/4); servo[0].SetPosition(110); //pie derecho servo[1].SetPosition(150); //pie izquiero delay(tempo/4); servo[0].SetPosition(110); //pie derecho servo[1].SetPosition(100); //pie izquiero delay(tempo); } void walk(int steps, int T){ int A[4]= {15, 15, 30, 30}; int O[4] = {0, 0, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(0), DEG2RAD(90), DEG2RAD(90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void run(int steps, int T){ int A[4]= {10, 10, 10, 10}; int O[4] = {0, 0, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(0), DEG2RAD(90), DEG2RAD(90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void backyard(int steps, int T){ int A[4]= {15, 15, 30, 30}; int O[4] = {0, 0, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(0), DEG2RAD(-90), DEG2RAD(-90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void backyardSlow(int steps, int T){ int A[4]= {15, 15, 30, 30}; int O[4] = {0, 0, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(0), DEG2RAD(-90), DEG2RAD(-90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void turnLeft(int steps, int T){ int A[4]= {20, 20, 10, 30}; int O[4] = {0, 0, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(0), DEG2RAD(90), DEG2RAD(90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void turnRight(int steps, int T){ int A[4]= {20, 20, 30, 10}; int O[4] = {0, 0, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(0), DEG2RAD(90), DEG2RAD(90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void moonWalkRight(int steps, int T){ int A[4]= {25, 25, 0, 0}; int O[4] = {-15 ,15, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(180 + 120), DEG2RAD(90), DEG2RAD(90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void moonWalkLeft(int steps, int T){ int A[4]= {25, 25, 0, 0}; int O[4] = {-15, 15, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(180 - 120), DEG2RAD(90), DEG2RAD(90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void crusaito(int steps, int T){ int A[4]= {25, 25, 30, 30}; int O[4] = {- 15, 15, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(180 + 120), DEG2RAD(90), DEG2RAD(90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void swing(int steps, int T){ int A[4]= {25, 25, 0, 0}; int O[4] = {-15, 15, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(0), DEG2RAD(90), DEG2RAD(90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void upDown(int steps, int T){ int A[4]= {25, 25, 0, 0}; int O[4] = {-15, 15, 0, 0}; double phase_diff[4] = {DEG2RAD(180), DEG2RAD(0), DEG2RAD(270), DEG2RAD(270)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void flapping(int steps, int T){ int A[4]= {15, 15, 8, 8}; int O[4] = {-A[0], A[1], 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(180), DEG2RAD(90), DEG2RAD(-90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); } void test(int steps, int T){ int A[4]= {15, 15, 8, 8}; int O[4] = {-A[0] + 10, A[1] - 10, 0, 0}; double phase_diff[4] = {DEG2RAD(0), DEG2RAD(180), DEG2RAD(90), DEG2RAD(-90)}; for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff); }[/mw_shl_code] 硬件完成之后就简单了,找个好用的app吧,你可以用官网的app,也可以用下面这个简单超酷的模拟游戏手柄界面的app(Arduino bluetooth controller,你可以在Google Play Store下载,也可以在文末的百度网盘地址下载): 使用前做一个简单的配置,选择一个按键发送指令,在Arduino里我们烧录的指令是“TO”,所以我就选择一个按钮设置成”TO”。 既然是DIY,其他的指令和动作就需要你自己动手完成了,如果想加上语音识别和语音合成,就安装好“叮当6号”app,并设置好对应的配置文件: [mw_shl_code=bash,true]{ "send":[ {"id":1,"listen":"打开","action":"TO","mode":"0","speak":"好的,已打开"}, {"id":2,"listen":"关闭","action":"TF","mode":"0","speak":"好的,已关闭"}, {"id":3,"listen":"你好","action":"","mode":"4","speak":"你好,很高兴认识你"}, {"id":4,"listen":"跳个舞","action":"TO","mode":"9","speak":"test.wav"} ] } [/mw_shl_code] 其中listen是你说话发出的指令,action就是对应刚才提到的Arduino烧录的指令,mode里0-4对应着发言“男声”、“女声”、“童声”等(9对应播放的mp3文件,需要和app.txt在同一目录下),speak则是你想让otto说的话(需要注意文本需要使用notepad++等编辑器,且保存格式是UTF-8无BOM;同时还要注意所有标点符号都是英文标点符号,即半码格式)。 接下来就是欣赏你的作品了: 资料下载地址: https://pan.baidu.com/s/19Lzt8RYCNRsSsUndrGsITw |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed