目录
源代码下载地址:
https://www.firebbs.cn/forum.php?mod=viewthread&tid=37943
开发文档写地址:
https://zhuanlan.zhihu.com/p/852031299
测试视频:
Renesas R7FA8D1BH (Cortex®-M85) 上光电编码器测速功能,同时使用pid控制速度
概述
本文主要介绍Renesas R7FA8D1BH (Cortex®-M85)的PWM和PID控制小车,包括系统实现的框架结构,小车运行方向的控制实现原理和控速原理,用以实现小车运行速度和方向的控制功能。
1 软硬件
1.1 软硬件环境信息
软硬件信息 | 版本信息 |
---|---|
Renesas MCU | R7FA8D1BH |
Keil | MDK ARM 5.38 |
FSP 版本 | 5.3.0 |
调试工具:N32G45XVL-STB | DAP-LINK |
1.2 开发板信息
笔者选择使用野火耀阳开发板_瑞萨RA8,该板块的主控MCU为R7FA8D1BHECBD,7FA8D1BHECBD的内核为ARM Contex-M85。
1.3 调试器信息
对于R7FA8D1BHECBD芯片,其使用的内核为Cortex®-M85 Core, ST-LINK-V2或者J-LINK-V9不支持下载和调试功能。笔者经过多次尝试,发现N32G45XVL-STB板卡上自带的DAP-LINK可以下载和调试R7FA8D1BHECBD。
下图为N32G45XVL-STB开发板实物图:
2 硬件架构
2.1 硬件框架结构
PWM控制小车接口介绍
左侧车轮控制:
1) 使用GPT1生成PWM控制P105接口
2) 使用GPT2生成PWM控制P102接口
右侧车轮控制:
1) 使用GPT6生成PWM控制PA11接口
1) 使用GPT4生成PWM控制P804接口
系统工作框架结构如下:
2.2 小车控制原理
1)前进功能:
P105:输出PWM
P102:停止输出PWM
PA11:输出PWM
P804:停止输出PWM
2)后退功能
P105:停止输出PWM
P102:输出PWM
PA11:停止输出PWM
P804:输出PWM
3)左转功能
P105:停止输出PWM
P102:输出PWM
PA11:输出PWM
P804:停止输出PWM
4)右转功能
P105:输出PWM
P102:停止输出PWM
PA11:停止输出PWM
P804:输出PWM
2.3 小车速度监测
IO接口配置功能:
IRQ1和IRQ11配置为外部中断模式,用于接收两个光电编码器的输入信号
TIMER-7: 配置为10us响应间隔,计算1s时间内总共经过的脉冲个数
系统工作框架结构如下:
2.4 小车距离检测
IO接口配置功能:
触发信号接口P7_10: 送触发信号(10us)的脉冲
测距数据响应接口P7_09: 该IO配置外部中断响应模式,用于接收HC-SR04发回的脉冲信号
TIMER-0: 配置为10us响应速度,用于计算数据的脉冲宽度
系统工作框架结构如下:
3 PID控制速度功能
3.1 数据结构定义
源代码
enum RUN_STATE
{
IDLE = 0,
UP_RUN,
DOWN_RUN,
LEFT_RUN,
RIGHT_RUN,
STOP_RUN,
};
typedef struct
{
uint8_t dirReady : 1; /* 1: UP, 0: DOWN*/
uint8_t start : 1;
uint8_t indexRefresh : 1;
uint8_t : 5;
} MotorCtrl_bit;
typedef struct {
uint8_t dir;
uint8_t speed;
uint8_t changeDirState;
// manual parameter
uint8_t maunal_State;
// auto parameter
uint8_t auto_upState;
uint8_t auto_downState;
uint8_t auto_pwmCycle;
//debug paramter
float debugSpeed;
union
{
uint8_t motorCtrl;
MotorCtrl_bit motorCtrl_bit;
};
}Stru_MotorOpt;
extern Stru_MotorOpt stru_MotorOpt;
3.2 PID控制速度
状态-1:
当障碍物离小车的距离小于30cm, 或者在100~120范围内时,小车停止运行
状态2:
当障碍物离小车的距离大于30cm, 或者小于100范围内时,小车向后倒退
状态3:
当障碍物离小车的距离大于120cm, 小车向前运行
3.3 源代码文件
/*
FILE NAME : app_motorpid.c
Description: application for motor PID control motor function
Author : tangmingfei2013@126.com
Date : 2024/09/24
*/
#include "app_motorPID.h"
#include "hc_sr04.h"
#include "pid_algorithm.h"
#include "motor_speed.h"
#include "app_motor.h"
float actual_distance;
float cal_distance;
/*
stop: 0 ~ 30, 100 ~ 120
down: 31~ 99
up: 120 ~ ....
*/
void motor_pid_control( void )
{
uint8_t is_match;
float tempspeed;
actual_distance = HC_SR04_getDistance();
if( actual_distance < 30 || (actual_distance > 100 && actual_distance < 120))
{
if( stru_MotorOpt.dir != STOP_RUN)
{
stru_MotorOpt.changeDirState = 0;
stru_MotorOpt.dir = STOP_RUN;
stru_MotorOpt.auto_downState = 0;
stru_MotorOpt.auto_upState = 0;
stru_MotorOpt.auto_pwmCycle = 0;
stru_MotorOpt.debugSpeed = 0;
motor_ctrlAct(STOP_RUN, 0);
}
}
else if( actual_distance > 30 && actual_distance < 100 )
{
// pid low the speed
switch( stru_MotorOpt.auto_downState )
{
default:
case 0: //set target speed
pid_param_init();
pid_set_target(&pid_speed, 35);
stru_MotorOpt.auto_downState = 1;
stru_MotorOpt.auto_upState = 0;
stru_MotorOpt.motorCtrl_bit.dirReady = 0;
stru_MotorOpt.dir = DOWN_RUN;
stru_MotorOpt.changeDirState = 0;
break;
case 1: // calculate the pid parameter
tempspeed = pid_speed_realize(&pid_speed, stru_MotorSpeed.leftSpeed);
// up the speed
is_match = abs((int)(stru_MotorSpeed.leftSpeed- pid_get_target(&pid_speed))) < 5 ? true : false;
if( is_match == false )
{
stru_MotorOpt.debugSpeed = (float)(tempspeed*0.01);
if(stru_MotorOpt.debugSpeed > 60 )
{
stru_MotorOpt.debugSpeed = 40;
}
else if(stru_MotorOpt.debugSpeed < 15 )
{
stru_MotorOpt.debugSpeed = 10;
}
stru_MotorOpt.debugSpeed = stru_MotorOpt.debugSpeed;
motor_AutoRunCtrlAction( stru_MotorOpt.dir, (uint8_t)stru_MotorOpt.debugSpeed);
}
printf("%.02f,%.02f,%.02f\r\n", actual_distance, stru_MotorSpeed.leftSpeed, stru_MotorOpt.debugSpeed);
break;
}
}
else if( actual_distance > 120)
{
// pid low the speed
switch( stru_MotorOpt.auto_upState )
{
default:
case 0: //set target speed
pid_param_init();
pid_set_target(&pid_speed, 40);
stru_MotorOpt.auto_upState = 1;
stru_MotorOpt.auto_downState = 0;
stru_MotorOpt.dir = UP_RUN;
stru_MotorOpt.changeDirState = 0;
break;
case 1: // calculate the pid parameter
//left speed
tempspeed = pid_speed_realize(&pid_speed, stru_MotorSpeed.leftSpeed);
// up the speed
is_match = abs((int)(stru_MotorSpeed.leftSpeed- pid_get_target(&pid_speed))) < 5 ? true : false;
if( is_match == false )
{
stru_MotorOpt.debugSpeed = (float)(tempspeed*0.01);
if(stru_MotorOpt.debugSpeed > 60 )
{
stru_MotorOpt.debugSpeed = 40;
}
else if(stru_MotorOpt.debugSpeed < 15 )
{
stru_MotorOpt.debugSpeed = 10;
}
stru_MotorOpt.debugSpeed = stru_MotorOpt.debugSpeed;
motor_AutoRunCtrlAction( stru_MotorOpt.dir, (uint8_t)stru_MotorOpt.debugSpeed);
}
printf("%.02f,%.02f,%.02f\r\n", actual_distance, stru_MotorSpeed.leftSpeed, stru_MotorOpt.debugSpeed);
break;
}
}
}
/* End of this file */