效果
基于STM32单片机的桌面宠物机器人
概要
语音模块:ASR PRO,通过天问block软件烧录语音指令
主控芯片:STM32F103C8T6 使用HAL库
屏幕:0.96寸OLED屏,用来显示表情
4个舵机,用来当作四只腿
底部一个面包板

分析
初始化代码,使用TIM3定时器的四个通道输出PWM驱动舵机,控制腿部的运动
cpp
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
OLED_Init();
OLED_Clear();
OLED_ShowImage(0, 0, 128, 64, BMP1);
mode_stand();
ASR PRO获取到语音后通过串口通信把数据发送到STM32,在单片机内使用中断的方式获取语音数据,,然后根据语音指令判断当前的动作
cpp
while (1) {
HAL_UART_Receive_IT(&huart1, &command, 1);
if (command == 0x32) { // 前进
mode_forward();
} else if (command == 0x31) {
mode_slowstand();
} else if (command == 0x33) { // 后退
mode_behind();
} else if (command == 0x34) { // 左转
mode_left();
} else if (command == 0x35) { // 右转
mode_right();
} else if (command == 0x36) { // 前后摇摆
mode_swing_qianhou();
} else if (command == 0x37) { // 左右摇摆
mode_swing_zuoyou();
} else if (command == 0x38) { // 跳舞
mode_dance();
} else if (command == 0x39) { // 立正
mode_stand();
} else if (command == 0x41) { // 起身
mode_slowstand();
} else if (command == 0x61) { // 坐下
mode_strech();
} else if (command == 0x63) { // 伸懒腰
mode_lanyao();
} else if (command == 0x64) { // 抬头
mode_headup();
} else if (command == 0x65) { // 趴下睡觉
mode_sleeppa();
} else if (command == 0x66) { // 卧下睡觉
mode_sleepwo();
} else if (command == 0x68) { // 睡觉
mode_sleepwo();
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
分别展示对应的表情和动作,OLED直接用的现成的库
cpp
#include "Mode.h"
#include <stdlib.h>
#include "Movement.h"
#include "OLED.h"
#include "gpio.h"
#include "main.h"
extern uint8_t command;
uint8_t previousCommand = 0;
void mode_forward(void) // 前进
{
OLED_ShowImage(0, 0, 128, 64, BMP2); // 前进脸
move_forward();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
}
void mode_behind(void) // 后退
{
OLED_ShowImage(0, 0, 128, 64, BMP2); // 前进脸
move_behind();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
}
void mode_left(void) // 左转
{
OLED_ShowImage(0, 0, 128, 64, BMP3); // 左转脸
move_left();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
}
void mode_right(void) // 右转
{
OLED_ShowImage(0, 0, 128, 64, BMP4); // 右转脸
move_right();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
}
void mode_swing_qianhou(void) // 前后摇摆
{
OLED_ShowImage(0, 0, 128, 64, BMP11); // 迷糊脸
move_shake_qianhou();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
}
void mode_swing_zuoyou(void) // 左右摇摆
{
OLED_ShowImage(0, 0, 128, 64, BMP11); // 迷糊脸
move_shake_zuoyou();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
}
void mode_dance(void) // 跳舞
{
OLED_ShowImage(0, 0, 128, 64, BMP5); // 特殊脸
move_dance();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
}
void mode_stand(void) // 立正
{
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
move_stand();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
command = 0;
HAL_Delay(1000);
}
void mode_slowstand(void) // 起身
{
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
move_slow_stand(previousCommand);
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
command = 0;
}
void mode_strech(void) // 坐下
{
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
move_slow_stand(previousCommand);
OLED_ShowImage(0, 0, 128, 64, BMP2); // 前进脸,
move_stretch();
OLED_ShowImage(0, 0, 128, 64, BMP12); // 猫猫脸
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
command = 0;
}
void mode_twohands(void) // 交替抬手
{
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
move_stand();
move_two_hands();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
command = 0;
}
void mode_lanyao(void) // 懒腰
{
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
move_slow_stand(previousCommand);
OLED_ShowImage(0, 0, 128, 64, BMP9); // 开心脸
lan_yao();
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
command = 0;
}
void mode_headup(void) // 抬头
{
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
move_slow_stand(previousCommand);
OLED_ShowImage(0, 0, 128, 64, BMP10); // 调皮脸
move_head_up();
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
previousCommand = command;
command = 0;
}
void mode_sleeppa(void) // 趴下睡觉
{
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
move_slow_stand(previousCommand);
if (rand() % 2) { // 随机产生两种表情中的一种
OLED_ShowImage(0, 0, 128, 64, BMP6); // 普通睡觉脸
} else {
OLED_ShowImage(0, 0, 128, 64, BMP8); // 酣睡脸
}
move_sleep_p();
previousCommand = command;
command = 0;
}
void mode_sleepwo(void) // 卧下睡觉
{
OLED_ShowImage(0, 0, 128, 64, BMP1); // 立正脸
move_slow_stand(previousCommand);
if (rand() % 2) { // 随机产生两种表情中的一种
OLED_ShowImage(0, 0, 128, 64, BMP6); // 普通睡觉脸
} else {
OLED_ShowImage(0, 0, 128, 64, BMP8); // 酣睡脸
}
move_sleep_w();
previousCommand = command;
command = 0;
}
void mode_nanshou(void) // 难受
{
OLED_ShowImage(0, 0, 128, 64, BMP2); // 前进脸
move_sleep_w();
previousCommand = command;
command = 0;
}
部分动作实现,分别设置对应腿的角度,通过延时达到效果
cpp
void move_stand(void) { // 站立
Servo_SetAngle1(90);
Servo_SetAngle2(90);
Servo_SetAngle3(90);
Servo_SetAngle4(90);
HAL_Delay(500);
}
void move_forward(void) { // 前进
Servo_SetAngle1(135);
Servo_SetAngle4(45);
HAL_Delay(movedelay);
Servo_SetAngle2(45);
Servo_SetAngle3(135);
HAL_Delay(movedelay);
Servo_SetAngle1(90);
Servo_SetAngle4(90);
HAL_Delay(movedelay);
Servo_SetAngle2(90);
Servo_SetAngle3(90);
HAL_Delay(movedelay);
Servo_SetAngle2(135);
Servo_SetAngle3(45);
HAL_Delay(movedelay);
Servo_SetAngle1(45);
Servo_SetAngle4(135);
HAL_Delay(movedelay);
Servo_SetAngle2(90);
Servo_SetAngle3(90);
HAL_Delay(movedelay);
Servo_SetAngle1(90);
Servo_SetAngle4(90);
HAL_Delay(movedelay);
}
void move_behind(void) { // 后退
Servo_SetAngle1(45);
Servo_SetAngle4(135);
HAL_Delay(movedelay);
Servo_SetAngle2(135);
Servo_SetAngle3(45);
HAL_Delay(movedelay);
Servo_SetAngle1(90);
Servo_SetAngle4(90);
HAL_Delay(movedelay);
Servo_SetAngle2(90);
Servo_SetAngle3(90);
HAL_Delay(movedelay);
Servo_SetAngle2(45);
Servo_SetAngle3(135);
HAL_Delay(movedelay);
Servo_SetAngle1(135);
Servo_SetAngle4(45);
HAL_Delay(movedelay);
Servo_SetAngle2(90);
Servo_SetAngle3(90);
HAL_Delay(movedelay);
Servo_SetAngle1(90);
Servo_SetAngle4(90);
HAL_Delay(movedelay);
}