因为之前开设过嵌入式想过课程所以对stm32了解比较多,但是感觉学的东西停留在纸面上,所以跟着江科大一起边学边做,学了一半突然起兴感觉自己可以做一个小车了,然后就开始着手设计。主要很多模块的调试和设计花比较长的时间。写这篇文章的目的是简单记录一下我购买的小车设计,代码编写的过程。因为我买的是一款配置非常简单的小车,所以我感觉这个项目的主要难点之一就是怎么利用现有的材料来设计小车。当然项目还有很多地方自己理解不周,自己也是第一次接触,分享一下自己的学习经历。
主要技术:手机连接蓝牙使用PWM波控制直流电机和舵机
(一)材料准备
MG90S舵机
直流电机
TB6612FNG电机驱动模块
HC-05蓝牙模块
USB转TTL转换器
STM32
面包板
杜邦线若干
热熔枪(或者502)
小车框架(我再淘宝上购买的13.9¥)
商家链接: link
(二)线路连接
使用stlink调试,
STLink
stlink | 接口 |
---|---|
SWCLK | stm32SWCLK |
SWDIO | stm32SWIO |
GND | stm32gnd |
3.3V | stm32vcc |
5v | 舵机模块 |
5v | 电机驱动模块 |
舵机
舵机 | 接口 |
---|---|
红线 | STLINK的5V |
棕线 | GND |
橙线 | PA6 |
TB6612FNG电机驱动模块
电机驱动 | 接口 |
---|---|
PWMA | PA2 |
AIN2 | PA3 |
AIN1 | PA4 |
STBY | GND |
VM | STLINK的5V |
VCC | 3.3V |
GND | GND |
AO1 | 直流电机任意一根引线 |
AO2 | 直流电机任意一根引线 |
蓝牙模块
蓝牙 | 接口 |
---|---|
RXD | PA9 |
TXD | PA10 |
GND | GND |
VCC | 3.3V |
直流电机
参照TB6612FNG电机驱动模块
调试模块(1):旋转编码器
旋转编码器 | 接口 |
---|---|
A | PA0 |
B | PA1 |
GND | GND |
VCC | 3.3V |
调试模块(2):OLED
OLED | 接口 |
---|---|
SCL | PB8 |
SDA | PB9 |
GND | GND |
VCC | 3.3V |
总结一下:我在开发过程一直借助面包板和STlink,目前我还没实现有让小车脱离stlink运行,但是我感觉难度应该也不大。程序烧入stm32后,只需要在面包板上加入一个电池模块,为面包板供3.3v电压和5v电压,然后使用面包板给stm32、舵机和电机驱动模块供电,再将面包板放在小车上即可实现独立运行。
注意事项:在开发过程中踩了很多坑。
(1)面包板上下两个电源和接地的槽的中间处可能是断路!!
(2)stm32可能部分引脚损坏无法正常输入输出!!
(3)杜邦线连接一定要准确,很多错误可能都是杜邦线没查好或者错插导致的
我的一些解决策略
(1)使用LED小灯来检测电路(物理Debug)
(2)使用了上述的两个调试模块,边做边调试
(三)小车拼装
(1)买回来是这样的,该商家卖小车是只需要按上电源,没有控制系统,小车只能直着跑,非常简陋
(2)我在尝试使用皮筋传输动力时发,发现自带的直流电机输出的扭矩不能驱动旋转。所以我选择了直接使用齿轮带动旋转的方式,如图所示
在后轮车轴上串上一个大齿轮,直流电机上加上一个小齿轮,齿轮大小正好匹配可以咬合!
注意车轴架安装不要太靠后
注意要使用黄色的圈圈固定车轴位置*
(3)转向系统的设计。
在我购置的这套小车里,有两个直流电机,四个固定车轴的三角形固定架,所以资源非常有限。查阅资料发现网上大多数小车的转向系统一般都采用对称车轮不同的旋转方向达到小车转向的功能,但是一方面采用了一体化车轴无法实现对称车轴的轮子旋转方向不同,另一方面我觉得那种转弯方式不够帅。
但是如何设计可以转向的小车呢?而且用于固定车轴的三角形固定架只有四个,在固定后车轮时已经使用了两个。如果使用两个固定的固定架那么前车轮就无法转向,所以只能固定一个,另一个前后移动配合实现车轴转动的效果!恰巧我手边有多余的舵机,问题又来了?舵机输出的的半圆形的力,而我需要前后的移动,且输出的力有较好的定位效果(如何不能很好的定位那么小车无法实现平稳运行,就连最基本的直线行驶可能都做不到)保证方向的准确和可持续!最开始我尝试直接使用热熔胶将舵机和三角形固定架粘在一起,不过在测试中发现舵机转动的时候,粘合处运动发现和距离刚性过大,直接将热熔胶扯断,借此灵感我想到使用弹性物体进行固定!且购买的小车套件中多了两个短的铁杆,配合上三角形固定架和黄色圆圈的定位装置可以保证车轴在同一水平高度,同时极大扩展的该三角形固定架的受力的方和角度,终于我的天才方案诞生了。
正面设计图
背面设计图
此处使用LED灯的引脚铁丝的作用是将皮筋固定在舵机摇杆上
使用热熔胶固定舵机
注意调整舵机的位置,保证舵机摇杆朝下时是舵机大概90°的位置
led灯在项目开发过程中起到了太大太大的作用
自此小车的拼装和设计过程就完成了!接下来就代码开发部分
(四)代码开发
代码的框架采用的是江科大!系统文件部分就不多赘述,和江科大一致,且省去所有文件的头文件
主函数
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"
#include "LightSensor.h"
#include "OLED.h"
#include "CountSensor.h"
//#include "Timer.h"
#include "PWM.h"
#include "Servo.h"
#include "Motor.h"
#include "Serial.h"
#include "HC05.h"
#include "PWM_servo.h"
uint8_t RxSTA = 1;
char RxData[100] = "None";
int8_t Num;
uint16_t ANGLE;
int main(void)
{
//GPIO_SetBits(GPIOC,GPIO_Pin_10);
//GPIO_ResetBits(GPIOC,GPIO_Pin_0);
//GPIO_WriteBit()
//GPIO_Write()
//LED_init();
//KEY_Init();
OLED_Init();
CountSensor_Init();
//PWM_Init();
Servo_Init();
//MOTOR_INIT();
Motor_Init();
Serial_Init();
PWM_servo_Init();
//PWM_servo_SetCompare3(1250);
//GPIO_SetBits(GPIOA,GPIO_Pin_6);
//GPIO_ResetBits(GPIOA,GPIO_Pin_9);
//Timer_Init();
HC05_Init();
OLED_ShowString(1,1,"Designed By Bi");
//OLED_ShowString(2,1,"202178040202");
OLED_ShowString(2,1,"Count:");
OLED_ShowString(3,1,"direction:");
OLED_ShowString(4,1,"turn:");
//PWM_SetCompare4(ANGLE);
//Motor_SetSpeed(0);
//Motor_SetSpeed(70);
while(1)
{
//HC05_GetData(RxData);
char x;
x = Serial_GetRxData();
//Motor_SetSpeed(0);
HC05_GetData(RxData);
Num += COUNT_GET(); //获取自上此调用此函数后,旋转编码器的增量值,并将增量值加到Num上
OLED_ShowSignedNum(2,7, Num, 5);
//OLED_ShowChar(3,8,x);
while(Serial_GetRxFlag())
{
if(x == 'w')
{
Motor_SetSpeed(40);
OLED_ShowString(3,11,"go");
}
else if(x == 's')
{
Motor_SetSpeed(-40);
OLED_ShowString(3,11,"back");
}
else if(x == 'r')
{
PWM_servo_SetCompare3(1000);
OLED_ShowString(4,6,"right");
//Delay_s(1);
//PWM_servo_SetCompare3(1200);
}
else if(x == 'l')
{
PWM_servo_SetCompare3(1300);
OLED_ShowString(4,6,"left");
//Delay_s(1);
//PWM_servo_SetCompare3(1200);
}
else if(x == 'p')
{
Motor_SetSpeed(0);
PWM_servo_SetCompare3(1200);
OLED_ShowString(3,11,"stop");
}
}
// if(RxSTA == 0)
// {
// OLED_ShowString(3,8,RxData);
// RxSTA = 1;
// if(RxData[1] == 'w')
// {
// Motor_SetSpeed(90);
// OLED_ShowSignedNum(4,7,50,5);
// }
// if(RxData[1] == 's')
// {
// Motor_SetSpeed(-90);
// OLED_ShowSignedNum(4,7,-50,5);
// }
// else
// {
// Motor_SetSpeed(0);
// OLED_ShowSignedNum(4,7,0,5);
// }
// }
// OLED_ShowSignedNum(4,7,Num *5,5);
// Motor_SetSpeed(Num * 5);
// ANGLE = Num * 50 + 1200;
// OLED_ShowSignedNum(4,6,ANGLE,5);
// PWM_servo_SetCompare3(ANGLE);
// PWM_servo_SetCompare3(ANGLE);
// PWM_SetCompare4(ANGLE);
// Servo_SetAngle(ANGLE);
// for(ANGLE = 1;ANGLE<=180;ANGLE++)
// {
//PWM_SetCompare4(ANGLE);
//}
// PWM_SetCompare1(Num * 10);
// for (i = 0; i <= 100; i++)
// {
// PWM_SET(i); //依次将定时器的CCR寄存器设置为0~100,PWM占空比逐渐增大,LED逐渐变亮
// Delay_ms(10); //延时10ms
// }
// for (i = 0; i <= 100; i++)
// {
// PWM_SET(100 - i); //依次将定时器的CCR寄存器设置为100~0,PWM占空比逐渐减小,LED逐渐变暗
// Delay_ms(10); //延时10ms
// }
// NUM += Encoder_Get();
//
//
// flag = Get_KeyNum();//每次while更新一次
// if(flag == 1)
// {
// LED0_ON();
// Delay_ms(100);
// LED0_OFF();
// LED1_ON();
// Delay_ms(100);
// LED1_OFF();
// }
// else
// {
// LED0_OFF();
// LED1_OFF();
// }
// if(GetLightData() == 1)
// {
// LED2_ON();
// }
// else
// {
// LED2_OFF();
// }
}
}
舵机驱动模块
舵机PWM波生成与控制模块
#include "stm32f10x.h" // Device header
void PWM_servo_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //开启TIM2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);