【嵌入式电机控制#16】电流环(三):过采样提高采集精度&看门狗监测总线电压

一、香农采样定律

为不失真的复现信号的变化,采样频率至少应大于等于连续信号最高频率分量的二倍

采样定律只能确定采样周期的上限(采样频率的下限),实际采样周期的选择受多方面影响。

一般情况下:

  1. 对于响应快波动大、易受干扰(压力、流量)的过程,应该选较高的采样频率

  2. 对于过程响应慢,滞后大(温度、化学成分等)选取较低采样频率

当过程的纯滞后时间较长时,选取采样周期为纯滞后时间的1/4到1/8

STM32的ADC分辨率为12bit,假设PWM脉冲频率为20KHz,则理论上讲采样频率达到40Khz就能正确采集波形。

二、代码改进

注意看写的注释,不然干看代码是看不懂的

(1)adc.h修改配置

VoltageResolution = ADC(Hex) * 3.3 / 2^n *1000 mV

根据香农采样定律,采样频率选取的最小值应该为PWM的两倍

再由过采样理论, 实际采样率 > 两倍PWM频率 * 4^2

所以采样频率能够拉到14bit,公式中应该改为除以2^14也就是16384

cpp 复制代码
#define VOLT_RESOLUTION     ((float)((VOLT_REF/(float)(16384))*(float)1000))
#define VOLTBUS_RESOLUTION  ((float)( 3.3f/(float)4096) * (42.4f+2.0f) / 2.0f)

(2)adc.c 采样DMA

cpp 复制代码
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)  
{
  uint16_t ConvCnt = 0;
  int32_t ADConv = 0 ; 
//定义采样次数计数器,定义采样结果寄存器(注意,这次移到中断里成动态量了)
//这里注意防止采样次数AverCnt溢出
  HAL_ADC_Stop_DMA(hadc);
//先停止DMA,目的是不干扰时序
  SetChannelAsRank1(hadc,ADC_VOLT_CHANNEL);
//设置电压采样优先,为电压提供专属的数据采集时机,为电流保留了数据处理的机会
//此时DMA只采集电压,电流DMA被维护
  HAL_ADC_Start(hadc);
//ADC重新开启,此时正式开始采集电压,与此同时处理电流
  for(ConvCnt = 0; ConvCnt < (ADC_BUFFER ); ConvCnt++)
  {
    ADConv += ((int32_t)ADC_ConvValueHex[ConvCnt]);
  }
//进行电流采集量累加,一共1024次
  ADConv >>= ADC_Base;
//进行取平均,注意这里只移动了8位,也就是256,故意少除以2^2,为12bit->14bit的过采样处理
  AverSum += ADConv;
//进行采样结果累加
  AverCnt++;
//采样次数自增 
  HAL_ADC_Stop(hadc);
//停止ADC,并把ADC权限留给电流,电压后续在窗口看门狗中进行总线电压监测
  SetChannelAsRank1(hadc,ADC_CURRENT_CHANNEL);
  
  HAL_ADC_Start_DMA(hadc,(uint32_t*)ADC_ConvValueHex,ADC_BUFFER);
//这句话不仅有重新开始DMA的含义,也有重启ADC的意思
}

(3) 定时器中断采样数据进一步处理

