[Atmel] 基于Arduino的语音控制调节台灯

[复制链接]
2171|0
 楼主 | 2015-8-6 16:06 | 显示全部楼层 |阅读模式

大家在平常的焊接电路中,都肯定会遇到这样的问题:一手拿着烙铁,一手拿着锡丝焊接电路时,在突然改变一个角度焊接后后,就把灯光挡住了。放下电烙去调整灯光,一是麻烦,二是高温的电烙铁随意一放又很危险。所以,我收到启发,何必不设计一款语音控制的台灯,在很多类似的情况中,都可以派得上用场。


有了初步的想法,首先,我们确定具体方案。由于受到皮克斯动画里开场小台灯的启发,我们给他取名为皮克斯。我们初步设想皮克斯台灯要实现语音控制,它可以根据不同的语音命令作出不同的动作,完成上、下、左、右、开、关、摇头、点头、跳舞的动作。
313864.jpg
即要实现台灯预想的功能,又要简化加工难度,我们设想直接运用机械臂的结构,在上端用螺丝固定用亚克力板雕刻的灯头。这样既满足基本的要求,制作起来有更加方便,而且外观比较简洁美观。为了保证灯光的充足,我们选用了一组24个led组成的灯板,作为光源。信号经过升压模块后,为led灯提供12V的电源。经过验证,亮度完全能满足使用要求。
313865.jpg
我们选用了Arduino MEGA2560 作为了主控板,声音模块是选用的DFRobot 中文语音识别模块Voice Recognition 。Voice Recognition语音识别模块是一款只需要在主控MCU的程序中设定好要识别的关键词语列表,并动态地把这些关键词语以字符的形式传送到芯片内部,就可以对用户说出的关键词语进行识别,不需要用户事先训练和录音的非特定人语音识别模块。该模块可以设置50项候选识别句,每个识别句可以是单字,词组或短句,长度为不超过10个汉字或者79个字母的拼音串,可由一个系统支持多种场景,并且可以根据当地一些口音,适当加入方言的拼音组合,这样一来还可以识别当地方言,增加了个性化。而且Voice Recognition语音识别模块采用叠层设计,可以直接插接到Arduino控制器上,用户使用Arduino便可以快速设计产品原型。在声音模块上我们还加上了一个V5扩展模块,方便舵机的插线。
313866.jpg
在设计和硬件制作完成后,就是调试了。整个运动模块是由三个舵机协调运动完成。最下面的舵机负责台灯左右旋转,同时还可以做出摇头的动作。中间的舵机不能单独完成动作,必须和其他的舵机同时动作才能完成相应的动作,比如“前”、“后”这两个动作就要求中间的舵机和最上面的舵机一个正转一个反转来完成。最上面的舵机可以实现上下运动,如果将上下运动连起来就是点头的动作了。另外,三个舵机同时运动还可以实现一些简单的舞蹈动作,再加上闪烁的灯光非常具有机械的动感,完成一些简单的人机互动。但实现整个运动的过程是十分枯燥的,需要反复计算舵机的旋转角度,还要考虑到一些极限情况和特殊情况,也唯有这样才能保证我们的皮克斯台灯尽可能完美。
313867.jpg
但在调试时发现,由于灯头比重比较大,在运动时容易失去平衡,在放慢舵机运转速度后,问题还是存在。经过商讨,我们决定再加一个木制底座,利用螺丝和垫片固定,稳定台灯的平衡。后来又发现在大范围的转动时,舵机时常出现震颤的现象,查资料才知道是由于Arduino本身的电流较小,无法支持三个舵机,所以我们又在V5扩展板上加上了6V的直流电源,问题才得到了解决。
313868.jpg
我们的设计还不够完美,还不能够胜任真正的皮克斯台灯,但是现阶段的功能也是很有应用前景的。对于一些特殊的场合,比如焊接时需要灯光照明,而一个人拿着灯光,一个人焊接又降低了效率,牙科医生同样也要可移动的灯光照明,此时如果有一个可以声音控制的灯光就可以增加效率。我们的台灯也适合那些长期坐在办公室里的人,因为我们的皮克斯不仅可以实现语音照明,而且还可以作出一些简单的舞蹈动作,识别一些潮流词语,如说“江南Style”,台灯就会边闪光边做出类似骑马舞的动作,实现人机互动,增加产品的互动乐趣性。我们希望在接下来的优化中,能让舵机的运转更加顺滑,并加入能台灯自己学习并识别用户想存入的词汇,并让用户自己设定相关的预设动作,让互动更加自由化,让台灯表现的更加智能。
313869.jpg
相关代码:

