当前位置:   article > 正文

FOC控制库MCSDK5.4.4梳理(2)——电流采样_st mcsdk adc 采集值为什么要乘以2

st mcsdk adc 采集值为什么要乘以2

一、前言

  本文讲解MCSDK中FOC控制的预备步骤——电流采样,电流采样的实现函数是R3_2_GetPhaseCurrents。MCSDK中的电流采样功能和上一篇文章SVPWM一样,也是分扇区来进行电流采样的,电流采样涉及到R3_2_ParamsM1.ADCConfig1和R3_2_ParamsM1.ADCConfig2两个数组的配置,因此电流采样部分也值得一说
  UVW和ABC都是表示电机的三个相序,只是说法不同

二、源代码解析

1、电流采样机制

  在FOC控制中,要求在同一时刻同时获得UVW三相的电流,最为理想的情况是一个引脚能同时复用成ADC1,ADC2和ADC3的通道,但这样的引脚并不多,而且有些引脚会复用成其他功能,所以该方法不可行。从上一章文章我们得知,三相电流的标量和为零,因此我们只需要在同一时刻读取到其中两相电流即可,基本上一个引脚可以同时复用成ADC1和ADC2,该方法可行
  这里相电流采样时,ADC要配置成注入转换模式,注入转换优先级比规则转化优先级高。比如,当ADC同时满足母线电压采样条件和相电流采样条件时,ADC会优先进行相电流采样,完成后再进行相电压采样
  相电流采样的触发源配置为驱动SVPWM所用的定时器的通道4,因此ADC采样频率为SVPWM的频率,一般为10kHz到20kHz之间,即adc中断频率

