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.
您好!
我 正在使用霍尔效应传感器进行 PMSM 电机控制。
这是计算霍尔效应传感器角度和速度的最佳方法。
如何在有传感器电机控制中集成快速环路。
相同的示例代码。
此致、
您好!
专题专家今天正在休假。 请在2天内回复。
此致、
Veena
您好 Sagar、您可以参阅通用电机控制实验室文档和霍尔传感器示例- C2000Ware_MotorControl_SDK_4_00_00_00\solutions\commone_motorcontrol_lab\doc
您好!
感谢你的答复。
如何在我的软件中集成估算器
EST_run (obj->estHandle、&obj->estInputData、&obj->estOutputData);//ssy
我想了解有关这方面的详细信息、这些信息将帮助我集成到我的软件中。
此致、
Sagar、您可以包含 在 universal_motorcontrol_lab 的 src_lib 下找到的 fast_full_lib.lib 和 est.h。 估算器的源代码受到保护。
我们从您那里得知、已经超过2周了、 因此我假设您不再需要对您的问题进行澄清、而是将此主题标记为"已关闭"。 如果您对此主题有任何其他疑问、您可以使用帖子进行回复或创建新主题。 谢谢。
您好、Navaneeth Narayanswamy
我们还停留在 EST_run、EST_getFm_LP_Hz 中、了解如何获取此 funions 或 est.c 文件的定义。
您可以在 est.h 中引用这两个函数的引用、并从 FAST 库中调用这两个函数。 TI 不提供 FAST 库中 API 函数的源代码。 您可以参考 Universal 实验来调用这些函数以进行电机控制、而无需源代码。
您好、Navaneeth、
我查看了通用电机控制实验室 PDF、该 PDF 主要配置用于 X25 MCU、该 MCU 没有 X49所具有的任何类型的 CMPDAC 外设 ePWM 跳闸故障缓解功能。 此外、还注意 到通用 PDF 文档搜索中未详细阐述的新型 FAST 估算器(eSMO)、最好将 eSMO 添加到 x49c 未来的芯片修订版本中。
想知道生成 最小 SVM 模式是否需要 x25 Launch Pad eSMO 估算器、与无传感器 FOC 相比、它是否更适合 Halls?
您可以参考 F28002x 和 F28004x 的技术参考手册、了解如何设置 CMPSS 和 ePWM 跳闸故障。 F28002x 和 F28004x 上的 CMPSS 和 ePWM 外设类型相同。
在 controlSUITE 中的 C2000器 件上已支持 eSMO、我们将该算法移植到具有开源的浮点版本、并将其放入 MCSDK 中的通用实验中。 该算法可用于任何更新的 C2000器件、包括 F28004x。
eSMO 仍然是无传感器 FOC 的估算器算法、与硬件和 SVM 模式无关。
从 cmpss 7 可以跳过 PWM 1、2和3。
是的。 您可以使用任何 CMPSS 触发 PWM。 请配置 CMPSS 并根据您的硬件将输出链接到 ePWM。
您好、Yanming、
[引用 userid="35051" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forume/1098605/tms320f280049c-q1-tms320f280049c/4109486#4109486"]该算法可用于任何更新的 C2000器件、包括 F28004x。
eSMO 仍然是无传感器 FOC 的估算器算法、与硬件和 SVM 模式无关。
[/报价]也许很好的了解、因为我在几周后无法尝试多种不同的方案以使其他 ePIE 中断与快速估算器置位一同工作。 其他 ePIE 通过较慢的中断源(CPU_timer0、SCI TX 中断或甚至没有启用 TX 中断)延迟中断 FAST 估算器。
调整(user.h) USER_NUM_PWM_TICKS_PER_ISR_TICK (6个节拍)会停止 ADCA1中断、参数拒绝在调试中加载。 将上传有关电机运行条件的私人视频。 然而、不管 ePIE 中断在运行什么、Instaspin 执行时间需要整个 CPU 时间才能正确运行电机。 因此、使用通用电机 SDK 检查 x25的原因似乎也很好。
执行时间 FAST 估算器 大约为11.7us、而本实验中整个 FOC 的执行时间大约为22.0us。
如果您没有机会查看技术讲座材料、我认为这将有助于揭秘一些术语和架构、并了解 C2000 MCU 以开始开发。
https://dev.ti.com/tirex/explore/node?node=AOXFCHdD4iiPtd8.R6R0Tw__jEBbtmC__LATEST
没有揭秘什么似乎是故障 ePIE 内核优先级芯片逻辑区域。 已经开发了许多代码、这些代码会在 ADCA1组1之前阻塞其他挂起的 INT、清除具有组1和组9内核优先级中 FAST 估算器运行时间的 ACK。
注意:SDK (FOC) ePWM 模块 CMPD (hal.c)配置为250us ADC 触发源。 我的 mainISR()执行时间大约为(快速有效、125µs μ s)@3个 PWM 周期、快速无效、75µs μ s 使用 GPIO 标记通过示波器捕捉实现 Instaspin 抽取时间。
//设置 EPWM1触发脉冲、
ePWM_setADCTriggerSource (obj->pwmHandle[0]、
ePWM_SOC_A、
ePWM_SOC_TBCTR_D_CMPD);
//为 ADC 触发器写入值(20kHz SOC_Int*5TBCTR= 250µs μ s、1周期= 50µs μ s)
ePWM_setCounterCompareValue (obj->pwmHandle[0]、
ePWM_COUNTER_COMPARE_D、
5);
通常、ADC 触发频率等于 PWM 或控制器频率、MCSDK 中的默认频率为10kHz、15KHz 或20kHz。 只需使用 CMPD 在 PWM 周期的某个时间点触发 ADC、每个 PWM 周期都会生成具有 CMPD 的事件。
然而20kHz 调制对于 mainISR() IRQ、ADC 触发周期被设定为5x50µs 或250µs。 Instaspin GPIO 抽取时间(空闲就绪)周期为150µs μ s 或两个 PWM 周期。 这似乎是一个非常快的 IRQ,因为它在调用 FAST 估算器和 mainISR()运行时间内的其它函数期间变得更快75µs。
点是 Instaspin 抽取时间、当 MCSDK 中添加了其他较慢的 ePIE 组时、几乎所有 CPU 执行带宽都需要运行、而不会导致电机控制问题。 对于 电感电流、它可能会使用3个单独的 ADC SOC 源(总共16个)、采样速度会降低。 和3 个 ADC_Trigger_ePWM_SoC 源之间的分压(Clarke)和电流控制器(Clarke)样本(共16个)可供选择。 对于其他 ePIE 组事件、硬件任务分配可能会使 MCSDK CPU 执行时间受益。 有什么想法可以提高 MCSDK 吞吐量吗?
MCSDK 电机控制 示例必须允许其他外设具有更大的 CPU 带宽、才能使用运行速度低于电机控制速度的免费 ePIE 组矢量、而无需 CCS 调试实时*。js 监控器。 似乎 MCSDK 不仅仅是一个示例、更像是一个用于工业 SVM 电机换向的飞行计划、它不是吗?
Gi 引述"似乎它可以使用3 个单独的 ADC SOC 源(共16个)、可能会降低电感电流的采样速度。 和3 个 ADC_Trigger_ePWM_SoC 源之间的分压(Clarke)和电流控制器(Clarke)样本、(共16个)可供选择。"
因此、我使用多个 SOC 和 ePWM ADC 触发源测试了硬件分配理念。 EPWM 无法通过单个 EPWM-A 发生器源的 CPMD 触发 ADCA、ADCB 或 ADCC。 通过 CCS 调试寄存器视图(刷新) ePWM 外设没有 ETSOPCPS 触发活动。 MCSDK ADC 的 HAL 按照该顺序使用 ePWM1、ePWM4、ePWM2、并镜像到每个 ADC 外设、使源与目标触发点(分别)匹配无法正常工作。 这个条件指向 ADC 模块有一些勘误表、除了被 应用的连续 IRQ 补丁所校正之外。
BTW:稍后手动搜索 UVMC-SDK (指南 PDF)以查找 eSMO 表示"增强滑模观测器"(eSMO)、表示无传感器 FOC。 还想知道、与具有3-12位 ADC 的 F2800x49c 相比、通过 CMPD 计数实现的 ePWM 多个 SOC ADC 触发对于2-12位 ADC (F2800x25c)是否能提供更好的结果? 也许 每个 SDK 和 MCU 之间的一些实验室基准测试(x25c 与 x49c)会让人更清楚地了解该主题。
mainISR()的输入频率等于 PWM 频率(USER_M1_PWM_FREQ_kHz=15kHz) / (USER_M1_NUM_PWM_TICKS_PER_ISR_TICK = 1)、因此默认频率为15kHz。
CMPA/B/C/D 可用于在时间递增或递减时生成事件、并在每个 μ 1~15事件中生成中断或触发 ADC。 事件可以 作为 ADC SOC 触发器触发任何 ADC 模块中的任何通道。
有关这方面的更多详细信息、您可以查看 F28002x/4x 技术手册中有关 ePWM 和 ADC 的一章。
instaspin 运行时抽取率大约为13KHz、通过3个 ePWM 周期进行20kHz 调制。 但比 SCIB 外设 IRQ 等较慢的数据吞吐量快得多。 当我尝试减慢 Instaspin 抽取时间>3个 ePWM 周期时(motor.params)无法加载 CCS 调试 Java 脚本并且 LED 保持亮起、永远不会闪烁。
[引用 userid="35051" URL"~ 1~15 μ C/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forume/1098605/tms320f280049c-q1-tms320f280049c/411560#4115560]CMPA/B/C/D 可用于在每次递增或递减事件时生成中断或触发事件[引用]。然而、为 ADC-A、B、C 配置多个 ePWM SOCA 触发器完全无法加载任何 CMPD 值。 我认为这可能是由于 ADC SOC 与 ePWM 触发器不匹配。 同样错误、即使从每个 ADC 为 mainISR()配置了3个 IRQ 矢量、CMPD 仍然不会通过 CCS 调试寄存器视图配置或显示计数值。 让每个 ePWM SOCA 触发每个 ADC 输入似乎更可靠、但它不起作用、只能配置1个 SOCA。
ePWM_enableADCtrigger (obj->pwmHandle[0]、ePWM_SOC_A);
ePWM_enableADCtrigger (obj->pwmHandle[cnT]、ePWM_SOC_A);
这取决于 user.h 中的设置、您可以在 MCSDK 中起诉每个1~15 μ s PWM 节拍、在 MotorWare 中起诉每个1~3 μ s PWM 节拍。 根据逆变器或电机建议尽可能快的 ISR/控制器。 确保每个 IST 不会占用太多 CPU 带宽来导致 溢出问题。
每个 PWM 支持两个 SOC 帽子、可由 CMPA/B/C/D 触发 每个 SOC 都可以触发一个或多个 ADC。
如上所示、它完全不会触发 SOC、而是仅从 ePWM1触发 SOC。 我怀疑 R3器件 ePWM 模块损坏、从未将其报告为 R1勘误表。 更好地在制造前检查 MCU 生产恢复时、x49c 更多。 我个人报告了几个器件问题 TM4C R1器件 PWM 模块故障 ADC 触发源随后在 R2器件中修复。 成像光学器件中的物体甚至灰尘都会被忽略、制造硅片的机器成本非常复杂、超过5亿美元。
[引用 userid="35051" URL"~μ C/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forume/1098605/tms320f280049c-q1-tms320f280049c/4116852#4116852"]根据 user.h 中的设置,您可以在每个1~15 μ s 中引用 MCWare/MotorWare 中的每个脉冲数[ 1~3 μ s ]同样、任何大于3的 PWM 节拍似乎都锁定 EOC 脉冲、但无法触发 ePIE、因此 mainISR()锁定。 没有溢出更像错误的 ISR 内核优先级处理、主 ISR 正被较低优先级的 INT9.4占据。
星期五、我报告了一个缺少 ePIE 优先级组屏蔽所需的 C2000ware DSK 文件夹的文件。 所有 x49c 示例都缺少用于控制外设 ePIE 内核优先级的文件。
请发布您使用的所有配置代码、以帮助我们了解并找到您提到的问题。
后来添加了通过3个不同 SOCA 进行的 ADC 触发器、为器件中的 ePWM 模块提供触发端点。 我还记得、ePWM1 CMPD 没有计数5加载 CCS 调试寄存器。 为什么 FE 仅在可能有3个 ADC 触发源时配置 ePWM1 CMPD。 我猜他一开始[cnT]就看到它不起作用,所以他通过(obj->pwmHandle[0]强制 ePWM1 SOC 触发。
您需要将以下代码放入上述"for (for)"循环中、以设置每个 PWM 模块的 SOC。
//禁用 ePWM 模块中断
ePWM_DisableInterrupt (obj->pwmHandle[cnt]);//0
//设置 EPWM1触发脉冲,TBCTR=50µs μ s*5 μ s 或250µs 25µs μ s*1 CMPD-D
ePWM_setADCTriggerSource (obj->pwmHandle[cnt]、//0
ePWM_SOC_A、
ePWM_SOC_TBCTR_D_CMPD);
//ePWM_SOC_TBCTR_ZERO、ePWM_SOC_TBCTR_PERIOD、ePWM_SOC_TBCTR_D_CMPD
//启用 EPWM1以触发 ADCA、ADCB、ADCC 采样事件
ePWM_enableADCtrigger (obj->pwmHandle[cnT]、ePWM_SOC_A);//0
//设置事件触发器预分频寄存器(ETPS)
if (numPWMTicksPerISRTick > 15)
{
ePWM_setInterruptEventCount (obj->pwmHandle[cnt]、15);//0
ePWM_setADCTriggerEventPrescale (obj->pwmHandle[cnT]、ePWM_SOC_A、15);//0
}
否则、如果(numPWMTicksPerISRTick < 1)
{
ePWM_setInterruptEventCount (obj->pwmHandle[cnt]、1);//0
ePWM_setADCTriggerEventPrescale (obj->pwmHandle[cnT]、ePWM_SOC_A、1);//0
}
其他
{
ePWM_setInterruptEventCount (obj->pwmHandle[cnT]、numPWMTicksPerISRTick);//0、0
ePWM_setADCTriggerEventPrescale (obj->pwmHandle[cnT]、
ePWM_SOC_A、
numPWMTicksPerISRTick);
}
//设置事件触发器清除寄存器(ETCLR)
ePWM_clearEventTriggerInterruptFlag (obj->pwmHandle[cnt]);//0
ePWM_clearADCTriggerFlag (obj->pwmHandle[cnT]、ePWM_SOC_A);//0
//为 ADC 触发器写入值(20kHz SOC_Int*5TBCTR= 250µs μ s、1周期= 50µs μ s)
ePWM_setCounterCompareValue (obj->pwmHandle[cnT]、
ePWM_COUNTER_COMPARE_D、
5);
Yanming、
为什么只复制不能配置任何 EPWM-An CMPD 的同一 SOCA 触发代码(hal.c)。 您是否在 CCS 调试中检查了每个 ePWM 发生器的 CMPD 计数是否为5? 当配置了多个 ePWMA CMPD 时、该配置无法执行、原因是什么?
将 SOCA 的配置代码置于"for "循环中。 如果不是、您只能使用 CMPD 配置第三个 ePWM SOCA。
是的、如上所述、它可以正常工作、不会出现任何问题。
只有在第一个 CMPD 上、没有其他器件会在 for 循环中进行配置、您如何才能从上面解释的内容中获得该配置? 请尝试在 x49c LaunchPad 上的 for 循环内同时配置所有3个 ADC 触发器、但在我的 LaunchPad 上根本不配置任何 ADC 触发器。
[引用 userid="35051" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forume/1098605/tms320f280049c-q1-tms320f280049c/4119024#4119024"]如果不是,则只能使用 CMPd 配置第三个 ePWM SOCA [/引用]。ePWM_SOCA_Trigger[0]是具有 DRV8320RS 的 x49c 上的第一个 ePWM SOCA。 我尝试第三次 ePWM CMPD 测试、可能是驱动程序库调用在 for loop 中存在问题。
它只配置了 ePWM4Regs CMPD 5。 因此、多个驱动程序库调用不允许超过1个 ADC SOCA 触发源用于按变量(cnt)循环。 这使得 HAL_SetupPWM ()调用更长、每个 driverlib 函数都被称为3x;SOCATrigger[0]、SOCATrigger[1]、SOCATrigger[2]。
为了简化这一过程、您可以查看以下代码并在您的项目中对其进行测试。 此外、您还可以仅使用从 CMPD 生成的 SOCA 来进行电压采样。
void HAL_setupPWMs(HAL_Handle handle, const float32_t systemFreq_MHz, const float32_t pwmPeriod_usec, const uint_least16_t numPWMTicksPerISRTick) { HAL_Obj *obj = (HAL_Obj *)handle; uint16_t halfPeriod_cycles = (uint16_t)(systemFreq_MHz * pwmPeriod_usec / (float32_t)2.0); uint16_t cnt, numPWMPerISRTick; // disable the ePWM module time base clock sync signal // to synchronize all of the PWMs SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // turns off the outputs of the EPWM peripherals which will put the power // switches into a high impedance state. EPWM_forceTripZoneEvent(obj->pwmHandle[0], EPWM_TZ_FORCE_EVENT_OST); EPWM_forceTripZoneEvent(obj->pwmHandle[1], EPWM_TZ_FORCE_EVENT_OST); EPWM_forceTripZoneEvent(obj->pwmHandle[2], EPWM_TZ_FORCE_EVENT_OST); if(numPWMTicksPerISRTick > 15) { numPWMPerISRTick = 15; } else if(numPWMTicksPerISRTick < 1) { numPWMPerISRTick =1; } else { numPWMPerISRTick = numPWMTicksPerISRTick; } for(cnt=0;cnt<3;cnt++) { // setup the Time-Base Control Register (TBCTL) EPWM_setTimeBaseCounterMode(obj->pwmHandle[cnt], EPWM_COUNTER_MODE_UP_DOWN); EPWM_disablePhaseShiftLoad(obj->pwmHandle[cnt]); EPWM_setPeriodLoadMode(obj->pwmHandle[cnt], EPWM_PERIOD_DIRECT_LOAD); EPWM_setSyncOutPulseMode(obj->pwmHandle[cnt], EPWM_SYNC_OUT_PULSE_ON_SOFTWARE); EPWM_setClockPrescaler(obj->pwmHandle[cnt], EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); EPWM_setCountModeAfterSync(obj->pwmHandle[cnt], EPWM_COUNT_MODE_UP_AFTER_SYNC); EPWM_setEmulationMode(obj->pwmHandle[cnt], EPWM_EMULATION_FREE_RUN); // setup the Timer-Based Phase Register (TBPHS) EPWM_setPhaseShift(obj->pwmHandle[cnt], 0); // setup the Time-Base Counter Register (TBCTR) EPWM_setTimeBaseCounter(obj->pwmHandle[cnt], 0); // setup the Time-Base Period Register (TBPRD) // set to zero initially EPWM_setTimeBasePeriod(obj->pwmHandle[cnt], 0); // setup the Counter-Compare Control Register (CMPCTL) EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_disableCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_B); // EPWM_disableCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_C); // EPWM_disableCounterCompareShadowLoadMode(obj->pwmHandle[cnt], EPWM_COUNTER_COMPARE_D); // setup the Action-Qualifier Output A Register (AQCTLA) EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA); // setup the Action-qualifier Continuous Software Force Register // (AQCSFRC) EPWM_setActionQualifierContSWForceAction(obj->pwmHandle[cnt], EPWM_AQ_OUTPUT_B, EPWM_AQ_SW_OUTPUT_HIGH); // setup the Dead-Band Generator Control Register (DBCTL) EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_RED, true); EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_FED, true); // select EPWMA as the input to the dead band generator EPWM_setRisingEdgeDeadBandDelayInput(obj->pwmHandle[cnt], EPWM_DB_INPUT_EPWMA); // configure the right polarity for active high complementary config. EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt], EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH); EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt], EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW); // setup the Dead-Band Rising Edge Delay Register (DBRED) EPWM_setRisingEdgeDelayCount(obj->pwmHandle[cnt],HAL_PWM_DBRED_CNT); // setup the Dead-Band Falling Edge Delay Register (DBFED) EPWM_setFallingEdgeDelayCount(obj->pwmHandle[cnt],HAL_PWM_DBFED_CNT); // setup the PWM-Chopper Control Register (PCCTL) EPWM_disableChopper(obj->pwmHandle[cnt]); // setup the Trip Zone Select Register (TZSEL) EPWM_disableTripZoneSignals(obj->pwmHandle[cnt], EPWM_TZ_SIGNAL_CBC1 | EPWM_TZ_SIGNAL_CBC2 | EPWM_TZ_SIGNAL_CBC3 | EPWM_TZ_SIGNAL_CBC4 | EPWM_TZ_SIGNAL_CBC5 | EPWM_TZ_SIGNAL_CBC6 | EPWM_TZ_SIGNAL_DCAEVT2 | EPWM_TZ_SIGNAL_DCBEVT2 | EPWM_TZ_SIGNAL_OSHT1 | EPWM_TZ_SIGNAL_OSHT2 | EPWM_TZ_SIGNAL_OSHT3 | EPWM_TZ_SIGNAL_OSHT4 | EPWM_TZ_SIGNAL_OSHT5 | EPWM_TZ_SIGNAL_OSHT6 | EPWM_TZ_SIGNAL_DCAEVT1 | EPWM_TZ_SIGNAL_DCBEVT1); // setup the Event Trigger Selection Register (ETSEL) EPWM_setADCTriggerSource(obj->pwmHandle[cnt], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPD); EPWM_setADCTriggerSource(obj->pwmHandle[cnt], EPWM_SOC_B, EPWM_SOC_TBCTR_U_CMPC); EPWM_enableADCTrigger(obj->pwmHandle[cnt], EPWM_SOC_A); EPWM_enableADCTrigger(obj->pwmHandle[cnt], EPWM_SOC_B); // setup the interrupt Event Trigger Prescale Register (ETPS) EPWM_setADCTriggerEventPrescale(obj->pwmHandle[cnt], EPWM_SOC_A, numPWMPerISRTick); EPWM_setADCTriggerEventPrescale(obj->pwmHandle[cnt], EPWM_SOC_B, numPWMPerISRTick); // setup the Event Trigger Clear Register (ETCLR) EPWM_clearADCTriggerFlag(obj->pwmHandle[cnt], EPWM_SOC_A); EPWM_clearADCTriggerFlag(obj->pwmHandle[cnt], EPWM_SOC_A); } // setup the Event Trigger Selection Register (ETSEL) EPWM_disableInterrupt(obj->pwmHandle[0]); // setup the interrupt Event Trigger Prescale Register (ETPS) EPWM_setInterruptEventCount(obj->pwmHandle[0], numPWMPerISRTick); // setup the Event Trigger Clear Register (ETCLR) EPWM_clearEventTriggerInterruptFlag(obj->pwmHandle[0]); // 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(obj->pwmHandle[0], halfPeriod_cycles); EPWM_setTimeBasePeriod(obj->pwmHandle[1], halfPeriod_cycles); EPWM_setTimeBasePeriod(obj->pwmHandle[2], halfPeriod_cycles); // write the PWM data value for ADC trigger EPWM_setCounterCompareValue(obj->pwmHandle[0], EPWM_COUNTER_COMPARE_C, 10); EPWM_setCounterCompareValue(obj->pwmHandle[0], EPWM_COUNTER_COMPARE_D, 5); EPWM_setCounterCompareValue(obj->pwmHandle[1], EPWM_COUNTER_COMPARE_C, 10); EPWM_setCounterCompareValue(obj->pwmHandle[1], EPWM_COUNTER_COMPARE_D, 5); EPWM_setCounterCompareValue(obj->pwmHandle[2], EPWM_COUNTER_COMPARE_C, 10); EPWM_setCounterCompareValue(obj->pwmHandle[2], EPWM_COUNTER_COMPARE_D, 5); // enable the ePWM module time base clock sync signal SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); return; } // end of HAL_setupPWMs() function
void HAL_setupADCs(HAL_Handle handle) { HAL_Obj *obj = (HAL_Obj *)handle; SysCtl_delay(100U); ADC_setVREF(obj->adcHandle[2], ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V); ADC_setVREF(obj->adcHandle[1], ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V); ADC_setVREF(obj->adcHandle[0], ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V); SysCtl_delay(100U); // Configure internal reference as 1.65V*2 = 3.3V ASysCtl_setAnalogReference1P65(ASYSCTL_VREFHIA | ASYSCTL_VREFHIB | ASYSCTL_VREFHIC); // Enable internal voltage reference ASysCtl_setAnalogReferenceInternal(ASYSCTL_VREFHIA | ASYSCTL_VREFHIB | ASYSCTL_VREFHIC); // Set main clock scaling factor (50MHz max clock for the ADC module) ADC_setPrescaler(obj->adcHandle[0], ADC_CLK_DIV_2_0); ADC_setPrescaler(obj->adcHandle[1], ADC_CLK_DIV_2_0); ADC_setPrescaler(obj->adcHandle[2], ADC_CLK_DIV_2_0); // set the ADC interrupt pulse generation to end of conversion ADC_setInterruptPulseMode(obj->adcHandle[0], ADC_PULSE_END_OF_CONV); ADC_setInterruptPulseMode(obj->adcHandle[1], ADC_PULSE_END_OF_CONV); ADC_setInterruptPulseMode(obj->adcHandle[2], ADC_PULSE_END_OF_CONV); // enable the ADCs ADC_enableConverter(obj->adcHandle[0]); ADC_enableConverter(obj->adcHandle[1]); ADC_enableConverter(obj->adcHandle[2]); // set priority of SOCs ADC_setSOCPriority(obj->adcHandle[0], ADC_PRI_ALL_HIPRI); ADC_setSOCPriority(obj->adcHandle[1], ADC_PRI_ALL_HIPRI); ADC_setSOCPriority(obj->adcHandle[2], ADC_PRI_ALL_HIPRI); // delay to allow ADCs to power up SysCtl_delay(1000U); #if (BOOST_to_LPD == BOOSTX_to_J1_J2) // configure the interrupt sources // configure the ample window to 15 system clock cycle wide by assigning 14 // to the ACQPS of ADCSOCxCTL Register. // RB2/B1 ADC_setInterruptSource(obj->adcHandle[1], ADC_INT_NUMBER1, ADC_SOC_NUMBER2); // configure the SOCs for hvkit_rev1p1 // ISENA - PGA5->A14->RA0 ADC_setupSOC(obj->adcHandle[0], ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM6_SOCA, ADC_CH_ADCIN14, HAL_ADC_SAMPLE_WINDOW); // ISENB - PGA3->C7->RC0 ADC_setupSOC(obj->adcHandle[2], ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM5_SOCA, ADC_CH_ADCIN7, HAL_ADC_SAMPLE_WINDOW); // ISENC - PGA1->B7->RB0 ADC_setupSOC(obj->adcHandle[1], ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM3_SOCA, ADC_CH_ADCIN7, HAL_ADC_SAMPLE_WINDOW); // VSENA - A5->RA1 ADC_setupSOC(obj->adcHandle[0], ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM6_SOCB, ADC_CH_ADCIN5, HAL_ADC_SAMPLE_WINDOW); // VSENB - B0->RB1 ADC_setupSOC(obj->adcHandle[1], ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM5_SOCB, ADC_CH_ADCIN0, HAL_ADC_SAMPLE_WINDOW); // VSENC - C2->RC1 ADC_setupSOC(obj->adcHandle[2], ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM3_SOCB, ADC_CH_ADCIN2, HAL_ADC_SAMPLE_WINDOW); // VSENVM - B1->RB2. hvkit board has capacitor on Vbus feedback, so // the sampling doesn't need to be very long to get an accurate value ADC_setupSOC(obj->adcHandle[1], ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM6_SOCA, ADC_CH_ADCIN1, HAL_ADC_SAMPLE_WINDOW); // Vthrottle - B3->RB3. hvkit board has capacitor on Vbus feedback, so // the sampling doesn't need to be very long to get an accurate value ADC_setupSOC(obj->adcHandle[1], ADC_SOC_NUMBER3, ADC_TRIGGER_EPWM6_SOCB, ADC_CH_ADCIN3, HAL_ADC_SAMPLE_WINDOW); #endif #if (BOOST_to_LPD == BOOSTX_to_J5_J6) // configure the interrupt sources // configure the ample window to 15 system clock cycle wide by assigning 14 // to the ACQPS of ADCSOCxCTL Register. // RC2/C1 ADC_setInterruptSource(obj->adcHandle[2], ADC_INT_NUMBER1, ADC_SOC_NUMBER2); // configure the SOCs for hvkit_rev1p1 // ISENA - PGA2->B9->RB0 ADC_setupSOC(obj->adcHandle[1], ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN9, HAL_ADC_SAMPLE_WINDOW); // ISENB - PGA4->A15->RA0 ADC_setupSOC(obj->adcHandle[0], ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN15, HAL_ADC_SAMPLE_WINDOW); // ISENC - PGA1->C9->RC0 ADC_setupSOC(obj->adcHandle[2], ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN9, HAL_ADC_SAMPLE_WINDOW); // VSENA - A6->RA1 ADC_setupSOC(obj->adcHandle[0], ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN6, HAL_ADC_SAMPLE_WINDOW); // VSENB - B6/A2->RB1 ADC_setupSOC(obj->adcHandle[1], ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN6, HAL_ADC_SAMPLE_WINDOW); // VSENC - C14->RC1 ADC_setupSOC(obj->adcHandle[2], ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN14, HAL_ADC_SAMPLE_WINDOW); // VSENVM - C1->RC2. hvkit board has capacitor on Vbus feedback, so // the sampling doesn't need to be very long to get an accurate value ADC_setupSOC(obj->adcHandle[2], ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN1, HAL_ADC_SAMPLE_WINDOW); #endif return; } // end of HAL_setupADCs() function
Yanming、
进一步发帖的目的是让您通知 TI 程序员、driverlib 调用设置多个 ePWM 触发源存在问题。 CMPx 触发器和加载调用应该能够在 x49c 中输入每个寄存器的基地址。 可疑对象->adcHandle[n]可能是未传递寄存器基址的原因。
BTW:您对所有 ADC 通道输入使用了相同的 ADC_TRIGGER_EWPM1_SOCA 源。 这样做的目的是将每个触发器与特定 ADC 通道输入1至1序列隔离到每个 Clarke 函数中。 目的是提高软件吞吐量、以解决在硬件中将负载转移到器件层的感知 FOC 位置时序问题。
感谢您关注此问题
我将每个 ADC 通道组设置为一个细化 ePWM 触发源(分别为1、2、4)、并且运行正常。 mainISR()仍然只有1个 IRQ,尽管怀疑软件可能会分支到3个 IRQ 中,每个 ADC 一个 IRQ 具有组1共享 INT 嵌套。
也许一个更简单、不太复杂的硬件分配也可以为每个 ADC 通道分配单独的 SIN,但仍然为 mainISR()保留1个 IRQ。
这是不同的设置和概念。 为什么电机控制 ISR、mainISR 需要3个 IRQ? 这毫无意义。 当然、您可以根据需要为每个 PWM SOC 或 ADC EOC 启用 IRS、只需配置相关寄存器即可。 您可以查看有关这方面的技术手册。
似乎您错过了较大的点、每个 ADC 触发器开始与每个 ePWM 发生器周期同步采样。 直接加载周期被视为导致电气干扰、而在 C2000 ePWM 模块中、主从器件同步模式不是默认模式。 这就是为什么开发了影子加载,特别是因为全局更新同步模式根本不适用于 runSVM()调用。
[引用 userid="35051" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forume/1098605/tms320f280049c-q1-tms320f280049c/4123494#413394"]当然、如果您需要配置 EOC 或 ADC 的每个 PWM SOC 或 ERS[引用]、您可以为每个 PWM SOC 或 ADC 启用寄存器、然而、ISR 未注册、而是注册到一个矢量、因此我认为 SVM 代码不能用于处理3个不同的矢量地址。 也许它可以是每个 CMPD 计数的 INT 源和用3 mainISR()(hal.h)注册的矢量表、但是 CPU 可以继续处理3个 ADC 中断的清晰 ACK 这一更大的问题。
下面 是它现在的工作方式、但它可以为每个 Clarke ADC 通道输入使用单独的 Sock 0、1、2来提供更好的位置和电流控制样本。 这就是我在一段时间前提到使用 PPB 的原因、因为在 motorware control suite 中配置了 x69m。
#ifdef INA240A1
// ISENB - PGA4_OF ADCC8->RC0 INA240 (J5-46)/RC 滤波器
ADC_setupSOC (obj->adcHandle[2]、ADC_SOC_NUMBER0、ADC_TRIGGER_EPWM4_SOCA、
ADC_CH_ADCIN8、HAL_ADC_PGAxABC_SAMPLE_WINDOW);//140ns 窗口
// ISENC - PGA6_OF ADCA8->RA0 J3-24 (B0) INA240 (J5-45)/RC 滤波器
ADC_setupSOC (obj->adcHandle[0]、ADC_SOC_NUMBER0、ADC_TRIGGER_EPWM1_SOCA、
ADC_CH_ADCIN8、HAL_ADC_PGAxABC_SAMPLE_WINDOW);//140ns
// ISENA - PGA2_OF ADCB8->RB0 INA240 (J5-48)/RC 滤波器
ADC_setupSOC (obj->adcHandle[1]、ADC_SOC_NUMBER0、ADC_TRIGGER_EPWM2_SOCA、
ADC_CH_ADCIN8、HAL_ADC_PGAxABC_SAMPLE_WINDOW);//140ns
#endif
// VSENA - A6->RA1 J7-63
ADC_setupSOC (obj->adcHandle[0]、ADC_SOC_number1、ADC_TRIGGER_EPWM1_SOCA、
ADC_CH_ADCIN6、HAL_ADC_SAMPLE_WINDOW);
// VSENC - B6/A2->RB1 J7-64
ADC_setupSOC (obj->adcHandle[1]、ADC_SOC_number1、ADC_TRIGGER_EPWM2_SOCA、
ADC_CH_ADCIN6、HAL_ADC_SAMPLE_WINDOW);
// VSENB - C14->RC1 J7-65
ADC_setupSOC (obj->adcHandle[2]、ADC_SOC_number1、ADC_TRIGGER_EPWM4_SOCA、
ADC_CH_ADCIN14、HAL_ADC_SAMPLE_WINDOW)
您可以通过设置 eWPM、CPU 计时器或其他事件、根据需要配置 ADC 触发时间点。 这些示例只是一个参考、并不限制您必须在所有情况下都使用它。 用户可以根据系统和 ADC 模块对其进行更改。
感谢您的建议。 您似乎可以 根据需要完成它。
我主要是想更多地考虑论坛上有关高速不稳定的所有投诉、可能是与 ADC 时间相关的问题。
谢谢、我们将检查并尝试一下。 让您知道是否有任何更新。