PID算法控制PWM占空比的代码详解

PID算法控制PWM占空比

PID算法控制PWM占空比的代码

PID控制的算法代码C++,其中输出控制函数可以依据各自的项目需要进行改写。

#include<string.h>
#include<stdio.h>
typedef struct PID {
double SetPoint; // 设定目标Desired value
double Proportion; // 比例常数Proportional Const
double Integral; // 积分常数Integral Const
double Derivative; // 微分常数Derivative Const
double LastError; // Error[-1]

double PrevError; // Error[-2]
double SumError; // Sums of Errors
} PID;

/*====================================================================================================
PID计算函数
=====================================================================================================*/
double PIDCalc( PID *pp, double NextPoint )
{
    double dError, Error;
    Error = pp->SetPoint - NextPoint; // 偏差
    pp->SumError += Error; // 积分
    dError = pp->LastError - pp->PrevError; // 当前微分
    pp->PrevError = pp->LastError;
    pp->LastError = Error;
    return (pp->Proportion * Error // 比例项
    + pp->Integral * pp->SumError // 积分项
    + pp->Derivative * dError );         // 微分项
}

/*====================================================================================================
PID结构体变量初始化函数
=====================================================================================================*/
void PIDInit (PID *pp)
{
memset ( pp,0,sizeof(PID));
}

/*====================================================================================================
读取输入变量函数(在此设定为固定值100)
======================================================================================================*/
double sensor (void)  
{
return 100.0;
}

/*====================================================================================================
输出变量控制函数
======================================================================================================*/
void actuator(double rDelta)  
{
//用户自定义,可自行决定的
}

//主函数
void main(void)
{
    PID sPID; // PID Control Structure
    double rOut; // PID Response (Output)
    double rIn; // PID Feedback (Input)
    PIDInit ( &sPID ); // Initialize Structure
    sPID.Proportion = 0.5; // Set PID Coefficients
    sPID.Integral = 0.5;
    sPID.Derivative = 0.0;
    sPID.SetPoint = 100.0; // Set PID Setpoint
    for (;;)
    {                                   // Mock Up of PID Processing
        rIn = sensor ();                // 读取输入变量函数(Read Input )
        rOut = PIDCalc ( &sPID,rIn );   // PID计算函数(Perform PID Interation)
        actuator ( rOut );              // 输出变量控制函数(Effect Needed Changes)
    }
}

PWM控制函数

//############################################################
#ifndef EPWM_int_H
#define EPWM_int_H
#include "DSP2833x_Project.h"

void EPWM3_int(void); //三对PWM初始化
void HVDMC_Protection(void); //PWM的保护初始化
void  PWMDAC_int(void);   // pwm做为RC滤波的DAC输出
void  Svpwm_Outpwm(void); // SVPWM调试波形输出
void START_CAR(void);  // 开始电机控制开PWM
void STOP_CAR(void);   // 停电机控制关PWM

extern Uint16 PWM_HalfPerMax;

#endif  // end of EPWM_int_H definition
//############################################################

#include "Main_PMSM_QEncoder.h"

#define ISR_FREQUENCY     12.5
#define SYSTEM_FREQUENCY  150

float32 T = 0.001/ISR_FREQUENCY;

Uint16   PWM_PeriodMax=0, PWM_HalfPerMax=0 ,PWM_Deadband=0 ;

