This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28335:TMS320F28335:PID 仿真(DCL)

Guru**** 2524260 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1239492/tms320f28335-tms320f28335-pid-simulation-dcl

器件型号:TMS320F28335

尊敬的 TI 成员:

我将为 PID 附加一个仿真代码。 我需要您的帮助来解释部分代码:

首先:如果 rk =0.25被置位、那么在12位 ADC 值(0-4095)的帮助下以及在代码行342下获得了 YK:

 YK=(((float) AdcRegs.ADCRESULT0 - 2048.0f)/ 2047.0f;

Kr 可以介于1和-1之间。 如果(悬空) AdcRegs.ADCRESULT0 介于(4095和0)之间。  

现在,下一行345 : Uk = DCL_runPID_C4(&pid1, rk, YS, lk);…… 用于运行 PID 函数。 它提供控制努力值 u (k)。

提问1:问题是 u (k)数值范围的数值是多少???? 请解释第345行。

第348行: clampactive = DCL_runClamp_C1 (&uk、upperlim、lowlim);定义上限和下限饱和。  

问题2:第350行: LK =(clampactive == 0U)? 1.0f: 0.0f;.. 没有强制选择1或0为 Clampactive。 我们可以选择其中任何一个吗???

对于353-354行:  

Duty =(UK / 2.0f + 0.5f)*(float) EPwm1Regs.TBPRD;
EPwm1Regs.CMPA.half.CMPA =(UINT16)占空比;

问题3:  

F ROM 上面的行、如果已知问题1中的 u (k)、那么为什么要除以2.5 (2.0f+0.5f)、然后乘以 EPwm1Regs.TBPRD? 这个 ePWM 是我们在第286行(EPwm1Regs.TBPRD = 0xFFFF)对 ADC 采样的 ePWM。  如果是、那么如果假设您的 y (k)将会费更改为 ADC 值、上述占空比会如何变化? 我想我应该删除线路309、然后检查 GPIO0或者 GPIO1、如果 y (k)发生变化、那么占空比会发生变化。

//###########################################################################
//
// FILE:   Example_2833xAdcSoc.c
//
// TITLE:  ADC Start of Conversion Example
//
//! \addtogroup f2833x_example_list
//! <h1> ADC Start of Conversion (adc_soc)</h1>
//!
//! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
//! Two channels are converted, ADCINA3 and ADCINA2.
//!
//! \b Watch \b Variables \n
//! - Voltage1[10]  - Last 10 ADCRESULT0 values
//! - Voltage2[10]  - Last 10 ADCRESULT1 values
//! - ConversionCount   - Current result number 0-9
//! - LoopCount     - Idle loop counter
//
//###########################################################################
// $TI Release: $
// $Release Date: $
// $Copyright:
// Copyright (C) 2009-2023 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the
//   distribution.
//
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//###########################################################################

//
// Included Files
//
#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
#include "DSP2833x_GlobalPrototypes.h"
#include "DCLF32.h"

//
// Function Prototypes
//

void gpio_select(void);
void Setup_ePWM1(void);

__interrupt void adc_isr(void);
//
// Globals
//
Uint16 LoopCount;
Uint16 ConversionCount;
Uint16 Voltage1[10];
Uint16 Voltage2[10];
//DCL_PID pid1 = PID_DEFAULTS;

//typedef struct dcl_pid pid1;

struct dcl_pid pid1;
//float pid1;
DCL_PID pid1 = PID_DEFAULTS;


float32_t yk;
float32_t lk;
float32_t uk;
//float32_t rk = 0.25;                             // initial value for control reference
//float32_t lk = 1.0;                              // control loop not saturated
float32_t rk;                             // initial value for control reference
float32_t lk;                              // control loop not saturated


float Duty;
float upperlim = 0.95;
float lowerlim = 0.05;
unsigned int clampactive;

//
// Main
//

void main(void)
{


    //DCL_PID pid1 = PID_DEFAULTS;

    pid1.Kp = 9.0f;
    pid1.Ki = 0.015f;
    pid1.Kd = 0.35f;
    pid1.Kr = 1.0f;
    pid1.c1 = 188.0296600613396f;
    pid1.c2 = 0.880296600613396f;
    pid1.d2 = 0.0f;
    pid1.d3 = 0.0f;
    pid1.i10 = 0.0f;
    pid1.i14 = 1.0f;
    pid1.Umax = 1.0f;
    pid1.Umin = -1.0f;

    rk = 0.25;                             // initial value for control reference
    lk = 1.0;

    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP2833x_SysCtrl.c file.
    //
    InitSysCtrl();

    EALLOW;
    #if (CPU_FRQ_150MHZ)     // Default - 150 MHz SYSCLKOUT
        //
        // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
        //
        #define ADC_MODCLK 0x3
    #endif
    #if (CPU_FRQ_100MHZ)
        //
        // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
        //
        #define ADC_MODCLK 0x2
    #endif
    EDIS;

    //
    // Define ADCCLK clock frequency ( less than or equal to 25 MHz )
    // Assuming InitSysCtrl() has set SYSCLKOUT to 150 MHz
    //
    EALLOW;
    SysCtrlRegs.HISPCP.all = ADC_MODCLK;
    EDIS;

    //
    // Step 2. Initialize GPIO:
    // This example function is found in the DSP2833x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    //
    // InitGpio();  // Skipped for this example

    //
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    //
    DINT;

    //
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the DSP2833x_PieCtrl.c file.
    //
    InitPieCtrl();

    //
    // Disable CPU interrupts and clear all CPU interrupt flags:
    //
    IER = 0x0000;
    IFR = 0x0000;

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in DSP2833x_DefaultIsr.c.
    // This function is found in DSP2833x_PieVect.c.
    //
    InitPieVectTable();

    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //
    EALLOW;  // This is needed to write to EALLOW protected register
    PieVectTable.ADCINT = &adc_isr;
    EDIS;    // This is needed to disable write to EALLOW protected registers

    //* configure ePWM1 */
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;

    //InitEPwm1Gpio();                             // [F2806x_EPwm.c]
    gpio_select();
    Setup_ePWM1();     // init  ePWM1A


    //void Setup_ePWM1(void)
    //{
    //EPwm1Regs.TBCTL.bit.CTRMODE = 3;        // freeze TB counter
    //EPwm1Regs.TBCTL.bit.PRDLD = 1;          // immediate load
    //EPwm1Regs.TBCTL.bit.PHSEN = 0;          // disable phase loading
    //EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;       // disable SYNCOUT signal
    //EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;      // TBCLK = SYSCLKOUT
    //EPwm1Regs.TBCTL.bit.CLKDIV = 0;         // clock divider = /1
    //EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;      // free run on emulation suspend
    //EPwm1Regs.TBPRD = 0x2328;               // set period for ePWM1 (0x2328 = 10kHz)
    //EPwm1Regs.TBPHS.all = 0;                // time-base Phase Register
    //EPwm1Regs.TBCTR = 0;                    // time-base Counter Register
    //EPwm1Regs.ETSEL.bit.SOCAEN = 1;         // enable SOC on A group
    //EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
    //EPwm1Regs.ETPS.bit.SOCAPRD = 1;         // generate pulse on 1st event
    //EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;     // enable shadow mode
    //EPwm1Regs.CMPCTL.bit.LOADAMODE = 2;     // reload on CTR=zero
    //EPwm1Regs.CMPA.half.CMPA = 0x0080;      // set compare A value
    //EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;      // HIGH on CMPA up match
    //EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;    // LOW on zero match
    //}

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;

    //
    // Step 4. Initialize all the Device Peripherals:
    // This function is found in DSP2833x_InitPeripherals.c
    //
    // InitPeripherals(); // Not required for this example
    InitAdc();  // For this example, init the ADC

    //
    // Step 5. User specific code, enable interrupts:
    //

    //gpio_select();
    //Setup_ePWM1();     // init  ePWM1A,ePWM1B


    //
    // Enable ADCINT in PIE
    //
    PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
    IER |= M_INT1;      // Enable CPU Interrupt 1
    EINT;               // Enable Global interrupt INTM
    ERTM;               // Enable Global realtime interrupt DBGM

    LoopCount = 0;
    ConversionCount = 0;

    //
    // Configure ADC
    //
    AdcRegs.ADCMAXCONV.all = 0x0001;       // Setup 2 conv's on SEQ1
    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x3; // Setup ADCINA3 as 1st SEQ1 conv.
    AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x2; // Setup ADCINA2 as 2nd SEQ1 conv.

    //
    // Enable SOCA from ePWM to start SEQ1
    //
    AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;

    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)

    //
    // Assumes ePWM1 clock is already enabled in InitSysCtrl();
    //
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;     // Enable SOC on A group
    EPwm1Regs.ETSEL.bit.SOCASEL = 4;    // Select SOC from from CPMA on upcount
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;     // Generate pulse on 1st event
    EPwm1Regs.CMPA.half.CMPA = 0x0080;  // Set compare A value
    EPwm1Regs.TBPRD = 0xFFFF;           // Set period for ePWM1
    EPwm1Regs.TBCTL.bit.CTRMODE = 0;    // count up and start

    //
    // Wait for ADC interrupt
    //
    for(;;)
    {
        LoopCount++;
    }
}

