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.
尊敬的支持人员:
我已经申请了多项测量应用于 BLDC 电机(反电动势)的波形的操作。 我将使用带 RC 滤波器的分压器、并使用示波器读取这些值。
问题是、在电机的某些速度下、它似乎有很多噪声。 在这里、我展示了以64kHz 为单位测量的 ADC 输入。
我的 pwmInput 在7500至12500个任意单位之间变化、实际上、这会将输入占空比从 1ms 变为2ms。 在下表中、在第16000个采样之前、我测量的波形的频率为1、68kHz、在该波形的频率高于2、04kHz。 我还执行了中等平均滤波器(MAF)、样本数量为3个和10个、如下图所示:
1、68kHz 波:
2、04 kHz 波形:
我放弃了一些可能性:
我的想法太多了、因此、我非常感谢在这个问题上提供的帮助。
这是包含图形的.xlsx。 我还使用不同的 aquisitons 和原始.csv 文件制作了一个驱动器:
e2e.ti.com/.../0217_5F00_Test2.xlsx
使用的代码(尽管与相关问题中的代码非常相似):
// //库 //********* #include #include #include "driverlib/adc.h" #include "driverlib/pio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/pinmwm.h" #include "driverlib/rom.h" #include "driverlib/mnts.h" #include "driverlib_mware.h"#include "drivers/intru.triggio.h"#include"#include "drivers.包含"drivers/driverlib#drivers.h.hw_sym.inc"#include"#drivers.intrintrintrintru.h"#include "drivers/drivers.hw_sym.intrinc/包含"#include "drivers.hw_sym.inc"#include"#include "drivers.hw. //为计时 器#include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_adc.h" #include "inc/hw_timer.h" #include "inc/hw_NVIC.h" #include "inc/hw_sysctl.h" #include "utils/uartdio.h * //信息 //********* // uint32_t - 32位的无符号整数-范围为0到2^32 - 1 //*************** //变量声明 //********* // ADC uint32_t ui32adcValues[4]; //用于存储来自 ADC volatile bool bDataReady 的值的变量= false; //指示 ADC 就绪的标志 // ADC 滤波 器 uint32_t adcSumFilterCounter = 1; //用于计数 器 uint32_t adc_sum_filter_samples_number = 1的变量; //总和滤波器 uint32_t analogValue_ADC3的大小= 0; //用于存储值的变量 //系统 uint32_t g_ui32SysClock; //系统时钟速率,单位为 Hz。 uint32_t system_clock = 60000000; // 64MHz // PWM 浮点类比值= 0、类比平均= 0、pwmMaxFloat = 6000; float adcToPwmRatio = 0; //使用的 PWM 值与 ADC 分辨率 间的比率 float pwmMin = 7500; // PWM 的最小值、零速时的电机 悬空 pwmMax = 14500; // PWM 的最大值、全速 浮动电机 analogValueFloat_ADC3; //滤波器后 ADC 的值以获取 uint32_t sumCounter = 0、iSamples = 1000、pwmValue = 0; volatile uint32_t pwmInput = 1; uint32_t pwmDutyCycle = 15000; // 500Hz //计时 器易失性无符号长整型 g_ui32TimerIntCount = 0; 易失性无符号长整型 g_ui32SecondsOnTime = 0; #define APP_TICKS_PER_SEC 100; bStatebTimerDone = false; uint32_t SampleFreq = 0; //测量采集 uint8_t 测量机器 的时间= 0;volatile enum = 0;//测量机器测量计数器 空闲、 初始测量、 初始计算、 WAIT_TO_POS_CYCLE、 WAIT_TO_HALF_CYCLE、 Wait_for_full_cycle、 Update_measurements }measState; //速度循环状态机 易失性枚举{ SPEED1、 Speed2、 SPEED3、 SPEED4、 SPEED5、 SPEED6、 停止 }循环状态; uint32_t iSpeedStateDelay = 0; uint32_t pwmMeas = 0; #define HYSTH_MIN_ADC 250 // ADC 识别电机处于运动 中的最小值#define INTRIAL_MEAS_NUMBER 50 //初始测量值 uint32_t sumADC3 = 0; //存储 ADC3 uint32_t iADCSum3=0的累积总和; // ADC3 uint32_t nCycl3完成的测量次数的初始计数器= 0; //由 ADC3 uint32_t avgADC3完成的测量次数的稳定计数器 = 0; // ADC3 uint32_t currentFreq3的平均值= 0; // ADC3 Long inV_deltaT 的电流频率 = 16000000; // ADC 采样频率- 16kHz bool bStartRunning = 0; //********* //驱动程序库遇到错误时调用的错误例程。 // #ifdef debug void __error__(char *dpcFilename、uint32_t ui32Line) { #endif //********* // ADC0序列 ISR - 19.01.2021 //********* void ADC0Sequence0ISR (void) { if (measureCounter = 1){ GPIOPinWrite (GPIO_PORTL_BASE、GPIO_PIN_3、0); measureCounter = 2; } if (measureCounter = 0){ GPIOPinWrite (GPIO_PORTL_BASE、GPIO_PIN_3、GPIO_PIN_3); measureCounter = 1; } if (measureCounter = 2){ measureCounter = 0; } ADCIntClear (ADC0_BASE、0); ADCSequenceDataGet (ADC0_BASE、0、ui32adcValues); 如果(!bDataReady) { bDataReady = true; } } //********* // ADC 初始化- 19.01.2021 //********* void ConfigureADC (void) { SysCtlPeripheralReset (SYSCTL_Periph_GPIOE); SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE); SysCtlPeripheralReset (SYSCTL_Periph_ADC0); SysCtlPeripheralEnable (SYSCTL_Periph_ADC0); SysCtlDelay (10); GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0); // //将 ADC 配置为在 system_clock (96MHz)上使用 PLL 除以3以获得 ADC // 32MHz 时钟,全速率采样。 // ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL、50); // //等待时钟配置设置。 // SysCtlDelay (10); //选择序列发生器2并将其设置为最高优先级。 ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_TIMER、0); //ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_AUSE_0); ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_CH0); ADCSequenceStepConfigure (ADC0_BASE、0、1、ADC_CTL_CH1); ADCSequenceStepConfigure (ADC0_BASE、0、2、ADC_CTL_CH2); ADCSequenceStepConfigure (ADC0_BASE、0、3、ADC_CTL_CH3 | ADC_CTL_IE | ADC_CTL_END); ADCSequenceEnable (ADC0_BASE、0); ADCIntClear (ADC0_BASE、0); ADCIntEnable (ADC0_BASE、0); IntEnable (INT_ADC0SS0); } //********* // PWM 初始化- 13.09.2020 //********* void Init_PWM (){ // 1. SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF); //启用端口 F while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOF)); // 2. SysCtlPeripheralDisable (SYSCTL_Periph_PWM0); SysCtlPeripheralReset (SYSCTL_Periph_PWM0); SysCtlPeripheralEnable (SYSCTL_Periph_PWM0); while (!(SysCtlPeripheralReady (SYSCTL_Periph_PWM0))); // PWM0_BASE:0 -> 0来自 M_0_PWM1 // PWM_OUT_1和 PWM_OUT_1_BIT:1来自 M0PWM_1 // PWM_GEN_0:针对 PWM0和 PWM1的 GEN_0、针对 PWM2和 PWM3的 GEN_1…… PWMClockSet (PWM0_BASE、PWM_SYSCLK_DIV_8); // system_clock/32 = 3MHz GPIOPinTypePWM (GPIO_PORTF_BASE、GPIO_PIN_1); //端口 F - PF1的引脚1 GPIOPinConfigure (GPIO_PF1_M0PWM1); PWMGenConfigure (PWM0_BASE、PWM_GEN_0、PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC); PWMGenPeriodSet (PWM0_BASE、PWM_GEN_0、pwmDutyCycle); // 120MHz/pwmMax = pwmFreq PWMPulseWidthSet (PWM0_BASE、PWM_OUT_1、1); PWMGenEnable (PWM0_BASE、PWM_GEN_0); PWMOutputState (PWM0_BASE、PWM_OUT_1_BIT、TRUE); PWMIntEnable (PWM0_BASE、PWM_INT_GEN_0); PWMGenIntTrigEnable (PWM0_BASE、PWM_GEN_0、PWM_TR_CNT_ZERO); IntEnable (INT_PWM0_0); } //********* // UART 初始化- 19.01.21 //************* void InitConsole (void){ SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); //启用用于 UART0引脚的 GPIO 端口 A。 // //为端口 A0和 A1上的 UART0功能配置引脚复用。 //如果您的器件不支持引脚复用、则无需执行此步骤。 // GPIOPinConfigure (GPIO_PA0_U0RX); GPIOPinConfigure (GPIO_PA1_U0TX); SysCtlPeripheralEnable (SYSCTL_Periph_UART0); //启用 UART0以便我们可以配置时钟。 UARTClockSourceSet (UART0_BASE、UART_CLOCK _PIOSC);//使用内部16MHz 振荡器作为 UART 时钟源。 // //为这些引脚选择替代(UART)功能。 // GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1); UARTStdioConfig (0、115200、16000000); //初始化控制台 I/O 的 UART } // //计时器初始化- 26.01.2021 //********* void ConfigureTimer (void){ // //启用此示例使用的外设。 // SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0); // //配置一个16位周期定时器。 // TimerConfigure (TIMER0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODICASE); // //将 ADC 采样频率设置为16KHz,即每隔62.5uS。 // TimerLoadSet (TIMER0_BASE、TIMER_A、(g_ui32SysClock/64000)- 1); // //启用 Timer A 的 ADC 触发输出 // TimerControlTrigger (TIMER0_BASE、TIMER_A、TRUE); // //启用处理器中断。 // IntMasterEnable(); // //启用计时器0,它将启动整个应用程序进程。 // TimerEnable (TIMER0_BASE、TIMER_A); } int main (void){ G_ui32SysClock = MAP_SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480)、SYSTEM_CLOCK); //从 PLL 以 system_clock MHz 运行 InitConsole(); //设置用于显示消息的串行控制台 ConfigureTimer();//设置计时器 ConfigureADC(); //设置 ADC init_pwm (); //设置 PWM SysCtlPeripheralEnable (SYSCTL_Periph_GPION); //启用端口 N while (!SysCtlPeripheralReady (SYSCTL_Periph_GPION)); GPIOPinTypeGPIOOutput (GPIO_PORTN_BASE、GPIO_PIN_1); //为 LED D1 (PN1)启用 GPIO 引脚。 SysCtlPeripheralEnable (SYSCTL_Periph_GPIOL); //启用端口 L while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOL)); GPIOPinTypeGPIOOutput (GPIO_PORTL_base、GPIO_PIN_3); //为 PL3启用 GPIO 引脚 IntMasterEnable(); //相对于最大和最小 PWM 以及 ADC 读数的转换 adcToPwmRatio =(pwmMax - pwmMin)/4095.0; // 4095 = 2^12位 pwmInput = pwmMin; //从 pwmMin 值开始 UARTprintf ("pwmValue"); UARTprintf ("AIN0、");//\r 替换、\n 替换为新行 //UARTprintf ("AIN1、"); //UARTprintf ("AIN2"); UARTprintf ("AIN3\n"); //UARTprintf ("avgADC3"); //UARTprintf ("currentFreq3"); //空闲时启动 MeasState MeasState = IDLE; //无限循环 while (1){ if (bDataReady){ UARTprintf ("%3D"、pwmInput); UARTprintf ("%4d、"、ui32adcValues[0]);//\r 要替换、\n 到新行 //UARTprintf ("%4d、"、ui32adcValues[1]); //UARTprintf ("%4d、"、ui32adcValues[2]); UARTprintf ("%4D\n"、ui32adcValues[3]); //UARTprintf ("%4d、"、avgADC3); //UARTprintf ("%8d\n"、currentFreq3); bDataReady = false; } if (iSpeedStateDelay < 191000){ iSpeedStateDelay = iSpeedStateDelay + 1; } if (iSpeedStateDelay = 20000){ pwmInput = 7500; } if (iSpeedStateDelay = 40000){ pwmInput = 8500; } if (iSpeedStateDelay = 60000){ pwmInput = 9500; } if (iSpeedStateDelay = 80000){ pwmInput = 10500; } if (iSpeedStateDelay = 100000){ pwmInput = 11500; } if (iSpeedStateDelay = 120000){ pwmInput = 12500; } if (iSpeedStateDelay = 140000){ pwmInput = 12000; } if (iSpeedStateDelay = 160000){ pwmInput = 10000; } if (iSpeedStateDelay = 170000){ pwmInput = 8200; } if (iSpeedStateDelay = 180000){ pwmInput = 7750; } if (iSpeedStateDelay = 190000){ pwmInput = 7500; } }
此致、
Gustavo Wegher
我看到的最常见问题是源阻抗和采样时间。 如果您的源阻抗对于采样时间来说太大、您转换的其他通道将影响您的结果。 可能的解决方案:
1.降低源阻抗
2.增加采样时间
3.添加一个外部采样电容器
您好 Gustavo、
查看您的代码、我注意到您配置了4个 ADC 步长和1个 PWM 发生器。 请注意、具有上数/ dwn 计数的中心对齐同步 PWM 发生器是最典型的。 必须将 ADC 采样与 PWM 发生器同步 与使用发生器触发源相比、通过计时器触发的 ADC 模块可能需要延迟才能将采样窗口缓慢/同步到所需的信号采集点/s 尽管采样 窗口的奈奎斯特频率可能是奈奎斯特频率的两倍、但这并不意味着信号采集点或计数将保持甚至实现。
BTW:如果您尝试创建一个正弦空间矢量调制方案、该方案可能是通过1294 MCU 类徒劳的尝试。 否则、很容易实现六步梯形波、但需要查找表以生成霍尔代码。