如何修改代码实现机器人电机速度渐变,解决转向不一致问题
机器人电机速度渐变与转向一致性问题修复建议
问题说明
需要实现机器人移动时电机速度渐变(先慢后快再慢),现有逻辑:
- 超声波传感器检测距离≥16cm时,机器人前进约15cm后右转
- 检测距离≤15cm时,机器人左转
当前转向动作不一致,推测由电机突然启停导致,尝试用for循环实现速度渐变但未生效,需修复代码。
初始代码
if (distance >= 16) { motors.setLeftSpeed(100); motors.setRightSpeed(100); delay(1120); motors.setLeftSpeed(100); motors.setRightSpeed(-100); delay(1000); } digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = duration * 0.034 / 2; if (distance <= 15) { motors.setLeftSpeed(-100); motors.setRightSpeed(100); delay(900); }
无效的修改代码
if (distance >= 16) { for (int speed = 200; speed >= 0; speed--) { motors.setLeftSpeed(100); motors.setRightSpeed(100); delay(1120); motors.setLeftSpeed(100); motors.setRightSpeed(-100); delay(1000); } } if (distance <= 15) { for (int speed = 200; speed >= 0; speed--) { motors.setLeftSpeed(-100); motors.setRightSpeed(100); delay(900); } }
核心问题分析
- 无效修改的for循环未使用循环变量
speed,全程固定速度100执行完整动作,完全没实现渐变逻辑 - 原代码依赖
delay()阻塞程序,导致超声波检测不及时,且电机突然满速启停会产生机械冲击,引发转向误差
修复后的代码示例
// 定义速度参数,根据电机实际性能调整 const int MAX_SPEED = 100; const int ACCEL_STEP = 5; // 每次增速/减速的步长 const int ACCEL_DELAY = 20; // 每步速度变化的间隔(ms) // 前进动作:先加速→匀速→减速 void moveForwardGradually() { // 加速阶段 for (int speed = 0; speed <= MAX_SPEED; speed += ACCEL_STEP) { motors.setLeftSpeed(speed); motors.setRightSpeed(speed); delay(ACCEL_DELAY); } // 匀速前进(抵消渐变阶段的时间消耗,保证总前进距离与原逻辑一致) delay(1120 - (MAX_SPEED / ACCEL_STEP) * ACCEL_DELAY * 2); // 减速阶段 for (int speed = MAX_SPEED; speed >= 0; speed -= ACCEL_STEP) { motors.setLeftSpeed(speed); motors.setRightSpeed(speed); delay(ACCEL_DELAY); } motors.setLeftSpeed(0); motors.setRightSpeed(0); } // 右转动作:渐变启停 void turnRightGradually() { // 右转加速 for (int speed = 0; speed <= MAX_SPEED; speed += ACCEL_STEP) { motors.setLeftSpeed(speed); motors.setRightSpeed(-speed); delay(ACCEL_DELAY); } // 匀速右转(抵消渐变阶段的时间消耗,保证转向角度与原逻辑一致) delay(1000 - (MAX_SPEED / ACCEL_STEP) * ACCEL_DELAY * 2); // 右转减速 for (int speed = MAX_SPEED; speed >= 0; speed -= ACCEL_STEP) { motors.setLeftSpeed(speed); motors.setRightSpeed(-speed); delay(ACCEL_DELAY); } motors.setLeftSpeed(0); motors.setRightSpeed(0); } // 左转动作:渐变启停 void turnLeftGradually() { // 左转加速 for (int speed = 0; speed <= MAX_SPEED; speed += ACCEL_STEP) { motors.setLeftSpeed(-speed); motors.setRightSpeed(speed); delay(ACCEL_DELAY); } // 匀速左转(抵消渐变阶段的时间消耗,保证转向角度与原逻辑一致) delay(900 - (MAX_SPEED / ACCEL_STEP) * ACCEL_DELAY * 2); // 左转减速 for (int speed = MAX_SPEED; speed >= 0; speed -= ACCEL_STEP) { motors.setLeftSpeed(-speed); motors.setRightSpeed(speed); delay(ACCEL_DELAY); } motors.setLeftSpeed(0); motors.setRightSpeed(0); } // 主逻辑 void loop() { // 超声波检测 digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = duration * 0.034 / 2; if (distance >= 16) { moveForwardGradually(); turnRightGradually(); } else if (distance <= 15) { turnLeftGradually(); } }
关键说明
- 将动作拆分为独立函数,逻辑更清晰,便于调整参数
- 每个动作都实现了加速→匀速→减速的渐变过程,避免电机突然启停产生的机械冲击
- 调整了匀速阶段的
delay时长,抵消渐变阶段的时间消耗,保证总动作的距离/角度与原逻辑一致 - 超声波检测移到主循环最前端,确保每次动作前都能获取最新的距离数据
内容的提问来源于stack exchange,提问作者Elo
相关产品推荐
相关产品推荐

