使用封装与继承控制Arduino舵机时舵机不工作问题排查
故障原因确认
你遇到的故障确实是全局实例化Base类的初始化时机异常导致的,核心原理如下:
- Arduino程序的执行顺序为:先运行所有全局对象的构造函数,之后才会完成硬件底层初始化(包括PWM定时器、串口等外设的配置),最后才进入
setup()函数 - 你在全局作用域实例化
Base base(SERVO_BASE)时,父类ServoPart的构造函数会立刻调用servo.attach()绑定引脚,但此时Arduino的PWM定时器还未完成初始化,attach()操作实际没有生效 Servo类的read()方法本身不会读取舵机的实际位置,只是返回类内部存储的上次写入的角度值,所以你调用setAngle()后getPosition()能返回正常数值,但对应的PWM信号根本没有输出到引脚,舵机自然不会转动- 你直接在main.cpp中创建Servo对象并调用write能正常运行,是因为你把这个Servo对象的创建放在了setup函数内部,避开了全局初始化的时机问题,attach操作执行时硬件已经就绪。
修复方案
有两种常用的修复方式:
方案1:把attach操作延后到init方法中调用
修改ServoPart类的结构,把构造函数里的attach逻辑剥离到单独的初始化方法里,在setup()中手动调用:servoPart.h修改后代码:
#include <Servo.h> #ifndef SERVO_PART_H #define SERVO_PART_H class ServoPart { protected: virtual void doJob() = 0; private: Servo servo; int _pin; int _minPWM; int _maxPWM; public: // 构造函数仅存储参数,不执行attach ServoPart(int pin, int minPWM, int maxPWM): _pin(pin), _minPWM(minPWM), _maxPWM(maxPWM) {}; // 新增初始化方法,在setup中调用 void init() { servo.attach(_pin, _minPWM, _maxPWM); } void setAngle(int angle) { servo.write(angle); }; int getPosition() { return servo.read(); }; }; #endif
main.cpp修改后代码:
#include <Arduino.h> #include "base.h" #define SERVO_BASE 9 Base base(SERVO_BASE); void setup() { Serial.begin(9600); base.init(); // 手动执行初始化,此时硬件已完成配置 delay(500); base.setAngle(80); Serial.println(base.getPosition()); delay(500); base.setAngle(110); Serial.println(base.getPosition()); } void loop() { }
方案2:使用指针延迟实例化
全局只声明Base类的指针,在setup()中再动态创建对象,保证构造函数执行时硬件已经初始化完成:main.cpp修改后代码:
#include <Arduino.h> #include "base.h" #define SERVO_BASE 9 Base* base; // 仅声明指针,不实例化 void setup() { Serial.begin(9600); base = new Base(SERVO_BASE); // 此时才执行构造函数调用attach,硬件已就绪 delay(500); base->setAngle(80); Serial.println(base->getPosition()); delay(500); base->setAngle(110); Serial.println(base->getPosition()); } void loop() { }
内容的提问来源于stack exchange,提问作者matthesinator
相关产品推荐
相关产品推荐

