电机复习总结-梯形算法-转速

一、引言

在电机驱动过程中,有一个很重要的参数:转速,电机以何种初始速度开始驱动,是否匀速,是否停止,怎么实现的,围绕这个话题,我们引出此文。

二、分析

57电机的步距角是1.8°,转一圈(360)需要走200步, 57电机是8分频,所以走1圈是200*8=1600步,又因为涉及中断设置的Toggle on match模式,到设置的值反转一次电平(一次跳变沿),需要两个跳变沿是一个周期,所以转1圈需要3200个周期(步)。

(1)初始化代码配置
cpp 复制代码
//定义电机参数的初始化 对应计数的周期数
static int32_t target_angle_cycles = 3200 * 5;
static uint32_t current_angle_cycles = 0;
static uint32_t max_speedRpm_cps = 3200 * 2;     
static uint32_t current_speedRpm_cps = 0;     

/* 定义电机的启动速度 */
static uint32_t min_speedRpm_cps = 1000;
//定义电机的加速度
static uint32_t acc_speedRpm_cps = 5000;    //启动速度太小 电机震动会很大
//定义电机加速度阶段所使用的计数周期数
static uint32_t acc_needSpeedRpm_cps = 0;
(2)电机硬件支持:由拨片开关前三位决定什么功能,后三位在转速中暂时用不少(不关注)。

(3)HAL库配置
(4)分析

又因为32系统的时钟频率为72MHz,方便计算分频数为72,得到分频后的信号为1MHz,经过换算为1us,也就是1us发送一个脉冲信号,达到arr的值会触发一次中断。所以arr的值越小,转速越高。

(5)转速怎么计算

1圈/1s -> 3200个周期/1s = 3200周期/1000000us -> 1个周期多少步=1000000/3200

----current_speedRpm_cps会随着电机运行达到目标速度,值越大,arr值越小,转速越高。

cpp 复制代码
// ! -------------------------------- 根据当前的速度值计算ARR的值 --------------------------------
uint16_t App_Motor_Value_GetUsFromCurrentSpeed(void){
    return 1000000/current_speedRpm_cps;
}
(6)根据转速不同,会有梯形算法模式

在电机运行过程中,会分为两种情况,梯形或者三角形速度变化。

两者的区别是,运行过程中加速阶段所需要的周期数是否等于一半的路程(梯形),或者大于一半路程(梯形),三角形最大速度不会达到计算的速度,会无法到最大速度。

整体代码分析

(1)电机驱动

/* 启动电机思路:

  1. 确认电机的旋转方向
  • 根据target_angle的正负值确定方向
  1. 电机旋转的目标角度
  • 根据当前的旋转角度来判断是否应该停止电机
  1. 电机的转速:
  • 由定时器的ARR的值决定,值越小,转速越快
  1. 驱动芯片使能:

*/

