Renesas R7FA8D1BH (Cortex®-M85)实现PID控制小车运行速度

目录

概述

1 软硬件

1.1 软硬件环境信息

1.2 开发板信息

1.3 调试器信息

2 硬件架构

2.1 硬件框架结构

2.2 小车控制原理

2.3 小车速度监测

2.4 小车距离检测

3 PID控制速度功能

3.1 数据结构定义

3.2 PID控制速度

3.3 源代码文件 


源代码下载地址:

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 MCUR7FA8D1BH
KeilMDK ARM 5.38
FSP 版本5.3.0
调试工具:N32G45XVL-STBDAP-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 */
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值