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.
-
Note: similar question to this one, but since the solution didn't work for me, I'm assuming it's not the same problem. Any help debugging it is also welcome (:Francisco Presencia– Francisco Presencia2014年08月06日 19:52:09 +00:00Commented Aug 6, 2014 at 19:52
-
Does the same setup work with the same pin when you test just the hip servo code outside of class? Does the problem only occur when the code is inside the Leg class?Omer– Omer2014年08月06日 21:03:49 +00:00Commented Aug 6, 2014 at 21:03
-
Your problem may be similar to this question: arduino.stackexchange.com/questions/830/…jfpoilpret– jfpoilpret2014年08月06日 22:12:02 +00:00Commented Aug 6, 2014 at 22:12
1 Answer 1
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 instanceservo_t servos[MAX_SERVOS];
,int8_t Channel[_Nbr_16timers ];
anduint8_t ServoCount = 0;
all defined inServo.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();
}
-
Just for clarification, the initialization order of global variables is not defined only between different translation units. In the same translation unit, it is the order of their definitions.Omer– Omer2014年08月07日 05:38:39 +00:00Commented Aug 7, 2014 at 5:38
-
+1 this is gold, the explanation just solved about 100% of the unresolved problems I've ever had with arduino and C++. Thank you, I'll test it when I get home.Francisco Presencia– Francisco Presencia2014年08月07日 06:11:01 +00:00Commented Aug 7, 2014 at 6:11
-
@Omer thanks for the clarification which I had forgotten to include. I have just edited my answer.jfpoilpret– jfpoilpret2014年08月07日 19:26:06 +00:00Commented Aug 7, 2014 at 19:26