Arduino 伺服对象在我自己的库中不起作用

Arduino servo object does not work within my own library

我已经为其他人写了一个库来慢慢地将伺服从一个位置扫到另一个位置。它没有像我预期的那样工作,我不得不从库中删除伺服对象。相反,我让新版本计算伺服位置并 return 这些值。但我真的很想知道为什么它不起作用。

包含私有 Servo 对象的头文件

#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() 运行s 和设置硬件之前。因此,当 init() 执行 运行 时,它可能会覆盖伺服库已写入定时器 1 的值。

这是一个常见问题,也是一个常见的新手陷阱。构造函数应该初始化变量并设置值和其他东西,但它们不是用于处理硬件的。为此,您需要一个可以从设置中调用的 begin() 或 init() 方法。想想伺服库如何具有您必须从设置中调用的附加功能。如果可以在构造函数中执行此操作,他们会让构造函数获取密码并执行此操作。想一想要使 Serial 工作必须调用的 begin 方法。这是同一个故事,需要设置硬件,您需要能够控制何时发生。

所以再做一个方法:

void ServoSweep::begin()  {
   servo.write( pos ) ;
   servo.attach( servoPin ) ;
}

并从每个对象的设置中调用它,并从构造函数中删除这些行。