1月19日
今天我会将底盘的代码全部放到这,而且会把之前没注释的内容注释,,如果有什么问题可以私信我,很多关于keil的基础内容我都没有写,主要是过几天就是向RM官方提交中期视频的时候,等提交完毕我会系统的全部都补上
昨天我写了底盘结构体和初始化函数,既然定义完毕了,那现在就开始写小车遥控器部分的代码(写代码时尽量根据功能分块写,然后最后只留一个接口,这样思维不容易混乱)
还是老样子,我们先写.h文件,之前关于硬件的部分信息我放到了自学笔记5中,现在我们就用到的上面的信息,其中remote.h(遥控器)处于初始状态时返回值为1024.
/*
------------------------------------------------------------------------
| 文件名 :remote.h
| 文件描述 :本文件用于遥控器接收函数的接口以及遥控器接收相关变量的定义
| 作者 : pinocchio
| 创建时间 :1.18
------------------------------------------------------------------------
修改日期 :未修改
修改人 :无
------------------------------------------------------------------------
**************************************************************************
* 1. 本代码基于STM32F427IIH(2018RM开发板A型)开发,编译环境为keil,基于freetos操作系统
* 2. 本代码只适用于Robomaster 2019步兵机器人,不建议用于其他用途
* 3.本代码最终解释权归哈尔滨工业大学(深圳)南工晓鹰所有
* 4.请勿转载!!!!!!!!!!!
* Copyright (c) 2019哈尔滨工业大学(深圳)南工晓鹰战队 版权所有
**************************************************************************
*/
#ifndef REMOTE_H_
#define REMOTE_H_
#include "remote.h"
#include "robot.h"
#include "stm32f4xx.h"
#include "usart.h"
#define CH0_BIAS 1024
#define CH0_BIAS 1024
#define CH0_BIAS 1024
#define CH0_BIAS 1024
extern uint8_t rc_data[18];
void RemoteReceiveHandle(void);
#endif
然后以上就是我们遥控器的.h文件
接下来就是遥控器具体函数的书写(remote.c)
/*
------------------------------------------------------------------------
| 文件名 :remote.h
| 文件描述 :本文件用于遥控器接收函数的接口以及遥控器接收相关变量的定义
| 作者 : pinocchio
| 创建时间 :1.18
------------------------------------------------------------------------
修改日期 :未修改
修改人 :无
------------------------------------------------------------------------
**************************************************************************
* 1. 本代码基于STM32F427IIH(2018RM开发板A型)开发,编译环境为keil,基于freetos操作系统
* 2. 本代码只适用于Robomaster 2019步兵机器人,不建议用于其他用途
* 3.本代码最终解释权归哈尔滨工业大学(深圳)南工晓鹰所有
* 4.请勿转载!!!!!!!!!!!
* Copyright (c) 2019哈尔滨工业大学(深圳)南工晓鹰战队 版权所有
**************************************************************************
*/
#include "remote.h"
uint8_t rc_data[18];
void RemoteReceiveHandle(void)
{
Robot1.Remote.Rc.ch0 = ((int16_t)rc_data[0] | ((int16_t)rc_data[1] << 8)) & 0x07FF;
Robot1.Remote.Rc.ch1 = (((int16_t)rc_data[1] >> 3) | ((int16_t)rc_data[2] << 5)) & 0x07FF;
Robot1.Remote.Rc.ch2 = (((int16_t)rc_data[2] >> 6) | ((int16_t)rc_data[3] << 2) |
((int16_t)rc_data[4] << 10)) & 0x07FF;
Robot1.Remote.Rc.ch3 = (((int16_t)rc_data[4] >> 1) | ((int16_t)rc_data[5]<<7)) & 0x07FF;
Robot1.Remote.Rc.s1 = ((rc_data[5] >> 4) & 0x000C) >> 2;
Robot1.Remote.Rc.s2 = ((rc_data[5] >> 4) & 0x0003);
Robot1.Remote.Mouse.x = ((int16_t)rc_data[6]) | ((int16_t)rc_data[7] << 8);
Robot1.Remote.Mouse.y = ((int16_t)rc_data[8]) | ((int16_t)rc_data[9] << 8);
Robot1.Remote.Mouse.z = ((int16_t)rc_data[10]) | ((int16_t)rc_data[11] << 8);
Robot1.Remote.Mouse.press_l = rc_data[12];
Robot1.Remote.Mouse.press_r = rc_data[13];
Robot1.Remote.Mouse.key = ((int16_t)rc_data[14]);
if(Robot1.Remote.Rc.s2 == 2)
{
Robot1.Remote.Robot_Mode = RC_Stop;
}
else if(Robot1.Remote.Rc.s2 == 3)
{
Robot1.Remote.Robot_Mode = RC_MouseKey;
}
else if(Robot1.Remote.Rc.s2 == 1)
{
Robot1.Remote.Robot_Mode = RC_Remote;
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1)
{
HAL_UART_Receive_DMA(&huart1,rc_data,18u);
RemoteReceiveHandle();
HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_8);
}
}
接下来就是关于can通讯电机的代码的书写
/*
------------------------------------------------------------------------
| 文件名 :canmotor.h
| 文件描述 :本文件用于can通讯电机数据接收和处理的接口和相关数据的定义
| 作者 : pinocchio
| 创建时间 :1.18
------------------------------------------------------------------------
修改日期 :未修改
修改人 :无
------------------------------------------------------------------------
**************************************************************************
* 1. 本代码基于STM32F427IIH(2018RM开发板A型)开发,编译环境为keil,基于freetos操作系统
* 2. 本代码只适用于Robomaster 2019步兵机器人,不建议用于其他用途
* 3.本代码最终解释权归哈尔滨工业大学(深圳)南工晓鹰所有
* 4.请勿转载!!!!!!!!!!!
* Copyright (c) 2019哈尔滨工业大学(深圳)南工晓鹰战队 版权所有
**************************************************************************
*/
#ifndef CANMOTOR_H_
#define CANMOTOR_H_
#include "stm32f4xx.h"
#include "robot.h"
#include "main.h"
#define CAN_BUF_SIZE 6
extern uint8_t can_data[8] ;
extern void Transmit(void);
extern void CanDataEncoderProcess_Chassis( struct CHASSIS_t *chassis);
#endif
然后就到相关can通讯函数的接收和数据的处理了
/*
------------------------------------------------------------------------
| 文件名 :canmotor.c
| 文件描述 :本文件用于can通讯电机数据接收和处理
| 作者 : pinocchio
| 创建时间 :1.18
------------------------------------------------------------------------
修改日期 :未修改
修改人 :无
------------------------------------------------------------------------
**************************************************************************
* 1. 本代码基于STM32F427IIH(2018RM开发板A型)开发,编译环境为keil,基于freetos操作系统
* 2. 本代码只适用于Robomaster 2019步兵机器人,不建议用于其他用途
* 3.本代码最终解释权归哈尔滨工业大学(深圳)南工晓鹰所有
* 4.请勿转载!!!!!!!!!!!
* Copyright (c) 2019哈尔滨工业大学(深圳)南工晓鹰战队 版权所有
**************************************************************************
*/
void CanTransmit_Chassis(CAN_HandleTypeDef *hcanx, int16_t cm1_iq, int16_t cm2_iq, int16_t cm3_iq, int16_t cm4_iq)
{
CAN_TxHeaderTypeDef TxMessage;
TxMessage.DLC=0x08;
TxMessage.StdId=0x200;
TxMessage.IDE=CAN_ID_STD;
TxMessage.RTR=CAN_RTR_DATA;
uint8_t TxData[8];
TxData[0] = (uint8_t)(cm1_iq >> 8);
TxData[1] = (uint8_t)cm1_iq;
TxData[2] = (uint8_t)(cm2_iq >> 8);
TxData[3] = (uint8_t)cm2_iq;
TxData[4] = (uint8_t)(cm3_iq >> 8);
TxData[5] = (uint8_t)cm3_iq;
TxData[6] = (uint8_t)(cm4_iq >> 8);
TxData[7] = (uint8_t)cm4_iq;
if(HAL_CAN_AddTxMessage(hcanx,&TxMessage,TxData,(uint32_t*)CAN_TX_MAILBOX0)!=HAL_OK)
{
Error_Handler();
}
}
void Transmit()
{
if(Robot1.Remote.Robot_Mode == RC_Stop)
{
CanTransmit_Chassis(&hcan1,0,0,0,0);
}
else
{
#ifdef CHASSIS
CanTransmit_Chassis(&hcan1, Robot1.Chassis_A.Speed_Pid.output, Robot1.Chassis_B.Speed_Pid.output, Robot1.Chassis_C.Speed_Pid.output, Robot1.Chassis_D.Speed_Pid.output);
#endif
}
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CAN_RxHeaderTypeDef RxHeader;
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, can_data) != HAL_OK)
{
Error_Handler();
}
CanDataReceive(RxHeader.StdId);
}
void CanDataReceive(int motor_index)
{
switch(motor_index)
{
#ifdef CHASSIS
case Robot1Chassis_A_ID:
// LostCounterFeed(CHASSIS_MOTOR1_INDEX);
CanDataEncoderProcess_Chassis(&Robot1.Chassis_A);break;
case Robot1Chassis_B_ID:
//LostCounterFeed(CHASSIS_MOTOR2_INDEX);
CanDataEncoderProcess_Chassis(&Robot1.Chassis_B);break;
case Robot1Chassis_C_ID:
// LostCounterFeed(CHASSIS_MOTOR3_INDEX);
CanDataEncoderProcess_Chassis(&Robot1.Chassis_C);break;
case Robot1Chassis_D_ID:
//LostCounterFeed(CHASSIS_MOTOR4_INDEX);
CanDataEncoderProcess_Chassis(&Robot1.Chassis_D);break;
#endif
}
}
此时数据已经接受了,因为是底盘,所以此处我们只接受了速度的返回值,然后我们需要利用pid对它进行调速了
/*
------------------------------------------------------------------------
| 文件名 :pid.h
| 文件描述 :本文件用于pid函数的接口和.h文件的引用
| 作者 : pinocchio
| 创建时间 :1.18
------------------------------------------------------------------------
修改日期 :未修改
修改人 :无
------------------------------------------------------------------------
**************************************************************************
* 1. 本代码基于STM32F427IIH(2018RM开发板A型)开发,编译环境为keil,基于freetos操作系统
* 2. 本代码只适用于Robomaster 2019步兵机器人,不建议用于其他用途
* 3.本代码最终解释权归哈尔滨工业大学(深圳)南工晓鹰所有
* 4.请勿转载!!!!!!!!!!!
* Copyright (c) 2019哈尔滨工业大学(深圳)南工晓鹰战队 版权所有
**************************************************************************
*/
#ifndef PID_H_
#define PID_H_
#include "robot.h"
extern void Pid_Calculate_Chassis(struct CHASSIS_t *chassis);
extern void Calculate(void);
#endif
然后就到pid.c文件
/*
------------------------------------------------------------------------
| 文件名 :pid.c
| 文件描述 :本文件用于pid函数的运算
| 作者 : pinocchio
| 创建时间 :1.18
------------------------------------------------------------------------
修改日期 :未修改
修改人 :无
------------------------------------------------------------------------
**************************************************************************
* 1. 本代码基于STM32F427IIH(2018RM开发板A型)开发,编译环境为keil,基于freetos操作系统
* 2. 本代码只适用于Robomaster 2019步兵机器人,不建议用于其他用途
* 3.本代码最终解释权归哈尔滨工业大学(深圳)南工晓鹰所有
* 4.请勿转载!!!!!!!!!!!
* Copyright (c) 2019哈尔滨工业大学(深圳)南工晓鹰战队 版权所有
**************************************************************************
*/
#include "pid.h"
void Calculate()
{
#ifdef CHASSIS
Pid_Calculate_Chassis(&Robot1.Chassis_A) ;
Pid_Calculate_Chassis(&Robot1.Chassis_B);
Pid_Calculate_Chassis(&Robot1.Chassis_C);
Pid_Calculate_Chassis(&Robot1.Chassis_D);
#endif
}
void Pid_Calculate_Chassis(struct CHASSIS_t * chassis)
{
chassis->Speed_Pid.error[0]=chassis->Speed_Pid.error[1];
chassis->Speed_Pid.error[1]=chassis->Speed_Pid.Ref_Speed - chassis->Speed_Pid.Fd_Speed ;
if(chassis->Speed_Pid.Fd_Speed >0.7*chassis->Speed_Pid.Ref_Speed ) chassis->Speed_Pid.error[2]+= chassis->Speed_Pid.error[1];
chassis->Speed_Pid.output = chassis->Speed_Pid.KP * (chassis->Speed_Pid.error[1]) \
+ chassis->Speed_Pid.KI * (chassis->Speed_Pid.error[2]) \
+ chassis->Speed_Pid.KD * (chassis->Speed_Pid.error[1] - chassis->Speed_Pid.error[0]) ;
if(chassis->Speed_Pid.error[2] > 200) chassis->Speed_Pid.error[2]=200;
if(chassis->Speed_Pid.output > chassis->Speed_Pid.OutputMAX) chassis->Speed_Pid.output = chassis->Speed_Pid.OutputMAX;
if(chassis->Speed_Pid.output < -chassis->Speed_Pid.OutputMAX) chassis->Speed_Pid.output = -chassis->Speed_Pid.OutputMAX;
}