//

void Setup_ePWM1(void)
    {
    EPwm1Regs.TBCTL.bit.CTRMODE = 3;        // freeze TB counter
    EPwm1Regs.TBCTL.bit.PRDLD = 1;          // immediate load
    EPwm1Regs.TBCTL.bit.PHSEN = 0;          // disable phase loading
    EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;       // disable SYNCOUT signal
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;      // TBCLK = SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV = 0;         // clock divider = /1
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;      // free run on emulation suspend
    EPwm1Regs.TBPRD = 0x2328;               // set period for ePWM1 (0x2328 = 10kHz)
    EPwm1Regs.TBPHS.all = 0;                // time-base Phase Register
    EPwm1Regs.TBCTR = 0;                    // time-base Counter Register
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;         // enable SOC on A group
    EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;         // generate pulse on 1st event
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;     // enable shadow mode
    EPwm1Regs.CMPCTL.bit.LOADAMODE = 2;     // reload on CTR=zero
    EPwm1Regs.CMPA.half.CMPA = 0x0080;      // set compare A value
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;      // HIGH on CMPA up match
    EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;    // LOW on zero match
    }


void gpio_select(void)
        {
        EALLOW;
        GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;   // Enable pullup on GPIO0
        GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;   // Enable pullup on GPIO1
        GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;  // GPIO0 = PWM1A
        GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;  // GPIO0 = PWM1B
        EDIS;

        }
// adc_isr -
//
__interrupt void
adc_isr(void)
{
    Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
    Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;

    // read ADC channel
    yk = ((float) AdcRegs.ADCRESULT0 - 2048.0f) / 2047.0f;

    // run PID controller
    uk = DCL_runPID_C4(&pid1, rk, yk, lk);

    // external clamp for anti-windup reset
    clampactive = DCL_runClamp_C1(&uk, upperlim, lowerlim);
    //clampactive = DCL_runClamp_C1(&uk, Umax, Umin);
    lk = (clampactive == 0U) ? 1.0f : 0.0f;

    // write u(k) to PWM
    Duty = (uk / 2.0f + 0.5f) * (float) EPwm1Regs.TBPRD;
    EPwm1Regs.CMPA.half.CMPA = (Uint16) Duty;

    //
    // If 40 conversions have been logged, start over
    //
    if(ConversionCount == 9)
    {
        ConversionCount = 0;
    }
    else
    {
        ConversionCount++;
    }

    //
    // Reinitialize for next ADC sequence
    //
    AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE

    return;
}

//
// End of File
//

请分步解释所有问题。 抱歉、我不熟悉 DCL PID 仿真。

谢谢

此致

