51单片机PID算法控制无刷直流电机proteus仿真 功能描述 1.五个按键,停止/启动,正转,反转,加速,减速 2.显示lcd1602,第一行设置速度set= 3.第二行实际速度speed= r/min 4.第一行右上角转正显示Z,反转显示F 5.驱动用ir2101加上6个mos管, 6.程序里有pid算法

最近在搞51单片机控制无刷直流电机的项目,用到了PID算法,还结合Proteus进行了仿真,和大家分享一下过程和心得。

硬件部分

  1. 按键模块:我们有五个按键,分别负责停止/启动、正转、反转、加速、减速。这就好比给电机配备了一套精准的操作手柄。在Proteus里,简单放置几个轻触按键就行,连接到单片机的I/O口,比如P1.0 - P1.4 。
  2. LCD1602显示模块:用来直观展示设置速度和实际速度,还能显示电机的转动方向。第一行显示 “set= ” 加上设置速度,右上角根据正反转显示 “Z” 或 “F”;第二行显示 “speed= ” 加上实际速度(单位r/min)。在Proteus里添加LCD1602模块,连接好数据引脚和控制引脚到单片机,比如数据口接P0口,控制引脚RS接P2.0,RW接P2.1,E接P2.2 。
  3. 驱动模块:采用IR2101加上6个MOS管来驱动无刷直流电机。IR2101是个很棒的半桥驱动器,它能很好地配合MOS管,给无刷直流电机提供所需的驱动信号。在Proteus里找到IR2101和合适的MOS管模型,按照其原理连接好电路,电机的三相分别连接到对应的MOS管输出端。

软件部分 - PID算法实现

PID算法核心代码如下(以C语言为例):

// 定义PID参数结构体
typedef struct {
    float SetSpeed;  // 设置速度
    float ActualSpeed; // 实际速度
    float Kp, Ki, Kd; // PID参数
    float Integral;
    float LastError;
} PID;

// PID初始化函数
void PID_Init(PID *pid, float SetSpeed, float Kp, float Ki, Kd) {
    pid->SetSpeed = SetSpeed;
    pid->ActualSpeed = 0;
    pid->Kp = Kp;
    pid->Ki = Ki;
    pid->Kd = Kd;
    pid->Integral = 0;
    pid->LastError = 0;
}

// PID计算函数
float PID_Calc(PID *pid) {
    float Error;
    float Pout, Iout, Dout;
    Error = pid->SetSpeed - pid->ActualSpeed;  // 计算误差
    Pout = pid->Kp * Error;  // P调节
    pid->Integral += Error;
    Iout = pid->Ki * pid->Integral;  // I调节
    Dout = pid->Kd * (Error - pid->LastError);  // D调节
    pid->LastError = Error;
    return Pout + Iout + Dout;  // 返回PID调节输出
}

在上述代码中,我们首先定义了一个 PID 结构体,用来存储设置速度、实际速度以及PID的三个参数 KpKiKd,还有积分项 Integral 和上一次的误差 LastError

PID_Init 函数用于初始化PID结构体里的各项参数,设定初始的设置速度,清零实际速度、积分项等。

51单片机PID算法控制无刷直流电机proteus仿真 功能描述 1.五个按键,停止/启动,正转,反转,加速,减速 2.显示lcd1602,第一行设置速度set= 3.第二行实际速度speed= r/min 4.第一行右上角转正显示Z,反转显示F 5.驱动用ir2101加上6个mos管, 6.程序里有pid算法

PID_Calc 函数则是PID算法的核心计算部分。通过计算当前设置速度与实际速度的误差 Error ,分别进行比例调节 Pout 、积分调节 Iout 和微分调节 Dout ,最后将三者相加得到PID调节的输出,这个输出可以用来控制电机的转速。

主程序实现

#include <reg51.h>
#include <intrins.h>
#include <lcd1602.h>  // 假设已经有LCD1602驱动函数定义

sbit Start_Stop = P1.0;
sbit Forward = P1.1;
sbit Reverse = P1.2;
sbit SpeedUp = P1.3;
sbit SpeedDown = P1.4;

PID motorPID;
// 假设这里还有电机驱动控制相关的端口定义和初始化

void main() {
    float controlValue;
    LCD_Init();  // 初始化LCD1602
    PID_Init(&motorPID, 100, 0.5, 0.1, 0.2);  // 初始化PID,设置初始速度100,设置PID参数
    while (1) {
        if (Start_Stop) {
            // 停止/启动逻辑
        }
        if (Forward) {
            // 正转逻辑
        }
        if (Reverse) {
            // 反转逻辑
        }
        if (SpeedUp) {
            motorPID.SetSpeed += 10;  // 加速10
        }
        if (SpeedDown) {
            if (motorPID.SetSpeed >= 10) {
                motorPID.SetSpeed -= 10;  // 减速10
            }
        }
        // 获取实际速度(假设这里有获取实际速度的函数)
        motorPID.ActualSpeed = Get_Actual_Speed();
        controlValue = PID_Calc(&motorPID);
        // 根据controlValue控制电机
        // 更新LCD1602显示
        char buffer[16];
        sprintf(buffer, "set=%d %c", (int)motorPID.SetSpeed, motor_direction? 'Z' : 'F');
        LCD_SetCursor(0, 0);
        LCD_Print(buffer);
        sprintf(buffer, "speed=%d r/min", (int)motorPID.ActualSpeed);
        LCD_SetCursor(0, 1);
        LCD_Print(buffer);
    }
}

在主程序里,我们首先定义了各个按键对应的单片机引脚。然后初始化LCD1602和PID参数。在循环中,不断检测各个按键状态进行相应操作,比如加速、减速改变设置速度。获取实际速度后,通过 PID_Calc 函数计算出控制值,再根据这个控制值去控制电机。最后,把设置速度、实际速度和转动方向更新显示在LCD1602上。

通过这次在Proteus里的仿真实践,对51单片机结合PID算法控制无刷直流电机有了更深刻的理解,硬件和软件的配合是实现精准控制的关键。希望这篇分享对同样在探索这方面的小伙伴有所帮助。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