7

I'm trying to make a class work with Arduino, however it doesn't seem to trigger properly. The code is compiling perfectly, and it's supposed to control the leg of an hexapod. Also, the example sweep works on this servo, so no problem here. However, the servo is not actually moving. I'm thinking it has something to do with the order of declaring the variables:

#include <Servo.h>

// Abstract each leg, so only those functions can be accessed
class Leg {
  // Actions that can be triggered from outside
  public:
    Leg(int hipPin, int kneePin);
    void up();

  // These should be only available for the leg
  private:
    Servo hip;
    Servo knee;
  };

Leg::Leg(int hipPin, int kneePin) {
  hip.attach(hipPin);
  knee.attach(kneePin);
  }

// Testing the leg: move it up
void Leg::up() {
  for(int pos = 0; pos < 180; pos += 1) {
    hip.write(pos);
    delay(15);
    }
  }


// Initialize the leg
Leg topLeft(9, 10);

void setup() {
  }

// Test the function up()
void loop() {
  topLeft.up();
  }

I'm testing only the pin 9 (leaving the 10 empty). It seems in pain, meaning, you can see the servo trembling but not moving really at 0 degrees.

1 Answers1

5

It looks this problem may be due to bad order of initializers calls for global variables.

In C++, the order of global variable initialization is unpredictable across different compilation units (i.e. C++ source files, not header files). Initialization order is only respected inside one compilation unit.

In your program, there are several global variables that, if initialized in the wrong order, will fail your program:

  • Leg topLeft; this is your class instance
  • servo_t servos[MAX_SERVOS];, int8_t Channel[_Nbr_16timers ]; and uint8_t ServoCount = 0; all defined in Servo.cpp

Calling Servo.attach() requires that the 3 variables above have already been initialized, which you cannot be sure of.

How can you fix that?

By not performing the attach() in Leg constructor but delegating it to some kind of init() method that you can call from setup():

class Leg {
    // Actions that can be triggered from outside
    public:
    void init(int hipPin, int kneePin);
    void up();

    // These should be only available for the leg
    private:
    Servo hip;
    Servo knee;
};

Leg::init(int hipPin, int kneePin) {
    hip.attach(hipPin);
    knee.attach(kneePin);
}

// Testing the leg: move it up
void Leg::up() {
    for(int pos = 0; pos < 180; pos += 1) {
        hip.write(pos);
        delay(15);
    }
}

// Declare the leg
Leg topLeft;

void setup() {
    // Initialize the leg
    topLeft.init(9, 10);
}

// Test the function up()
void loop() {
    topLeft.up();
}
jfpoilpret
  • 9,162
  • 7
  • 38
  • 54