阿尔萨兰  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Arsalan:

    对于 Q1、PID 控制器还具有一个在122&123行设置的内部钳位、因此输出范围将钳位到1.0 ~-1.0

    对于第二季度,我不是完全确定你的意思是"没有强迫选择1或0为 clampactive ". 该外部钳位的目的是确保控制器不会因饱和响应而发生过阻尼(如果控制力度被钳制)、因此不会因反馈环路的影响而恢复。 我们的示例仅实施了基本的响应、允许100%的反馈或0%的反馈、如图所示、lk 表示输入控制器的反馈比率:

    您可以随意更改周围的值、实际上、该外部钳位是不必要的、因为 PID 控制器还包括一个内部钳位。 我认为该钳位的目的仅是展示 Lk 何时被钳位。 指的是 DCL_PID_C3的代码实现、它是 ASM C4的内联 C 版本。

    对于 Q3、我必须联系我们的 C2000 PWM 导出、以便具体回答我们为何要将其除以2.5。 但我认为您需要进行一些清理、因为您有多个 EPwm1Regs 初始化实例。  一旦我收到来自内部出口部门的反馈、我们会稍后回复您。

    此致!

    王森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Seng:

    感谢您提供的背景信息。 对我来说非常有帮助。 我将等待您对2.5部分的进一步反馈。

    昨天、我在硬件上测试了代码。 我总结一下这里的结果:信号被施加在 ADCINA3上作为0 - 3V 设置的输入( 见图1 )

    因此、我在这里绘制了 电压1图 :给出一个大约243的值。 在 0.1V  ADCINA3作为输入电压 和  TBPRD 0xFFFF ( 参阅  图2 )。

    图3 显示了所有 DCL 值参数(KP、ki、Kd、C1、C2、D1、D2.、VMAX、Vmin 等)。 此处、Rk = 0.25、Lk =0、YK=0.9、UK = 0.05、占空比= 34405.875、  0.1V  ADCINA3作为输入电压

    图1  

    图2:   

    图3:

    在升高   输入电压 ADCINA3  从0.1V 缓慢 变化至3V、中以表格形式列出了结果 图片4和图片5

    电压1图 :图4中给出了一个大约4095的值。   在 Picture5中、rk = 0.25、lk =0、YK=30.9、UK = 0.05、占空比= 34405.875、   3V ADCINA3作为输入电压

    图4:

    图5:

    问题1:  

    没有电源时。 全部接地、示波器上的占空比为2.4%。 当电源接通时,占空比为48%。 随着输入电压 ADCINA3的增加、占空比编号34405.875 (图5)没有变化。 它保持不变、为什么呢?  我想它应该会根据施加的电压变化来改变占空比。 因为我 会将该占空比发送到其中一个 ePWM GPIO 端口、以通过示波器观察结果、从而检查占空比是否会随施加的输入电压的增大而变化。 请对此进行解释。 我按照此设置在我的硬件上进行构建:

      

    问题2:  

    如上图所示、当将电压从0V 增加到3V ADCINA3作为输入电压时、y (k)从0.9增加到30.9。

    在 DCL 指南的 "示例5:在 FPU32上运行的 PID 控制器"中、y (k)必须在稳定后等于 r (k)。 因此、在这里、增加了输入 ADCINA3电压后、图5显示了小延迟后的稳定输出、但 y (k)不等于基准电压 r (k)。 请说明。

    问题3:  

    C1和 C2是滤波器系数,但 D2和 D3与 I10和 i14相同? 我们可以说它们是延迟后的系数吗? 上图中、在增大电压时只有 D2和 D3发生变化、为什么?  请说明。

    此处附有代码: 此处删除了多 EPwm1Regs 初始化)

    //###########################################################################
    //
    // FILE:   Example_2833xAdcSoc.c
    //
    // TITLE:  ADC Start of Conversion Example
    //
    //! \addtogroup f2833x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
    //! Two channels are converted, ADCINA3 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10]  - Last 10 ADCRESULT0 values
    //! - Voltage2[10]  - Last 10 ADCRESULT1 values
    //! - ConversionCount   - Current result number 0-9
    //! - LoopCount     - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright:
    // Copyright (C) 2009-2023 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    #include "DSP2833x_Device.h"
    #include "DSP2833x_Examples.h"
    #include "DSP2833x_GlobalPrototypes.h"
    #include "DCLF32.h"
    
    //
    // Function Prototypes
    //
    
    void gpio_select(void);
    void Setup_ePWM1(void);
    
    __interrupt void adc_isr(void);
    //
    // Globals
    //
    Uint16 LoopCount;
    Uint16 ConversionCount;
    Uint16 Voltage1[10];
    Uint16 Voltage2[10];
    
    
    //typedef struct dcl_pid pid1;
    
    struct dcl_pid pid1;
    
    //DCL_PID pid1 = PID_DEFAULTS;
    DCL_PID pid1 = PID_DEFAULTS;
    
    
    float32_t yk;
    float32_t lk;
    float32_t uk;
    float32_t rk;                             // initial value for control reference
    float32_t lk;                              // control loop not saturated
    
    
    float Duty;
    float upperlim = 0.95;
    float lowerlim = 0.05;
    unsigned int clampactive;
    
    //
    // Main
    //
    
    void main(void)
    {
    
    
        pid1.Kp = 9.0f;
        pid1.Ki = 0.015f;
        pid1.Kd = 0.35f;
        pid1.Kr = 1.0f;
        pid1.c1 = 188.0296600613396f;
        pid1.c2 = 0.880296600613396f;
        pid1.d2 = 0.0f;
        pid1.d3 = 0.0f;
        pid1.i10 = 0.0f;
        pid1.i14 = 1.0f;
        pid1.Umax = 1.0f;
        pid1.Umin = -1.0f;
    
        rk = 0.25;               // initial value for control reference
        lk = 1.0;                // control loop not saturated
    
        //
        // Step 1. Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        // This example function is found in the DSP2833x_SysCtrl.c file.
        //
        InitSysCtrl();
    
        EALLOW;
        #if (CPU_FRQ_150MHZ)     // Default - 150 MHz SYSCLKOUT
            //
            // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
            //
            #define ADC_MODCLK 0x3
        #endif
        #if (CPU_FRQ_100MHZ)
            //
            // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
            //
            #define ADC_MODCLK 0x2
        #endif
        EDIS;
    
        //
        // Define ADCCLK clock frequency ( less than or equal to 25 MHz )
        // Assuming InitSysCtrl() has set SYSCLKOUT to 150 MHz
        //
        EALLOW;
        SysCtrlRegs.HISPCP.all = ADC_MODCLK;
        EDIS;
    
        //
        // Step 2. Initialize GPIO:
        // This example function is found in the DSP2833x_Gpio.c file and
        // illustrates how to set the GPIO to it's default state.
        //
        // InitGpio();  // Skipped for this example
    
        //
        // Step 3. Clear all interrupts and initialize PIE vector table:
        // Disable CPU interrupts
        //
        DINT;
    
        //
        // Initialize the PIE control registers to their default state.
        // The default state is all PIE interrupts disabled and flags
        // are cleared.
        // This function is found in the DSP2833x_PieCtrl.c file.
        //
        InitPieCtrl();
    
        //
        // Disable CPU interrupts and clear all CPU interrupt flags:
        //
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the interrupt
        // is not used in this example.  This is useful for debug purposes.
        // The shell ISR routines are found in DSP2833x_DefaultIsr.c.
        // This function is found in DSP2833x_PieVect.c.
        //
        InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        EALLOW;  // This is needed to write to EALLOW protected register
        PieVectTable.ADCINT = &adc_isr;
        EDIS;    // This is needed to disable write to EALLOW protected registers
    
        //* configure ePWM1 */
        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        //InitEPwm1Gpio();                             // [F2806x_EPwm.c]
        gpio_select();
        Setup_ePWM1();     // init  ePWM1A
    
        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
        EDIS;
    
        //
        // Step 4. Initialize all the Device Peripherals:
        // This function is found in DSP2833x_InitPeripherals.c
        //
        // InitPeripherals(); // Not required for this example
        InitAdc();  // For this example, init the ADC
    
        //
        // Step 5. User specific code, enable interrupts:
        //
    
        //
        // Enable ADCINT in PIE
        //
        PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
        IER |= M_INT1;      // Enable CPU Interrupt 1
        EINT;               // Enable Global interrupt INTM
        ERTM;               // Enable Global realtime interrupt DBGM
    
        LoopCount = 0;
        ConversionCount = 0;
    
        //
        // Configure ADC
        //
        AdcRegs.ADCMAXCONV.all = 0x0001;       // Setup 2 conv's on SEQ1
        AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x3; // Setup ADCINA3 as 1st SEQ1 conv.
        AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x2; // Setup ADCINA2 as 2nd SEQ1 conv.
    
        //
        // Enable SOCA from ePWM to start SEQ1
        //
        AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
    
        AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)
    
        //
        // Assumes ePWM1 clock is already enabled in InitSysCtrl();
    
        //
        // Wait for ADC interrupt
        //
        for(;;)
        {
            LoopCount++;
        }
    }
    
    //
    
    void Setup_ePWM1(void)
        {
        //EPwm1Regs.TBCTL.bit.CTRMODE = 3;        // freeze TB counter
        EPwm1Regs.TBCTL.bit.CTRMODE = 0;        // count up and start
        EPwm1Regs.TBCTL.bit.PRDLD = 1;          // immediate load
        EPwm1Regs.TBCTL.bit.PHSEN = 0;          // disable phase loading
        EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;       // disable SYNCOUT signal
        EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;      // TBCLK = SYSCLKOUT
        EPwm1Regs.TBCTL.bit.CLKDIV = 0;         // clock divider = /1
        EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;      // free run on emulation suspend
        //EPwm1Regs.TBPRD = 0x2328;               // set period for ePWM1 (0x2328 = 10kHz)
        EPwm1Regs.TBPRD = 0xFFFF;               // set period for ePWM1 (0x2328 = 10kHz)
        EPwm1Regs.TBPHS.all = 0;                // time-base Phase Register
        EPwm1Regs.TBCTR = 0;                    // time-base Counter Register
        EPwm1Regs.ETSEL.bit.SOCAEN = 1;         // enable SOC on A group
        //EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
        EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
        //EPwm1Regs.ETSEL.bit.SOCASEL = 4;        // select SOC from zero match
        EPwm1Regs.ETPS.bit.SOCAPRD = 1;         // generate pulse on 1st event
        EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;     // enable shadow mode
        EPwm1Regs.CMPCTL.bit.LOADAMODE = 2;     // reload on CTR=zero
        EPwm1Regs.CMPA.half.CMPA = 0x0080;      // set compare A value
        EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;      // HIGH on CMPA up match
        EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;    // LOW on zero match
        }
    
    
    void gpio_select(void)
            {
            EALLOW;
            GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;   // Enable pullup on GPIO0
            GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;   // Enable pullup on GPIO1
            GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;  // GPIO0 = PWM1A
            GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;  // GPIO0 = PWM1B
            EDIS;
    
            }
    // adc_isr -
    //
    __interrupt void
    adc_isr(void)
    {
        Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
        Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;
    
        // read ADC channel
        yk = ((float) AdcRegs.ADCRESULT0 - 2048.0f) / 2047.0f;
    
        // run PID controller
        uk = DCL_runPID_C4(&pid1, rk, yk, lk);
    
        // external clamp for anti-windup reset
        clampactive = DCL_runClamp_C1(&uk, upperlim, lowerlim);
        //clampactive = DCL_runClamp_C1(&uk, Umax, Umin);
        lk = (clampactive == 0U) ? 1.0f : 0.0f;
    
        // write u(k) to PWM
        Duty = (uk / 2.0f + 0.5f) * (float) EPwm1Regs.TBPRD;
        EPwm1Regs.CMPA.half.CMPA = (Uint16) Duty;
    
        //
        // If 40 conversions have been logged, start over
        //
        if(ConversionCount == 9)
        {
            ConversionCount = 0;
        }
        else
        {
            ConversionCount++;
        }
    
        //
        // Reinitialize for next ADC sequence
        //
        AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
    
        return;
    }
    
    //
    // End of File
    //
    
    

    谢谢

    此致

    阿尔萨兰   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我将等待您对2.5部门的进一步反馈。

    尊敬的 Arsalan:

    这一行不能除以2.5f。 相反、它由以下主题进行解释: e2e.ti.com/.../ccs-tms320f28379d-dcl-c200-motorware

    "针对第一个问题、该示例中的假设是将控制器输出标准化为+/-1.0f。 代码行进行缩放、然后偏移控制器输出、使其在0 - 1.0f 的范围内、再乘以 PWM 周期以获得占空比。 这只是一个代码示例。"

    此致、

    马瑞安

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Arsalan、很抱歉耽误了时间。

    正如 Ryan 所说、UK/2.0f + 0.5f 是尝试将控制输出范围从-1.0~1.0f 标准化到0~1.0f、表示占空比的0%至100%。

    从您的代码来看、您已经在 F28335上设置了 ADCINA2、ADCINA3、但 ISR 仍在从 F28069 DCL 示例中读取 ADCRESULT0、向 ADCINA3提供信号不应对 ADCRESULT0产生任何影响、ADCRESULT0和 PID 的所有后续更改都可能是由于电压浮动造成的。  

    有一点我忘记提到了、那就是还有一个外部饱和、用于将饱和范围进一步钳位到0.05f~0.95f、而不是+/-1.0f。  因此、如果不需要额外的饱和、您可以注释掉第315行的 runClamp_C1。

    此致!

    王森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ryan、

    感谢您的答复。 我会在落实您的建议后很快回复您。 我很快就会告诉你结果。

    此致

    阿尔萨兰

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Sen:

    感谢您的答复。 我会在落实您的建议后很快回复您。 我很快就会告诉你结果。

    此致

    阿尔萨兰

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我们将等待您的结果。

    此致!

    马瑞安

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Sen 和 Ryan:

    感谢您的全面回复。 非常有帮助

    从您的代码来看、您已经在 F28335上设置了 ADCINA2、ADCINA3、但 ISR 仍在从 F28069 DCL 示例中读取 ADCRESULT0、向 ADCINA3提供信号不应对 ADCRESULT0产生任何影响、ADCRESULT0和 PID 的所有后续更改都可能是由于电压浮动造成的。  

    正如建议的那样、我修复了这个问题、现在我在 ADCINA0上进行应用、并且  ISR 正在读取 ADCRESULT。 它仅以2个值读取占空比。 (6553.5或0)、温度分别为0V 和3V。 我将电压设为1.2V、占空比设为0时、不会得出中间值(周围没有中间值)。 参见图。 以下内容:

    在应用于 ADCINA0上0V (接地)时、输出电压1 = 0在观察窗口上大约为65535、(因为 TBPRD = FFFF)请参见图1、2、并且当应用3V 时、占空比显示0图3、4。

    图5显示、当我在  ADCINA0上施加了大约1.2的电压时、占空比不会显示在中间值附近。 它会保持为0。 占空比必须根据施加的任何电压而变化。

    画面1 (0V 时)

    Picture2 (0V 时)--占空比= 65535

     

    画面3 (3V 时)

    图4 (3V 时)--占空比= 0

    图5 (1.2V 时大约)... 占空比没有中间值。 它会保持为0。

    更新的代码附在此处

    //###########################################################################
    //
    // FILE:   Example_2833xAdcSoc.c
    //
    // TITLE:  ADC Start of Conversion Example
    //
    //! \addtogroup f2833x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
    //! Two channels are converted, ADCINA3 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10]  - Last 10 ADCRESULT0 values
    //! - Voltage2[10]  - Last 10 ADCRESULT1 values
    //! - ConversionCount   - Current result number 0-9
    //! - LoopCount     - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright:
    // Copyright (C) 2009-2023 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    #include "DSP2833x_Device.h"
    #include "DSP2833x_Examples.h"
    #include "DSP2833x_GlobalPrototypes.h"
    #include "DCLF32.h"
    
    //
    // Function Prototypes
    //
    
    void gpio_select(void);
    void Setup_ePWM1(void);
    
    __interrupt void adc_isr(void);
    //
    // Globals
    //
    Uint16 LoopCount;
    Uint16 ConversionCount;
    Uint16 Voltage1[10];
    Uint16 Voltage2[10];
    
    
    //typedef struct dcl_pid pid1;
    
    struct dcl_pid pid1;
    
    //DCL_PID pid1 = PID_DEFAULTS;
    DCL_PID pid1 = PID_DEFAULTS;
    
    
    float32_t yk;
    float32_t lk;
    float32_t uk;
    float32_t rk;                             // initial value for control reference
    float32_t lk;                              // control loop not saturated
    
    
    float Duty;
    float upperlim = 0.95;
    float lowerlim = 0.05;
    unsigned int clampactive;
    
    //
    // Main
    //
    
    void main(void)
    {
    
    
        pid1.Kp = 9.0f;
        pid1.Ki = 0.015f;
        pid1.Kd = 0.35f;
        pid1.Kr = 1.0f;
        pid1.c1 = 188.0296600613396f;
        pid1.c2 = 0.880296600613396f;
        pid1.d2 = 0.0f;
        pid1.d3 = 0.0f;
        pid1.i10 = 0.0f;
        pid1.i14 = 1.0f;
        pid1.Umax = 1.0f;
        pid1.Umin = -1.0f;
    
        rk = 0.25;               // initial value for control reference
        lk = 1.0;                // control loop not saturated
    
        //
        // Step 1. Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        // This example function is found in the DSP2833x_SysCtrl.c file.
        //
        InitSysCtrl();
    
        EALLOW;
        #if (CPU_FRQ_150MHZ)     // Default - 150 MHz SYSCLKOUT
            //
            // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
            //
            #define ADC_MODCLK 0x3
        #endif
        #if (CPU_FRQ_100MHZ)
            //
            // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
            //
            #define ADC_MODCLK 0x2
        #endif
        EDIS;
    
        //
        // Define ADCCLK clock frequency ( less than or equal to 25 MHz )
        // Assuming InitSysCtrl() has set SYSCLKOUT to 150 MHz
        //
        EALLOW;
        SysCtrlRegs.HISPCP.all = ADC_MODCLK;
        EDIS;
    
        //
        // Step 2. Initialize GPIO:
        // This example function is found in the DSP2833x_Gpio.c file and
        // illustrates how to set the GPIO to it's default state.
        //
        // InitGpio();  // Skipped for this example
    
        //
        // Step 3. Clear all interrupts and initialize PIE vector table:
        // Disable CPU interrupts
        //
        DINT;
    
        //
        // Initialize the PIE control registers to their default state.
        // The default state is all PIE interrupts disabled and flags
        // are cleared.
        // This function is found in the DSP2833x_PieCtrl.c file.
        //
        InitPieCtrl();
    
        //
        // Disable CPU interrupts and clear all CPU interrupt flags:
        //
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the interrupt
        // is not used in this example.  This is useful for debug purposes.
        // The shell ISR routines are found in DSP2833x_DefaultIsr.c.
        // This function is found in DSP2833x_PieVect.c.
        //
        InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        EALLOW;  // This is needed to write to EALLOW protected register
        PieVectTable.ADCINT = &adc_isr;
        EDIS;    // This is needed to disable write to EALLOW protected registers
    
        //* configure ePWM1 */
        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        //InitEPwm1Gpio();                             // [F2806x_EPwm.c]
        gpio_select();
        Setup_ePWM1();     // init  ePWM1A
    
        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
        EDIS;
    
        //
        // Step 4. Initialize all the Device Peripherals:
        // This function is found in DSP2833x_InitPeripherals.c
        //
        // InitPeripherals(); // Not required for this example
        InitAdc();  // For this example, init the ADC
    
        //
        // Step 5. User specific code, enable interrupts:
        //
    
        //
        // Enable ADCINT in PIE
        //
        PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
        IER |= M_INT1;      // Enable CPU Interrupt 1
        EINT;               // Enable Global interrupt INTM
        ERTM;               // Enable Global realtime interrupt DBGM
    
        LoopCount = 0;
        ConversionCount = 0;
    
        //
        // Configure ADC
        //
        AdcRegs.ADCMAXCONV.all = 0x0001;       // Setup 2 conv's on SEQ1
        AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA0 as 1st SEQ1 conv.
        AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x2; // Setup ADCINA2 as 2nd SEQ1 conv.
    
        //
        // Enable SOCA from ePWM to start SEQ1
        //
        AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
    
        AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)
    
        //
        // Assumes ePWM1 clock is already enabled in InitSysCtrl();
    
        //
        // Wait for ADC interrupt
        //
        for(;;)
        {
            LoopCount++;
        }
    }
    
    //
    
    void Setup_ePWM1(void)
        {
        //EPwm1Regs.TBCTL.bit.CTRMODE = 3;        // freeze TB counter
        EPwm1Regs.TBCTL.bit.CTRMODE = 0;        // count up and start
        EPwm1Regs.TBCTL.bit.PRDLD = 1;          // immediate load
        EPwm1Regs.TBCTL.bit.PHSEN = 0;          // disable phase loading
        EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;       // disable SYNCOUT signal
        EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;      // TBCLK = SYSCLKOUT
        EPwm1Regs.TBCTL.bit.CLKDIV = 0;         // clock divider = /1
        EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;      // free run on emulation suspend
        //EPwm1Regs.TBPRD = 0x2328;               // set period for ePWM1 (0x2328 = 10kHz)
        EPwm1Regs.TBPRD = 0xFFFF;               // set period for ePWM1 (0x2328 = 10kHz)
        EPwm1Regs.TBPHS.all = 0;                // time-base Phase Register
        EPwm1Regs.TBCTR = 0;                    // time-base Counter Register
        EPwm1Regs.ETSEL.bit.SOCAEN = 1;         // enable SOC on A group
        //EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
        EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
        //EPwm1Regs.ETSEL.bit.SOCASEL = 4;        // select SOC from zero match
        EPwm1Regs.ETPS.bit.SOCAPRD = 1;         // generate pulse on 1st event
        EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;     // enable shadow mode
        EPwm1Regs.CMPCTL.bit.LOADAMODE = 2;     // reload on CTR=zero
        EPwm1Regs.CMPA.half.CMPA = 0x0080;      // set compare A value
        EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;      // HIGH on CMPA up match
        EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;    // LOW on zero match
        }
    
    
    void gpio_select(void)
            {
            EALLOW;
            GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;   // Enable pullup on GPIO0
            GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;   // Enable pullup on GPIO1
            GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;  // GPIO0 = PWM1A
            GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;  // GPIO0 = PWM1B
            EDIS;
    
            }
    // adc_isr -
    //
    __interrupt void
    adc_isr(void)
    {
        Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
        Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;
    
        // read ADC channel
        yk = ((float) AdcRegs.ADCRESULT0 - 2048.0f) / 2047.0f;
    
        // run PID controller
        uk = DCL_runPID_C4(&pid1, rk, yk, lk);
    
        // external clamp for anti-windup reset
        //clampactive = DCL_runClamp_C1(&uk, upperlim, lowerlim);
        //clampactive = DCL_runClamp_C1(&uk, Umax, Umin);
        lk = (clampactive == 0U) ? 1.0f : 0.0f;
    
        // write u(k) to PWM
        Duty = (uk / 2.0f + 0.5f) * (float) EPwm1Regs.TBPRD;
        EPwm1Regs.CMPA.half.CMPA = (Uint16) Duty;
    
        //
        // If 40 conversions have been logged, start over
        //
        if(ConversionCount == 9)
        {
            ConversionCount = 0;
        }
        else
        {
            ConversionCount++;
        }
    
        //
        // Reinitialize for next ADC sequence
        //
        AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
    
        return;
    }
    
    //
    // End of File
    //
    

    请 相应地建议此问题

    谢谢

    此致

    阿尔萨兰

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Sen 和 Ryan:

    感谢您的全面回复。 非常有帮助

    从您的代码来看、您已经在 F28335上设置了 ADCINA2、ADCINA3、但 ISR 仍在从 F28069 DCL 示例中读取 ADCRESULT0、向 ADCINA3提供信号不应对 ADCRESULT0产生任何影响、ADCRESULT0和 PID 的所有后续更改都可能是由于电压浮动造成的。  

    正如建议的那样、我修复了这个问题、现在我在 ADCINA0上进行应用、并且  ISR 正在读取 ADCRESULT。 它仅以2个值读取占空比。 (6553.5或0)、温度分别为0V 和3V。 我将电压设为1.2V、占空比设为0时、不会得出中间值(周围没有中间值)。 参见图。 以下内容:

    在应用于  ADCINA0上0V (接地)时、输出电压1 = 0在观察窗口上大约为65535、(因为 TBPRD = FFFF)请参见图1、2、并且当应用3V 时、占空比显示0图3、4。

    图5显示、当我在  ADCINA0上施加了大约1.2的电压时、占空比不会显示在中间值附近。 它会保持为0。 占空比必须根据施加的任何电压而变化。

    画面1 (0V 时)

    Picture2 (0V 时)--占空比= 65535

     

    画面3 (3V 时)

    图4 (3V 时)--占空比= 0

    图5 (1.2V 时大约)... 占空比没有中间值。 它会保持为0。

    更新的代码附在此处

    //###########################################################################
    //
    // FILE:   Example_2833xAdcSoc.c
    //
    // TITLE:  ADC Start of Conversion Example
    //
    //! \addtogroup f2833x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
    //! Two channels are converted, ADCINA3 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10]  - Last 10 ADCRESULT0 values
    //! - Voltage2[10]  - Last 10 ADCRESULT1 values
    //! - ConversionCount   - Current result number 0-9
    //! - LoopCount     - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright:
    // Copyright (C) 2009-2023 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    #include "DSP2833x_Device.h"
    #include "DSP2833x_Examples.h"
    #include "DSP2833x_GlobalPrototypes.h"
    #include "DCLF32.h"
    
    //
    // Function Prototypes
    //
    
    void gpio_select(void);
    void Setup_ePWM1(void);
    
    __interrupt void adc_isr(void);
    //
    // Globals
    //
    Uint16 LoopCount;
    Uint16 ConversionCount;
    Uint16 Voltage1[10];
    Uint16 Voltage2[10];
    
    
    //typedef struct dcl_pid pid1;
    
    struct dcl_pid pid1;
    
    //DCL_PID pid1 = PID_DEFAULTS;
    DCL_PID pid1 = PID_DEFAULTS;
    
    
    float32_t yk;
    float32_t lk;
    float32_t uk;
    float32_t rk;                             // initial value for control reference
    float32_t lk;                              // control loop not saturated
    
    
    float Duty;
    float upperlim = 0.95;
    float lowerlim = 0.05;
    unsigned int clampactive;
    
    //
    // Main
    //
    
    void main(void)
    {
    
    
        pid1.Kp = 9.0f;
        pid1.Ki = 0.015f;
        pid1.Kd = 0.35f;
        pid1.Kr = 1.0f;
        pid1.c1 = 188.0296600613396f;
        pid1.c2 = 0.880296600613396f;
        pid1.d2 = 0.0f;
        pid1.d3 = 0.0f;
        pid1.i10 = 0.0f;
        pid1.i14 = 1.0f;
        pid1.Umax = 1.0f;
        pid1.Umin = -1.0f;
    
        rk = 0.25;               // initial value for control reference
        lk = 1.0;                // control loop not saturated
    
        //
        // Step 1. Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        // This example function is found in the DSP2833x_SysCtrl.c file.
        //
        InitSysCtrl();
    
        EALLOW;
        #if (CPU_FRQ_150MHZ)     // Default - 150 MHz SYSCLKOUT
            //
            // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
            //
            #define ADC_MODCLK 0x3
        #endif
        #if (CPU_FRQ_100MHZ)
            //
            // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
            //
            #define ADC_MODCLK 0x2
        #endif
        EDIS;
    
        //
        // Define ADCCLK clock frequency ( less than or equal to 25 MHz )
        // Assuming InitSysCtrl() has set SYSCLKOUT to 150 MHz
        //
        EALLOW;
        SysCtrlRegs.HISPCP.all = ADC_MODCLK;
        EDIS;
    
        //
        // Step 2. Initialize GPIO:
        // This example function is found in the DSP2833x_Gpio.c file and
        // illustrates how to set the GPIO to it's default state.
        //
        // InitGpio();  // Skipped for this example
    
        //
        // Step 3. Clear all interrupts and initialize PIE vector table:
        // Disable CPU interrupts
        //
        DINT;
    
        //
        // Initialize the PIE control registers to their default state.
        // The default state is all PIE interrupts disabled and flags
        // are cleared.
        // This function is found in the DSP2833x_PieCtrl.c file.
        //
        InitPieCtrl();
    
        //
        // Disable CPU interrupts and clear all CPU interrupt flags:
        //
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the interrupt
        // is not used in this example.  This is useful for debug purposes.
        // The shell ISR routines are found in DSP2833x_DefaultIsr.c.
        // This function is found in DSP2833x_PieVect.c.
        //
        InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        EALLOW;  // This is needed to write to EALLOW protected register
        PieVectTable.ADCINT = &adc_isr;
        EDIS;    // This is needed to disable write to EALLOW protected registers
    
        //* configure ePWM1 */
        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        //InitEPwm1Gpio();                             // [F2806x_EPwm.c]
        gpio_select();
        Setup_ePWM1();     // init  ePWM1A
    
        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
        EDIS;
    
        //
        // Step 4. Initialize all the Device Peripherals:
        // This function is found in DSP2833x_InitPeripherals.c
        //
        // InitPeripherals(); // Not required for this example
        InitAdc();  // For this example, init the ADC
    
        //
        // Step 5. User specific code, enable interrupts:
        //
    
        //
        // Enable ADCINT in PIE
        //
        PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
        IER |= M_INT1;      // Enable CPU Interrupt 1
        EINT;               // Enable Global interrupt INTM
        ERTM;               // Enable Global realtime interrupt DBGM
    
        LoopCount = 0;
        ConversionCount = 0;
    
        //
        // Configure ADC
        //
        AdcRegs.ADCMAXCONV.all = 0x0001;       // Setup 2 conv's on SEQ1
        AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA0 as 1st SEQ1 conv.
        AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x2; // Setup ADCINA2 as 2nd SEQ1 conv.
    
        //
        // Enable SOCA from ePWM to start SEQ1
        //
        AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
    
        AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)
    
        //
        // Assumes ePWM1 clock is already enabled in InitSysCtrl();
    
        //
        // Wait for ADC interrupt
        //
        for(;;)
        {
            LoopCount++;
        }
    }
    
    //
    
    void Setup_ePWM1(void)
        {
        //EPwm1Regs.TBCTL.bit.CTRMODE = 3;        // freeze TB counter
        EPwm1Regs.TBCTL.bit.CTRMODE = 0;        // count up and start
        EPwm1Regs.TBCTL.bit.PRDLD = 1;          // immediate load
        EPwm1Regs.TBCTL.bit.PHSEN = 0;          // disable phase loading
        EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;       // disable SYNCOUT signal
        EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;      // TBCLK = SYSCLKOUT
        EPwm1Regs.TBCTL.bit.CLKDIV = 0;         // clock divider = /1
        EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;      // free run on emulation suspend
        //EPwm1Regs.TBPRD = 0x2328;               // set period for ePWM1 (0x2328 = 10kHz)
        EPwm1Regs.TBPRD = 0xFFFF;               // set period for ePWM1 (0x2328 = 10kHz)
        EPwm1Regs.TBPHS.all = 0;                // time-base Phase Register
        EPwm1Regs.TBCTR = 0;                    // time-base Counter Register
        EPwm1Regs.ETSEL.bit.SOCAEN = 1;         // enable SOC on A group
        //EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
        EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
        //EPwm1Regs.ETSEL.bit.SOCASEL = 4;        // select SOC from zero match
        EPwm1Regs.ETPS.bit.SOCAPRD = 1;         // generate pulse on 1st event
        EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;     // enable shadow mode
        EPwm1Regs.CMPCTL.bit.LOADAMODE = 2;     // reload on CTR=zero
        EPwm1Regs.CMPA.half.CMPA = 0x0080;      // set compare A value
        EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;      // HIGH on CMPA up match
        EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;    // LOW on zero match
        }
    
    
    void gpio_select(void)
            {
            EALLOW;
            GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;   // Enable pullup on GPIO0
            GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;   // Enable pullup on GPIO1
            GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;  // GPIO0 = PWM1A
            GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;  // GPIO0 = PWM1B
            EDIS;
    
            }
    // adc_isr -
    //
    __interrupt void
    adc_isr(void)
    {
        Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
        Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;
    
        // read ADC channel
        yk = ((float) AdcRegs.ADCRESULT0 - 2048.0f) / 2047.0f;
    
        // run PID controller
        uk = DCL_runPID_C4(&pid1, rk, yk, lk);
    
        // external clamp for anti-windup reset
        //clampactive = DCL_runClamp_C1(&uk, upperlim, lowerlim);
        //clampactive = DCL_runClamp_C1(&uk, Umax, Umin);
        lk = (clampactive == 0U) ? 1.0f : 0.0f;
    
        // write u(k) to PWM
        Duty = (uk / 2.0f + 0.5f) * (float) EPwm1Regs.TBPRD;
        EPwm1Regs.CMPA.half.CMPA = (Uint16) Duty;
    
        //
        // If 40 conversions have been logged, start over
        //
        if(ConversionCount == 9)
        {
            ConversionCount = 0;
        }
        else
        {
            ConversionCount++;
        }
    
        //
        // Reinitialize for next ADC sequence
        //
        AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
    
        return;
    }
    
    //
    // End of File
    //
    

    请 相应地建议此问题

    谢谢

    此致

    阿尔萨兰

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Arsalan:

    您现在看到的是正确的 ADC 样本、对吗? 电压似乎为1.2V 时、UK 为-1、这是不正确的、我认为应该为0? 这样、占空比为 TBPRD 的50%。 为什么在1.2V 时、英国为-1V、我认为英国返回的浮点值不正确。 在这里有什么缺失吗?

    此致!

    马瑞安

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Arsalan:

    是的,对于一个因第309行而被限定为+/-1的 YK,但在图5中则是12.8。  当 KP 为9.0f 时、控制器会返回最大控制力度、范围为+/-1、这可能会解释为什么占空比只显示为0或100%。 控制器对大于/小于预期输入的响应过大、因此输出了最大的控制力度。

    此致!  

    王森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Seng:

    感谢您的答复。

    对于其中一个,YK 的值应限定为+/-1

    正如您所说的,YK 的值应该是1或-1。 但是根据下面的公式行309、这个值应该在-1到+1之间、包含+1和-1。 它们之间可以是任意值、具体取决于0 - 3V 范围内的 ADC 输入 ADCINA0。

    当 KP 为9.0f 时、控制器会返回最大控制力度、范围为+/-1、这可能会解释为何占空比仅为0或100%

    我是否应该更改 KP 以便能够在(0到100%)之间更改占空比?? 不完全是0或100%。 因为此处的目的是根据我的 ADC 输入生成不同的占空比。  正如 Ryan 所说的、如果我施加1.2V 电压、那么我的占空比必须接近50%。 您能否请我如何生成不同的占空比、如10、20、50、55、68、77、90 %等??? 是否应该在程序中设置其他参数

    代码附在此处

    //###########################################################################
    //
    // FILE:   Example_2833xAdcSoc.c
    //
    // TITLE:  ADC Start of Conversion Example
    //
    //! \addtogroup f2833x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
    //! Two channels are converted, ADCINA3 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10]  - Last 10 ADCRESULT0 values
    //! - Voltage2[10]  - Last 10 ADCRESULT1 values
    //! - ConversionCount   - Current result number 0-9
    //! - LoopCount     - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright:
    // Copyright (C) 2009-2023 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    #include "DSP2833x_Device.h"
    #include "DSP2833x_Examples.h"
    #include "DSP2833x_GlobalPrototypes.h"
    #include "DCLF32.h"
    
    //
    // Function Prototypes
    //
    
    void gpio_select(void);
    void Setup_ePWM1(void);
    
    __interrupt void adc_isr(void);
    //
    // Globals
    //
    Uint16 LoopCount;
    Uint16 ConversionCount;
    Uint16 Voltage1[10];
    Uint16 Voltage2[10];
    
    
    //typedef struct dcl_pid pid1;
    
    struct dcl_pid pid1;
    
    //DCL_PID pid1 = PID_DEFAULTS;
    DCL_PID pid1 = PID_DEFAULTS;
    
    
    float32_t yk;
    float32_t lk;
    float32_t uk;
    float32_t rk;                             // initial value for control reference
    float32_t lk;                              // control loop not saturated
    
    
    float Duty;
    float upperlim = 0.95;
    float lowerlim = 0.05;
    unsigned int clampactive;
    
    //
    // Main
    //
    
    void main(void)
    {
    
    
        pid1.Kp = 9.0f;
        pid1.Ki = 0.015f;
        pid1.Kd = 0.35f;
        pid1.Kr = 1.0f;
        pid1.c1 = 188.0296600613396f;
        pid1.c2 = 0.880296600613396f;
        pid1.d2 = 0.0f;
        pid1.d3 = 0.0f;
        pid1.i10 = 0.0f;
        pid1.i14 = 1.0f;
        pid1.Umax = 1.0f;
        pid1.Umin = -1.0f;
    
        rk = 0.25;               // initial value for control reference
        lk = 1.0;                // control loop not saturated
    
        //
        // Step 1. Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        // This example function is found in the DSP2833x_SysCtrl.c file.
        //
        InitSysCtrl();
    
        EALLOW;
        #if (CPU_FRQ_150MHZ)     // Default - 150 MHz SYSCLKOUT
            //
            // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
            //
            #define ADC_MODCLK 0x3
        #endif
        #if (CPU_FRQ_100MHZ)
            //
            // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
            //
            #define ADC_MODCLK 0x2
        #endif
        EDIS;
    
        //
        // Define ADCCLK clock frequency ( less than or equal to 25 MHz )
        // Assuming InitSysCtrl() has set SYSCLKOUT to 150 MHz
        //
        EALLOW;
        SysCtrlRegs.HISPCP.all = ADC_MODCLK;
        EDIS;
    
        //
        // Step 2. Initialize GPIO:
        // This example function is found in the DSP2833x_Gpio.c file and
        // illustrates how to set the GPIO to it's default state.
        //
        // InitGpio();  // Skipped for this example
    
        //
        // Step 3. Clear all interrupts and initialize PIE vector table:
        // Disable CPU interrupts
        //
        DINT;
    
        //
        // Initialize the PIE control registers to their default state.
        // The default state is all PIE interrupts disabled and flags
        // are cleared.
        // This function is found in the DSP2833x_PieCtrl.c file.
        //
        InitPieCtrl();
    
        //
        // Disable CPU interrupts and clear all CPU interrupt flags:
        //
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the interrupt
        // is not used in this example.  This is useful for debug purposes.
        // The shell ISR routines are found in DSP2833x_DefaultIsr.c.
        // This function is found in DSP2833x_PieVect.c.
        //
        InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        EALLOW;  // This is needed to write to EALLOW protected register
        PieVectTable.ADCINT = &adc_isr;
        EDIS;    // This is needed to disable write to EALLOW protected registers
    
        //* configure ePWM1 */
        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        //InitEPwm1Gpio();                             // [F2806x_EPwm.c]
        gpio_select();
        Setup_ePWM1();     // init  ePWM1A
    
        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
        EDIS;
    
        //
        // Step 4. Initialize all the Device Peripherals:
        // This function is found in DSP2833x_InitPeripherals.c
        //
        // InitPeripherals(); // Not required for this example
        InitAdc();  // For this example, init the ADC
    
        //
        // Step 5. User specific code, enable interrupts:
        //
    
        //
        // Enable ADCINT in PIE
        //
        PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
        IER |= M_INT1;      // Enable CPU Interrupt 1
        EINT;               // Enable Global interrupt INTM
        ERTM;               // Enable Global realtime interrupt DBGM
    
        LoopCount = 0;
        ConversionCount = 0;
    
        //
        // Configure ADC
        //
        AdcRegs.ADCMAXCONV.all = 0x0001;       // Setup 2 conv's on SEQ1
        AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA0 as 1st SEQ1 conv.
        AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x2; // Setup ADCINA2 as 2nd SEQ1 conv.
    
        //
        // Enable SOCA from ePWM to start SEQ1
        //
        AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
    
        AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)
    
        //
        // Assumes ePWM1 clock is already enabled in InitSysCtrl();
    
        //
        // Wait for ADC interrupt
        //
        for(;;)
        {
            LoopCount++;
        }
    }
    
    //
    
    void Setup_ePWM1(void)
        {
        //EPwm1Regs.TBCTL.bit.CTRMODE = 3;        // freeze TB counter
        EPwm1Regs.TBCTL.bit.CTRMODE = 0;        // count up and start
        EPwm1Regs.TBCTL.bit.PRDLD = 1;          // immediate load
        EPwm1Regs.TBCTL.bit.PHSEN = 0;          // disable phase loading
        EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;       // disable SYNCOUT signal
        EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;      // TBCLK = SYSCLKOUT
        EPwm1Regs.TBCTL.bit.CLKDIV = 0;         // clock divider = /1
        EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;      // free run on emulation suspend
        //EPwm1Regs.TBPRD = 0x2328;               // set period for ePWM1 (0x2328 = 10kHz)
        EPwm1Regs.TBPRD = 0xFFFF;               // set period for ePWM1 (0x2328 = 10kHz)
        EPwm1Regs.TBPHS.all = 0;                // time-base Phase Register
        EPwm1Regs.TBCTR = 0;                    // time-base Counter Register
        EPwm1Regs.ETSEL.bit.SOCAEN = 1;         // enable SOC on A group
        //EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
        EPwm1Regs.ETSEL.bit.SOCASEL = 1;        // select SOC from zero match
        //EPwm1Regs.ETSEL.bit.SOCASEL = 4;        // select SOC from zero match
        EPwm1Regs.ETPS.bit.SOCAPRD = 1;         // generate pulse on 1st event
        EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0;     // enable shadow mode
        EPwm1Regs.CMPCTL.bit.LOADAMODE = 2;     // reload on CTR=zero
        EPwm1Regs.CMPA.half.CMPA = 0x0080;      // set compare A value
        EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;      // HIGH on CMPA up match
        EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;    // LOW on zero match
        }
    
    
    void gpio_select(void)
            {
            EALLOW;
            GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;   // Enable pullup on GPIO0
            GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;   // Enable pullup on GPIO1
            GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;  // GPIO0 = PWM1A
            GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;  // GPIO0 = PWM1B
            EDIS;
    
            }
    // adc_isr -
    //
    __interrupt void
    adc_isr(void)
    {
        Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
        Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;
    
        // read ADC channel
        yk = ((float) AdcRegs.ADCRESULT0 - 2048.0f) / 2047.0f;
    
        // run PID controller
        uk = DCL_runPID_C4(&pid1, rk, yk, lk);
    
        // external clamp for anti-windup reset
        //clampactive = DCL_runClamp_C1(&uk, upperlim, lowerlim);
        //clampactive = DCL_runClamp_C1(&uk, Umax, Umin);
        lk = (clampactive == 0U) ? 1.0f : 0.0f;
    
        // write u(k) to PWM
        Duty = (uk / 2.0f + 0.5f) * (float) EPwm1Regs.TBPRD;
        EPwm1Regs.CMPA.half.CMPA = (Uint16) Duty;
    
        //
        // If 40 conversions have been logged, start over
        //
        if(ConversionCount == 9)
        {
            ConversionCount = 0;
        }
        else
        {
            ConversionCount++;
        }
    
        //
        // Reinitialize for next ADC sequence
        //
        AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
    
        return;
    }
    
    //
    // End of File
    //

     谢谢

    此致

    阿尔萨兰

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Arsalan:

    我担心的是,YD 远远超出了+/-1的范围,它在图5上显示12.9f,应该不是这样的。 如果我们 快速计算、P 路径的控制力度将是 ABS (YK - RK)* KP =(12.9 - 0.25)* 9 = 113.85、这个值会被钳位到1。

    您能不能要求我如何生成不同的占空比,如10、20、50 55、68、77、90 %等??

    目前、您是否有任何反馈机制 允许 使用占空比并影响 ADC 输入? 如果没有任何反馈、 PID 控制器将永远无法达到目标电压、且其 I 路径最终会使反馈达到饱和。 如果 无法持续施加输入影响、控制器最终会在达到目标值时稳定在0%。 要让控制器 不断提供控制措施、唯一方法是 从不断施加影响开始。

    如果我正在申请1.2V,那么我必须有接近50%的工作[/报价]

    如果只需要基于 ADC 读数的成比例占空比、 则不需要 PID 来实现、直接将 ADC 读数分配到占空比寄存器就足够了、前提是不会对系统产生外部影响。

    此致!

    王森