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

一、引言

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

二、分析

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);
}
相关推荐
大神与小汪10 小时前
STM32WB55蓝牙广播数据
stm32·单片机·嵌入式硬件
Funing712 小时前
BUCK降压电路如何同时兼顾效率和纹波?——12V 转 3.3V 供电的工程解法
嵌入式硬件·电路·开关电源·buck降压
秋深枫叶红12 小时前
嵌入式第五十一篇——IMX6ULL中断和EPIT定时器
单片机·嵌入式硬件
【赫兹威客】浩哥12 小时前
【赫兹威客】Arduino安装教程
stm32·单片机·嵌入式硬件
flashier12 小时前
ESP32学习笔记_WiFi(3)——HTTP
网络·笔记·单片机·网络协议·学习·http·esp32
兆龙电子单片机设计12 小时前
【STM32项目开源】STM32单片机智能宠物管家
stm32·单片机·物联网·开源·毕业设计·宠物
阿呀呀呀13 小时前
ESP32复位电路分析
单片机·嵌入式硬件
华清远见IT开放实验室13 小时前
【课程升级】STM32U5体系化课程深度升级!全103集,覆盖裸机开发+TouchGFX图形界面+智能手表项目,从入门到实战!
stm32·单片机·嵌入式硬件·智能手表
一路往蓝-Anbo13 小时前
第 2 篇:单例模式 (Singleton) 与 懒汉式硬件初始化
开发语言·数据结构·stm32·单片机·嵌入式硬件·链表·单例模式
嵌入你的世界14 小时前
cmBacktrace 实现原理解析:从 HardFault 现场到源码回溯
stm32·单片机·嵌入式硬件·cmbacktrace