简体   繁体   English

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

[英]Arduino servo object does not work within my own library

I have written a libary for somebody else to slowly sweep servo's from one position to another.我已经为其他人编写了一个库,可以将伺服器从一个位置缓慢扫描到另一个位置。 It did not work like I intented and I had to remove the servo objects from the library.它不像我想要的那样工作,我不得不从库中删除伺服对象。 Instead I let the new version calculate the servo positions and return those values instead.相反,我让新版本计算伺服位置并返回这些值。 Yet I really like to know why it is not working.但我真的很想知道为什么它不起作用。

The header file with the private Servo objects带有私有伺服对象的头文件

#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 ;

} ;

And the source file:和源文件:

#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 ;
}

The servo signal was complete jitter caused by the arduino.伺服信号完全是由arduino引起的抖动。 The example sketch I used:我使用的示例草图:


#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 ) ;
 
}

Even I comment out al code inside the loop, the jitter is there.即使我注释掉循环内的所有代码,抖动仍然存在。 The jitter starts as soon as I construct the ServoSweep objects.一旦我构造了 ServoSweep 对象,抖动就会开始。

What did I wrong with the servo objects?我对伺服对象做错了什么? I assume this has to be possible.我认为这必须是可能的。

The problem is most likely in your constructor.问题很可能出在您的构造函数中。 These lines:这些线路:

servo.write( pos ) ;
servo.attach( servoPin ) ;

in the constructor are trying to work with hardware that may not be ready yet.在构造函数中尝试使用可能尚未准备好的硬件。 You are calling the constructor at global scope, so these things may be happening before init() runs and sets up the hardware.您正在全局范围内调用构造函数,因此这些事情可能会在 init() 运行和设置硬件之前发生。 So when init() does run, it is probably overwriting values that the servo library had written to timer 1.因此,当 init() 确实运行时,它可能会覆盖伺服库已写入计时器 1 的值。

This is a common issue and a common newbie trap.这是一个常见的问题,也是一个常见的新手陷阱。 Constructors should initialize variables and set up values and things, but they are not for handling hardware.构造函数应该初始化变量并设置值和事物,但它们不是用于处理硬件。 For that you need a begin() or init() method that you can call from setup.为此,您需要一个可以从设置调用的 begin() 或 init() 方法。 Think about how the servo library has the attach function that you have to call from setup.想想伺服库如何具有您必须从设置中调用的附加功能。 If it were possible to do that in the constructor, they would have had the constructor take the pin number and do it.如果可以在构造函数中做到这一点,他们会让构造函数获取 pin 号并执行。 Think about the begin method that you have to call for Serial to work.想想必须调用 Serial 才能工作的 begin 方法。 That's the same story, there's hardware to setup and you need to be able to control when that happens.这是同一个故事,需要设置硬件,您需要能够控制何时发生。

So make one more method:所以再做一个方法:

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

And call that from setup for each object and remove those lines from the constructor.并从每个对象的 setup 调用它并从构造函数中删除这些行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM