【嵌入式电机控制#15】电流闭环控制(二):电流采样

代码解析

        (1)main.c中ADC的DMA中断回调

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  __IO uint16_t ConvCnt = 0;
  __IO int32_t ADConv = 0 ;
//这里其实没必要用IO定义,变量与外设寄存器无直接交互
  HAL_ADC_Stop_DMA(hadc);
//注意:对于信号传递速度极快的DMA,即使你用了HT中断也很难同步数据,所以这里最好解决方法是
//直接暂停DMA,这样虽然数据也会有一定不同步,但是至少保证数据时序是正确的

  for(ConvCnt = 0; ConvCnt < ADC_BUFFER; ConvCnt++)
  {
    ADConv += ((int32_t)ADC_ConvValueHex[ConvCnt]);
  }
  ADC_Resul = ADConv>>ADC_Base;
//求和求平均值,上面这个移位操作相当于除以ADC_Buffer
//重新打开DMA
  HAL_ADC_Start_DMA(hadc,(uint32_t*)ADC_ConvValueHex,ADC_BUFFER);
}

     (2)main.c中的定时器中断处理

        需要对平均值滤波后的采样信号进行动态偏差校准处理

        原理:

        采样电路刚启动时存在零漂、偏置等,导致测量值=真实值+误差。

        而此时理论上ADC的电流应该是0,由于误差,将它提升到了一个非零值。那么这个非零值就是长期存在的规律性误差

        那么,我们是否可以找到它的正常工作开始的零状态响应,然后作为一个基准偏差,让后续数据减去?

void HAL_SYSTICK_Callback(void)
{
  __IO float Volt_Result = 0;
  //电压采样结果
  __IO float ADC_CurrentValue;
  //实际电流值
    //50ms中断一次,这里可以直接在定时器中配置
  if((uwTick % 50) == 0)
  {
   //给平均值处理次数自增,这里注意防溢出
    if(OffsetCnt<4294967296){
        OffsetCnt_Flag++;
    }
    else {
        OffsetCnt_Flag=0;
    }
    if(OffsetCnt_Flag >= 16)   //达到预设的零状态,则开始误差校准
    {
      if(OffsetCnt_Flag == 16)  //在16的点取误差
      {
        OffSetHex = ADC_Resul;
      }
      OffsetCnt_Flag = 32;  //这里用了严格的状态机逻辑,以32区分16,表示已完成校准
      ADC_Resul -= OffSetHex; //第一次经过,把零状态本身误差清零,为后续经过减去误差
    }
    //把ADC结果乘以分辨率换算为电压值
    Volt_Result = ( (float)( (float)(ADC_Resul) * VOLT_RESOLUTION) );
    //电压值由公式换算为采样点电流值
    ADC_CurrentValue = (float)( (Volt_Result / GAIN) / SAMPLING_RES);

    vofa_data();
    
  }
}

 

总结

此节内容较为简单,注意理解动态偏差中断的频率设定 和 偏差校准的过程

        

你可能感兴趣的:(嵌入式电机控制系统,电机控制,嵌入式系统,控制算法,单片机)