Arduino向Android发送初始锁状态异常致舵机故障求助
解决HC-06蓝牙连接时舵机失效的问题
看起来你遇到的核心问题是阻塞式循环占用了全部CPU资源,导致舵机无法得到足够的资源维持PWM信号。咱们一步步拆解和解决:
问题根源
你写的while(!blue.available()){ blue.println(pos); }是一个死循环——只要蓝牙模块没有数据传来,Arduino就会一直卡在这个循环里反复发送状态,完全没时间处理舵机的PWM更新(哪怕setup里已经设置了舵机位置,舵机也需要持续的信号来保持姿态,后续的操作也会被彻底阻塞)。同时,高频的串口发送也会干扰SoftwareSerial和Servo的定时器资源,让舵机彻底罢工。
修复方案
把阻塞的while改成非阻塞的if判断,这样每次loop循环都会检查一次蓝牙状态:如果没有数据,就发送一次初始状态,然后立刻继续执行后面的代码,不会卡住CPU。同时我们还要完善几个细节:
修改后的完整代码
#include <Servo.h> #include <SoftwareSerial.h> #include <EEPROM.h> char state; Servo myservo; int btx = 3; int brx = 2; SoftwareSerial blue(btx, brx); int pos = 0; void setup() { Serial.begin(9600); myservo.attach(9); blue.begin(9600); // 初始化EEPROM默认状态(第一次运行时,EEPROM值为0,默认设为锁定) int storedState = EEPROM.read(0); if (storedState == 1) { // 解锁状态 myservo.write(70); delay(200); pos = 1; } else if (storedState == 2) { // 锁定状态 myservo.write(180); delay(200); pos = 2; } else { // 默认锁定 myservo.write(180); delay(200); pos = 2; EEPROM.write(0, 2); EEPROM.commit(); // 确保数据写入EEPROM } // 连接后立即发送初始状态(加个短延时确保蓝牙连接稳定) delay(500); blue.println(pos); } void loop() { // 非阻塞式发送状态:如果蓝牙无数据,发送一次当前状态 if (!blue.available()) { blue.println(pos); // 加个短延时避免高频发送,减轻串口压力 delay(100); } String voice = ""; while (blue.available()) { delay(10); char c = blue.read(); if (c == '#') { break; } voice += c; } if (voice.length() > 0) { if (voice == "open") { myservo.write(70); pos = 1; EEPROM.write(0, 1); EEPROM.commit(); blue.println(1); delay(15); } else if (voice == "close") { myservo.write(180); pos = 2; EEPROM.write(0, 2); EEPROM.commit(); blue.println(2); delay(15); } } }
关键改动说明
- 移除阻塞循环:把
while(!blue.available())改成if(!blue.available()),这样每次loop只会发送一次状态,不会卡住CPU,舵机就能正常工作。 - 添加EEPROM默认处理:第一次运行时EEPROM值为0,我们默认设置为锁定状态,避免未知状态导致的异常。
- 确保EEPROM写入生效:每次
EEPROM.write后调用EEPROM.commit()(Arduino 1.6.6及以上版本支持),保证状态被真正保存到EEPROM。 - setup中提前发送初始状态:在setup里完成舵机初始化后,加个短延时再发送状态,确保蓝牙连接稳定后能收到初始值,不需要等loop循环。
- 降低发送频率:在非阻塞发送后加
delay(100),避免高频发送占用过多串口资源,减少和Servo的冲突。
额外注意事项
- 如果你的Arduino是Uno/Nano这类AVR板,SoftwareSerial和Servo可能存在定时器冲突(Servo用定时器1,SoftwareSerial用定时器0或2),如果还是有问题,可以试试用硬件串口(Serial)代替SoftwareSerial,或者更换舵机引脚到不冲突的定时器通道。
- 舵机的
delay(200)是为了让舵机完成转动,这个时间可以根据你的舵机实际转动速度调整。
内容的提问来源于stack exchange,提问作者MissPaper
相关产品推荐
相关产品推荐