cpp 复制代码
void App_Motor_Start(void)
{
  
  // ! 1. 确认电机的旋转方向
  if (App_Motor_Value_GetTargetAngle_cycles() > 0)
  {
    // 电机正转(顺时针)
    HAL_GPIO_WritePin(MOTOR_DIR_GPIO_Port, MOTOR_DIR_Pin, GPIO_PIN_SET);
  }
  else
  {
    // 电机反转(逆时针)
    HAL_GPIO_WritePin(MOTOR_DIR_GPIO_Port, MOTOR_DIR_Pin, GPIO_PIN_RESET);
  }

  // ! 2. 电机的转速(本质是设置ARR)
  setArrInit();

  // ! 3. 启动编码器
  Int_Encoder_Start();

  // ! 3. 计算加速度阶段需要使用的周期数
  calcAccNeedCyclyes();

  // ! 4. 驱动芯片使能
  HAL_GPIO_WritePin(MOTOR_SD_GPIO_Port, MOTOR_SD_Pin, GPIO_PIN_SET);

  // ! 5. 启动定时器
  HAL_TIM_OC_Start_IT(&htim1, TIM_CHANNEL_1);
}
(2)电机停止
cpp 复制代码
void App_Motor_Stop(void)
{
  // 定时器关闭
  HAL_TIM_OC_Stop_IT(&htim1, TIM_CHANNEL_1);
  // 清空当前的角度值和速度值
  App_Motor_Value_SetCurrenttAngle_cycles(0);
  App_Motor_Value_SetCurrentSpeedRpm_cps(0);
}
(3)触发中断实现
cpp 复制代码
/* 通常用于输出PWM方波或者是单脉冲 */
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM1)
  {
    // 更新当前的旋转角度对应的周期数
    App_Motor_Value_SetCurrenttAngle_cycles(App_Motor_Value_GetCurrentAngle_cycles() + 1);
    // 更新下一步(下一个计数周期的快慢)
    updateNextSpeedRpmCps();
    // 判断是否要停止电机
    if (App_Motor_Value_GetCurrentAngle_cycles() >= abs(App_Motor_Value_GetTargetAngle_cycles()))
    {
      // ! 停止电机
      App_Motor_Stop();
    }
  }
}
(4)电机转速的代码
cpp 复制代码
void setArrInit(void)
{
  // TODO 可以先将最大速度作为启动速度, 隐患(启动速度过大,会导致电机堵转)
  // 设置最小速度为初始化速度
  App_Motor_Value_SetCurrentSpeedRpm_cps(App_Motor_Value_GetMinSpeedRpm_cps());

  // 计算ARR的值
  uint16_t arr = App_Motor_Value_GetUsFromCurrentSpeed();

  // 设置ARR的值
  __HAL_TIM_SetAutoreload(&htim1, arr);
}
(4)计算加速度阶段需要使用的周期数:求S 判断整体走向:梯形还是三角形
cpp 复制代码
void calcAccNeedCyclyes(void)
{
  /* 思路分析:
    - 已知条件:
      V1: 最大速度
      V0: 最小速度(初始化速度)
      a: 加速度
    - 求: S(加速度阶段需要使用的周期数)
    alt + 0178
    S = (V1² - V0²) / 2a
  */
  uint32_t acc_need_cycles = (App_Motor_Value_GetMaxSpeedRpm_cps() * App_Motor_Value_GetMaxSpeedRpm_cps() - App_Motor_Value_GetMinSpeedRpm_cps() * App_Motor_Value_GetMinSpeedRpm_cps()) / (2 * App_Motor_Value_GetAccSpeedRpm_cps());
  if (acc_need_cycles < abs(App_Motor_Value_GetTargetAngle_cycles()) / 2)
  {
    // 梯形
    App_Motor_Value_SetAccNeedSpeedRpm_cps(acc_need_cycles);
    can_reach_maxSpeed = true;
  }
  else
  {
    // 三角形
    App_Motor_Value_SetAccNeedSpeedRpm_cps(abs(App_Motor_Value_GetTargetAngle_cycles()) / 2);
    can_reach_maxSpeed = false;
  }
}
(5)计算下一步的速度:在中断触发的时候更新速度
cpp 复制代码
void updateNextSpeedRpmCps(void)
{
  /* 思路分析:
    已知条件:
      - V0
      - a
      - s: 1
    求V1
  */
  uint32_t V1 = 0;
  // 判断当前处在哪个阶段
  if (App_Motor_Value_GetCurrentAngle_cycles() < App_Motor_Value_GetAccNeedSpeedRpm_cps())
  {
    // 加速阶段
    V1 = sqrt(App_Motor_Value_GetCurrentSpeedRpm_cps() * App_Motor_Value_GetCurrentSpeedRpm_cps() + 2 * App_Motor_Value_GetAccSpeedRpm_cps() * 1);
  }
  // 匀速阶段
  else if (
      can_reach_maxSpeed &&
      App_Motor_Value_GetCurrentAngle_cycles() >= App_Motor_Value_GetAccNeedSpeedRpm_cps() &&
      App_Motor_Value_GetCurrentAngle_cycles() <= abs(App_Motor_Value_GetTargetAngle_cycles()) - App_Motor_Value_GetAccNeedSpeedRpm_cps())
  {
    V1 = App_Motor_Value_GetMaxSpeedRpm_cps();
  }
  // 减速阶段
  else
  {
    V1 = sqrt(App_Motor_Value_GetCurrentSpeedRpm_cps() * App_Motor_Value_GetCurrentSpeedRpm_cps() - 2 * App_Motor_Value_GetAccSpeedRpm_cps() * 1);
  }

  // 处理边界
  if (V1 > App_Motor_Value_GetMaxSpeedRpm_cps())
  {
    V1 = App_Motor_Value_GetMaxSpeedRpm_cps();
  }

  if (V1 < App_Motor_Value_GetMinSpeedRpm_cps())
  {
    V1 = App_Motor_Value_GetMinSpeedRpm_cps();
  }

  // 将V1更新至当前速度
  App_Motor_Value_SetCurrentSpeedRpm_cps(V1);
  // 更新ARR的值
  __HAL_TIM_SetAutoreload(&htim1, App_Motor_Value_GetUsFromCurrentSpeed());
}
(6)编码器开启
cpp 复制代码
void Int_Encoder_Start(void)
{
  // 开启更新中断
  __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_UPDATE);
  // 启动定时器, 默认开启的CC中断
  HAL_TIM_Encoder_Start_IT(&htim4, TIM_CHANNEL_ALL);

  HAL_Delay(100);
  // 清除干扰数据, CNT的值置0
  __HAL_TIM_SetCounter(&htim4, 0);
  // overflow_counter置0
  overflow_count = 0;
}
void Int_Encoder_Stop(void)
{
  HAL_TIM_Encoder_Stop_IT(&htim4, TIM_CHANNEL_ALL);
}
相关推荐
三佛科技-1341638421213 分钟前
FT32F072xx、FT32F072xB、FT32F072x6/x8基于ARM Cortex-M0内核32位单片机分析
arm开发·单片机·嵌入式硬件·智能家居·pcb工艺
清风66666613 分钟前
基于单片机的火焰与温度联动检测及声光灭火控制系统
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
chen_mangoo27 分钟前
Rockchip debian预置安装deb包
linux·驱动开发·嵌入式硬件
梁山1号31 分钟前
【关于CAN】
c语言·stm32·单片机
尼喃32 分钟前
汽车摩托车LED车灯驱动芯片IC,精准调光抗干扰,为车灯性能提升赋能
单片机·汽车·51单片机·芯片
金线银线还是铜线?1 小时前
BLE设备 MF9006 PMIC 能量协同设计 低功耗物联网供电方案
嵌入式硬件·物联网·射频工程·iot
yuanmenghao1 小时前
CAN系列 — (3) Radar Object List 在 MCU 内部是如何被拼装、校验并最终被消费的?
单片机·嵌入式硬件·自动驾驶·信息与通信
yuanmenghao1 小时前
CAN系列 — (4) Radar Header 报文:为什么它是 MCU 感知周期的“锚点”
网络·单片机·自动驾驶·信息与通信
飞睿科技1 小时前
乐鑫ESP32-S3-BOX-3,面向AIoT与边缘智能的新一代开发套件
人工智能·嵌入式硬件·esp32·智能家居·乐鑫科技
Y1rong1 小时前
STM32之SPI
stm32·单片机·嵌入式硬件