图1 UVW三相电流与电角度关系

  如图1所示,在电角度从’π/3’到’π’的过程中,即扇区2和扇区3,U相和W相电流变化幅度最大且单调,幅度为3/2。同理,扇区4和扇区5,U相和V相电流变化幅度最大且单调,扇区6和扇区1,V相和W相电流变化幅度最大且单调。看下面ADC通道配置,处于扇区1时ADC1检测V相电流,ADC2检测W相电流,正如我们预料的那样,这就是这两个ADC配置数组的由来。

  .ADCConfig1 = {   MC_ADC_CHANNEL_4<<ADC_JSQR_JSQ4_Pos    //V
                   ,MC_ADC_CHANNEL_5<<ADC_JSQR_JSQ4_Pos    //U
                   ,MC_ADC_CHANNEL_5<<ADC_JSQR_JSQ4_Pos    //U
                   ,MC_ADC_CHANNEL_5<<ADC_JSQR_JSQ4_Pos    //U
                   ,MC_ADC_CHANNEL_5<<ADC_JSQR_JSQ4_Pos    //U
                   ,MC_ADC_CHANNEL_4<<ADC_JSQR_JSQ4_Pos    //V
                  },

  .ADCConfig2 = {   MC_ADC_CHANNEL_3<<ADC_JSQR_JSQ4_Pos    //W
                   ,MC_ADC_CHANNEL_3<<ADC_JSQR_JSQ4_Pos    //W
                   ,MC_ADC_CHANNEL_3<<ADC_JSQR_JSQ4_Pos    //W
                   ,MC_ADC_CHANNEL_4<<ADC_JSQR_JSQ4_Pos    //V
                   ,MC_ADC_CHANNEL_4<<ADC_JSQR_JSQ4_Pos    //V
                   ,MC_ADC_CHANNEL_3<<ADC_JSQR_JSQ4_Pos    //W
                  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2、电流采样代码

void R3_2_GetPhaseCurrents( PWMC_Handle_t * pHdl, ab_t* pStator_Currents )
  • 1

  函数入参是两个指针,用于接收返回值:pHdl是FOC库中的一个结构体,存储了SVPWM占空比和采样电流等参数;pStator_Currents是存储了UV两相电流的结构体,用于后续FOC的计算

LL_TIM_CC_DisableChannel(TIMx, LL_TIM_CHANNEL_CH4);
  • 1

  禁用控制SVPWM定时器的4通道,防止再次触发ADC采样中断,防止中断嵌套的产生

bSector = pHandle->_Super.Sector;
hReg1 = *pHandle->pParams_str->ADCDataReg1[bSector] * 2;
hReg2 = *pHandle->pParams_str->ADCDataReg2[bSector] * 2;
等同于
hReg1 = ADC1->JDR1 * 2;
hReg2 = ADC2->JDR1 * 2;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  此处代码写的有些多余,目的就是将ADC1和ADC2的注入通道1的采样值读取出来。
  此处多说一些,代码中将ADC配置为左对齐模式。规则通道的有效位数是16位,因此ADC采样值范围是0-65535;而注入通道的有效位数是15位,最高位作为符号位存在,乘以2是将采样值范围扩大到0-65535,方便归一化计算。可以在ADC_JOFRx寄存器中配置ADC注入通道的偏移量,以此来改变JDRx寄存器的符号值

switch(bSector)
{
    case SECTOR_6:
    case SECTOR_1:
      /* A相电流不可用     */
      /* B相电流 = B相零漂 - ADC采样值 */
      wAux = ( int32_t )( pHandle->PhaseBOffset ) - ( int32_t )( hReg1 );
      /* B相电流异常判断 */
      if ( wAux < -INT16_MAX )
      {
        pStator_Currents->b = -INT16_MAX;
      }
      else  if ( wAux > INT16_MAX )
      {
        pStator_Currents->b = INT16_MAX;
      }
      else
      {
        pStator_Currents->b = ( int16_t )wAux;
      }

      /* C相电流 = C相零漂 - ADC采样值 */
      /* A相电流 = -C相电流 -B相电流 */
      wAux = ( int32_t )( pHandle->PhaseCOffset ) - ( int32_t )( hReg2 );
      wAux = -wAux - ( int32_t )pStator_Currents->b;

      /* A相电流异常判断 */
      if ( wAux > INT16_MAX )
      {
        pStator_Currents->a = INT16_MAX;
      }
      else  if ( wAux < -INT16_MAX )
      {
        pStator_Currents->a = -INT16_MAX;
      }
      else
      {
        pStator_Currents->a = ( int16_t )wAux;
      }
      break;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

  从上一节中我们得知,在扇区6和扇区1内,检测的是V相和W相的电流,因此会有pHandle->PhaseBOffset - hReg1得到V相电流,会有pHandle->PhaseCOffset - hReg2得到W相电流,因为三相电流标量和等于零,所以再通过-wAux - pStator_Currents->b得到U相电流,如此便得到AB(UV)两相的电流值

3、电流采样的触发

  电流采样的触发是R3_2_TIMx_UP_IRQHandler,该函数在SVPWM的每个周期都会调用一次,以下是该函数的实现

void * R3_2_TIMx_UP_IRQHandler( PWMC_R3_2_Handle_t * pHandle)
{
  TIM_TypeDef* TIMx = pHandle->pParams_str->TIMx;
  ADC_TypeDef * ADCx_1 = pHandle->pParams_str->ADCx_1;
  ADC_TypeDef * ADCx_2 = pHandle->pParams_str->ADCx_2;
  uint32_t ADCInjFlags;
  
  /* ADC状态检测 LL_ADC_FLAG_JSTRT为通道开始标志 LL_ADC_FLAG_JEOS为通道转换结束标志*/
  ADCInjFlags = ADCx_1->SR & (LL_ADC_FLAG_JSTRT|LL_ADC_FLAG_JEOS);
  if ( ADCInjFlags == LL_ADC_FLAG_JSTRT )
  {
    /* ADC转换已开始,但未完成*/
    do
    {
      /* 等待转换结束  */
      ADCInjFlags = ADCx_1->SR & (LL_ADC_FLAG_JSTRT|LL_ADC_FLAG_JEOS);
    } 
    while ( ADCInjFlags != (LL_ADC_FLAG_JSTRT|LL_ADC_FLAG_JEOS) );
  }
  else if ( ADCInjFlags == 0 )
  {
    /* ADC转换未开始*/
    while ( ( TIMx->CNT ) < ( pHandle->pParams_str->Tw ) )
    {
      /* 等待一段时间,我配置的是3us */
    }
    
    ADCInjFlags = ADCx_1->SR & (LL_ADC_FLAG_JSTRT|LL_ADC_FLAG_JEOS);
    if ( ADCInjFlags == LL_ADC_FLAG_JSTRT )
    {
      /* ADC转换已开始,但未完成 */
      do
      {
        /* 等待转换结束 */
        ADCInjFlags = ADCx_1->SR & (LL_ADC_FLAG_JSTRT|LL_ADC_FLAG_JEOS);
      }
      while ( ADCInjFlags != (LL_ADC_FLAG_JSTRT|LL_ADC_FLAG_JEOS) );
    }
  }
  else
  {
    /* ADC转换已结束 */
  }
  
  /* 关闭ADC1和ADC2转换 */
  LL_ADC_INJ_StopConversionExtTrig(ADCx_1);
  LL_ADC_INJ_StopConversionExtTrig(ADCx_2);

  /* 根据扇区设置下一个电流转换通道  */
  ADCx_1->JSQR = pHandle->pParams_str->ADCConfig1[pHandle->_Super.Sector];
  ADCx_2->JSQR = pHandle->pParams_str->ADCConfig2[pHandle->_Super.Sector];

  /* 设置ADC1和ADC2触发源为内部 */
  LL_ADC_INJ_SetTriggerSource(ADCx_1,pHandle->ADC_ExternalTriggerInjected);
  LL_ADC_INJ_SetTriggerSource(ADCx_2,pHandle->ADC_ExternalTriggerInjected);
    
  /* 使能ADC触发源 */
  LL_TIM_CC_EnableChannel(TIMx, LL_TIM_CHANNEL_CH4);
  /* 开始转换 */
  LL_ADC_INJ_StartConversionExtTrig(ADCx_1, pHandle->ADCTriggerEdge);
  LL_ADC_INJ_StartConversionExtTrig(ADCx_2, pHandle->ADCTriggerEdge);

  return &( pHandle->_Super.Motor );
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

三、结语

  调试过程中遇到过有些电机线序倒相的情况,需要根据电机改动ADCConfig1和ADCConfig2两个数组,这个地方让我困惑了很久,如今问题解决了,拿出来分享一下
  电流采样还有UVW三相的零漂值没有采样没有说,放到后面的状态机部分一块说

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/600343
推荐阅读
相关标签
  

闽ICP备14008679号