cpp 复制代码
void HAL_SYSTICK_Callback(void)
{
  __IO int32_t ADC_Resul= 0;
  __IO float Volt_Result = 0;
  __IO float ADC_CurrentValue;
 //定义ADC结果寄存器,电流采样电压结果寄存器,最终实际电流值寄存器
  if((uwTick % 50) == 0)
  {
    ADC_Resul = AverSum/AverCnt ;
//每一次中断,进行动态窗口滤波,窗口长度根据此前DMA次数调整
    OffsetCnt_Flag++;
    if(OffsetCnt_Flag >= 16)
    {
    //经过实际测试,17次进入定时器中断时,电流波形才稳定
    //那么我们就把前一次的值当作零漂
      if(OffsetCnt_Flag == 16)
      {
        OffSetHex = ADC_Resul;
      }
    //标准的状态机写法,以固定的32代表电流采样进入正常状态,每次进来都会被赋为32
    //那么我们如果需要在控制日志中导出电流数据,就可以在这个大判断后print它的flag
      OffsetCnt_Flag = 32;
    //adc结果减去偏差才是真正的采样值
      ADC_Resul -= OffSetHex;
    }
//计算进入单片机的电压模拟量
    Volt_Result = ( (float)( (float)(ADC_Resul) * VOLT_RESOLUTION) );
//计算电机端实际的电流
    ADC_CurrentValue = (float)( (Volt_Result / GAIN) / SAMPLING_RES);
//对动态窗口的计数值、累加值清零
    AverCnt = 0;
    AverSum = 0;
   
      printf("Volt: %.1f mV -- Curr: %d mA\n",Volt_Result,(int32_t(ADC_CurrentValue+10));
  }
}

(4) 窗口看门狗实现总线电压监测

这段代码实现了一个逻辑:如果电压异常被WD连续检测出六次,则强制关闭电机,然后关闭定时器PWM输出。

cpp 复制代码
void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
{
  //给一个计数值i,并定义为静态量
  //注意这种用法,下一次触发看门狗时,i的值还保留,效果类似全局静态
  static uint8_t i = 0;
  i++;
  //这里直接自增了 ,说明一切从i==1开始
  if(ADC_VoltBus > VOLT_LIMIT_MIN  && ADC_VoltBus < VOLT_LIMIT_MAX)
    //如果总线电压大于最小供电,并小于最大电压限制
    i = 0 ;
  else if(i>=6)
  {
    SHUTDOWN_MOTOR();
    //禁用驱动
    HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
    //关闭输出
    PWM_Duty = 0;
    //这里可以直接做PID清理
//    ADC_VoltBus = (float)ADC_VoltBus * VOLTBUS_RESOLUTION;
     //如果需要在控制日志中查看危险电压到底是多少,可以算一下ADC
    printf("Bus Voltage is out of range!!\n");
    //汇报控制日志
    printf("Please Reset the Target!\n");
    //死循环,等待用户reset
    while(1);
  }
}

(5)以上三个中断的优先级配置建议

为了安全起见,看门狗的中断优先级必须是三个中最高的。这样单片机才能在安全环境下稳定工作。

其次,ADC采样速率要求较快,并且是定时器数据处理的基础,所以我们安排次高优先级。

最后,当ADC数据处理完毕后,再将数据送给数据处理中断,所以它安排最低。

总结:

最高:窗口看门狗中断

适中:ADC的DMA中断

最低:数据处理的定时器中断

相关推荐
DIY机器人工房4 小时前
在开发板tmp目录下传输文件很快的原因和注意事项:重启开发板会清空tmp文件夹,记得复制文件到其他地方命令如下(cp 文件所在路径 文件要复制到的路径—)
嵌入式硬件·嵌入式·tftp·diy机器人工房
学不动CV了6 小时前
基于按键开源MultiButton框架深入理解代码框架(三)(指针的深入理解与应用)
c语言·arm开发·stm32·单片机·算法·51单片机
GC_June078 小时前
STM32 + 移远EC800 4G通信模块数传
arm开发·stm32·嵌入式硬件
通信射频老兵9 小时前
如何优化transceiver芯片的供电
经验分享·单片机·嵌入式硬件·5g·信号处理·射频工程
酷飞飞9 小时前
模电基础-电阻和功率
单片机·嵌入式硬件
如愿小李14 小时前
STM32之L298N电机驱动模块
stm32·单片机·嵌入式硬件
CC呢16 小时前
基于单片机宠物喂食器/智能宠物窝/智能饲养
单片机·嵌入式硬件·物联网·宠物喂食
DIY机器人工房16 小时前
关于在VScode中使用git的一些步骤常用命令及其常见问题:
大数据·stm32·单片机·嵌入式硬件·elasticsearch·搜索引擎·diy机器人工房
muub16 小时前
【黄山派-SF32LB52】—硬件原理图学习笔记
单片机·嵌入式硬件·原理图·黄山派·sf32·思澈科技·立创开发板