音频电源使用PID控制保护

音频电源使用PID控制保护

简介

  • 使用ADC采集PSU电压并结合增量式PID控制实现PSU Limit功能;
  • 改善前期使用逻辑电平方式实现的PSU Limit功能;
  • 增加了温度负反馈调节保护功能,温度超过85度则减小有效输出功率,使机器在90度以下的环境中工作

描述

控制框图

PSU Block在这里插入图片描述

原理介绍

  • 第一个框图是整个PSU 模块框图,通过检测PSU电源电压使用负反馈的形式实现PSU的保护功能;
  • 第二个框图是比较详细的反馈控制框图,前一级是单纯的温度负反馈,当温度超过85度时增大PSU目标设定电压vR(t),这样对应的输出功率就会减小;后一级是电压增量PD(PID)反馈控制,功率输出很大使得电压下降时,反馈系统会降低输出功率使电压稳定在设定的电压值vR(t)上;前级温度反馈控制中温度每超过1度,PSU目标设定电压vR(t)增加2V。
  • 反馈系统实际实现中使用了一阶滞后滤波算法,整个PSU Limit程序模块每1.33ms运行一次,采样PSU电压的ADC是8位ADC;ADC的精度越高PID调节后,输出波形波动会越小;ADC采样电压的范围(2.2473V ~ 3.0564V)对应的电源电压范围是(50V ~ 68V), 所以在8位ADC参考电压3.3V采样下,电源电压变化超过 0.286796 V [ 0.286796 = 3.3 256 ∗ 68 3.0564 ] 0.286796V [0.286796 = \frac{3.3 }{256} *\frac{68} {3.0564} ] 0.286796V[0.286796=2563.33.056468]时,ADC的数据才会有变化,若是使用12位的ADC并且参考电压是3.3下,则电源电压变化超过0.018V,ADC的采样数据就会有变化,这样精度越高,调节会越及时,产生的波动就会越小,声音效果也会更好。
  • 一阶滞后滤波算法公式: S ( n ) = α S ( n − 1 ) + ( 1 − α ) G s S(n) = αS(n-1) + (1 - α)G_s S(n)=αS(n1)+(1α)Gs
  • PID算法公式: U ( n ) = K p ( E r r ( n ) + T T i ∑ i = 1 n E r r ( i ) + T D T ( E r r ( n ) − E r r ( n − 1 ) ) ) U(n)=K_p(E_{rr}(n)+\frac{T}{T_i}\sum_{i=1}^n{E_{rr}(i)}+\frac{T_D}{T}(E_{rr}(n)-E_{rr}(n-1))) U(n)=Kp(Err(n)+TiTi=1nErr(i)+TTD(Err(n)Err(n1)))
    Δ U ( n ) = K p ( [ E r r ( n ) − E r r ( n − 1 ) ] + T T i E r r ( n ) + T D T [ E r r ( n ) − 2 E r r ( n − 1 ) + E r r ( n − 2 ) ] ) \Delta{U(n)}=K_p([E_{rr}(n)-E_{rr}(n-1)]+\frac{T}{T_i}{E_{rr}(n)}+\frac{T_D}{T}[E_{rr}(n)-2E_{rr}(n-1)+E_{rr}(n-2)]) ΔU(n)=Kp([Err(n)Err(n1)]+TiTErr(n)+TTD[Err(n)2Err(n1)+Err(n2)])
    U ( n ) = Δ U ( n ) + U ( n − 1 ) U(n)=\Delta{U(n)}+U(n-1) U(n)=ΔU(n)+U(n1)
  • U(n)才是PID控制的输出
  • 温度反馈公式: t U ( t ) = 2.0 ∗ ( T m p r R e f − t E ( t ) ) ; t E ( t ) = t R ( t ) − t Y ( t ) ; T m p r R e f = 85 tU(t) = 2.0 * (TmprRef - tE(t));tE(t) =tR(t) - tY(t); TmprRef = 85 tU(t)=2.0(TmprReftE(t))tE(t)=tR(t)tY(t);TmprRef=85 t Y ( t ) tY(t) tY(t)采样反馈值, t R ( t ) tR(t) tR(t)设定值, t E ( t ) tE(t) tE(t)偏差, t U ( t ) tU(t) tU(t)输出电压(一般为负值)。

程序

/**
  * @brief  power limit param
  * @param
  * @retval None
  */
  
#if 0
void vPwrExec(float* input, LIM_Type* pLim)
{
    int i;
    volatile float aA = 0.0;
    for(i = 0; i < MG_DEF_BLK_SZ; i++)
    {
        if(pLim->Pro.fGc <= pLim->Pro.fGs)
        {
            aA = pLim->Set.aA;    /* compress time*/
        }
        /* release period*/
        else
        {
            aA = pLim->Set.aR;    /* release time*/
        }
        pLim->Pro.fGs = aA * pLim->Pro.fGs + (1 - aA) * pLim->Pro.fGc;    /* one order lag algrithm*/
        input[i] = pLim->Pro.fGs * input[i];
    }
}
#endif

