
这里使用的是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); // 低电平时间
}

1761

被折叠的 条评论
为什么被折叠?



