原视频:好,自制一个桌面宠物!_哔哩哔哩_bilibili
基础所需:基础电路认识,C语言,STM32开发,STM32CUBEIDE或CUBEMX和Keil使用(重要),一点点艺术细胞、一点点耐心。
CAUTION:本文重点在代码部分的开源,是基于HAL库。硬件手工部分不出教程(没必要)可以直接看视频P2,文末附步态参考出处,接线图,舵机安排。
硬件配置:
主控:STM32F103C8T6 粉色沉金板(也可以用C6T6,价格便宜一半)
舵机:SG90 *4
屏幕:1.3寸OLED (IIC驱动)
供电:锂电池 (3.7V 30mm*40mm 800mah,建议购买尺寸合适的飞控专用锂电池或两块普通锂电池并联,输出功率大,不需要后续拆保护板) + 锂电池充放电模块(不会自动断电、适配3.7V锂电池、输出5V、充放电同口)
蓝牙:低功耗蓝牙(BLE,串口透传,便宜又好用)
软件配置:
手机app开发:appinventor制作(这里不附教程,因为我也不熟,唯一有用的建议是我的蓝牙模组要用BLE而不是普通蓝牙,需另外下载并配置,建议另寻他佬教程
单片机开发:
平台:STM32CUBEIDE(等效STM32CUBEMX+Keil)
软件开源:
提纲:
1.定时器pwm波输出
2.串口信息交互
3.OLED显示
CUBEMX配置:
(这里没有配置驱动屏幕的IIC,选择直接软件模拟,文末会附驱动代码。
1.RCC时钟配置:
(无脑选择外部时钟,无脑拉最高频。
2.定时器配置PWM输出模式:
(一个定时器直接开四个PWM通道即可,并关注输出引脚是否正确。根据舵机参数,配置PWM频率为50Hz。通道一为前右脚,通道二为后右脚,通道三为前左脚,通道四为后左脚,脚的位置和角度见文末图,是参考文末大佬的视频的
注意引脚为PA0,PA1,PA2,PA3。
3.配置串口
(也很无脑,但要根据蓝牙模块的参数配置传输速率(Baud Rate),我是115200。
并且开中断NVIC,优先级按经验来填2就可。
考虑到单片机引脚位置,需要把串口引脚重定向到PB6和PB7。
4.IIC引脚配置(软件模拟IIC,引脚任意两个IO就可以,要命名成这个是因为和驱动代码匹配)
小Tip:
经验所得,把系统滴答时钟的优先级拉最高可以防止卡死在HAL_Delay里面。
5.最后生成工程,用keil的这里改成MDK_ARM
推荐打勾这个,为每个外设建.c和.h文件,使工程结构更清晰。
最后直接ctrl+s即可生成工程(用STM32CUBEMX+Keil的点Generate code建立工程)
代码部分:(最后会附完整代码,其中LED的控制可有可无
(即“HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);”)。
1.PWM波输出(姿态
uint16_t angle(uint8_t angle) //角度CCR值转换 { return angle*2000/180+500; } void Rbt_Init(void) //立正 { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(90)); HAL_Delay(100); } void move_forward(void) //前进 { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(135)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(45)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(45)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(135)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(90)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(90)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(135)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(45)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(45)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(135)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(90)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(90)); HAL_Delay(move_delay); } void move_behind(void) //后退 { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(45)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(135)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(135)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(45)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(90)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(90)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(45)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(135)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(135)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(45)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(90)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(90)); HAL_Delay(move_delay); } void move_right(void) //右转 { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(45)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(45)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(135)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(135)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(90)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(90)); HAL_Delay(move_delay); } void move_left(void) //左转 { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(135)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(135)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(45)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(45)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(90)); HAL_Delay(move_delay); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(90)); HAL_Delay(move_delay); } void move_swing(void) //摇摆 { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(130)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(130)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(50)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(50)); HAL_Delay(250); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(50)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(50)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(130)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(130)); HAL_Delay(250); } void move_stretch(void){ //伸懒腰+坐下招手 __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_3,angle(90)); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4,angle(90)); if(TIM2->CCR1CCR3>angle(25)){ for(uint8_t i=0;iangle(25)){ for(uint8_t i=0;i