以stm32c8t6芯片写出关于光电编码器测试的直流电机转速控制,用标准库写代码,控制算法为模糊PID
时间: 2023-06-13 21:06:24 浏览: 111
STM32C8T6单片机与CS5463芯片互感器的单相用电器分析监测装置原理图PCB+软件源码.zip
5星 · 资源好评率100%
好的,以下是一个简单的基于STM32标准库的光电编码器测试的直流电机转速控制代码,使用模糊PID算法:
```c
#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#define PWM_PERIOD 9999 // PWM周期
#define ENCODER_RESOLUTION 1024 // 光电编码器分辨率
#define MAX_RPM 3000 // 电机最大转速
#define MIN_RPM 0 // 电机最小转速
// PID控制器参数
#define KP 0.5
#define KI 0.2
#define KD 0.1
#define KF 0.05
// 电机控制状态
typedef enum {
STOPPED,
ACCELERATING,
DECELERATING,
CRUISING
} MotorState;
// PID控制器结构体
typedef struct {
float setpoint; // 目标转速
float error; // 当前误差
float last_error; // 上一次误差
float integral_error; // 积分误差
float derivative_error; // 微分误差
float output; // 控制器输出
} PIDController;
// 电机控制结构体
typedef struct {
TIM_TypeDef* pwm_timer; // PWM计时器
uint16_t pwm_channel; // PWM通道
TIM_TypeDef* encoder_timer; // 编码器计时器
uint16_t encoder_channel_a; // 编码器通道A
uint16_t encoder_channel_b; // 编码器通道B
GPIO_TypeDef* encoder_port; // 编码器端口
uint16_t encoder_pin_a; // 编码器引脚A
uint16_t encoder_pin_b; // 编码器引脚B
float rpm; // 当前转速
MotorState state; // 电机状态
PIDController pid; // PID控制器
} MotorController;
// 初始化PID控制器
void init_pid_controller(PIDController* pid, float setpoint) {
pid->setpoint = setpoint;
pid->error = 0;
pid->last_error = 0;
pid->integral_error = 0;
pid->derivative_error = 0;
pid->output = 0;
}
// 更新PID控制器
void update_pid_controller(PIDController* pid, float input, float dt) {
pid->last_error = pid->error;
pid->error = pid->setpoint - input;
pid->integral_error += pid->error * dt;
pid->derivative_error = (pid->error - pid->last_error) / dt;
pid->output = KP * pid->error + KI * pid->integral_error + KD * pid->derivative_error + KF * pid->setpoint;
}
// 初始化电机控制器
void init_motor_controller(MotorController* motor, TIM_TypeDef* pwm_timer, uint16_t pwm_channel,
TIM_TypeDef* encoder_timer, uint16_t encoder_channel_a, uint16_t encoder_channel_b,
GPIO_TypeDef* encoder_port, uint16_t encoder_pin_a, uint16_t encoder_pin_b) {
motor->pwm_timer = pwm_timer;
motor->pwm_channel = pwm_channel;
motor->encoder_timer = encoder_timer;
motor->encoder_channel_a = encoder_channel_a;
motor->encoder_channel_b = encoder_channel_b;
motor->encoder_port = encoder_port;
motor->encoder_pin_a = encoder_pin_a;
motor->encoder_pin_b = encoder_pin_b;
motor->rpm = 0;
motor->state = STOPPED;
init_pid_controller(&motor->pid, 0);
}
// 获取编码器计数器值
int32_t get_encoder_counter(TIM_TypeDef* timer) {
return (int16_t)timer->CNT;
}
// 重置编码器计数器
void reset_encoder_counter(TIM_TypeDef* timer) {
timer->CNT = 0;
}
// 获取电机当前转速
float get_motor_rpm(MotorController* motor, float dt) {
int32_t count = get_encoder_counter(motor->encoder_timer);
float rpm = (float)count / ENCODER_RESOLUTION * 60 / dt;
reset_encoder_counter(motor->encoder_timer);
return rpm;
}
// 设置电机PWM占空比
void set_motor_pwm(MotorController* motor, uint16_t duty_cycle) {
TIM_SetCompare(motor->pwm_timer, motor->pwm_channel, duty_cycle);
}
// 停止电机
void stop_motor(MotorController* motor) {
set_motor_pwm(motor, 0);
motor->state = STOPPED;
}
// 加速电机
void accelerate_motor(MotorController* motor) {
set_motor_pwm(motor, 1000);
motor->state = ACCELERATING;
}
// 减速电机
void decelerate_motor(MotorController* motor) {
set_motor_pwm(motor, 500);
motor->state = DECELERATING;
}
// 控制电机
void control_motor(MotorController* motor, float dt) {
switch (motor->state) {
case STOPPED:
// 如果电机停止,则直接停止
stop_motor(motor);
break;
case ACCELERATING:
// 如果电机正在加速,则加速到目标转速
if (motor->rpm >= motor->pid.setpoint) {
motor->state = CRUISING;
}
break;
case DECELERATING:
// 如果电机正在减速,则减速到目标转速
if (motor->rpm <= motor->pid.setpoint) {
motor->state = CRUISING;
}
break;
case CRUISING:
// 如果电机正在巡航,则使用PID控制器来维持目标转速
update_pid_controller(&motor->pid, motor->rpm, dt);
set_motor_pwm(motor, motor->pid.output);
break;
}
}
int main(void) {
// 初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 初始化GPIO
GPIO_InitTypeDef gpio_init;
gpio_init.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
gpio_init.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &gpio_init);
gpio_init.GPIO_Pin = GPIO_Pin_3;
gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &gpio_init);
// 初始化PWM
TIM_TimeBaseInitTypeDef timer_init;
timer_init.TIM_Prescaler = 72 - 1;
timer_init.TIM_CounterMode = TIM_CounterMode_Up;
timer_init.TIM_Period = PWM_PERIOD;
timer_init.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2, &timer_init);
TIM_OCInitTypeDef pwm_init;
pwm_init.TIM_OCMode = TIM_OCMode_PWM1;
pwm_init.TIM_OutputState = TIM_OutputState_Enable;
pwm_init.TIM_Pulse = 0;
pwm_init.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &pwm_init);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_Cmd(TIM2, ENABLE);
// 初始化编码器
TIM_EncoderInterfaceConfigTypeDef encoder_init;
encoder_init.TIM_EncoderMode = TIM_EncoderMode_TI12;
encoder_init.TIM_IC1Polarity = TIM_ICPolarity_Rising;
encoder_init.TIM_IC2Polarity = TIM_ICPolarity_Rising;
encoder_init.TIM_IC1Selection = TIM_ICSelection_DirectTI;
encoder_init.TIM_IC2Selection = TIM_ICSelection_DirectTI;
encoder_init.TIM_IC1Prescaler = TIM_ICPSC_DIV1;
encoder_init.TIM_IC2Prescaler = TIM_ICPSC_DIV1;
TIM_EncoderInterfaceConfig(TIM2, &encoder_init);
TIM_SetCounter(TIM2, 0);
// 初始化电机控制器
MotorController motor;
init_motor_controller(&motor, TIM2, TIM_Channel_1, TIM2, TIM_Channel_1, TIM_Channel_2, GPIOA, GPIO_Pin_0, GPIO_Pin_1);
init_pid_controller(&motor.pid, 1000);
// 循环读取编码器计数器并控制电机
float dt = 0.01;
while (1) {
motor.rpm = get_motor_rpm(&motor, dt);
control_motor(&motor, dt);
if (motor.rpm >= MAX_RPM) {
motor.pid.setpoint = MAX_RPM;
motor.state = DECELERATING;
} else if (motor.rpm <= MIN_RPM) {
motor.pid.setpoint = MIN_RPM;
motor.state = ACCELERATING;
} else {
motor.pid.setpoint = MAX_RPM / 2;
}
for (int i = 0; i < 100000; i++); // 等待一段时间
}
}
```
该代码使用TIM2作为PWM计时器和编码器计时器,PA3用作PWM输出,PA0和PA1用作编码器输入。控制器初始化之后,通过读取编码器计数器来获取电机当前转速,并使用模糊PID控制器来控制电机转速。在主循环中,根据电机的转速状态来决定加速、减速或巡航,并在巡航状态下使用PID控制器来维持目标转速。同时,为了防止电机转速过高或过低,设置了最大和最小转速限制。
阅读全文