Go Down

Topic: Wierd Behavior when including Servo Class within my own Robot Class (Read 945 times) previous topic - next topic

mbackus

I'm putting together a very cheap differential drive robot using Parallax's continuous rotation servos. A pulse of 1500 keeps the servos still, a pulse of 1700 makes them rotate counter clockwise as fast as they can go, and a pulse of 1300 makes them rotate clockwise as fast as they can go. Because of the motors' orientation, I must provide the left one with a pulse of 1700 and the right with a pulse of 1300 to get the robot to drive forward. When I use the following code, the robot drives forward as expected:
Code: [Select]

#include "Servo.h"

Servo servoLeft;
Servo servoRight;

void setup()
{
  servoLeft.attach(13);
  servoRight.attach(12);
  servoLeft.writeMicroseconds(1700);
  servoRight.writeMicroseconds(1300);
  delay(1000);
}

void loop() {}


However, when I try to do the same thing with a library I wrote called BBBot (short for Bread Board Bot), the robot rotates instead of driving forward. I checked what was being written to the servos, and it was 1700 & 1300 as well.
Code: [Select]

#include "BBBot.h"
#include "Servo.h"

BBBot myBot(13,12);

void setup()
{
  myBot.forward(200);
}

void loop() {}


Here's the BBBot.h code:
Code: [Select]

#ifndef BBBot_h
#define BBBot_h

#include "Arduino.h"
#include "Servo.h"

class BBBot
{
  public:
    BBBot(byte leftMotorPin, byte rightMotorPin);
    void forward(int power);
  private:
    Servo servoLeft;
    Servo servoRight;
};

#endif


And here's the BBBot.cpp code:
Code: [Select]

#include "BBBot.h"

BBBot::BBBot(byte leftPin, byte rightPin)
{
  servoLeft.attach(leftPin);
  servoRight.attach(rightPin);
}

void BBBot::forward(int power)
{
  servoLeft.writeMicroseconds(1500 + power);
  servoRight.writeMicroseconds(1500 - power);
}


Not sure why, but I'm guessing it has something to do with timers getting messed up within the servo class. Any ideas?

Coding Badly


Do not access hardware from a constructor.  Create a begin method that does what your constructor does and call begin in setup.

mbackus

I did as you suggested and it's working now. I have a few questions though.

1) Why do I have to wait until setup in order to access hardware? Why can't I do so when creating objects in a constructor?

2) When my robot first starts, the left motor twitches 3 times-always the exact same twitch each time. Any way to get rid of this?

3) Last but not least, what would be the best way to not need to include the Servo library in my main sketch? Seems to me that if it's included in the .h file that should be good enough, but of course this causes an error. I've looked online and there are suggestions, but I can't get any of them to work.

My code as of now is as follows.

Main sketch:
Code: [Select]

#include "BBBot.h"
#include "Servo.h"

BBBot myBot;

void setup()
{
  myBot.begin(13,12);
  myBot.forward(200);
  delay(1000);
  myBot.stop();
}

void loop() {}


BBBot.h file:
Code: [Select]

#ifndef BBBot_h
#define BBBot_h

#include "Arduino.h"
#include "Servo.h"

class BBBot
{
  public:
    BBBot();
    void begin(byte leftPin, byte rightPin);
    void forward(int power);
    void stop();
  private:
    Servo servoLeft;
    Servo servoRight;
};

#endif


BBBot.cpp file:
Code: [Select]

#include "BBBot.h"

BBBot::BBBot()
{}

void BBBot::begin(byte leftPin, byte rightPin)
{
  servoLeft.attach(leftPin);
  servoRight.attach(rightPin);
}

void BBBot::forward(int power)
{
  servoLeft.writeMicroseconds(1500 + power);
  servoRight.writeMicroseconds(1500 - power);
}

void BBBot::stop()
{
  servoLeft.writeMicroseconds(1500);
  servoRight.writeMicroseconds(1500);
}

PaulS

Quote
1) Why do I have to wait until setup in order to access hardware? Why can't I do so when creating objects in a constructor?

The IDE creates a main() function, that calls init(), setup() (your function) and loop() (also your function).

The hardware initialization happens in the init() method. The main() function is called AFTER the constructors. Clearly, then, diddling with the hardware is useless before the init() method is called.

Quote
2) When my robot first starts, the left motor twitches 3 times-always the exact same twitch each time. Any way to get rid of this?

Set the position before you attach the servo.

Quote
3) Last but not least, what would be the best way to not need to include the Servo library in my main sketch? Seems to me that if it's included in the .h file that should be good enough, but of course this causes an error. I've looked online and there are suggestions, but I can't get any of them to work.

You can't. The IDE is designed to prevent you from hiding the use of a library from the sketch.

Well, maybe that is only a side effect of the way the IDE works, but only the cpp file that the IDE creates from the sketch is scanned for include files, and only those file, and associated source files, are copied to the build directory.

mbackus

I went ahead and changed the code as suggested. My BBBot.cpp file now looks as follows:

Code: [Select]

#include "BBBot.h"

BBBot::BBBot()
{}

void BBBot::begin(byte leftPin, byte rightPin)
{
  servoLeft.writeMicroseconds(1500);
  servoRight.writeMicroseconds(1500);
  servoLeft.attach(leftPin);
  servoRight.attach(rightPin);
}

void BBBot::forward(int power)
{
  servoLeft.writeMicroseconds(1500 + power);
  servoRight.writeMicroseconds(1500 - power);
}

void BBBot::stop()
{
  servoLeft.writeMicroseconds(1500);
  servoRight.writeMicroseconds(1500);
}


Unfortunately, I still see the glitch every single time I reset the robot and run the program again.

PaulS

What does your sketch look like? Specifically, where are you calling the begin() method?

mbackus

The main sketch and the BBBot.h files didn't change from my previous post (post #3).

mbackus

Found the problem!

Parallax documentation lists the following precaution:

LED connected to digital pin 13 after reset. Digital pin 13 also controls a servo if it's connected to port 13, so it may twitch in response to this on/off signal when the program restarts.

I switched to pins 10 & 11 and everything's working as it should (aside from the annoyance of having to include Servo.h in the main sketch).

Nick Gammon


(aside from the annoyance of having to include Servo.h in the main sketch).


That's documentation. ;)
http://www.gammon.com.au/electronics

PaulS

Quote
I went ahead and changed the code as suggested. My BBBot.cpp file now looks as follows:

which included adding a begin method.

So, I asked:
Quote
What does your sketch look like? Specifically, where are you calling the begin() method?


And you replied:
Quote
The main sketch and the BBBot.h files didn't change from my previous post (post #3).


So, I have to wonder why you are wasting our time here.

Go Up