#if 1
void vPwrExec(float* input, LIM_Type* pLim)
{
    fGc = pLim->Pro.fGc;
    aA = pLim->Set.aA;
    aR = pLim->Set.aR;
    PsuLimExec(input, &pLim->Pro.fGs);
}
#endif

/**
  * @brief  get Power Limiter param
  * @param
  * @retval None
  */
void getPwrParam(LIM_Type* pLim)
{
    pLim->Pro.fSCdBu = pLim->Pro.fInRMSdBu;
    pLim->Set.fVth = VthdBu + pLim->HwGain;
    /*no soft knee*/
    if(pLim->Pro.fInRMSdBu <= (pLim->Set.fVth))
    {
        pLim->Pro.fSCdBu = pLim->Pro.fInRMSdBu;
    }
    if(pLim->Pro.fInRMSdBu > (pLim->Set.fVth))
    {
        pLim->Pro.fSCdBu = pLim->Set.fVth;
    }
    pLim->Pro.fGc = pLim->Pro.fSCdBu - pLim->Pro.fInRMSdBu;
    pLim->Pro.fGc = gain_computer(pLim->Pro.fGc, 20);
}

/**
  * @brief  get ObjVth
  * @param
  * @retval None
  */
void getObjVth(void)
{
    float fMaxInRMSdBu;
    PwrData[0].Pro.fInRMSdBu = (20 * log10(fInPwrRms[0]) + dBuVrefCoef);
    PwrData[1].Pro.fInRMSdBu = (20 * log10(fInPwrRms[1]) + dBuVrefCoef);
    PwrData[0].Pro.fInRMSdBu = (PwrData[0].Pro.fInRMSdBu > (-140)) ? PwrData[0].Pro.fInRMSdBu : (-140);
    PwrData[1].Pro.fInRMSdBu = (PwrData[1].Pro.fInRMSdBu > (-140)) ? PwrData[1].Pro.fInRMSdBu : (-140);
    fMaxInRMSdBu = (PwrData[0].Pro.fInRMSdBu > PwrData[1].Pro.fInRMSdBu) ? \
                    PwrData[0].Pro.fInRMSdBu : PwrData[1].Pro.fInRMSdBu;
    VpsuRef = (gDeviceType != 0) ? VpsuRef2402 : VpsuRef1202;
    //vPID.SetVal = VpsuRef;    /* 1202 2402 have different reference*/
    tNgFeedBack(DeviceTEMP_info[2]);   /* if the temperature is bigger than 85'C ,change the psu voltage set value*/
    ReadADC(&iVadc);
    fVpsu = iVadc * VpsuAdcG;
    vPIDinc(fVpsu);
    vPID.SumVal = (vPID.SumVal > 0.0) ? vPID.SumVal : 0.0;
    VthdBu = fMaxInRMSdBu + (-fOutGainHW) - vPID.SumVal;
    VthdBu = (VthdBu <= VthMax) ? VthdBu : VthMax;
    VthdBu = (VthdBu >= VthMin) ? VthdBu : VthMin;
}

/**
  * @brief  vPID caculate
  * @param
  * @retval None
  */

void vPIDinc(float ActVal)
{
    vPID.Err = vPID.SetVal - ActVal;
    vPID.Err = (ActVal <= (vPID.SetVal + 5)) ? vPID.Err : 0.0;    /* 5V ahead of SetVal to active vPID control*/
    vPID.IncVal= vPID.P * (vPID.Err - vPID.LastErr) + vPID.I * vPID.Err + vPID.D * (vPID.Err - 2.0 * vPID.LastErr + vPID.PrevErr);
    vPID.PrevErr = vPID.LastErr;
    vPID.LastErr = vPID.Err;
    vPID.SumVal += vPID.IncVal;
    vPID.SumVal = (ActVal <= (vPID.SetVal + 5)) ? vPID.SumVal : 0.0;
}

/**
  * @brief  temperature negative feedback
  * @param vPID.SetVal controled by PSU temperature
  * @retval None
  */
void tNgFeedBack(int ActTmpr)
{
    int tErr = 0;    /* temperature error difference value*/
    tErr = TmprRef - ActTmpr;
    tErr = (ActTmpr >= TmprRef) ? tErr : 0.0;
    tErr= 2.0 * tErr;
    vPID.SetVal = VpsuRef - tErr;    /*if temperature over TmprRef, needs to increase vPID.SetVal that means decrease output power*/
}

效果图

IPX1200压缩图

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值