#include “Voice.h” //申明语音识别库文件
#include”Servo.h”
Servo servo1; //舵机1
Servo servo2; //舵机2
Servo servo3; //舵机3
#define SUM 28 //定义待识别的单词数量
uint8 nAsrStatus=0; //申明语音模块工作状态
int ledPin=3;
int power1=20;
int power2=20;
int a=70,b=70,c=100;
char sRecog[SUM][80] = //定义识别单词“拼音”内容的数组,加入一些口头语可以增加准确度,减少误操作
{“qian”,”hou”,”zuo”,”you”,”shang”,”xia”,”kai”,”kaideng”,”fuwei”,
”guan”,”guandeng”,”jiangnan”,”sidaier”,”jiannan”};
char flag; //定义向上位机发送字符命令的变量
//根据单词数组的元素号,执行相应命令
void finally (unsigned char n)
{
switch(n)
{
case 0:
b=b+power1;
c=c+power1;
if(b<145)
servo2.write(b); //前进
else
servo2.write(b=b-power1);
if(c>50)
servo3.write(c);
else
servo3.write(c=c-power1);
break;
case 1:
b=b-power1;
c=c-power1;
if(b>20)
servo2.write(b); //后退
else
servo2.write(b=b+power1);
if(c<160)
servo3.write(c);
else
servo3.write(c=c+power1);
break;
case 2:
a=a-power2;
if(a>0)
servo1.write(a=a); //左转
else
servo1.write(a=a+power2);
break;
case 3:
a=a+power2;
if(a<150)
servo1.write(a); //右转
else
servo1.write(a=a-power2);
break;
case 4:
c=c+power1;
if(c<160)
servo3.write(c); //起
else
servo3.write(c=c-power1);
break;
case 5:
c=c-power1;
if(c>50)
servo3.write(c); //下
else
servo3.write(c=c+power1);
break;
case 6:
servo1.write(a=70); //开始时默认位置
servo2.write(b=70);
servo3.write(c=100);
digitalWrite(ledPin, HIGH); // sets the LED on
break;
case 7:
servo1.write(a=70);//Begin
servo2.write(b=70);
servo3.write(c=100);
digitalWrite(ledPin, HIGH); // sets the LED on
break;
case 8:
servo1.write(a=70);//Begin
servo2.write(b=70);
servo3.write(c=100);
digitalWrite(ledPin, HIGH); // sets the LED on
break;
case 9:
servo1.write(a=70); //停止
servo2.write(b=30);
servo3.write(c=50);
digitalWrite(ledPin, LOW); // sets the LED off
break;
case 10:
servo1.write(a=70); //停止
servo2.write(b=30);
servo3.write(c=50);
digitalWrite(ledPin, LOW); // sets the LED off
break;
case 11: //jiangnanSTYLE
servo1.write(a=70);
servo2.write(b=70);
servo3.write(c=100);
for(int j=0;j<5;j++)
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000);
digitalWrite(ledPin,LOW); // sets the LED off
delay(1000);
}
digitalWrite(ledPin, HIGH); // sets the LED on
for(a;a>=30;a=a-5)
{
servo1.write(a);
delay(100);
}
delay(1000);
for(int i=0;i<3;i++)
{
for(c;c<115;c=c+5)
{
servo3.write(c);
delay(100);
}
for(c;c>85;c=c-5)
{
servo3.write(c);
delay(100);
}
}
delay(500);
for(a;a<=120;a=a+5)
{
servo1.write(a);
delay(100);
}
delay(1000);
for(int i=0;i<3;i++)
{
for(c;c<115;c=c+5)
{
servo3.write(c);
delay(100);
}
for(c;c>85;c=c-5)
{
servo3.write(c);
delay(100);
}
}
servo1.write(a=70);
servo2.write(b=70);
servo3.write(c=100);
for(int i=0;i<5;i++)
{
for(b,c;b<105;b=b+5,c=c+7)
{
servo2.write(b);
servo3.write(c);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(50);
}
for(b,c;b>55;b=b-5,c=c-7)
{
servo2.write(b);
servo3.write(c);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(50);
}
}
servo1.write(a=70);
servo2.write(b=70);
servo3.write(c=100);
digitalWrite(ledPin, HIGH);
break;
case 12: //yaotou
servo1.write(a=70);
for(int i=0;i<5;i++)
{
for(a;a>35;a=a-5)
{
servo1.write(a);
delay(100);
}
for(a;a<105;a=a+5)
{
servo1.write(a);
delay(100);
}
}
servo1.write(a=70);
break;
case 13: //diantou
servo3.write(c=100);
for(int i=0;i<3;i++)
{
for(c;c<115;c=c+5)
{
servo3.write(c);
delay(100);
}
for(c;c>85;c=c-5)
{
servo3.write(c);
delay(100);
}
}
servo3.write(c=100);
break;
default:
break;
}
}
//识别到声音,产生一个触发中断
void ExtInt0Handler ()
{
Voice.ProcessInt0(); //执行中断服务子程序
}
//初始化
void setup()
{
servo1.attach(8);
servo1.write(70);
servo2.attach(10);
servo2.write(70);
servo3.attach(13);
servo3.write(100);
pinMode(ledPin, OUTPUT); // sets the digital pin as output
digitalWrite(ledPin, HIGH); // sets the LED on
Voice.Initialise(MIC); //初始化语音模块
attachInterrupt(0,ExtInt0Handler,LOW);
}
//主循环
void loop()
{
uint8 nAsrRes;
nAsrStatus = LD_ASR_NONE;
while(1)
{
//当语音模块处于各状态,执行相应工作
switch(nAsrStatus)
{
case LD_ASR_RUNING:
case LD_ASR_ERROR:
break;
case LD_ASR_NONE:
{
nAsrStatus=LD_ASR_RUNING;
if (Voice.RunASR(SUM,80,sRecog)==0)
{
nAsrStatus= LD_ASR_ERROR;
// Serial.println( “ASR_ERROR”);
}
//Serial.println( “ASR_RUNING…..”);
break;
}
//识别到单词是设定单词
case LD_ASR_FOUNDOK:
{
//Serial.print( “ASR_FOUN ONE: “);
//提取所识别到的单词是数组的第几个元素
nAsrRes =Voice. LD_GetResult();
//根据数组元素号,执行相应命令
finally(nAsrRes);
nAsrStatus = LD_ASR_NONE;
break;
}
//识别到单词“不是”设定单词
case LD_ASR_FOUNDZERO:
{
//Serial.println( “ASR_FOUND ZERO”);
nAsrStatus = LD_ASR_NONE;
break;
}
default:
{
nAsrStatus = LD_ASR_NONE;
break;
}
}// switch
delay(100); //延时0.1s
}// while
}


扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /5 下一条

在线客服 快速回复 返回顶部 返回列表