逐飞科技 TC264 PID

YIN 发布于 2025-05-23 121 次阅读


程序

c

C
#include "zf_common_headfile.h"
#include "isr_config.h"


/* 使用类型A的电机控制器请注释掉下述代码 */
#define MOTOR_CONTROLLER_TYPE_B

/* 未实现 */
#define MOTOR_L_ROTATION 1
#define MOTOR_R_ROTATION -1

#define SERVO_MOTOR          (ATOM1_CH1_P33_9)    //舵机PWM通道
#define SERVO_MOTOR_FREQ     (100)                //舵机PWM频率
#define SERVO_MOTOR_MAX      (110)                //舵机最大绝对偏转角
#define SERVO_MOTOR_MIN      (80)                 //舵机最小绝对偏转角
#define SERVO_MOTOR_MID      (95)                 //舵机中心绝对偏转角
#define SERVO_MOTOR_DUTY(x)  ((double)PWM_DUTY_MAX/(1000.0/(double)SERVO_MOTOR_FREQ)*(0.5+(double)(x)/90.0))

#define PIT0                 (CCU60_CH0)          //中断源
#define GEAR_RATIO           (2320)               //轮速编码器比
#define PID_MS               (1)                  //两轮运算时间差
#define MAX_RPM              (100)

#define WHEEL_CIRCUMFERENCE  (6.7 * 3.14 * 0.01)  // 轮子周长
#define FRONT_WHEEL_DISTANCE (0.152)              // 前轮轴距
#define BACK_WHEEL_DISTANCE  (0.152)              // 后轮轴距
#define WHEELBASE            (0.20)               // 前后轮距离
#define MOTOR_MAX            (60)                 // 最大PWM
/* 接口与通道定义 */
#define MOTORL_1             (ATOM0_CH4_P02_4)
#define MOTORL_2             (ATOM0_CH5_P02_5)
#define MOTORR_2             (ATOM1_CH6_P02_6)
#define MOTORR_1             (ATOM1_CH7_P02_7)
#define MOTOR_L              (ATOM1_CH7_P02_7)
#define MOTOR_R              (ATOM0_CH5_P02_5)
#define MOTOR_L_DIRECTION    (P02_6)
#define MOTOR_R_DIRECTION    (P02_4)

#define ENCODER1_DIR         (TIM5_ENCODER)
#define ENCODER1_DIR_PULSE   (TIM5_ENCODER_CH1_P10_3)
#define ENCODER1_DIR_DIR     (TIM5_ENCODER_CH2_P10_1)

#define ENCODER2_DIR         (TIM6_ENCODER)
#define ENCODER2_DIR_PULSE   (TIM6_ENCODER_CH1_P20_3)
#define ENCODER2_DIR_DIR     (TIM6_ENCODER_CH2_P20_0)

int32 Encoder1Count = 0;
int32 Encoder2Count = 0;

double Encoder1RPM = 0;
double Encoder2RPM = 0;

typedef struct {
        double SetSpeed;
        double ActualSpeed;
        double CurrSpeed;
        double Kp;
        double Ki;
        double Kd;
        double Err;
        double ErrLast;
        double ErrPrev;
}pid_config_t;

pid_config_t MotorPid1 = {
        .Kp = 0.8,
        .Ki = 0,
        .Kd = 2.5,
};

pid_config_t MotorPid2 = {
        .Kp = 0.8,
        .Ki = 0.0,
        .Kd = 2.5,
};

double speed_test = 0.3;
double distance_test= 0.45;
double offset_test = 0;

double L = 0;
double R = 0;
void movControl(double speed, double distance, double offset);
void motorPwmExpect (double LPwm,double RPwm);
void motorPwmSet(double LPwm,double RPwm);
void servoAngleSet(double angle);
void motorPwmInit() {
    pwm_init(SERVO_MOTOR, SERVO_MOTOR_FREQ, 0);

#ifdef MOTOR_CONTROLLER_TYPE_B
    pwm_init(MOTOR_L, 17000, 0);
    pwm_init(MOTOR_R, 17000, 0);
    gpio_init(MOTOR_R_DIRECTION, GPO, GPIO_LOW, GPO_PUSH_PULL);
    gpio_init(MOTOR_L_DIRECTION, GPO, GPIO_LOW, GPO_PUSH_PULL);
#else
    pwm_init(MOTORL_1, 17000, 0);
    pwm_init(MOTORL_2, 17000, 0);
    pwm_init(MOTORR_1, 17000, 0);
    pwm_init(MOTORR_2, 17000, 0);
#endif
    encoder_dir_init(ENCODER1_DIR, ENCODER1_DIR_PULSE, ENCODER1_DIR_DIR);
    encoder_dir_init(ENCODER2_DIR, ENCODER2_DIR_PULSE, ENCODER2_DIR_DIR);
    motorPwmExpect(0,8);
    pit_ms_init(PIT0, PID_MS);
    while (TRUE) {
        printf("1:%f\n",Encoder1RPM);
        printf("2:%f\n",Encoder2RPM);
        // motorPwmSet(L,R);
        movControl(speed_test, distance_test, offset_test);
        system_delay_ms(100);
    }

}

