A49888控制42步进电机

这里使用的是esp32,只要是能发生脉冲的单片机都可以。

拨码调整为123

EN->D25

STEP->D27

DIR->D26

控制代码这里是正反转90度,中间间隔一秒。(有一说一步进电机声音真好听qwq

// 1. 引脚定义(与硬件连接对应)
#define STEP_PIN    27  // 连接A4988的STEP引脚(脉冲信号)
#define DIR_PIN     26  // 连接A4988的DIR引脚(方向控制)
#define ENABLE_PIN  25  // 连接A4988的ENABLE引脚(使能控制,低电平有效)

// 2. 电机核心参数(根据42步进电机特性配置)
const int stepsPerRevolution = 200;  // 42步进电机默认参数:200步/圈(对应1.8°/步)
const int microsteps = 1;           // A4988细分设置(需与驱动器拨码一致:1/2/4/8/16)
const float stepsPerDegree = (stepsPerRevolution * microsteps) / 360.0;  // 每度所需步数(精确计算)

// 3. 运动优化参数(解决卡顿关键)
const long accelerationSteps = 50;  // 加速/减速阶段的步数(越大越平滑,建议50-100)
const int maxSpeed = 600;           // 电机最大速度(步/秒,42电机推荐500-700,过高易卡顿)
const int minSpeed = 100;           // 电机起始速度(步/秒,避免启动扭矩不足)

void setup() {
  // 初始化引脚模式
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(ENABLE_PIN, OUTPUT);

  // 初始化电机状态
  digitalWrite(ENABLE_PIN, LOW);    // 使能电机(A4988低电平有效,高电平电机锁死)
  digitalWrite(STEP_PIN, LOW);      // 复位STEP引脚电平,避免误触发
  digitalWrite(DIR_PIN, LOW);       // 复位方向引脚(初始方向可根据需求调整)

  // 初始化串口(用于调试,波特率115200)
  Serial.begin(115200);
  while (!Serial);  // 等待串口连接(电脑打开串口监视器后再继续,可选)
  Serial.println("=== 42步进电机控制启动 ===");

  // 4. 执行核心动作:正转90° → 等待1秒 → 反转90°
  smoothRotate(90);   // 正转90度(角度为正,方向可通过DIR_PIN电平调整)
  delay(1000);        // 中间暂停1秒,观察状态
  smoothRotate(-90);  // 反转90度(角度为负,回到初始位置)

  Serial.println("=== 动作执行完成 ===");
  // digitalWrite(ENABLE_PIN, HIGH);  // 可选:完成后禁用电机,降低功耗
}

void loop() {
  // 程序仅执行一次(setup中完成所有动作),如需循环,可将smoothRotate()移至此处
}

// 5. 带加减速的平滑转动函数(核心逻辑,解决卡顿)
// angle:目标转动角度(正=顺时针,负=逆时针)
void smoothRotate(int angle) {
  // 计算总步数(四舍五入确保角度精度)
  long totalSteps = round(abs(angle) * stepsPerDegree);
  if (totalSteps == 0) return;  // 角度为0时直接返回,避免无效操作

  // 设置转动方向
  digitalWrite(DIR_PIN, angle > 0 ? HIGH : LOW);
  Serial.printf("当前任务:转动%d°,需执行步数:%ld\n", angle, totalSteps);

  // 拆分运动阶段:加速 → 匀速 → 减速(避免速度突变导致卡顿)
  long accelerateSteps = min(accelerationSteps, totalSteps / 2);  // 加速步数(不超过总步数一半)
  long decelerateSteps = min(accelerationSteps, totalSteps - accelerateSteps);  // 减速步数
  long cruiseSteps = totalSteps - accelerateSteps - decelerateSteps;  // 匀速步数

  // 阶段1:加速(从minSpeed逐步提升到maxSpeed)
  for (long i = 0; i < accelerateSteps; i++) {
    int currentSpeed = calculateSpeed(i, accelerateSteps, true);
    stepWithSpeed(currentSpeed);
  }

  // 阶段2:匀速(保持maxSpeed,减少速度波动)
  if (cruiseSteps > 0) {
    int fixedDelay = 1000000 / maxSpeed;  // 匀速时固定延迟(微秒)
    for (long i = 0; i < cruiseSteps; i++) {
      stepWithFixedDelay(fixedDelay);
    }
  }

  // 阶段3:减速(从maxSpeed逐步降至minSpeed)
  for (long i = 0; i < decelerateSteps; i++) {
    int currentSpeed = calculateSpeed(i, decelerateSteps, false);
    stepWithSpeed(currentSpeed);
  }
}

// 6. 计算加减速阶段的实时速度
// step:当前阶段内的步数,totalStageSteps:当前阶段总步数,isAccelerate:true=加速,false=减速
int calculateSpeed(long step, long totalStageSteps, bool isAccelerate) {
  float speedRatio;
  if (isAccelerate) {
    speedRatio = (float)step / totalStageSteps;  // 加速时:比例从0→1
  } else {
    speedRatio = 1.0 - (float)step / totalStageSteps;  // 减速时:比例从1→0
  }
  // 计算当前速度(确保在minSpeed~maxSpeed范围内)
  int currentSpeed = minSpeed + (int)(speedRatio * (maxSpeed - minSpeed));
  return constrain(currentSpeed, minSpeed, maxSpeed);  // 防止速度超范围
}

// 7. 按指定速度走一步(动态调整延迟)
void stepWithSpeed(int speed) {
  if (speed <= 0) return;  // 速度无效时跳过
  int delayUs = 1000000 / speed;  // 速度→延迟(微秒)转换
  stepWithFixedDelay(delayUs);
}

// 8. 按固定延迟走一步(确保脉冲稳定)
void stepWithFixedDelay(int delayUs) {
  digitalWrite(STEP_PIN, HIGH);
  delayMicroseconds(delayUs / 2);  // 高电平时间(占空比50%,A4988接收更稳定)
  digitalWrite(STEP_PIN, LOW);
  delayMicroseconds(delayUs / 2);  // 低电平时间
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值