测试环境
大疆开发板 C型
STM32F407IGH6TR 芯片
大疆M3508直流无刷电机2
大疆C620无刷电机调速器2
大疆M2006直流无刷电机2
大疆C610无刷电机调速器2
蓝牙模块
蓝牙调试助手APP
RT-Thread操作系统
面向对象模块接口设计
双舵轮底盘,四个小全向轮为支撑轮
代码工程
stm32f407_DJIc.rar
工程基础:
LED频闪指示灯模块: https://www.yuque.com/wangxi_chn/qaxke0/mltilp
DJIC610620电机群模块:https://www.yuque.com/wangxi_chn/qaxke0/ulrbrk
蓝牙驱动遥控模块:https://www.yuque.com/wangxi_chn/qaxke0/dmwgwv
工程组成
将电机群和蓝牙进一步封装为底盘控制的模块。命名为
- App_SteerWheelBase.c
-
App_SteerWheelBase.h
#define SPEEDWHEELID_LEFT DjiC610620ID_1
#define SPEEDWHEELID_RIGHT DjiC610620ID_2
#define ANGLEWHEELID_LEFT DjiC610620ID_3
#define ANGLEWHEELID_RIGHT DjiC610620ID_4
指定使用的电机对应的电机号
- SPEEDWHEELID_LEFT:左侧速度轮
- SPEEDWHEELID_RIGHT:右侧速度轮
- ANGLEWHEELID_LEFT:左侧转向轮
ANGLEWHEELID_RIGHT:右侧转向轮
enum STEERWHEELBASE_STATION
{
STATIC = 0,
GO_AHEAD,
GO_AHEAD_RIGHT,
GO_RIGHT,
GO_RIGHT_BACK,
GO_BACK,
GO_BACK_LEFT,
GO_LEFT,
GO_LEFT_AHEAD,
ROTATE_CLOCKWISE,
ROTATE_UNCLOCKWISE,
};
枚举指示底盘运动的各种状态,包括八个方位和顺时针逆时针转动
struct _APP_STEERWHEELBASE
{
/* Property */
rt_uint16_t SPEEDWHEELRATE;
rt_uint16_t ANGLEWHEELRATE;
MODULE_DjiC610620GROUP dev_motorGroup;
MODULE_BLUETOOTHHC06 dev_btControler;
模块结构体中的必要初始化属性
- SPEEDWHEELRATE:3508电机转速比率(电机群的控制针对的永远是转子得到的原始数据,通过设置这个参数,实现减速比的转换,齿轮的转换等,映射到轮子的转速)
- ANGLEWHEELRATE:2006电机角度转换比率,(电机群的控制针对的永远是转子得到的原始数据,通过设置这个参数,实现减速比的转换,齿轮的转换等,映射到转向轮转过的角度)
- dev_motorGroup:使用的电机群模块实体(结构体嵌套)
- dev_btControler:使用的蓝牙模块实体(结构体嵌套)
/* Value */
enum STEERWHEELBASE_STATION Value_station;
rt_uint16_t Value_DataShowPeriod;
rt_int16_t Value_Speed; //mm/s
rt_int16_t Value_Angle; //°
模块结构体中的中间数值
- Value_station:当前底盘状态
- Value_DataShowPeriod:蓝牙回传显示数据的周期
- Value_Speed:底盘运动速度
- Value_Angle:转向轮转过的角度
/* Method */
void (*Method_Init)(struct _APP_STEERWHEELBASE *app);
void (*Method_OrderUpdate)(struct _APP_STEERWHEELBASE *app);
void (*Method_DataUpdate)(struct _APP_STEERWHEELBASE *app);
void (*Method_DataShow)(struct _APP_STEERWHEELBASE *app);
void (*Method_Control)(struct _APP_STEERWHEELBASE *app);
};
typedef struct _APP_STEERWHEELBASE APP_STEERWHEELBASE;
模块结构体提供的方法函数(函数指针成员)
- Method_Init:模块初始化函数,不为用户调用,在调用Config全局函数时自动进行
- Method_OrderUpdate:模块命令更新函数,在某一线程中被用户调用,用来更新蓝牙遥控下达的命令
- Method_DataUpdate:模块数据更新函数,在某一线程中被用户调用,用来更新电机回传数据
- Method_DataShow:模块数据显示函数,在某一线程中被用户调用,用来回传到手机中参数,比如当前车速等
- Method_Control:模块控制函数,在某一线程中被用户调用,用来发送电机的控制报文
/* Glodal Method */
rt_err_t App_SteerWheelBase_Config(APP_STEERWHEELBASE *App_SteerWheelBase);
使能模块的全局函数
这里重点讲述底盘控制的方法函数
static void App_SteerWheelBaseControl(APP_STEERWHEELBASE *App_SteerWheelBase)
{
rt_int8_t ClockWiseFlag_L = 1;
rt_int8_t ClockWiseFlag_R = 1;
指示底盘顺时针逆时针旋转的电机控制系数
switch(App_SteerWheelBase->dev_btControler.Value_keyMask)
{
case (0x0001<<0):
App_SteerWheelBase->Value_station = GO_LEFT_AHEAD;
App_SteerWheelBase->Value_Speed += 5;
App_SteerWheelBase->Value_Angle = 45;
App_SteerWheelBase->dev_btControler.Value_keyMask = 0;
break;
...
...
...
case (0x0001<<11):
App_SteerWheelBase->Value_station = ROTATE_CLOCKWISE;
App_SteerWheelBase->Value_Speed += 5;
App_SteerWheelBase->Value_Angle = 0;
App_SteerWheelBase->dev_btControler.Value_keyMask = 0;
break;
}
读取蓝牙模块下的按键标识掩码(在模块的命令更新方法中被标记哪个按键被按下)
- 根据标识,修改底盘模块状态、控制参数(速度,角度)
清空标识,放置反复作用(这里为什么不放在整个switch后清空,避免按键还未发生作用就没清空,影响控制效率,确保按键生效,修改控制参数后再清空)
if(App_SteerWheelBase->Value_station == ROTATE_CLOCKWISE)
{
ClockWiseFlag_L = 1;
ClockWiseFlag_R = -1;
}
else if(App_SteerWheelBase->Value_station == ROTATE_UNCLOCKWISE)
{
ClockWiseFlag_L = -1;
ClockWiseFlag_R = 1;
}
else
{
ClockWiseFlag_L = 1;
ClockWiseFlag_R = 1;
}
根据底盘状态(顺时针/逆时针),修改参数值
/* If open the blue tooth connect check, and now is disconnected, stop all movement */
if( App_SteerWheelBase->dev_btControler.ConnectCheckSwitch == 1 &&
App_SteerWheelBase->dev_btControler.ConnectStatus == DISCONNECTED)
{
App_SteerWheelBase->Value_Angle = 0;
App_SteerWheelBase->Value_Speed = 0;
}
蓝牙掉线保护,蓝牙是否发生掉线在蓝牙数据发送中已判断,这里直接读取状态
当蓝牙保护已开启,而且发生掉线时,强制制动,角度归零 ```c App_SteerWheelBase->dev_motorGroup.Value_module_DjiC610620[ANGLEWHEELID_LEFT].Value_motor_AimAngle = App_SteerWheelBase->Value_Angle App_SteerWheelBase->ANGLEWHEELRATE; App_SteerWheelBase->dev_motorGroup.Value_module_DjiC610620[ANGLEWHEELID_RIGHT].Value_motor_AimAngle = App_SteerWheelBase->Value_Angle App_SteerWheelBase->ANGLEWHEELRATE;
App_SteerWheelBase->dev_motorGroup.Value_module_DjiC610620[SPEEDWHEELID_LEFT].Value_motor_AimRPM = ClockWiseFlag_L App_SteerWheelBase->Value_Speed App_SteerWheelBase->SPEEDWHEELRATE; App_SteerWheelBase->dev_motorGroup.Value_module_DjiC610620[SPEEDWHEELID_RIGHT].Value_motor_AimRPM = ClockWiseFlag_R App_SteerWheelBase->Value_Speed App_SteerWheelBase->SPEEDWHEELRATE;
App_SteerWheelBase->dev_motorGroup.Method_Send(&(App_SteerWheelBase->dev_motorGroup));
- 将底盘参数作用于电机群上,发送电机控制报文
<a name="fhP7i"></a>
## main
- 初始化配置
```c
MODULE_LED dev_led_state =
{
.pin = GET_PIN(H, 10),
.Switch = 1,
.LED_TIME_CYCLE = 4000,
.LED_TIME_OUTPUT = 200
};
MODULE_LED dev_led_alarm =
{
.pin = GET_PIN(H, 12),
.Switch = 1,
.LED_TIME_CYCLE = 4000,
.LED_TIME_OUTPUT = 200
};
频闪指示灯(运行灯和警示灯)
APP_STEERWHEELBASE app_SteerWheelBase = {
.SPEEDWHEELRATE = 189 ,//45*23/11*3591/187*2*3.1416/60
.ANGLEWHEELRATE = 148 ,//66/16*36
.Value_DataShowPeriod = 500,
/* motor device */
.dev_motorGroup = {
.Property_CanDevName = "can1",
/* Left Speed Wheel */
.Value_module_DjiC610620[SPEEDWHEELID_LEFT] = {
.Enable = 1,
.Mode = DjiC610620MODE_SPEED,
.PID_Speed = {
.Property_Kp = 5, .Property_Ki = 0, .Property_Kd = 0, .Property_dt = 0.005,
.Property_integralMax = 500, .Property_AimMax = 9000, .Property_OutputMax =16300},},
/* Right Speed Wheel */
.Value_module_DjiC610620[SPEEDWHEELID_RIGHT] = {
.Enable = 1,
.Mode = DjiC610620MODE_SPEED,
.PID_Speed = {
.Property_Kp = 5, .Property_Ki = 0, .Property_Kd = 0, .Property_dt = 0.005,
.Property_integralMax = 500, .Property_AimMax = 9000, .Property_OutputMax =16300},},
/* Left Direction Wheel */
.Value_module_DjiC610620[ANGLEWHEELID_LEFT] = {
.Enable = 1,
.Mode = DjiC610620MODE_ANGLE,
.PID_Speed = {
.Property_Kp = 3, .Property_Ki = 1, .Property_Kd = 0, .Property_dt = 0.005,
.Property_integralMax = 500, .Property_AimMax = 14000, .Property_OutputMax =10000},
.PID_Angle = {
.Property_Kp = 1, .Property_Ki = 0.2, .Property_Kd = 0, .Property_dt = 0.005,
.Property_integralMax = 500, .Property_AimMax = 60000, .Property_OutputMax =14000},},
/* Right Direction Wheel */
.Value_module_DjiC610620[ANGLEWHEELID_RIGHT] = {
.Enable = 1,
.Mode = DjiC610620MODE_ANGLE,
.PID_Speed = {
.Property_Kp = 3, .Property_Ki = 1, .Property_Kd = 0, .Property_dt = 0.005,
.Property_integralMax = 500, .Property_AimMax = 14000, .Property_OutputMax =10000},
.PID_Angle = {
.Property_Kp = 1, .Property_Ki = 0.2, .Property_Kd = 0, .Property_dt = 0.005,
.Property_integralMax = 500, .Property_AimMax = 60000, .Property_OutputMax =14000},},},
/* bluetooth controler device */
.dev_btControler = {
.Property_UartDevName = "uart6",
.ConnectStatusPin = GET_PIN(I, 7),
.ConnectCheckSwitch = 1,
},
};
对模块的各个成员赋值,这里仅对Property属性赋值即可,模块作用的必要参数
- 换算率
- 显示周期
- 电机群模块
- 电机群can设备
- 电机1
- 电机使能
- 电机模式(速度控制/角度控制)
- 电机速度PID
- 电机角度PID
- 电机2
- …
- …
- 电..
- 蓝牙模块
使能各个模块
rt_thread_t led_thread = rt_thread_create("ledshine", led_shine_entry, RT_NULL,
512, RT_THREAD_PRIORITY_MAX - 3, 20);
if (led_thread != RT_NULL){
rt_thread_startup(led_thread);
}
rt_thread_t OrderUpdate_thread = rt_thread_create("OrderUpdate_thread", OrderUpdate_entry, RT_NULL,
512, RT_THREAD_PRIORITY_MAX - 9, 20);
if (OrderUpdate_thread != RT_NULL){
rt_thread_startup(OrderUpdate_thread);
}
rt_thread_t DataUpdate_thread = rt_thread_create("DataUpdate_thread", DataUpdate_entry, RT_NULL,
512, RT_THREAD_PRIORITY_MAX - 8, 20);
if (DataUpdate_thread != RT_NULL){
rt_thread_startup(DataUpdate_thread);
}
rt_thread_t Control_thread = rt_thread_create("Control_thread", Control_entry, RT_NULL,
512, RT_THREAD_PRIORITY_MAX - 10, 20);
if (Control_thread != RT_NULL){
rt_thread_startup(Control_thread);
}
rt_thread_t DataShow_thread = rt_thread_create("DataShow_thread", DataShow_entry, RT_NULL,
512, RT_THREAD_PRIORITY_MAX - 4, 20);
if (DataShow_thread != RT_NULL){
rt_thread_startup(DataShow_thread);
}
-
控制效果
角度响应很快,但是否准确还需再测试,原因可见链接https://www.yuque.com/wangxi_chn/qaxke0/ulrbrk#ZzYzP
还未配合舵轮上的磁编码器使用,手动定转向轮初始位置
现有双舵轮+四支撑轮结构对地面平整要求较高,如果不平整会导致两个舵轮被架空
两轮转速可能会受地面影响而不一致导致自然偏斜,需要配合陀螺仪角度闭环