void EPWM3_int(void)
{
	  PWM_PeriodMax=SYSTEM_FREQUENCY*1000000*T/2;
	  PWM_HalfPerMax=PWM_PeriodMax/2;
	  PWM_Deadband  =2.0*SYSTEM_FREQUENCY;
	  EALLOW;
      EPwm1Regs.TBCTL.bit.SYNCOSEL = 0;
      EPwm2Regs.TBCTL.bit.SYNCOSEL = 0;
      EPwm3Regs.TBCTL.bit.SYNCOSEL = 0;

      EPwm1Regs.TBCTL.bit.PHSEN = 1;
      EPwm2Regs.TBCTL.bit.PHSEN = 1;
      EPwm3Regs.TBCTL.bit.PHSEN = 1;

      EPwm1Regs.TBPRD = PWM_PeriodMax;    //  6000
      EPwm2Regs.TBPRD = PWM_PeriodMax;
      EPwm3Regs.TBPRD = PWM_PeriodMax;

      EPwm1Regs.TBPHS.half.TBPHS = 0;
      EPwm2Regs.TBPHS.half.TBPHS = 0;
      EPwm3Regs.TBPHS.half.TBPHS = 0;

      EPwm1Regs.TBCTL.all = 0xA00A;
      EPwm2Regs.TBCTL.all = 0xA00A;
      EPwm3Regs.TBCTL.all = 0xA00A;

      EPwm1Regs.CMPCTL.all = 0;
      EPwm2Regs.CMPCTL.all = 0;
      EPwm3Regs.CMPCTL.all = 0;

      EPwm1Regs.AQCTLA.all = 0x0090;
      EPwm2Regs.AQCTLA.all = 0x0090;
      EPwm3Regs.AQCTLA.all = 0x0090;

      EPwm1Regs.DBCTL.all = 0x000B;  // 0x0003
      EPwm2Regs.DBCTL.all = 0x000B;  // 全一致  低电平
      EPwm3Regs.DBCTL.all = 0x000B;

      EPwm1Regs.DBFED =  PWM_Deadband;
      EPwm1Regs.DBRED =  PWM_Deadband;
      EPwm2Regs.DBFED =  PWM_Deadband;
      EPwm2Regs.DBRED =  PWM_Deadband;
      EPwm3Regs.DBFED =  PWM_Deadband;
      EPwm3Regs.DBRED =  PWM_Deadband;

      EPwm1Regs.PCCTL.all = 0;
      EPwm2Regs.PCCTL.all = 0;
      EPwm3Regs.PCCTL.all = 0;

      EPwm1Regs.TZSEL.all = 0;
      EPwm2Regs.TZSEL.all = 0;
      EPwm3Regs.TZSEL.all = 0;

      EDIS;                         /* Disable EALLOW*/
}

// GPIO12引脚硬件过流触发保护引脚,硬件母线电流与电压比较低电平有效保护关闭6路PWM
void HVDMC_Protection(void)
{
      EALLOW;

      EPwm1Regs.TZSEL.bit.CBC6=0x1;
      EPwm2Regs.TZSEL.bit.CBC6=0x1;
      EPwm3Regs.TZSEL.bit.CBC6=0x1;

      EPwm1Regs.TZSEL.bit.OSHT1   = 1;  //enable TZ1 for OSHT
      EPwm2Regs.TZSEL.bit.OSHT1   = 1;  //enable TZ1 for OSHT
      EPwm3Regs.TZSEL.bit.OSHT1   = 1;  //enable TZ1 for OSHT

      EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // EPWMxA will go low
      EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // EPWMxB will go low

      EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // EPWMxA will go low
      EPwm2Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // EPWMxB will go low

      EPwm3Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // EPWMxA will go low
      EPwm3Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // EPWMxB will go low

      EDIS;

//************************** End of Prot. Conf. ***************************//
}

void  Svpwm_Outpwm(void)
{
	 // Tabc=0.5*Svpwmdq.Tabc+0.5
   EPwm1Regs.CMPA.half.CMPA = _IQmpy(PWM_HalfPerMax,Svpwmdq.Ta)+ PWM_HalfPerMax;
   EPwm2Regs.CMPA.half.CMPA = _IQmpy(PWM_HalfPerMax,Svpwmdq.Tb)+ PWM_HalfPerMax;
   EPwm3Regs.CMPA.half.CMPA = _IQmpy(PWM_HalfPerMax,Svpwmdq.Tc)+ PWM_HalfPerMax;
}

void STOP_CAR(void)           //  上下桥臂 全为低
{
	EALLOW;
	 EPwm1Regs.DBCTL.bit.POLSEL = 0;
	 EPwm2Regs.DBCTL.bit.POLSEL = 0;
	 EPwm3Regs.DBCTL.bit.POLSEL = 0;

	 EPwm1Regs.AQCSFRC.all = 0x05;
	 EPwm2Regs.AQCSFRC.all = 0x05;
	 EPwm3Regs.AQCSFRC.all = 0x05;
	 EDIS;
}


