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.

[参考译文] TMS320F280039C:SVPWM 问题

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions

器件型号:TMS320F280039C
主题中讨论的其他器件:INA296A

您好!

 

我正在使用另一个 MCU 将一个已经正常工作的系统迁移到使用 TI 的 C2000 MCU。 该系统依赖于交流 FOC 电机控制。 我已经在运行稳压器、并且我正在通过一个库在两个微控制器之间共享的 Park、Clarke、逆向 Park 变换。 因此,我知道这不是问题。 FOC 控制中唯一不同的是 SVPWM 模块。 我没有自己的 SVPWM 模块,并且正在使用 MCU 供应商的 SVPWM 模块。 我本周休假、TI e2e 站点因维护而中断、因此我要让一位同事为我发布此信息、我希望在假期回来之前看到一些后续步骤! 提前感谢!

 

总体问题:我命令100 RPM、我获得100 RPM、但足够的电机电压、我可以获得400 RPM (40.14V、当我应该具有21.74V 时)。 我命令500RPM、我获得500RPM、但我获得了足够的电机电压以达到1500RPM (当我应该具有55.757V 时为145.17V)。

怀疑是问题的原因:我有一吨 D 电流–D 电流基准为0,因此我施加一吨 D 电压来尝试将 D 电流保持为0。 我认为 D 电流是由 TI 的 SVPWM 模块出现问题引起的。 我不了解输入/输出,或者 SVPWM 模块无法正常工作。 我怀疑 SVPWM 模块工作正常、问题在于我的理解。

 

请注意、工作系统/TI 之间的 Park、Clarke、逆向 Park 变换和下面使用的所有稳压器是相同的、因此这不是稳压器问题。 在这方面、工作系统/ TI 之间的代码是相同的、因为所有这些都在我们在 MCU 之间共享的库中。 这里唯一的区别是 SVPWM。 这就是我怀疑 SVPWM 存在问题的原因。

 

TI SVPWM 模块

输入:alpha/Beta 电压除以 DcLinkVoltage、得到 Alpha / Beta 占空比

输出:A、B、C PWM 从-0.5缩放到0.5

TI SVPWM–

 

有3个不同的 SVPWM 模块。 我已经尝试了3个中的2个。 我的下一步是在我休假回来后尝试第三个模块,但我希望这里的人可能会建议他们在我使用的 SVPWM 模块中看到一些内容,并提出一些我误解的内容。

 

我正在使用的当前 SVPWM 模块实际上是它们具有的旧模块。 他们建议不要使用它和使用新的。 我之所以使用它、是因为它计算 SVM 扇区、而其他2个扇区没有计算、我们需要使用这些扇区进行当前相位重建。

 

 

这将输出-0.5V 至0.5V 的 PWM、然后我将其设置为电机 PWM 计数器比较值。

 

与此相关的问题–我比较了工作系统和 TI 之间在100RPM 和500RPM 下的数据、以了解它们的比较情况。 我从这一点出发、了解工作系统和 TI 之间的主要差异、就是这样–

  1. Q 电流在2之间是相同的、这是有道理的、因为这是扭矩的来源
  2. TI 的 D 电流吨数–导致 D 电压吨数、进而导致电机电压吨数
  3. 示波器迹线上的占空比在500 RPM 60Nm 时明显不同–这让我认为 SVPWM 是错误的–要么我不了解它的输出或它的输入、要么算法是错误的。
  4. 为什么我需要对已经被2除以2的周期进行分频、这意味着我将它除以4? 这些示例也会实现这一点。 这使我很困惑。
  5. 为什么示例会(周期*占空比)+周期? 为-0.5至0.5。 这使我很困惑。 较新的 SVPWM 允许我们将占空比从0.0缩放到1.0、然后将其乘以周期、这对我来说更有意义。

 

阅读下面的数据,因为我在这里展示了 TI 较新的 SVPWM 选项。

 

100转/分60牛米

 

工作系统

 

示波器迹线

 

 

采样频率为10ms 时的趋势–仅适用于平均值比较

 

捕获采样率为250us 的缓冲器–很适合了解实际情况

 

 

占空比:-32767(-1)至32768(1)

 

 

TI

 

趋势–

 

 

 

 

 

捕获缓冲器

 

 

 

 

 

500转/分60牛米

 

工作系统

 

示波器捕获

 

 

趋势:

 

 

 

捕获缓冲器

 

 

 

 

TI

 

 

趋势

 

 

 

捕获缓冲器

 

 

 

 

TI 新的 SVPWM 选项1–

 

SVGEN_RUN

 

输入–Alpha / Beta (函数将它们除以 DcLink 电压以获取占空比)

输出–A、B、C 占空比从-0.5至0.5

 

在这里、我不确定两件事–

  1. 它们如何在不计算扇区的情况下成功地实现 SVPWM? 他们如何判断要打开哪些 IGBT?
  2. 我们采用哪种 SVM 模式? 我尝试了 SVM_COM_C、结果与计算我现在尝试的扇区的旧 SVGEN 相同。

 

TI 新的 SVPWM 选项2–

 

第二个选项将 SVGEN_RUN 与 SVGEN_CURRENT 组合在一起、SVGEN_CURRENT 为我们执行电流重构、看起来它们必须计算扇区才能实现该目的、但不能真正调用扇区并保存扇区。

 

要使用它、请运行 SVGEN_RunRegenCurrent 以计算要重建的相位、然后运行上面的 SVGEN_RUN、然后在它下面调用 SVGENCURRENT_COMPPWMData ()。 我还没有尝试这样做-它可能会做我们想要的事情、但它看起来就像它描述了阶段重建。 在这里、您不需要再次将已经被2除以2的 PWM 周期进行除法、只需将周期乘以占空比、就像我执行对我来说有意义的其他 ePWM 一样。 我喜欢这个。

 

SVGEN_RunRegenCurrent 看起来与我们使用 SVM 扇区重建电流的电流重构非常相似、但它允许重建3个相中的2个相位。

 

 

然后、在计算 PWM 之后、您决定要忽略哪个分流器、这似乎非常类似于决定您所在的 SVM 扇区:

 

 

因此、我的下一步是尝试使用此方法并查看其执行方式。

 

