我为其他人写了一个库,让他们慢慢地将伺服从一个位置扫到另一个位置。它并没有像我想要的那样工作,我不得不从库中删除伺服对象。相反,我让新版本计算伺服位置,并返回这些值。然而,我真的很想知道为什么它不起作用。
带有专用伺服对象的头文件
#include <Arduino.h>
#include <Servo.h>
class ServoSweep {
public:
ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed ) ; // constructor 1
ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed, byte _relayPin ) ; // constructor 2
void sweep( );
void setState( uint8_t _state );
private:
Servo servo ;
unsigned long timeToRun ;
byte pos ;
byte state ;
byte prevPos;
byte servoPin ;
byte servoSpeed ;
byte servoMin ;
byte servoMax ;
byte middlePosition ;
byte relayPresent ;
byte relayPin ;
} ;
和源文件:
#include "ServoSweep.h"
ServoSweep::ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed ) { // constructor 1
servoPin = _servoPin ;
servoSpeed = _speed ;
servoMin = _min ;
servoMax = _max ;
middlePosition = ( (long)servoMax - (long)servoMin ) / (long)2 + (long)servoMin ; // start with middle position
pos = middlePosition ;
servo.write( pos ) ;
servo.attach( servoPin ) ;
}
ServoSweep::ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed, byte _relayPin ) { // constructor 2
servoPin = _servoPin ;
servoSpeed = _speed ;
servoMin = _min ;
servoMax = _max ;
middlePosition = ( (long)servoMax - (long)servoMin ) / (long)2 + (long)servoMin ;
pos = middlePosition ;
servo.write( pos ) ;
servo.attach( servoPin ) ;
relayPresent = 1;
relayPin = _relayPin ;
pinMode( relayPin, OUTPUT ) ;
}
void ServoSweep::sweep () {
if( millis() > timeToRun ) {
timeToRun = millis() + servoSpeed ;
if( state ) {
if( pos < servoMax ) pos ++ ;
}
else {
if( pos > servoMin ) pos -- ;
}
if( prevPos != pos ) {
prevPos = pos ;
if( relayPresent == 1 ) {
if( pos < middlePosition ) digitalWrite( relayPin, LOW ) ;
else digitalWrite( relayPin, HIGH ) ;
}
servo.write( pos ) ;
}
}
}
void ServoSweep::setState( uint8_t _state ) {
state = _state ;
}
伺服信号是由arduino引起的完全抖动。我使用的示例草图:
#include "ServoSweep.h"
const int inputButton = 12 ;
const int servoPin1 = 2 ;
const int servoPin2 = 3 ;
unsigned long prev ;
byte state ;
// pin min max speed (bigger speed = slower movement ;
ServoSweep servo1(servoPin1, 10, 30, 50) ;
ServoSweep servo2(servoPin2, 10, 30, 50) ;
void setup() {
pinMode( inputButton, INPUT_PULLUP ) ;
}
void loop() {
servo1.sweep();
servo2.sweep();
if( digitalRead( inputButton ) ) servo1.setState( 1 ) ;
else servo1.setState( 0 ) ;
if( digitalRead( inputButton ) ) servo2.setState( 0 ) ;
else servo2.setState( 1 ) ;
}
即使我在循环中注释掉所有代码,抖动也存在。一旦构建ServoSweep对象,抖动就开始了。
伺服对象出了什么问题?我想这一定是可能的。
问题很可能出现在构造函数中。这些线路:
servo.write( pos ) ;
servo.attach( servoPin ) ;
在构造函数中,正在尝试使用可能尚未准备好的硬件。您正在全局范围内调用构造函数,因此这些事情可能会在init((运行和设置硬件之前发生。因此,当init((运行时,它可能会覆盖伺服库写入计时器1的值。
这是一个常见问题,也是一个常见的新手陷阱。构造函数应该初始化变量并设置值和东西,但它们不是用来处理硬件的。为此,您需要一个可以从安装程序调用的begin((或init((方法。想想伺服库是如何具有附加功能的,您必须从设置中调用该功能。如果可以在构造函数中做到这一点,他们会让构造函数获取引脚号并执行。想想你必须调用的begin方法才能使Serial工作。这是同样的故事,有硬件需要设置,你需要能够控制何时发生。
所以再做一个方法:
void ServoSweep::begin() {
servo.write( pos ) ;
servo.attach( servoPin ) ;
}
并从安装程序中为每个对象调用它,并从构造函数中删除这些行。