void START_CAR(void)   //   上下桥臂 对称互补
{
	EALLOW;
	 EPwm1Regs.DBCTL.bit.POLSEL = 2;
	 EPwm2Regs.DBCTL.bit.POLSEL = 2;
	 EPwm3Regs.DBCTL.bit.POLSEL = 2;

	 EPwm1Regs.AQCSFRC.all = 0x00;
	 EPwm2Regs.AQCSFRC.all = 0x00;
	 EPwm3Regs.AQCSFRC.all = 0x00;
	EDIS;
}

// EPWM6在除正交编码器的永磁同步电机FOC控制中运用  将数字量转换模拟量可以在示波器上显示变化规律
// 其他程序代码做用PWM输出数字量通过RC电阻低通滤波后就可以测到数据波形,例如马鞍矢量波
// https://blog.csdn.net/qq_27334499/article/details/52186336

void  PWMDAC_int(void)  // PWMDAC
{
   EALLOW;
   EPwm6Regs.TBCTL.bit.SYNCOSEL = 0;
   EPwm6Regs.TBCTL.bit.PHSEN = 1;
   EPwm6Regs.TBPRD =4000;
   EPwm6Regs.TBPHS.half.TBPHS = 0;
   EPwm6Regs.TBCTL.all = 0xA00A;
   EPwm6Regs.CMPCTL.all = 0x0000;
   EPwm6Regs.AQCTLA.all = 0x0090;
   EPwm6Regs.AQCTLB.all = 0x0900;
   EPwm6Regs.DBCTL.all = 0x0000;
   EPwm6Regs.PCCTL.all = 0x0000;
   EPwm6Regs.TZSEL.all = 0x0000;
   EPwm6Regs.TZCTL.all = 0x0000;
   EDIS;
}


//===========================================================================
// No more.
//===========================================================================

  • 21
    点赞
  • 276
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
以下是一个简单的 STM32F103 上使用 PID 算法控制 PWM 的示例代码。假设你已经配置好了定时器 TIM2 作为 PWM 输出。 ```c #include "stm32f10x.h" // PID 控制器的参数 float Kp = 1.0; float Ki = 0.5; float Kd = 0.1; // PID 控制器的状态 float error = 0; float last_error = 0; float integral = 0; float derivative = 0; // 目标 PWM 占空比 uint16_t target_duty_cycle = 500; // 当前 PWM 占空比 uint16_t current_duty_cycle = 0; void TIM2_IRQHandler(void) { // 清除中断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 更新当前 PWM 占空比 current_duty_cycle = TIM_GetCapture1(TIM2); // 计算 PID 控制器的输出 error = target_duty_cycle - current_duty_cycle; integral += error; derivative = error - last_error; last_error = error; float output = Kp * error + Ki * integral + Kd * derivative; // 根据 PID 控制器的输出调整 PWM 占空比 current_duty_cycle += (uint16_t)output; if (current_duty_cycle > 1000) { current_duty_cycle = 1000; } else if (current_duty_cycle < 0) { current_duty_cycle = 0; } // 更新 PWM 输出 TIM_SetCompare1(TIM2, current_duty_cycle); } int main(void) { // 初始化 TIM2 定时器作为 PWM 输出 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_Period = 1000 - 1; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_Pulse = 0; TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM2, &TIM_OCInitStruct); TIM_Cmd(TIM2, ENABLE); // 配置中断 NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 进入主循环 while (1) { // 更新目标 PWM 占空比 target_duty_cycle = // 根据实际情况计算目标占空比 } } ``` 在这个示例代码中,我们使用定时器 TIM2 作为 PWM 输出,并且在中断处理函数中计算 PID 控制器的输出并根据输出调整 PWM 占空比。你需要根据实际情况调整 PID 控制器的参数和目标 PWM 占空比

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昔时扬尘处

你的鼓励会让技术更加具有价值!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值