感谢您的帮助、很抱歉发帖很长! 希望数据和我的共享有助于找出问题的根本原因、并尝试一个很好的下一步!

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="525818" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions "]
    • 它们如何在不计算扇区的情况下成功地实现 SVPWM? 他们如何判断要打开哪些 IGBT?
    • 我们采用哪种 SVM 模式? 我尝试了 SVM_COM_C、结果与计算我现在尝试的扇区的旧 SVGEN 相同。
    [/报价]

    您的问题是否与以上两个相同? 最小值-最大值方法不需要计算 SVPWM 的扇区、它仍然计算打开/关闭 IGBT PWM 的 PWM 占空比。

    您可以使用 SVM_COM_C、它是您在上面提到的 SVGEN。

     SVGEN_CURRENT_c/h 中的所有函数仅用于 OVM 模式下的电流重构。

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

    您好、Yanming、  

    Chris 在我度假时为我发布了这个问题。 感谢 Chris 发表这篇文章! 我希望您能与我合作、即使 Chris 发布了问题。  

    我从使用较旧 的 runSVGenDQ 切换到将 SVGEN_RUN ()与 SvgenCurrent()结合使用。 SVGEN_RUN ()的输入为 Alpha / Beta 电压、此电压也等于电机线路 RMS 电压。 我不确定 TI 是否希望这是更高的 SQRT_3? 与其他微控制器供应商一起、他们希望 Alpha / Beta 等于电机线路 RMS 电压。  

    对于 PWM、我将其设置如下:  

      // Get PWM period
        float periodA = (float)(EPWM_getTimeBasePeriod(A_PWM_HS_BASE));
        float periodB = (float)(EPWM_getTimeBasePeriod(B_PWM_HS_BASE));
        float periodC = (float)(EPWM_getTimeBasePeriod(C_PWM_HS_BASE));
    
        // Limit PWMs to be safe
        float dutyALim = Limit(dutyA, 0.5, -0.5);
        float dutyBLim = Limit(dutyB, 0.5, -0.5);
        float dutyCLim = Limit(dutyC, 0.5, -0.5);
    
        // Scale duty cycles from 0 to 1
        float dutyAScaled = dutyALim + 0.5; // 0~1.0
        float dutyBScaled = dutyBLim + 0.5; // 0~1.0
        float dutyCScaled = dutyCLim + 0.5; // 0~1.0
    
        // Compute Compare value
        int16_t dutyACmpVal = (int16_t) Limit(dutyAScaled * periodA, periodA, pwmData.minCMPValue);
        int16_t dutyBCmpVal = (int16_t) Limit(dutyBScaled * periodB, periodB, pwmData.minCMPValue);
        int16_t dutyCCmpVal = (int16_t) Limit(dutyCScaled * periodC, periodC, pwmData.minCMPValue);
    
        // write the PWM data value
        EPWM_setCounterCompareValue(A_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyACmpVal);
        EPWM_setCounterCompareValue(A_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyACmpVal);
        EPWM_setCounterCompareValue(B_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyBCmpVal);
        EPWM_setCounterCompareValue(B_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyBCmpVal);
        EPWM_setCounterCompareValue(C_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyCCmpVal);
        EPWM_setCounterCompareValue(C_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyCCmpVal);

    下面是使用 TI SVGEN/SVGEN_CURRENT 模块的所有函数。  

    uint16_t SVM_TI(GE_Primary_Container_t *pContainer)
    {
        // setup the space vector generator (SVGEN) module
        float OneDivDcBus = 1 / pContainer->mpStatusBuffer->mPage1.mDcLinkVoltage;
    
        // Set Alpha / Beta from core libraries
        Vab_out_V.value[0] = pContainer->mpDrive->mAcPMSMController.mAlphaBetaVoltsReq.Alpha;
        Vab_out_V.value[1] = pContainer->mpDrive->mAcPMSMController.mAlphaBetaVoltsReq.Beta;
    
        SVGEN_setup(svgenHandle, OneDivDcBus);
    
        // run the space vector generator (SVGEN) module
        SVGEN_run(svgenHandle, &Vab_out_V, &(Vabc_pu));
    
        // Determine Alpha / Beta duty cycles
        pContainer->mpDrive->mAcPMSMController.mAlphaBetaCompensatedVoltsFlt.Alpha = pContainer->mpDrive->mAcPMSMController.mAlphaBetaVolts.Alpha * OneDivDcBus;
        pContainer->mpDrive->mAcPMSMController.mAlphaBetaCompensatedVoltsFlt.Beta = pContainer->mpDrive->mAcPMSMController.mAlphaBetaVolts.Beta * OneDivDcBus;
    //    svgen.Ualpha = pContainer->mpDrive->mAcPMSMController.mAlphaBetaCompensatedVoltsFlt.Alpha;
    //    svgen.Ubeta  = pContainer->mpDrive->mAcPMSMController.mAlphaBetaCompensatedVoltsFlt.Beta;
    
        // Run SVPWM
        //runSVGenDQ(&svgen);
    
        // Store duty cycles
        pContainer->mpDrive->mAcPMSMController.mABCDutyFlt.PhA = Vabc_pu.value[0];
        pContainer->mpDrive->mAcPMSMController.mABCDutyFlt.PhB = Vabc_pu.value[1];
        pContainer->mpDrive->mAcPMSMController.mABCDutyFlt.PhC = Vabc_pu.value[2];
        dutyALocal = pContainer->mpDrive->mAcPMSMController.mABCDutyFlt.PhA;
        dutyBLocal = pContainer->mpDrive->mAcPMSMController.mABCDutyFlt.PhB;
        dutyCLocal = pContainer->mpDrive->mAcPMSMController.mABCDutyFlt.PhC;
    
        GE_PriConvStatus_SetDebug1(pContainer, pContainer->mpDrive->mAcPMSMController.mAlphaBetaCompensatedVoltsFlt.Alpha);
        GE_PriConvStatus_SetDebug2(pContainer, pContainer->mpDrive->mAcPMSMController.mAlphaBetaCompensatedVoltsFlt.Beta);
        pContainer->mpStatusBuffer->mPage4.mDebug3 = Vab_out_V.value[0];
    
        // run the PWM compensation and current ignore algorithm
        SVGENCURRENT_compPWMData(svgencurrentHandle, &pwmData.Vabc_pu, &pwmDataPrev);
    
    
        // Return SVM sector
        //return svgen.VecSector;
        return svgenHandle->sector;
    }
    
    void Motor_PWMSetTrigger()
    {
        int16_t pwmNum = midVolShunt;
        int16_t pwmCMPA = EPWM_getCounterCompareValue(pwmHandle[pwmNum],
                                                       EPWM_COUNTER_COMPARE_A);
    
        int16_t pwmSOCCMP = 5;
    
        if(svgencurrent.ignoreShunt == SVGENCURRENT_USE_ALL)
        {
            // Set up event source for ADC trigger
            EPWM_setADCTriggerSource(A_PWM_HS_BASE,
                                     EPWM_SOC_A,
                                     EPWM_SOC_TBCTR_D_CMPC);
        }
        else
        {
            pwmSOCCMP = pwmCMPA - pwmData.deadband - pwmData.noiseWindow;
    
            if(pwmSOCCMP <= 0)
            {
                pwmSOCCMP = 5;
    
                // Set up event source for ADC trigger
                EPWM_setADCTriggerSource(A_PWM_HS_BASE,
                                         EPWM_SOC_A,
                                         EPWM_SOC_TBCTR_U_CMPC);
            }
            else
            {
                pwmSOCCMP = 5;
    
                // Set up event source for ADC trigger
                EPWM_setADCTriggerSource(A_PWM_HS_BASE,
                                         EPWM_SOC_A,
                                         EPWM_SOC_TBCTR_D_CMPC);
            }
    
        }
    
        //
        pwmData.socCMP = pwmSOCCMP;
    
        // write the PWM data value  for ADC trigger
        EPWM_setCounterCompareValue(A_PWM_HS_BASE,
                                    EPWM_COUNTER_COMPARE_C,
                                    pwmSOCCMP);
    }
    
    // Set 3Phs PWMs
    bool Motor_PWMSet()
    {
        // Invert PWMs to match NXP
        float dutyA = dutyALocal * -1;
        float dutyB = dutyBLocal * -1;
        float dutyC = dutyCLocal * -1;
    
        // Get PWM period
        float periodA = (float)(EPWM_getTimeBasePeriod(A_PWM_HS_BASE));
        float periodB = (float)(EPWM_getTimeBasePeriod(B_PWM_HS_BASE));
        float periodC = (float)(EPWM_getTimeBasePeriod(C_PWM_HS_BASE));
    
        // Limit PWMs to be safe
        float dutyALim = Limit(dutyA, 0.5, -0.5);
        float dutyBLim = Limit(dutyB, 0.5, -0.5);
        float dutyCLim = Limit(dutyC, 0.5, -0.5);
    
        // Scale duty cycles from 0 to 1
        float dutyAScaled = dutyALim + 0.5; // 0~1.0
        float dutyBScaled = dutyBLim + 0.5; // 0~1.0
        float dutyCScaled = dutyCLim + 0.5; // 0~1.0
    
        // Compute Compare value
        int16_t dutyACmpVal = (int16_t) Limit(dutyAScaled * periodA, periodA, pwmData.minCMPValue);
        int16_t dutyBCmpVal = (int16_t) Limit(dutyBScaled * periodB, periodB, pwmData.minCMPValue);
        int16_t dutyCCmpVal = (int16_t) Limit(dutyCScaled * periodC, periodC, pwmData.minCMPValue);
    
        // write the PWM data value
        EPWM_setCounterCompareValue(A_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyACmpVal);
        EPWM_setCounterCompareValue(A_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyACmpVal);
        EPWM_setCounterCompareValue(B_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyBCmpVal);
        EPWM_setCounterCompareValue(B_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyBCmpVal);
        EPWM_setCounterCompareValue(C_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyCCmpVal);
        EPWM_setCounterCompareValue(C_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyCCmpVal);
    
        ignoreShuntNextCycle = SVGENCURRENT_getIgnoreShunt(svgencurrentHandle);
        midVolShunt = SVGENCURRENT_getVmid(svgencurrentHandle);
    
        // Set trigger point in the middle of the low side pulse
        Motor_PWMSetTrigger();
    
        return 0;
    }
    
    


    这样可以解决我的 D 电流非常高的问题。 但是、当使用此电机并且 IGBT 在大约500RPM 的去饱和故障下跳闸时、电机的声音非常大。 因此、与另一家微控制器供应商的 SVM 相比、情况仍然不好。  

    这就是现在在500 RPM 和30 Nm 扭矩下的情况。 正如我说过的、所有电机控制算法都与不同的 MCU 供应商合作、并且在两个 MCU 之间共享相同的功能。 电机控制的唯一区别是 SVPWM 模块。 我没有自己的 SVPWM 模块、因此我依赖使用 TI 提供的模块。  

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

    您可能必须 同时使用 svgen()和 HAL_writePWMData(),并且 PWM 的活动电平为高电平。

    [报价 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4363386 #4363386"]我不确定 TI 是否期望 SQRT_3更高? 与其他微控制器供应商一起、他们希望 Alpha / Beta 等于电机线路 RMS 电压。  [/报价]

    SVGEN 的输入是采用 SI 格式的 alpha/Beta 电压(V)。

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

    您好、Yanming、  

    我同时使用 svgen 和 HAL_writePWMData ()。  

    这是 HAL_writePWMData 函数 。  

    static inline void
    HAL_writePWMData(HAL_MTR_Handle handle, HAL_PWMData_t *pPWMData)
    {
        HAL_MTR_Obj *obj = (HAL_MTR_Obj *)handle;
    
        float32_t period = (float32_t)(EPWM_getTimeBasePeriod(obj->pwmHandle[0]));
    
        uint16_t pwmCnt;
    
        for(pwmCnt=0; pwmCnt<3; pwmCnt++)
        {
          // compute the value
            float32_t V_pu = -pPWMData->Vabc_pu.value[pwmCnt];      // Negative
            float32_t V_sat_pu = __fsat(V_pu, 0.5, -0.5);           // -0.5~0.5
            float32_t V_sat_dc_pu = V_sat_pu + 0.5;                 // 0~1.0
            pPWMData->cmpValue[pwmCnt]  = (int16_t)(V_sat_dc_pu * period);  //
    
            if(pPWMData->cmpValue[pwmCnt] < pPWMData->minCMPValue)
            {
                pPWMData->cmpValue[pwmCnt] = pPWMData->minCMPValue;
            }
    
            // write the PWM data value
            EPWM_setCounterCompareValue(obj->pwmHandle[pwmCnt],
                                        EPWM_COUNTER_COMPARE_A,
                                        pPWMData->cmpValue[pwmCnt]);
    
            EPWM_setCounterCompareValue(obj->pwmHandle[pwmCnt],
                                        EPWM_COUNTER_COMPARE_B,
                                        pPWMData->cmpValue[pwmCnt]);
        }
    
        return;
    } // end of HAL_writePWMData() function

    我创建了自己的函数、或多或少与该函数执行相同的操作。 除了占空比反转之外、我没有看到任何差异、我在 svgen_current 函数中添加了这些函数-您在这里看到了什么大差异吗?

    // Set 3Phs PWMs
    bool Motor_PWMSet()
    {
        // Invert PWMs to match NXP
        float dutyA = dutyALocal * -1;
        float dutyB = dutyBLocal * -1;
        float dutyC = dutyCLocal * -1;
    
        // Get PWM period
        float periodA = (float)(EPWM_getTimeBasePeriod(A_PWM_HS_BASE));
        float periodB = (float)(EPWM_getTimeBasePeriod(B_PWM_HS_BASE));
        float periodC = (float)(EPWM_getTimeBasePeriod(C_PWM_HS_BASE));
    
        // Limit PWMs to be safe
        float dutyALim = Limit(dutyA, 0.5, -0.5);
        float dutyBLim = Limit(dutyB, 0.5, -0.5);
        float dutyCLim = Limit(dutyC, 0.5, -0.5);
    
        // Scale duty cycles from 0 to 1
        float dutyAScaled = dutyALim + 0.5; // 0~1.0
        float dutyBScaled = dutyBLim + 0.5; // 0~1.0
        float dutyCScaled = dutyCLim + 0.5; // 0~1.0
    
        // Compute Compare value
        int16_t dutyACmpVal = (int16_t) Limit(dutyAScaled * periodA, periodA, pwmData.minCMPValue);
        int16_t dutyBCmpVal = (int16_t) Limit(dutyBScaled * periodB, periodB, pwmData.minCMPValue);
        int16_t dutyCCmpVal = (int16_t) Limit(dutyCScaled * periodC, periodC, pwmData.minCMPValue);
    
        // write the PWM data value
        EPWM_setCounterCompareValue(A_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyACmpVal);
        EPWM_setCounterCompareValue(A_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyACmpVal);
        EPWM_setCounterCompareValue(B_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyBCmpVal);
        EPWM_setCounterCompareValue(B_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyBCmpVal);
        EPWM_setCounterCompareValue(C_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyCCmpVal);
        EPWM_setCounterCompareValue(C_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyCCmpVal);
    
        ignoreShuntNextCycle = SVGENCURRENT_getIgnoreShunt(svgencurrentHandle);
        midVolShunt = SVGENCURRENT_getVmid(svgencurrentHandle);
    
        // Set trigger point in the middle of the low side pulse
        Motor_PWMSetTrigger();
    
        return 0;
    }

    我认为 svgen 的输入是正确的。 它采用 V 的格式  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4365300 #4365300"]我创建了自己的函数、该函数与该函数的作用或多或少相同。 除了占空比反转之外、我没有看到任何差异、我在 svgen_current 函数中添加了 svgen_current 函数-您在这里看到了什么大差异吗?

    为什么不直接在 TI 示例实验室中使用这两个函数? 还是使用 您自己的所有功能、并根据 PWM 输出的活动电平设置 PWM 占空比和 CMPA?

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

    "或者使用 您自己的所有功能、并根据 PWM 输出的活动电平设置 PWM 占空比和 CMPA?"  

    这不是我要做的? 我需要 TI 提供的唯一功能是空间矢量 PWM。 这是我在 TI 使用的唯一电机控制功能。 原因是我希望不同 MCU 之间的功能尽可能接近。  

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

    我只是检查所有器件的输入-根据 D/Q 电压、α/β 电压看起来是正确的。 我的电机需要89V/1000 RPM。 这是以500 RPM 的转速运行的。 我在左光标上总共请求44.33伏的电机电压、这是正确的。  

    占空比对于左右光标提供的 alpha/beta 电压是否正确?  

    我获取这些占空比中的每个、将它们乘以-1、将它们限制在0.5至-0.5之间、然后在它们之间加0.5、得到一个从0缩放到1的占空比、然后将周期乘以比例为0至1的占空比。 这也与 HAL_writePWMData 的功能类似。 我弄错了吗?  

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

    尊敬的 Derek:

    如何确定旋转角度以在正确的时间更新周期? FAST 估算器块还具有 PIE 速度和转矩控制器、用于限制电流饱和。 较新的增强型滑模观测器(eSMO)或较旧的(LSMO)可使用 FOC 无传感器模式以开环方式启动电机、然后切换到速度大于1Hz 的闭环模式。

    为什么不尝试通过电机控制 SDK 实验熟悉与 NXP 模型完全不同的嵌入式电机控制块。 电机 ID 方法决定了电感、电阻和少量其他参数、以便与您的电机电流设置和许多其他系统变量一起输入 user.h 文件。 我注意到 x39c 具有4MSPS ADC、这是一个很好的功能。 SDK 具有针对 ePWM 输出的 CMPSS 故障跳闸功能、可检测过流情况您可以设置电流阈值跳闸点以保护直流逆变器。

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

    您好!  

    我有一个旋转变压器、我读取了每个快速线程的角度、该线程由 ADC 转换使用4kHz PWM 触发、如示例项目中所示。  

    我们的项目与示例项目执行所有相同的操作。

    每250us 快速中断、我们都会执行以下操作:

    1) 1)从旋转变压器读取电角/从 ADC 读取三相电流

    2) 2) 我们使用电角和三相电流来使用 Clark 变换计算 α/β 电流

    3) 3)使用请求的 Alpha / Beta 电压和电角、通过 Park 变换获得估计的 D/Q 电压

    4) 4)我们有一个电流调节器、它接受请求的 D/Q 电流、然后使用 Park 变换输出所需的 D/Q 电压

    5) 5)我们获取请求的 D/Q 电压、然后执行逆向 Park 变换以获取请求的 Alpha / Beta 电压

    6) 6)我们将请求的 Alpha / Beta 电压输入到 SVGEN、然后将占空比应用到 ePWM 比较值(这是该过程中唯一的新功能)

    每1ms 慢速中断、我们就会执行以下操作:  

    1) 1) 我们获取速度目标、使用轨迹计算驱动速度所需的 Q 电流

    这 看起来与您共享的方框图完全相同。 我们拥有自己的所有稳压器、轨迹、克拉克和帕克变换、我们已经使用多年、并且已经过很好的证明。 我们需要 MCU 供应商提供的唯一功能是 SVPWM 模块。 我不确定除占空比之外、该过程中还有什么可能出错的地方? 如果电角错误、电机根本不会旋转、我们的软件将在过流时跳闸。 我不需要检测电阻、电感、惯性等、因为我的电流稳压器会考虑这些因素。  

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

    我们是否可以通过任何方式让大家联机并了解这一点? 我不确定燕明的位置-如果你在中国、我可以在晚上和早上工作、如果你可以打电话帮助我。 我也有中国同事可以和你一起工作。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4365811 #4365811"]我们需要 MCU 供应商提供的唯一功能是 SVPWM 模块。 [/报价]

    但它是使用 ROM 中的 FAST 估算器开发的。 我注意到您的工作系统示波器电流捕获存在一个奇怪现象、过零事件中存在死区时间。 真正的正弦波电流在过零事件中没有死区时间。

    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4365811 #4365811"]每1ms 慢速中断我们就执行一次: 

    这可能是一个 ePIE 中断问题,但通常 x39c ePWM 模块会触发预先配置的时间,使 ADC 具有 SOCA 事件中断,其中调用了 SVGEN_setup/run (), 调用了 HAL_writePWMData ()(接近 ISR 末尾),以重新 加载 CMPA。

     HAL_writePWMData() 通过 CMPC 或 CMPD 重新加载 SOCA 的 ADC 触发计时器计数,但在代码中看不到该计数。 请注意、SDK 实验的 SVM 调用或死区发生器中未使用 CMPB。 虽然 CMPB 使  HAL_writePWMData()复杂化,但它可能只出现在示例中以显示周期也可以重新加载。

    实验7模块的以下部分还用于过调制模式电流重构(SDK 实验8/13) 100%占空比。 请注意、我 在 顶部为编译器优化(全局)速度定义了贴图5似乎减少了 THD 总谐波失真。 该模块可产生非连续 SVM 调制、在任何给定的时间、只有少数几个逆变器开关处于导通状态。  

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

    尊敬的 Derek:

    实际上、SVGEN/SVPWM 仍然是一个不依赖于器件的算法模块。 如果现有 SVGEN/SVPWM 的输出是三个相位的 PWM 占空比、您仍然可以使用它、只需将 PWM 占空比转换为 PWM 比较值、并根据您使用的器件将 PWM 比较值设置为相关寄存器。

    如果您在上面提到的步骤6中尝试使用 TI Universal Lab 提供的示例 SVGEN/SVPWM 函数、请注意 、SVGEN 的输入 Alpha / Beta 电压是带有"VOLT"的 SI 值、而 SVGEN 中使用的"oneOverDcBus_invV"是1.0f/Vdcbus。

    您使用什么电流传感器进行电机控制? 您可以首先删除与过调制相关的代码、并尝试使用开环为电机运行代码以验证 SVPWM 和 PWMDRV。

    IgneShuntNextCycle = SVGENCURRENT_getIgnoreShunt (svgencurrentHandle);
    midVolShunt = SVGENCURRENT_getVMID (svgencurentHandle);

    //运行 PWM 补偿和电流忽略算法
    SVGENCURRENT_COMPPWMData (svgencurentHandle、&pwmData.Vabc_pu、&pwmDataPrev);

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

    由于 svgen()的源代码是由 TI 提供的,我确实将其复制到了另一个使用其 SVPWM 模块的 MCU 供应商项目(我没有该模块的源代码-否则我会尝试使用 TI MCU 执行相同的操作 (请参阅此处是否更好))查看我是否有相同的问题、并比较 TI 的 svgen 和它们与其他 MCU 一起提供的 SVPWM 模块的占空比、以查看我是否可以使用该占空比来计算发生的情况。 似乎有一个东西在某处丢失。 svgen 似乎没有计算对称的占空比。 要使用 svgen、您不需要我从演示项目中看到的任何额外内容。 该函数采用 Alpha / Beta 电压、然后计算占空比。 但是、我的非 TI-MCU 项目中的此函数与我的 TI MCU 项目中的此函数有相同的问题。 电机听起来很糟糕、占空比不对称。 它使我感到缺少一个块。 我这样做的目的是让我们更清楚地了解、围绕该函数的一些事情以及我使用它的方式导致了我的问题。  

    我获取了 svgen 源代码并创建了以下函数:  

    lib_uint16_t SVM(GE_Primary_Container_t *pContainer, Drive_AlphaBeta_Flt_t *AlphaBeta, Drive_3PhABC_Int_t *DutyABC, float DcLinkVoltage)
    {
    	// Get 1 div DcLink
    	float oneDivDcBus = 1 / DcLinkVoltage;
    
    	// Get Alpha / Beta duty cycles
        float AlphaDuty = AlphaBeta->Alpha * oneDivDcBus;
        float BetaDuty = AlphaBeta->Beta * oneDivDcBus;
    
        // Calculate Valpha / Vbeta
        float VaTmp = 0.5 * AlphaDuty;
        float VbTmp = SQRT_3_OVER_2 * BetaDuty;
    
        // Calculate Va, Vb, Vc
        float Va = AlphaDuty;
        float Vb = -VaTmp + VbTmp;
        float Vc = -VaTmp - VbTmp;
    
        // Get Vmax and Vmin
        float Vmax = 0.0;
        float Vmin = 0.0;
        if(Va > Vb)
        {
        	Vmax = Va;
        	Vmin = Vb;
        }
        else
        {
        	Vmax = Vb;
        	Vmin = Va;
        }
    
        if(Vc > Vmax)
        {
        	Vmax = Vc;
        }
        else if(Vc < Vmin)
        {
        	Vmin = Vc;
        }
    
    	// Compute Vcom
        float Vcom = 0.5 * (Vmax + Vmin);
    
        // Subtract common mode term to achieve SV modulation
        Drive_3PhABC_Flt_t FltDtyCycles;
        FltDtyCycles.PhA = Va - Vcom;
        FltDtyCycles.PhB = Vb - Vcom;
        FltDtyCycles.PhC = Vc - Vcom;
    
        // Convert float duty cycles to 16 bit integer
        DutyABC->PhA = FRAC16(FltDtyCycles.PhA);
        DutyABC->PhB = FRAC16(FltDtyCycles.PhB);
        DutyABC->PhC = FRAC16(FltDtyCycles.PhC);
    
    	return 0;
    }

    这与 TI 的 svgen 函数所执行的操作相匹配。 如下所示:  

    static inline void
    SVGEN_run(SVGEN_Handle handle, const MATH_Vec2 *pVab_V, MATH_Vec3 *pVabc_pu)
    {
        float32_t Vmax_pu = 0,Vmin_pu = 0,Vcom_pu;
        float32_t oneOverDcBus_invV = SVGEN_getOneOverDcBus_invV(handle);
        SVM_Mode_e svmMode = SVGEN_getMode(handle);
    
        float32_t Valpha_pu = pVab_V->value[0] * oneOverDcBus_invV;
        float32_t Vbeta_pu = pVab_V->value[1] * oneOverDcBus_invV;
    
        float32_t Va_tmp = (float32_t)(0.5f) * Valpha_pu;
        float32_t Vb_tmp = MATH_SQRTTHREE_OVER_TWO * Vbeta_pu;
    
        float32_t Va_pu = Valpha_pu;
    
        //
        // -0.5*Valpha + sqrt(3)/2 * Vbeta
        //
        float32_t Vb_pu = -Va_tmp + Vb_tmp;
    
        //
        // -0.5*Valpha - sqrt(3)/2 * Vbeta
        float32_t Vc_pu = -Va_tmp - Vb_tmp;
    
        //
        // Find Vmax and Vmin
        //
        if(Va_pu > Vb_pu)
        {
            Vmax_pu = Va_pu;
            Vmin_pu = Vb_pu;
        }
        else
        {
            Vmax_pu = Vb_pu;
            Vmin_pu = Va_pu;
        }
    
        if(Vc_pu > Vmax_pu)
        {
            Vmax_pu = Vc_pu;
        }
        else if(Vc_pu < Vmin_pu)
        {
            Vmin_pu = Vc_pu;
        }
    
        // Compute Vcom = 0.5*(Vmax+Vmin)
        Vcom_pu = 0.5f * (Vmax_pu + Vmin_pu);
    
        if(svmMode == SVM_COM_C)
        {
            // Subtract common-mode term to achieve SV modulation
            pVabc_pu->value[0] = (Va_pu - Vcom_pu);
            pVabc_pu->value[1] = (Vb_pu - Vcom_pu);
            pVabc_pu->value[2] = (Vc_pu - Vcom_pu);
        }
        else if(svmMode == SVM_MIN_C)
        {
            pVabc_pu->value[0] = (Va_pu - Vmin_pu) - 0.5f;
            pVabc_pu->value[1] = (Vb_pu - Vmin_pu) - 0.5f;
            pVabc_pu->value[2] = (Vc_pu - Vmin_pu) - 0.5f;
        }
        else if(svmMode == SVM_MAX_C)
        {
            pVabc_pu->value[0] = (Va_pu - Vmax_pu) + 0.5f;
            pVabc_pu->value[1] = (Vb_pu - Vmax_pu) + 0.5f;
            pVabc_pu->value[2] = (Vc_pu - Vmax_pu) + 0.5f;
        }
    
        return;
    } // end of SVGEN_run() function

    我在一个项目中遇到的完全相同的问题、该项目多年来一直在完美地工作、只是取代了这一单一功能。 这是我在使用 TI 的 svgen 函数的500RPM 时的占空比看起来的样子-可以看到占空比不对称。 这会导致 α/β 电压不是一个完美的正弦波、因为我们正在针对所产生的 D 电流进行调整。  

    而我希望它们在500RPM 时看起来是这样的-这是我的另一个 MCU 供应商提供的 SVPWM 功能产生的结果:

    请注意、对于 svgen 函数、alpha/beta 电压不是正弦电压、这是由于对不良占空比的补偿。 在两张图片之间、我只更改了一行代码-我在下面评论/取消评论的行:  

        // Uncomment to test TI's svgen
        //pAcPMSMController->mSVMSector = SVM(pContainer, &pAcPMSMController->mAlphaBetaVoltsReq, &pAcPMSMController->mABCDuty, pContainer->mpStatusBuffer->mPage1.mDcLinkVoltage);
        
        // Use MCU vendor SVPWM - comment to test TI's svgen
        pAcPMSMController->mSVMSector = hal.mpSVM(pContainer);

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

    Yanming、  

    您在这里的评论"SVGEN/SVPWM 仍然是一个不依赖于器件的算法模块。 如果现有 SVGEN/SVPWM 的输出是三个相位的 PWM 占空比、您仍然可以使用它、只需将 PWM 占空比转换为 PWM 比较值、并根据您使用的器件将 PWM 比较值设置为相关寄存器。" 就是我做我刚才所做的事情的原因。  

    我的另一个 MCU 供应商项目已经工作多年、我应该能够采用 svgen 并在那里使用它、因为它只是一种算法。 它不是特定于供应商、MCU 或电机的。 因此、我的想法是调试算法、以及正在进行的操作会导致我的问题。 我觉得、由于我刚切换到 C2000 MCU、它在这里引入了太多变量、而调试为什么算法引入了这个问题是最好的步骤。  

    电流感应:我们有在分流器上读取的低侧 IGBT 电流感应。 满量程为0至4095、从-400A 至400A 计数。 我们通常使用 SVM 扇区来进行我们自己的电流重构、这就是当 svgen 未计算扇区时我感到困惑的原因。 但是、您有自己的函数用于当前重建。  

    "请注意 、SVGEN 的输入 Alpha / Beta 电压是 SI 值、带有"VOLT"、而 SVGEN 中使用的"oneOverDcBus_invV"是1.0f/Vdcbus。" 这也是正确的-我将在我的图片中看到的电压与 SI 值"volte"直接输入 svgen。  

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

    您好、Yanming、  

    我修复了将 svgen 移植到其他项目时的缩放问题。 该项目需要一个16位整数、该整数按-1到1进行缩放、以16383为中心。 现在、svgen 产生的占空比看起来更干净。  

    现在、只需将 svgen 与我的其他 MCU SVPWM 进行比较、就会在相同/相似的占空比下导致双 α/β 电压。  

    其他 MCU:
    A Max = 18422
    A min = 14318
    B 最大值= 18488
    B MIN = 14318
    C Max = 18434
    C MIN = 14311
    α 峰值= 42.860
    最小值=-42.640
    Beta Peak = 41.797
    Beta min =-41.455

    TI:
    A Max = 18417
    A min = 14514
    B 最大值= 18423
    B MIN = 14360
    C Max = 18413
    C MIN = 14340
    α 峰值= 82.860
    最小值=-84.262
    Beta Peak = 83.884
    Beta min =-82.062

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

    好的、我现在确信 svgen 不是问题。 svgen 与我的另一个项目完美配合、现在替换它的 SVPWM 函数。 为了使 svgen 与我的另一个项目一同工作、我最后要做的是将计算的占空比乘以2、因为 svgen 的输出为-0.5~0.5、而我的另一个 MCU 项目预期为1-1。  

    这意味着 svgen 不会导致我的问题。 它可能是读取电角或 ePWM 设置的内容。 可能是 GI 提到的线程优先级问题。 我现在将注释 svgen 当前及类似内容、只需使用 svgen 查看我是否可以确定 TI 项目出现了什么问题。  

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

    您可以使用 Universal Lab 中的示例 HAL_writePWMData()或您在上面发布的代码。 如果您需要使用 PWM SOC 来触发 ADC 和中断、另请参阅 PWM 配置。

    您可以运行开环电机以检查 PWM 输出是否正确,开环不需要电流/反馈信号。 您还可以检查电流/电压反馈感应信号是否正确、以验证 ADC 的 PWM 和中断配置。

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

    您好、Yanming、  

    这是一个很好的建议。 接下来、我将请求恒定电压并查看所示的 PWM。 我从 TI 切换回 svgen 函数、并删除了除它之外的所有内容、然后使用以下函数设置 PWM。  

    设置 PWM 的函数:  

    // Set 3Phs PWMs
    bool Motor_PWMSet()
    {
        // Invert PWMs to match NXP
        float dutyA = dutyALocal * -1;
        float dutyB = dutyBLocal * -1;
        float dutyC = dutyCLocal * -1;
    
        // Get PWM period
        float periodA = (float)(EPWM_getTimeBasePeriod(A_PWM_HS_BASE));
        float periodB = (float)(EPWM_getTimeBasePeriod(B_PWM_HS_BASE));
        float periodC = (float)(EPWM_getTimeBasePeriod(C_PWM_HS_BASE));
    
        // Limit PWMs to be safe
        float dutyALim = Limit(dutyA, 0.5, -0.5);
        float dutyBLim = Limit(dutyB, 0.5, -0.5);
        float dutyCLim = Limit(dutyC, 0.5, -0.5);
    
        // Scale duty cycles from 0 to 1
        float dutyAScaled = dutyALim + 0.5; // 0~1.0
        float dutyBScaled = dutyBLim + 0.5; // 0~1.0
        float dutyCScaled = dutyCLim + 0.5; // 0~1.0
    
        // Compute Compare value
        uint16_t dutyACmpVal = (uint16_t) Limit(dutyAScaled * periodA, periodA, pwmData.minCMPValue);
        uint16_t dutyBCmpVal = (uint16_t) Limit(dutyBScaled * periodB, periodB, pwmData.minCMPValue);
        uint16_t dutyCCmpVal = (uint16_t) Limit(dutyCScaled * periodC, periodC, pwmData.minCMPValue);
    
        // write the PWM data value
        EPWM_setCounterCompareValue(A_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyACmpVal);
        EPWM_setCounterCompareValue(A_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyACmpVal);
        EPWM_setCounterCompareValue(B_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyBCmpVal);
        EPWM_setCounterCompareValue(B_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyBCmpVal);
        EPWM_setCounterCompareValue(C_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyCCmpVal);
        EPWM_setCounterCompareValue(C_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyCCmpVal);
    
    //    ignoreShuntNextCycle = SVGENCURRENT_getIgnoreShunt(svgencurrentHandle);
    //    midVolShunt = SVGENCURRENT_getVmid(svgencurrentHandle);
    
        // Set trigger point in the middle of the low side pulse
        //Motor_PWMSetTrigger();
    
        return 0;
    }

    您可以看到、PWM 和 α/β 电压非常不稳定。 我在与其他 MCU 供应商一起运行代码时没有看到这种问题。 我不确定这是由于 PWM 设置错误还是电角不是每次读取相同?  

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

    您好、Yanming、  

    开环是一个很好的建议! 我认为这已经消除了电流感应、svgen 或电角方面的问题。 我想我们已经把它缩小到 PWM 的范围。  

    如果我执行开环并仅命令10V、我将获得优美的 α/β 电压和 SVM 占空比:  

    我需要检查 PWM 上输出的实际值。 看起来、我应该具有最大+/- 0.015的电压、并请求10V 的电压。  

    我还检查了100V -在这里、我很高兴 IGBT 发生了去饱和。 这将更容易在开环模式下进行调试。 使用100V 时、我有漂亮的 SVM 和 Alpha / Beta 电压。 我将查看示波器上的占空比、看看我是否可以确定导致去饱和的原因是什么。  

    在100V 电压下、我在占空比上得到+/-0.15、因此看起来一切都是正确的。 在本例中、电角只是从-1到1的旋转60Hz 正弦波、因此我认为这也消除了电角作为变量的作用、我们已经通过 PWM 将其缩小到了一定范围

    我将告诉您我在 PWM 上看到的内容! 上次我尝试读取系统中的 PWM 时、我将转换器炸毁。 我们的直流链路为565V、接地基准为-565V、因此测量实际 PWM 非常棘手。 明天、我的硬件团队今天晚上向我介绍测量系统中 PWM 的最佳方法时、我就会这样做。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4367539 #4356739"]您可以看到 PWM 和 alpha/beta 电压非常不稳定。

    出现这种问题的原因可能是 μ 250µs SOC 中断嵌套了1ms 的中断时间。 对于 Instaspin、我们使用抽取 时间(GPIO 标记脉冲)来检查 MAIN_ISR()循环是否永远不会被另一个 IRQ (GPIO 标记脉冲)抢占。

    SCIB 30ms IRQ 对 SOC ISR 造成附带损害150µs、似乎具有类似的 x49c 未解决问题。 也许在执行最后提到的破坏性测试之前检查抽取时间。 通过2个插头适配器隔离示波器交流接地引脚的典型做法。

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

    嘿、GI 和 Yanming、  

    Gi -我将研究中断的时序、并确保读取电角的中断绝不会被另一个 IRQ 抢先。  

    燕明-  

    我在命令100V 开环时捕获了在 IGBT 上发生去饱和时 PWM 的样子。   

    示波器上测得的占空比低于-  

    ahs -针对129.47us 打开(ALS 与 AHS 相反)

    BHS -针对167.227us 开启(BLS 与 BHS 成反比)   

    CHS -针对81.003us 开启(CLS 与 CHS 相反)

    这意味着在这种情况下、svgen 命令的占空比低于

    A 相为129.47 /250 = 0.51788 - 0.5 = 0.01788

    B 相为 167.227 / 250 = 0.6689 - 0.5 = 0.1689

    C 相为81.003/250 = 0.3240 - 0.5 =-0.17598

    看起来我在这里捕获了 svgen:  

    看一下占空比-您看到它们有什么问题吗? 没有什么真正的东西会跳出来给我。  

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

    我想我越来越近了! 我比较了我的其他 MCU 和 TI C2000之间的占空比、它们是相当的。 因此、我认为 PWM 是正确的。 但是、我的 TI 项目似乎缺少死区时间。 我想我已经设置了它、但它不起作用。 调试死区时间将是我星期一上午做的第一件事。  

    在我共享的最后一个示波器跟踪中、您可以看到、AHS 和 ALS 同时切换。 开关 IGBT 之间需要3us 的死区时间。  

    100V 开环的其他 MCU 占空比:  

    PWM 具有可比性、但您会注意到这里的死区时间:  

    123.917us 的 HS 导通= 123.917/250 = 0.495668–0.5 =-0.004332

    B HS 导通时间:159.611us = 159.611/250 = 0.638444–0.5 = 0.13844

    C HS 导通时间:83.474us = 83.474/250 = 0.3339–0.5 =-0.166104

    3us 死区时间、我的 TI 项目中缺少该项目:  

    如何初始化并获得在 IGBT 开关之间提供3us 的死区时间?  

    我在通用电机控制实验室中尝试了两件事情。  

    将 ePWM 比较值的最小比较值设置为死区时间-这甚至是必要的、如果我正确初始化 PWM 驱动器会自行插入死区时间吗? 我不确定我是否需要这样做、驾驶员似乎会自行处理死区时间。

        // Set up deadband and noise window
        pwmData.deadband = ABC_DEADTIME;
        pwmData.noiseWindow = NOISE_WINDOW;
        pwmData.minCMPValue = pwmData.deadband + pwmData.noiseWindow + 33; // 33 is copied from TI demo project
        
        bool Motor_PWMSet()
    {
        // Invert PWMs to match NXP
        float dutyA = dutyALocal * -1;
        float dutyB = dutyBLocal * -1;
        float dutyC = dutyCLocal * -1;
    
        // Get PWM period
        float periodA = (float)(EPWM_getTimeBasePeriod(A_PWM_HS_BASE));
        float periodB = (float)(EPWM_getTimeBasePeriod(B_PWM_HS_BASE));
        float periodC = (float)(EPWM_getTimeBasePeriod(C_PWM_HS_BASE));
    
        // Limit PWMs to be safe
        float dutyALim = Limit(dutyA, 0.5, -0.5);
        float dutyBLim = Limit(dutyB, 0.5, -0.5);
        float dutyCLim = Limit(dutyC, 0.5, -0.5);
    
        // Scale duty cycles from 0 to 1
        float dutyAScaled = dutyALim + 0.5; // 0~1.0
        float dutyBScaled = dutyBLim + 0.5; // 0~1.0
        float dutyCScaled = dutyCLim + 0.5; // 0~1.0
    
        // Compute Compare value
        uint16_t dutyACmpVal = (uint16_t) Limit(dutyAScaled * periodA, periodA, pwmData.minCMPValue);
        uint16_t dutyBCmpVal = (uint16_t) Limit(dutyBScaled * periodB, periodB, pwmData.minCMPValue);
        uint16_t dutyCCmpVal = (uint16_t) Limit(dutyCScaled * periodC, periodC, pwmData.minCMPValue);
    
        // write the PWM data value
        EPWM_setCounterCompareValue(A_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyACmpVal);
        EPWM_setCounterCompareValue(A_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyACmpVal);
        EPWM_setCounterCompareValue(B_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyBCmpVal);
        EPWM_setCounterCompareValue(B_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyBCmpVal);
        EPWM_setCounterCompareValue(C_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyCCmpVal);
        EPWM_setCounterCompareValue(C_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyCCmpVal);
    
    //    ignoreShuntNextCycle = SVGENCURRENT_getIgnoreShunt(svgencurrentHandle);
    //    midVolShunt = SVGENCURRENT_getVmid(svgencurrentHandle);
    
        // Set trigger point in the middle of the low side pulse
        //Motor_PWMSetTrigger();
    
        return 0;
    }
    

    当我初始化 PWM 时、我尝试使用3us 死区时间进行初始化-我在这里缺少什么吗?  

        // setup the Dead-Band Generator Control Register (DBCTL)
        EPWM_setDeadBandDelayMode(A_PWM_HS_BASE, EPWM_DB_RED, true);
        EPWM_setDeadBandDelayMode(A_PWM_HS_BASE, EPWM_DB_FED, true);
        EPWM_setDeadBandDelayMode(B_PWM_HS_BASE, EPWM_DB_RED, true);
        EPWM_setDeadBandDelayMode(B_PWM_HS_BASE, EPWM_DB_FED, true);
        EPWM_setDeadBandDelayMode(C_PWM_HS_BASE, EPWM_DB_RED, true);
        EPWM_setDeadBandDelayMode(C_PWM_HS_BASE, EPWM_DB_FED, true);
    
        // select EPWMA as the input to the dead band generator
        EPWM_setRisingEdgeDeadBandDelayInput(A_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
        EPWM_setRisingEdgeDeadBandDelayInput(A_PWM_LS_BASE, EPWM_DB_INPUT_EPWMB);
        EPWM_setRisingEdgeDeadBandDelayInput(B_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
        EPWM_setRisingEdgeDeadBandDelayInput(B_PWM_LS_BASE, EPWM_DB_INPUT_EPWMB);
        EPWM_setRisingEdgeDeadBandDelayInput(C_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
        EPWM_setRisingEdgeDeadBandDelayInput(C_PWM_LS_BASE, EPWM_DB_INPUT_EPWMB);
    
        // configure the right polarity for active high complementary config.
        EPWM_setDeadBandDelayPolarity(A_PWM_HS_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
        EPWM_setDeadBandDelayPolarity(A_PWM_HS_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
        EPWM_setDeadBandDelayPolarity(B_PWM_HS_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
        EPWM_setDeadBandDelayPolarity(B_PWM_HS_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
        EPWM_setDeadBandDelayPolarity(C_PWM_HS_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH);
        EPWM_setDeadBandDelayPolarity(C_PWM_HS_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    
        // setup the Dead-Band Rising Edge Delay Register (DBRED)
        EPWM_setRisingEdgeDelayCount(A_PWM_HS_BASE, ABC_DEADTIME_PWM_MIN);
        EPWM_setRisingEdgeDelayCount(B_PWM_HS_BASE, ABC_DEADTIME_PWM_MIN);
        EPWM_setRisingEdgeDelayCount(C_PWM_HS_BASE, ABC_DEADTIME_PWM_MIN);
    
        // setup the Dead-Band Falling Edge Delay Register (DBFED)
        EPWM_setFallingEdgeDelayCount(A_PWM_HS_BASE, ABC_DEADTIME_PWM_MIN);
        EPWM_setFallingEdgeDelayCount(B_PWM_HS_BASE, ABC_DEADTIME_PWM_MIN);
        EPWM_setFallingEdgeDelayCount(C_PWM_HS_BASE, ABC_DEADTIME_PWM_MIN);
    

    我的死区时间常量是-我不确定在什么地方、对于具有120MHz 时钟的4kHz PWM、我得到 ABC_DEADTIME = 25?  

    #define ABC_DEADTIME_PWM_MIN 25  // 3us - measured with testing PWM driver
    #define ABC_DEADTIME 360  // 3us - 3 * 120 MHz
    #define NOISE_WINDOW 180  // 3us - Deadtime / 2 * 120 MHz

    感谢您的帮助! 希望你有一个美好的周末!

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

    我修复了死区时间、现在为3us -我通过将 上面的 ABC_DEADTIME_PWM_MIN 从25更改为360来实现这一点。 我不确定我从哪里得到25。 这使我能够获得+/- 3000 RPM 的转速、但是、我仍然在整个速度范围内听到响亮的声音、并且我仍然在 IGBT 上得到去饱和、因此仍有一些工作要做。 进一步延长死区时间不能解决此问题、因此也有其他问题。 不过、我认为 PWM 现在看起来会更好。 我现在再次得到 desat 时、会看到它们的样子。   

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

    实际上、我不确定死区时间是否合适。 与我的其他 MCU 供应商一起、我在 LS 上的 HS 更改为3us、然后在 LS 更改为之前 HS 变为 false 时、死区时间为3us。  

    在 TI 看来、在 HS 上升之前、我有3us 的死区时间、但在 HS 下降之前、LS 上升。 这也正是发生去饱和时的情况。  

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

    您是否根据需要检查了 PWM 频率是否正确?

    您可以尝试按  如下方式设置频带发生器的输入。

    //选择 EPWMA 作为死区发生器的输入
    ePWM_setRisingEdgeDeadBandDelayInput (A_PWM_HS_base、ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (A_PWM_LS_BASE、ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (B_PWM_HS_base、ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (B_PWM_LS_BASE、ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (C_PWM_HS_base、ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (C_PWM_LS_BASE、ePWM_DB_INPUT_EPWMA);

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

    这有点奇怪。 我的死区时间在大部分时间都是正确的。 但是,当我明白了这一点时,似乎死区时间是错误的。 可能导致这种情况的原因-似乎只有在较高占空比期间才会错过下降沿死区时间、同时开启 HS 和 LS。  

    在高占空比- 300V 输出期间、死区时间是正确的:  

    在下降沿缺少死区时间-出现死区-我认为这也可能是我可怕噪音的来源:  




    //选择 EPWMA 作为死区发生器的输入
    ePWM_setRisingEdgeDeadBandDelayInput (A_PWM_HS_base、ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (A_PWM_LS_BASE、 ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (B_PWM_HS_base、ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (B_PWM_LS_BASE、 ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (C_PWM_HS_base、ePWM_DB_INPUT_EPWMA);
    ePWM_setRisingEdgeDeadBandDelayInput (C_PWM_LS_BASE、 ePWM_DB_INPUT_EPWMA);

    为什么只有 EPWMA? 如果 A 是高侧 IGBT、B 是低侧 IGBT、为什么不是 B?  

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

    我想您应该对 PWM 使用互补模式、因此 EPWMB 输出取决于 EWPMA 输出。

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

    我在这样做-每当我在 A 上设置占空比时、该占空比的倒数就会在 B 上输出  

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

    您可以参考通用实验来使用构建级别1来检查 ePWM 模块三相的时钟是否同步。

    您可以在配置 PWM 之前尝试调用以下代码  

     //禁用 ePWM 模块时基时钟同步信号
    //同步所有 PWM
    SYSCTL_DisablePeripheral (SYSCTL_Periph_CLK_TBCLKSYNC);

    然后在配置 PWM 后调用下面的代码。

    //启用 ePWM 模块时基时钟同步信号
    SYSCTL_enablePeripheral (SYSCTL_Periph_CLK_TBCLKSYNC);

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

    您好、Yanming、  

    我认为、我似乎已经解决了去饱和/死区时间问题。  

    我需要做的是:  

    1) 1)由于 PWM 处于补码模式、因此请勿设置 EPWMB 的比较值:  

        // write the PWM data value
        EPWM_setCounterCompareValue(A_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyACmpVal);
    //    EPWM_setCounterCompareValue(A_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyACmpVal);
        EPWM_setCounterCompareValue(B_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyBCmpVal);
    //    EPWM_setCounterCompareValue(B_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyBCmpVal);
        EPWM_setCounterCompareValue(C_PWM_HS_BASE, EPWM_COUNTER_COMPARE_A, dutyCCmpVal);
    //    EPWM_setCounterCompareValue(C_PWM_LS_BASE, EPWM_COUNTER_COMPARE_B, dutyCCmpVal);

    2) 2)删除 EPWM_setRisingEdgeDeadBandDelayInput (B_PWM_LS_BASE、EPWM_DB_INPUT_EPWMB)并添加 EPWM_setFallingEdgeDeadBandDelayInput (A_PWM_HS_base、EPWM_DB_INPUT_EPWMA)。   

        // select EPWMA as the input to the dead band generator
        EPWM_setRisingEdgeDeadBandDelayInput(A_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
        EPWM_setFallingEdgeDeadBandDelayInput(A_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
    //    EPWM_setRisingEdgeDeadBandDelayInput(A_PWM_LS_BASE, EPWM_DB_INPUT_EPWMB);
        EPWM_setRisingEdgeDeadBandDelayInput(B_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
        EPWM_setFallingEdgeDeadBandDelayInput(B_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
    //    EPWM_setRisingEdgeDeadBandDelayInput(B_PWM_LS_BASE, EPWM_DB_INPUT_EPWMB);
        EPWM_setRisingEdgeDeadBandDelayInput(C_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
        EPWM_setFallingEdgeDeadBandDelayInput(C_PWM_HS_BASE, EPWM_DB_INPUT_EPWMA);
    //    EPWM_setRisingEdgeDeadBandDelayInput(C_PWM_LS_BASE, EPWM_DB_INPUT_EPWMB);

    我仍有2个问题-  

    1) 1)电机的声音比它应该大得多。 我认为这是因为问题2 (可能是什么原因导致的)。  

    2) 2)我在速度上有大约1000 RPM 的噪声-我的目标是2540 RPM、并将其作为平均值、但精度很差。  

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

    我认为这个问题是由我用来计算速度并使用稳压器进行调节的电角引起的。 我正在以每1000 RPM 的速度进行66次角度计数、如果我将其删除、问题就会变得更好。 我还会在打印 CPU 周期计数器时看到这一点、该计数器显示系统中不同进程所需的时间。 我想我不是每次都同时向"慢速"中断报告电角。 有时、我会在4个快速中断后报告它、有时会在5个快速中断后报告它。  

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

    您可以尝试在同一 ISR 中运行角度发生器和 SVPWM。

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

    尊敬的 Derek:

    120MHz PWMCLK 的25*8.3ns=208ns 死区时间、取决于您的 DSAT 时序、对于一些较慢的 NFETS 安全。 看到您决定坚持使用 CMPA 现在似乎是明智的选择、或许稍后在代码最少的情况下打开油门。

    上面使用的反转语法似乎不适合进行乘法(value *-1)。 整数反转的一些示例非常有效地使用(^=)符号。

    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4371098 #4371098">有时、我会在4个快速中断后报告、有时会在5个快速中断后报告。  [/报价]

    在 SDK 示例实验中的 MAIN_ISR()期间,FAST 估算器角度是根据嵌入式 ROM 代码确定的。 奇怪的是、我的示波器在许多150µs μ s 周期后看到300ms 的相位消隐重复、通过两个 GPIO 端口抽取间隔 CH1和 CH2进行观察。 ePIE 通常与 MAIN_ISR()外设内核优先级顺序150µs 周期重叠,当外设总线空闲时,不会等待300ms 的消隐间隔。 由于固件未检查任何寄存器以确定相位驱动器串事件的结束、从而发出 CPU 总线空闲300ms 的信号、这是怎么可能的。 回想一下、我的慢速中断只有30ms 长的事件、但它重叠在几个 MAIN_ISR() 150µs 到甚至是375µs μ s 的抽取周期中。

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

    您好、GI、  

    这话什么意思? 您能告诉我这是在哪里完成的吗? 它在 universal_moter_control_lab 中是这样做的吗?  

    "在 SDK 示例实验的 MAIN_ISR()期间,FAST 估算器角度似乎是根据嵌入式 ROM 代码确定的。  "

    您好、Yanming、  

    我在同一 ISR 中同时具有角度发生器和 SVPWM。 将优化提高到5可以解决我遇到的可怕噪声问题、并降低我看到的 RPM 噪声、但这仍然不是完美的。 我将查看我是否可以确定 ISR 中的过度运行情况。  

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

    更改或更新 FAST 估算器角度的 ROM 调用在 SDK 中内联 MAIN_ISR(),它不是单独的中断。 该注释涉及先前的闭环后驱动1ms 中断。 150µs、同一 ISR 内的1ms 调用可能会超过运行时间 μ s 抽取时间。 除非重写电流控制以花费比计算和输出 PWM 周期所需的 CPU 时间更短。 这似乎是 FAST 估算器进行快速 ROM 调用以更新角度的原因。 即使是 UVMC SDK 也会对 FAST 估算器使用相同的 ROM 调用、这是很难的。

    MCSDK 获取 ROM 角度集正弦/余弦相量

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4371249 #4371249"]。 我将查看我是否可以确定 ISR 中的过度运行情况。  [/报价]

    您可以检查时钟的 PLL 是否配置正确、PWM 频率是否正确。 您的项目中的 PWM 和控制频率是多少?

    如果您只是以开环方式运行电机而没有负载、是否仍然有噪声? 是否可以在此测试条件下捕获电机相电流?

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

    您好、Yanming 和 GI、  

    我已经使噪声变得更好了-我的1ms 任务被分成了4个100us 部分、这样没有250us ISR 溢出、并且其中一个多路复用器超过100us。 我已经将其修复了。 溢出现在只有我们几个人、我在这里有另一篇文章、要求我们提供有关该问题的帮助: https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1163233/tms320f280039c-spi-dma-setup-function-taking-too-many-cpu-cycles/4375942#4375942

    我还遇到另一个奇怪的问题、即来自旋转变压器的不良 SPI 数据导致了一些噪声、我在这里创建了另一篇文章: https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1163699/tms320f280039c-bad-spi-data

    一旦我修复了这2个问题,我将使用 SVGENCURRENT_COMPPWMData 转到具有最大占空比的电流重构();

    PWM 频率在4kHz 时正确-请参阅我的周期为250us:

    我将此 XTAL 用于 PLL:  

    我想、如果时钟的 PLL 配置不正确、PWM 周期将是错误的?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4376643 #4376643"] PWM 频率在4kHz 时正确-请参阅我的周期为250us:

    对于 TBPRD 时钟、这似乎有点慢、通常设置为20-40KHz 周期、120MHz PWMCLK。 对于快速 NFET、GaN 或 IGBT 器件、典型周期为50µs μ s 至25µs μ s、具体取决于电机速度和 开关 SOA 曲线。 ISR 时间可以超过 PWM 周期多达 x6、而不是更多。

    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4376643 #4376643"]我认为时钟的 PLL 配置不正确 PWM 周期是错误的?  [/报价]

    这是正确的、如果周期250µs、似乎是可能的。 许多器件 SOA 表显示、面积仅适合非常低的 DS、EC 电流。

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

    您好、GI、  

    我们的电机必须以4kHz 频率运行-这将是250us 的周期。 您可以看到、我为此频率设置了 PWM、这是我测量的周期:  

        // since the PWM is configured as an up/down counter, the period register is
        // set to one-half of the desired PWM period
        EPWM_setTimeBasePeriod(A_PWM_HS_BASE, ABC_PWM_FREQ);
        EPWM_setTimeBasePeriod(B_PWM_HS_BASE, ABC_PWM_FREQ);
        EPWM_setTimeBasePeriod(C_PWM_HS_BASE, ABC_PWM_FREQ);

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4376643 #4376643"]我认为时钟的 PLL 配置不正确 PWM 周期是错误的?  [/报价]

    你是对的。

    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4376643 #4376643"]我已经使噪声变得更好了-我的1ms 任务被分成4个100us 部分、因此没有250us 的 ISR 溢出、并且其中一个多路复用器的超时超过100us

    您可以启用嵌套中断、使其不会丢失任何用于电机控制的 ISR、如下链接所示。

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1026118/tms320f280049-nesting-interrupt

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1033085/tms320f280025-nesting-interrupts-with-priority-levels

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

    PWM 周期通常设置为25或50微秒、从而产生20或40 KHz 的频率。  也许 TB 模块预分频时钟分频值设置不正确、SYSCLK 确认为120MHz?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="365463" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4376643 #4376643"]我还遇到另一个与解析器的不良 SPI 数据有关的奇怪问题,导致一些噪声,我在另一篇有关的文章中创建了另一篇有关此问题的文章。

     我不认为最好 将 TBPRD 的递增/递减计数设置为4kHz 周期、仅用于产生250µs ISR。  更常见的方法是 使用 ePWM 模块 SOCA 触发源设置来实现 MAIN_ISR()抽取时间,或5个 CMP-C/D 静态计数重触发器250µs ISR。 50µs、驱动逆变器开关20kHz/μ s 的频率保持在 SOA 范围内、并且看起来与使用 SPI 等 SYSCLK 的其他外设更加同步。

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

    Gi、

    正如 Derek 在前面提到的、他们必须根据其电源逆变器使用低 PWM 频率、这可能无法支持高开关频率。 如果需要、请创建一个新主题、以讨论有关电机驱动应用的 PWM 和控制频率的主题。 谢谢!

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

    您好、Yanming 和 GI、  

    现在、我对电机控制及其声音非常满意!  我修复了阻碍我向前发展的两个问题、这些问题是我昨天列出的:  

    1) 1) DMA 传输到 SPI https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1163233/tms320f280039c-spi-dma-setup-function-taking-too-many-cpu-cycles/4375942#4375942时 CPU 周期变慢

    2)由于糟糕的 SPI 数据包导致旋转变压器角度丢失(我在这一个问题上已经解决、但我仍在与 Manoj 一起解决问题、以解决根本原因)。  https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1163699/tms320f280039c-bad-spi-data

    星期一、我将开始研究当前重构/最大占空比、如果我对此有疑问、我将发布另一个问题! 我们已经解决了我的 SVM/PWM 问题!  

    感谢你们的所有帮助!  

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

    Yanming 如果你检查我的评论,那是关于 MAIN_ISR()是如何使用周期为 SVM 驱动器创建 IRQ 的。 说到 SOA 电流频率、IGBT 仍然更喜欢250us 的导通时间。 自2008年以来、TI 工程师从未设计过一个推销低频调制的 IGBT 逆变器、因此出现了警告标志。 尽管 Derek 的直流逆变器以电气角度的机械滑动来驱动交流电机。

    另一方面、TIDA 套件始终推动高电压 IGBT 开关频率40KHz 或更高、以实现高效率。  它们不会降低 PWM 频率以处理更大的电感电流、而是始终永久地增加频率以减少 IGBT 模块和散热器上的应力。 通过 PWM 周期驱动 ADC 中断看起来与直觉相反、Derek 似乎不知道可以通过 SOCA 功能同步触发 ADC ISR。 Derek 可以选择是否使用该触发功能、但建议使用该功能。

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

    Gi、

    ADC 触发频率也取决于电流传感器和采样模式。 如果使用低侧分流电流感应模式、则必须使用采样频率作为 PWM 频率。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="35051" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4379726 #4379726"]如果使用低侧分流电流感应模式、则必须使用采样频率作为 PWM 频率。[/quot]

    这可能是从上下文中获取的、但对于 FAST (FOC)、SOCA 触发 ADC 为 TBPRD 的 PWM 频率的5倍、20Khz 抽取率约为250µs μ s。

    在第一次调用 HAL_writePWMdata()之后,我将 CMPC/D 减少到3倍周期,然后再进行此操作。 最好通过 FAST 读取您最近的回复后 FOC、速度约为21µs 100MHz 和12µs 200MHz MCU。 MAIN_ISR()的其余部分用于 ADC 读取、PWM 周期更新、轨迹速度或扭矩、PID 电流和其他转子位置跟踪任务。 也许、添加到 SDK 中的流程概要可以消除 ISR 汇总中的一些神秘之处。

    检查今天的 x39c 时钟树我注意到 SPI 已经降低了 SYSCLK 域中的时钟速率 PERx.LSPCLK 和分频器图6-9 x39c 数据表。 看起来旋转变压器更新可能需要将延迟时间添加到 ADC 预设触发源、以解决 SPI 数据流中的任何位置延迟。 就个人而言、如果我使用外部旋转变压器来确定转子位置、则它将是与 EPWM 和 ADC 外设在同一时钟域中的高速 eQEP 输入。  首先使用 FAST 估算器来减少运行时间、然后通过 eQEP 位置传感器测试位置精度。 如果后一个计划 B 失败、则可以回到计划 A 重新组织我的鸭子、稍后再试。   

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

    是的、您可以抽取更高的 PWM 频率以使用低控制频率、但使用低侧分流感应方法时、使用比采样频率更高的控制频率毫无意义。

    您可以查看有关使用低侧电流感应方法和 ADC 所需触发点的相关应用手册。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="35051" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4381423 #4381423"]但使用低侧分流感应方法时、使用比采样频率更高的控制频率毫无意义。[/quot]

    您说过使用低侧分流器的电流控制吗? 在上面、我指的是相位(α β)、而不是将高速 eQEP 用于 FAST 估算器中的转子位置(α β)。 由于 SPI 外设时钟位于不同的域中、因此可能会使 ADC 采样时序复杂化。 但相位不需要通过 eQEP 位置控制模块提供任何快速反馈、 对吧?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="35051" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1158246/tms320f280039c-svpwm-issues-and-questions/4381423 #4381423"]您可以查看有关使用低侧电流感应方法和 ADC 所需触发点的相关应用手册。[/quot]

    BTW:应用手册(SPRUHJ1I–2013年1月–2021年10月修订)中没有关于 PWM 触发事件或子模块触发 EOC 以进行转子位置控制的内容、只有下面的 TRM 图、但 PRD 可以在4kHz 调制下产生250µs μ A INT、这与 PWM 滤波器极点文本相反。 但是、它表示应更改针对 PMSM 的 RC 滤波器(20 - 40) KHz PWM 调制、而不是交流电机滤波器极点。 本主题后期提到交流电机(感应?) 但是、许多 SPM (例如4极 Anaheim)在交流正弦波相电流下运行得同样出色。  

    滤波器极点文本建议仅生成几 kHz 左右电压的低频高速电机应更改 RC 滤波器。 也许 x39c TRM (技术资源手册)更详细、这个线程 SVM 模块似乎被用于 ACIM 电机驱动。

    我假设通过 SW 位置模块转换 eQEP 输入(A 相、B 相、索引)、(绕过 Clarke)将(α、β)和速度(rads/sec)传递到 FAST 估算器数字电压输入和轨迹控制。 位置控制模块示例没有该互连方法的可视图。

    如果使用最新的 MCSDK FAST 库 x39c、则可能正是您所想的、因为低侧分流器仅用于通过 FAST 估算器的电流控制块。 这种新的 FAST 库应该可以减少将代码转换或迁移到不同 MCU 类以保持向后兼容性的麻烦。