/* 算法存在潜在问题,已废弃 */
//void movControl(double speed, double distance, double offset) {
//    if (offset == 0) {
//        servoAngleSet (0);
//        motorPwmExpect (speed / WHEEL_CIRCUMFERENCE,1.0 / WHEEL_CIRCUMFERENCE * speed);
//        return;
//    }
//    double Radius = sqrt(distance * distance + offset * offset) / 2 * 1.0 / cos (atan (distance / offset));
//    double Delta = (atan (WHEELBASE / Radius)) * ((offset > 0) ? -1.0 : 1.0);
//    Delta *= 180;
//    Delta /= 3.1415926;
//    servoAngleSet (Delta);
//    double DeltaVPrime = speed * BACK_WHEEL_DISTANCE / Radius;
//    DeltaVPrime /= 2;
//    double LeftWheelRPM = (speed + ((offset > 0) ? DeltaVPrime : -DeltaVPrime)) / WHEEL_CIRCUMFERENCE;
//    double RightWheelRPM = 1.0 / WHEEL_CIRCUMFERENCE * (speed + ((offset < 0) ? DeltaVPrime : -DeltaVPrime));
//    motorPwmExpect (LeftWheelRPM,RightWheelRPM);
//}

void movControl(double speed, double distance, double offset)
{
    if (offset == 0) {
        servoAngleSet (0);
        motorPwmExpect (speed / WHEEL_CIRCUMFERENCE,1.0 / WHEEL_CIRCUMFERENCE * speed);
        return;
    }
    double Radius = (distance * distance + offset * offset) / (2 * offset);
    double Delta = atan(WHEELBASE / Radius);
    servoAngleSet (Delta * -180.0 / 3.1415926);
    double DeltaSpeed = speed * BACK_WHEEL_DISTANCE / Radius / 2.0;
    double LeftWheelRPM = (speed + DeltaSpeed) / WHEEL_CIRCUMFERENCE;
    double RightWheelRPM = 1.0 / WHEEL_CIRCUMFERENCE * (speed - DeltaSpeed);
    motorPwmExpect (LeftWheelRPM,RightWheelRPM);
}

void servoAngleSet(double angle) {
    angle /= 3;
    angle += SERVO_MOTOR_MID;
    double angle1 = angle;
    if (angle1 > SERVO_MOTOR_MAX) angle1 = SERVO_MOTOR_MAX;
    if (angle1 < SERVO_MOTOR_MIN) angle1 = SERVO_MOTOR_MIN;
    pwm_set_duty(SERVO_MOTOR, SERVO_MOTOR_DUTY(angle1));
}

void motorPwmExpect (double LPwm,double RPwm) {
    MotorPid1.SetSpeed = LPwm;
    MotorPid2.SetSpeed = RPwm;
}

void motorPwmSet(double LPwm,double RPwm) {
    LPwm = (LPwm > MOTOR_MAX) ? MOTOR_MAX : LPwm ;
    LPwm = (LPwm < -MOTOR_MAX) ? -MOTOR_MAX : LPwm ;
    RPwm = (RPwm > MOTOR_MAX) ? MOTOR_MAX : RPwm ;
    RPwm = (RPwm < -MOTOR_MAX) ? -MOTOR_MAX : RPwm ;

#ifdef MOTOR_CONTROLLER_TYPE_B
    pwm_set_duty(MOTOR_L, ((LPwm >= 0) ? LPwm : -LPwm) * 100);
    pwm_set_duty(MOTOR_R, ((RPwm >= 0) ? RPwm : -RPwm) * 100);
    gpio_set_level(MOTOR_L_DIRECTION, (LPwm >= 0) ? 0 : 1);
    gpio_set_level(MOTOR_R_DIRECTION, (RPwm >= 0) ? 1 : 0);
#else
    if (LPwm >= 0) {
            pwm_set_duty(MOTORL_1, LPwm * 100);
            pwm_set_duty(MOTORL_2, 0);
        } else {
            pwm_set_duty(MOTORL_1, 0);
            pwm_set_duty(MOTORL_2, -LPwm * 100);
        }
        if (RPwm >= 0) {
            pwm_set_duty(MOTORR_1, RPwm * 100);
            pwm_set_duty(MOTORR_2, 0);
        } else {
            pwm_set_duty(MOTORR_1, 0);
            pwm_set_duty(MOTORR_2, -RPwm * 100);
        }
#endif
}


void pidCalc(pid_config_t* Pid) {
    Pid->ErrPrev = Pid->ErrLast;
    Pid->ErrLast = Pid->Err;
    Pid->Err = Pid->SetSpeed - Pid->CurrSpeed;
    double Delta = Pid->Kd * (Pid->Err - Pid->ErrLast)
                   + Pid->Kp * Pid->Err
                   + Pid->Ki * (Pid->Err - 2 * Pid->ErrLast + Pid->ErrPrev);
    Pid->ActualSpeed += Delta;
    if (Pid->ActualSpeed > MAX_RPM)
        Pid->ActualSpeed = MAX_RPM;
    if (Pid->ActualSpeed < -MAX_RPM)
        Pid->ActualSpeed = -MAX_RPM;
}

IFX_INTERRUPT(cc60_pit_ch0_isr, 0, CCU6_0_CH0_ISR_PRIORITY) {
    interrupt_global_enable(0);
    pit_clear_flag(CCU60_CH0);

    Encoder1Count = encoder_get_count(ENCODER1_DIR);
    Encoder2Count = encoder_get_count(ENCODER2_DIR);

    encoder_clear_count(ENCODER1_DIR);
    encoder_clear_count(ENCODER2_DIR);

    Encoder1RPM = 1.0 * Encoder1Count / GEAR_RATIO * (1000/PID_MS);
    Encoder2RPM = 1.0 * Encoder2Count / GEAR_RATIO * (1000/PID_MS);

    MotorPid1.CurrSpeed = Encoder1RPM;
    MotorPid2.CurrSpeed = -Encoder2RPM;

    pidCalc(&MotorPid1);
    pidCalc(&MotorPid2);

    motorPwmSet(MotorPid1.ActualSpeed,MotorPid2.ActualSpeed);
}

h

C
#ifndef MOTOR_H
#define MOTOR_H

void motorPwmInit();
void movControl(double speed, double distance, double offset);

#endif
此作者没有提供个人介绍。
最后更新于 2025-05-26