正文开始:
硬件设计部分
博主根据教程重新设计了一个性能稳定,语音识别与语音输出,OLED人机交互,可充放电的四足式桌面机器人,采用嘉立创EDA设计了原理图以及对应的PCB文件。将语音模块、OLED显示屏模块、SG90舵机模块、蓝牙模块集成到一块电路板上,采用异步全双工串口通信的方式与蓝牙模块进行数据交互,然后通过IIC通信与0.96寸OLED显示屏进行通信,采用锂电池为单片机和其他的模块提供稳定的电源。所设计的原理图如下图所示。
系统整体PCB如下图所示,其中为了保证信号传输的稳定性和提高系统的抗干扰性,降低信号传输的失真率,博主对所有的信号走线均采用包地处理。因地线的面积较小时,地线的阻抗会增大,容易导致电源噪声回路产生较高的电压差,进而影响电路中的其他信号,所以本设计采用双面铺铜的方案,进一步提高整个GND的面积,从而让电流在地线上的分布就越均匀,有助于减少噪声和干扰的传播。每块被信号线分割开的铜皮上也都增设了数个过孔,增强其过电流能力。 此外,为了减小信号之间的相关干扰,从而造成信道传输过程中的失真,系统将以IIC通信的OLED显示屏放在了边缘,而有用天线的蓝牙模块放到了板子的下方,同时为避免在高频段工作的天线下方的铜层会对天线信号产生屏蔽作用,模块下方做了禁止铺铜处理。
程序设计部分
系统整体的程序并不难,本质就是用运行初始化后,各个模块逐一初始化,确保每个组件都正常工作。紧接着,OLED显示屏会展示当前机器人的表情,直观地反映出机器人的情绪或状态。随后,语音模块开始识别用户的语音词条,解析用户的指令和需求。根据语音识别的结果,机器人会根据指令做出相应的动作,从而完成与用户的互动。 用户通过麦克风输入语音信号,SU-03T1模块将语音信号转换为电信号并进行数字化处理。接下来,模块利用内置的语音识别算法对数字化后的语音信号进行分析,提取关键特征,并与数据库中的语音模板进行比对。识别过程包括语音信号的预处理、特征提取、模式匹配等多个环节。然后,模块将比对结果转换为文本信息,并将其通过串口打印给STM32F103C8T6单片机。
这是动作部分程序。
#include "stm32f10x.h" // Device header
#include "Servo.h"
#include "Delay.h"
#include "BlueTooth.h"
/*舵机位置
1 2
3 4
*/
//舵机充当腿,括号里的值为0时表示的是腿向前进的方向甩,90度是站立
#define Chongfunumber 2 //动作重复次数
uint16_t PAnumbers=Chongfunumber;//动作重复次数
uint16_t TiaoTurn=0;
uint16_t TiaoTurn2=0;
void Action_relaxed_getdowm(void)
{
Servo_Angle1(20);
Servo_Angle2(20);
Delay_ms(80);
Servo_Angle3(160);
Servo_Angle4(160);
}
void Action_upright(void)//站立
{
Servo_Angle1(90);
Servo_Angle2(90);
Delay_ms(80);
Servo_Angle3(90);
Servo_Angle4(90);
if(WeiBa==1)
{
Action_Mode=9;
}
}
void Action_upright2(void)//站立
{
Servo_Angle3(90);
Servo_Angle4(90);
Delay_ms(80);
Servo_Angle1(90);
Servo_Angle2(90);
if(WeiBa==1)
{
Action_Mode=9;
}
}
void Action_getdowm(void)//趴下
{
Servo_Angle1(20);
Servo_Angle2(20);
Delay_ms(80);
Servo_Angle3(20);
Servo_Angle4(20);
if(WeiBa==1)
{
Action_Mode=9;
}
}
void Action_sit(void)//坐下
{
Servo_Angle1(90);
Servo_Angle2(90);
Delay_ms(80);
Servo_Angle3(20);
Servo_Angle4(20);
if(WeiBa==1)
{
Action_Mode=9;
}
}
//作者是Sngels_wyh只在抖音与B站
void Action_advance(void)//前进
{
while(Action_Mode==4)
{
PAnumbers=Chongfunumber;
while((PAnumbers || Sustainedmove)&& Action_Mode==4)
{
Servo_Angle2(45);
Servo_Angle3(45);
Delay_ms(SpeedDelay);
if(Action_Mode!=4)break;
Servo_Angle1(135);
Servo_Angle4(135);
Delay_ms(SpeedDelay);
if(Action_Mode!=4)break;
Servo_Angle2(90);
Servo_Angle3(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=4)break;
Servo_Angle1(90);
Servo_Angle4(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=4)break;
Servo_Angle1(45);
Servo_Angle4(45);
Delay_ms(SpeedDelay);
if(Action_Mode!=4)break;
Servo_Angle2(135);
Servo_Angle3(135);
Delay_ms(SpeedDelay);
if(Action_Mode!=4)break;
Servo_Angle1(90);
Servo_Angle4(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=4)break;
Servo_Angle2(90);
Servo_Angle3(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=4)break;
PAnumbers--;
}
if(Sustainedmove!=1 && Action_Mode==4)
Action_Mode=2;
}
}
void Action_back(void)//后退
{
while(Action_Mode==5)
{
PAnumbers=Chongfunumber;
while((PAnumbers || Sustainedmove) && Action_Mode==5 )
{
Servo_Angle2(135);
Servo_Angle3(135);
Delay_ms(SpeedDelay);
if(Action_Mode!=5)break;
Servo_Angle1(45);
Servo_Angle4(45);
Delay_ms(SpeedDelay);
if(Action_Mode!=5)break;
Servo_Angle2(90);
Servo_Angle3(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=5)break;
Servo_Angle1(90);
Servo_Angle4(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=5)break;
Servo_Angle1(135);
Servo_Angle4(135);
Delay_ms(SpeedDelay);
if(Action_Mode!=5)break;
Servo_Angle2(45);
Servo_Angle3(45);
Delay_ms(SpeedDelay);
if(Action_Mode!=5)break;
Servo_Angle1(90);
Servo_Angle4(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=5)break;
Servo_Angle2(90);
Servo_Angle3(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=5)break;
PAnumbers--;
}
if(Sustainedmove!=1 && Action_Mode==5)
Action_Mode=2;
}
}
void Action_Lrotation(void)//向左旋转
{
while(Action_Mode==6)
{
PAnumbers=Chongfunumber;
PAnumbers=PAnumbers+Chongfunumber;
while((PAnumbers || Sustainedmove) && Action_Mode==6)
{
Servo_Angle2(45);
Servo_Angle3(135);
Delay_ms(SpeedDelay);
if(Action_Mode!=6)break;
Servo_Angle1(45);
Servo_Angle4(135);
Delay_ms(SpeedDelay);
if(Action_Mode!=6)break;
Servo_Angle2(90);
Servo_Angle3(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=6)break;
Servo_Angle1(90);
Servo_Angle4(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=6)break;
PAnumbers--;
}
if(Sustainedmove!=1 && Action_Mode==6)
Action_Mode=2;
}
}
void Action_Rrotation(void)//向右旋转
{
while(Action_Mode==7)
{
PAnumbers=Chongfunumber;
PAnumbers=PAnumbers+Chongfunumber;
while((PAnumbers || Sustainedmove) && Action_Mode==7)
{
Servo_Angle1(45);
Servo_Angle4(135);
Delay_ms(SpeedDelay);
if(Action_Mode!=7)break;
Servo_Angle2(45);
Servo_Angle3(135);
Delay_ms(SpeedDelay);
if(Action_Mode!=7)break;
Servo_Angle1(90);
Servo_Angle4(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=7)break;
Servo_Angle2(90);
Servo_Angle3(90);
Delay_ms(SpeedDelay);
if(Action_Mode!=7)break;
PAnumbers--;
}
if(Sustainedmove!=1 && Action_Mode==7)
Action_Mode=2;
}
}
void Action_Swing(void)//摇摆
{
while(Action_Mode==8)
{
for(uint8_t i=30;i<150;i++)
{
Servo_Angle1(i);
Servo_Angle2(i);
Servo_Angle3(i);
Servo_Angle4(i);
Delay_ms(SwingDelay);
if(Action_Mode!=8)break;
}
for(uint8_t i=150;i>30;i--)
{
Servo_Angle1(i);
Servo_Angle2(i);
Servo_Angle3(i);
Servo_Angle4(i);
Delay_ms(SwingDelay);
if(Action_Mode!=8)break;
}
if(Action_Mode!=8)break;
}
}
void Action_SwingTail(void)//摇尾巴
{
Delay_ms(60);
while(Action_Mode==9)
{
for(uint8_t i=30;i<150;i++)
{
WServo_Angle(i);
Delay_ms(SwingDelay);
if(Action_Mode!=9)break;
}
for(uint8_t i=150;i>30;i--)
{
WServo_Angle(i);
Delay_ms(SwingDelay);
if(Action_Mode!=9)break;
}
if(Action_Mode!=9)break;
}
Delay_ms(100);
}
void Action_JumpU(void)//向前跳
{
if(TiaoTurn==0)
{
Servo_Angle1(140);
Servo_Angle4(35);
Delay_ms(SpeedDelay);
Servo_Angle2(140);
Servo_Angle3(35);
Delay_ms(SpeedDelay+80);
Action_Mode=2;
TiaoTurn=1;
}
else
{
Servo_Angle2(140);
Servo_Angle3(35);
Delay_ms(SpeedDelay);
Servo_Angle1(140);
Servo_Angle4(35);
Delay_ms(SpeedDelay+80);
Action_Mode=2;
TiaoTurn=0;
}
}
void Action_JumpD(void)//向后跳
{
if(TiaoTurn2==0){
Servo_Angle4(35);
Servo_Angle1(140);
Delay_ms(SpeedDelay);
Servo_Angle3(35);
Servo_Angle2(140);
Delay_ms(SpeedDelay);
Action_Mode=12;
TiaoTurn2=1;
}
else
{
Servo_Angle3(35);
Servo_Angle2(140);
Delay_ms(SpeedDelay);
Servo_Angle4(35);
Servo_Angle1(140);
Delay_ms(SpeedDelay);
Action_Mode=12;
TiaoTurn2=0;
}
}
void Action_Hello(void)
{
Servo_Angle3(20);
Servo_Angle4(45);
Delay_ms(80);
Servo_Angle1(90);
while(Action_Mode==13)
{
if(Action_Mode!=13)break;
for(int i=0;i<=45;i++)
{
if(Action_Mode!=13)break;
Servo_Angle2(i);
Delay_ms(SwingDelay);
}
for(int i=45;i>0;i--)
{
if(Action_Mode!=13)break;
Servo_Angle2(i);
Delay_ms(SwingDelay);
}
if(Action_Mode!=13)break;
}
}
void Action_stretch(void)//伸懒腰
{
Servo_Angle3(90);
Servo_Angle4(90);
Delay_ms(80);
for(int i=90;i>10;i--)
{
Servo_Angle1(i);
Servo_Angle2(i);
if(Action_Mode!=14)break;
Delay_ms(15);
}
for(int i=10;i<90;i++)
{
Servo_Angle1(i);
Servo_Angle2(i);
if(Action_Mode!=14)break;
Delay_ms(15);
}
for(int i=90;i<170;i++)
{
Servo_Angle3(i);
Servo_Angle4(i);
if(Action_Mode!=14)break;
Delay_ms(15);
}
for(int i=170;i>90;i--)
{
Servo_Angle3(i);
Servo_Angle4(i);
if(Action_Mode!=14)break;
Delay_ms(15);
}
if(Action_Mode==14)
Action_Mode=15;
}
void Action_Lstretch(void)//后腿拉伸
{
int breakvalue=1;
int temp=3;
while(breakvalue)
{
Servo_Angle1(90);
Servo_Angle2(20);
Delay_ms(60);
Servo_Angle4(110);
for(int i=90;i<180;i++)
{
if(Action_Mode!=15)break;
Servo_Angle3(i);
Delay_ms(6);
}
while(temp && Action_Mode==15)
{
for(int i=180;i>150;i--)
{
if(Action_Mode!=15)break;
Servo_Angle3(i);
Delay_ms(15);
}
temp--;
}
if(Action_Mode!=15)break;
Delay_ms(100);
Servo_Angle1(90);
Servo_Angle2(90);
if(Action_Mode!=15)break;
Delay_ms(80);
Servo_Angle3(90);
Servo_Angle4(90);
Delay_ms(100);
if(Action_Mode!=15)break;
temp=3;
Servo_Angle2(90);
Servo_Angle1(20);
if(Action_Mode!=15)break;
Delay_ms(60);
Servo_Angle3(110);
for(int i=90;i<180;i++)
{
if(Action_Mode!=15)break;
Servo_Angle4(i);
Delay_ms(6);
}
while(temp && Action_Mode==15)
{
for(int i=180;i>150;i--)
{
if(Action_Mode!=15)break;
Servo_Angle4(i);
Delay_ms(15);
}
temp--;
}
if(Action_Mode==15)
Action_Mode=2;
breakvalue=0;
}
}
这是表情管理部分代码
点击从零打造STM32智能桌面机器狗查看全文。