给你的Arduino加上"耳朵"和"嘴巴"之一:Hello world和OTTO机器人
最近在玩Arduino的时候,突然在想能不能让他“听懂”别人说的话。于是查了很多资料,发现现有的硬件有很多局限(比如识别精度和合成效果);某宝里虽然有新的硬件,但是价格不菲,而且毕竟还要考虑学习成本和后期维护费用。偶然想起Android平台,发现了更好的实现方式,于是用了几周时间搞定代码,以飨读者。先看视频效果(Hello world—语音识别开灯、关灯)
http://v.youku.com/v_show/id_XMzQ4ODc1MTI3Ng.html
“耳朵”部分:注意这里的语音识别是可以“听懂”你说的话的,不是简单的声控,比如你可以设置多个命令,“打开灯”、“打开风扇”,或者你可以说“屋里有点暗”、“我有点热”,都是可以执行命令的。玩硬件的朋友加上继电器就可以实现电影里的智能家居,通过“语音”控制家里的各种电器以及其他酷炫功能了。
“嘴巴”部分:同样这里的语音合成也不是简单的播放mp3文件,他是可以将你输入的文字转化为声音,并有“男声” ,”女声”,”童声”等多种声音可以选择。
### 现在说一下我们需要的硬件
- Arduino uno或nano X 1
- Android手机 X 1
- HC-05或HC-06蓝牙模块 X 1
- Led灯 X 1
- 电源、电阻、导线、面包板等
#### 一、Arduino部分
arduino接线方式如下图:
需要说明的是Arduino的控制电压是5V,而HC-05或HC-06蓝牙模块的控制电压是3.6V,所以黄色导线连接蓝牙模块RX引脚时,需要加上分压电阻(例如图中3个300欧电阻),这里蓝牙模块不需要接收信息,所以暂时也可以先不连接(^_^)。
对应的烧录文件如下:
```
char command;
String string;
boolean ledon = false;
#define led 13
void setup()
{
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop()
{
if (Serial.available() > 0)
{string = "";}
while(Serial.available() > 0)
{
command = ((byte)Serial.read());
if(command == ':')
{
break;
}
else
{
string += command;
}
delay(1);
}
if(string == "TO")
{
ledOn();
ledon = true;
Serial.println(string);
}
if(string =="TF")
{
ledOff();
ledon = false;
Serial.println(string);
}
}
void ledOn()
{
digitalWrite(led, HIGH);
delay(1000);
}
void ledOff()
{
digitalWrite(led, LOW);
delay(1000);
}
```
代码很简单,限于篇幅这里就不再赘述了。
#### 二、Android部分
下载app并安装,以百度第三方登陆。
配置app.txt文件,并将dingdang6hao文件夹及里面的文件拷贝到安卓手机内置存储根目录下(可用ES文件浏览器,内置SD卡根目录为”/storage/emulated/0”)。
```
{
"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"}
]
}
```
其中listen是“听“到的话,action是执行的动作(注意要和Arduino里的指令对应),mode模式可指定不同的发声,speak是”说“出指定的内容(其中模式9是播放音频文件),注意app.txt编码采用UTF-8无BOM格式。
打开并查看搜索到的蓝牙设备。
开始你的对话吧^_^
如果你觉得不过瘾,那就试试OTTO机器人吧。
视频地址:http://v.youku.com/v_show/id_XMzQ4ODc3NTc0MA
http://v.youku.com/v_show/id_XMzQ4ODc3NTc0MA.html
OTTO的硬件资料见:https://www.dfrobot.com.cn/commun ... iewthread&tid=34838
## 硬件连接如图:
## 核心代码如下:
```
//----------------------------------------------------------------
//-- 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_YR4
#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;
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.attach(PIN_RR);
servo.attach(PIN_RL);
servo.attach(PIN_YR);
servo.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.SetTrim(trim);
}
}
else{
servo.SetTrim(TRIM_RR);
servo.SetTrim(TRIM_RL);
servo.SetTrim(TRIM_YR);
servo.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, int O, int T, double phase_diff){
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;
int oldPosition[]={90,90,90,90};
void moveNServos(int time, intnewPosition[]){
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.SetPosition(80);
servo.SetPosition(100);
delay(tempo);
servo.SetPosition(70);
servo.SetPosition(110);
delay(tempo);
servo.SetPosition(60);
servo.SetPosition(120);
delay(tempo);
servo.SetPosition(50);
servo.SetPosition(130);
delay(tempo);
servo.SetPosition(40);
servo.SetPosition(140);
delay(tempo);
servo.SetPosition(30);
servo.SetPosition(150);
delay(tempo);
servo.SetPosition(20);
servo.SetPosition(160);
delay(tempo);
while(millis()<pause+8*t);
}
void primera_parte(){
int move1 = {60,120,90,90};
int move2 = {90,90,90,90};
int move3 = {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 = {90,90,80,100};
int move2 = {90,90,100,80};
int move3 = {90,90,80,100};
int move4 = {90,90,100,80};
int move5 = {40,140,80,100};
int move6 = {40,140,100,80};
int move7 = {90,90,80,100};
int move8 = {90,90,100,80};
int move9 = {40,140,80,100};
int move10 = {40,140,100,80};
int move11 = {90,90,80,100};
int move12 = {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.SetPosition(40);
else servo.SetPosition(140);
delay(tempo/2);
servo.SetPosition(90);
servo.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 = {120,140,90,90};
int move2 = {140,140,90,90};
int move3 = {120,140,90,90};
int move4 = {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.SetPosition(50); //pie derecho
servo.SetPosition(70); //pie izquiero
delay(tempo);
servo.SetPosition(80); //pie derecho
servo.SetPosition(70); //pie izquiero
delay(tempo/4);
servo.SetPosition(30); //pie derecho
servo.SetPosition(70); //pie izquiero
delay(tempo/4);
servo.SetPosition(80); //pie derecho
servo.SetPosition(70); //pie izquiero
delay(tempo/4);
servo.SetPosition(30); //pie derecho
servo.SetPosition(70); //pie izquiero
delay(tempo/4);
servo.SetPosition(80); //pie derecho
servo.SetPosition(70); //pie izquiero
delay(tempo);
}
void kickRight(int tempo){
for(int i=0;i<4;i++) servo.SetPosition(90);
delay(tempo);
servo.SetPosition(110); //pie derecho
servo.SetPosition(130); //pie izquiero
delay(tempo);
servo.SetPosition(110); //pie derecho
servo.SetPosition(100); //pie izquiero
delay(tempo/4);
servo.SetPosition(110); //pie derecho
servo.SetPosition(150); //pie izquiero
delay(tempo/4);
servo.SetPosition(110); //pie derecho
servo.SetPosition(80); //pie izquiero
delay(tempo/4);
servo.SetPosition(110); //pie derecho
servo.SetPosition(150); //pie izquiero
delay(tempo/4);
servo.SetPosition(110); //pie derecho
servo.SetPosition(100); //pie izquiero
delay(tempo);
}
void walk(int steps, int T){
int A= {15, 15, 30, 30};
int O = {0, 0, 0, 0};
double phase_diff = {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= {10, 10, 10, 10};
int O = {0, 0, 0, 0};
double phase_diff = {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= {15, 15, 30, 30};
int O = {0, 0, 0, 0};
double phase_diff = {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= {15, 15, 30, 30};
int O = {0, 0, 0, 0};
double phase_diff = {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= {20, 20, 10, 30};
int O = {0, 0, 0, 0};
double phase_diff = {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= {20, 20, 30, 10};
int O = {0, 0, 0, 0};
double phase_diff = {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= {25, 25, 0, 0};
int O = {-15 ,15, 0, 0};
double phase_diff = {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= {25, 25, 0, 0};
int O = {-15, 15, 0, 0};
double phase_diff = {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= {25, 25, 30, 30};
int O = {- 15, 15, 0, 0};
double phase_diff = {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= {25, 25, 0, 0};
int O = {-15, 15, 0, 0};
double phase_diff = {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= {25, 25, 0, 0};
int O = {-15, 15, 0, 0};
double phase_diff = {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= {15, 15, 8, 8};
int O = {-A, A, 0, 0};
double phase_diff = {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= {15, 15, 8, 8};
int O = {-A + 10, A - 10, 0, 0};
double phase_diff = {DEG2RAD(0), DEG2RAD(180), DEG2RAD(90), DEG2RAD(-90)};
for(int i=0;i<steps;i++)oscillate(A,O, T, phase_diff);
}
```
资料可在百度网盘下载,如果大家喜欢,我们会继续添加新的功能和好玩的实例,有什么好的意见和建议,也请大家踊跃发言并关注我们后续的作品,谢谢!
有什么意见和建议欢迎加入qq群(732520726):
“叮当6号”资料下载:
https://pan.baidu.com/s/19Lzt8RYCNRsSsUndrGsITw
OTTO新玩法,赞赞! lkk255 发表于 2018-3-25 11:03
OTTO新玩法,赞赞!
谢谢! 一直想做语音机器人,这个帮大忙了,谢谢分享 先马一下,以后学习 学习了,感谢大神 走起 点赞点赞!@Ash 可以移到Otto机器人专区么?:lol jarvis_chan 发表于 2018-3-28 16:24
点赞点赞!@Ash 可以移到Otto机器人专区么?
可以啊~ 大神啊,这个绝对可以啊 这样可以做很多有意思的玩具了
大佬,网盘文件失效了,能重发一份吗,万分感谢 lkk255 发表于 2018-3-25 11:03
OTTO新玩法,赞赞!
大哥,叮当6号的网盘失效了,能帮忙发一份吗 学习了,感谢大神 西红柿酱 发表于 2018-3-25 12:16
一直想做语音机器人,这个帮大忙了,谢谢分享
学习中,希望自己能成功做出一个来!谢谢分享! 叮当6号 发表于 2018-3-25 11:17
谢谢!
学习中,希望自己能成功做出一个来!谢谢分享! 在分享一下链接
可以再发一次网盘吗? 好厉害! 好厉害! 大神可以分享一下你的资料吗,我好像知道弄一个出来玩玩
页:
[1]
2