Pages: [1]   Go Down
Author Topic: Wierd Behavior when including Servo Class within my own Robot Class  (Read 715 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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:
#include "BBBot.h"
#include "Servo.h"

BBBot myBot(13,12);

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

void loop() {}

Here's the BBBot.h code:
Code:
#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:
#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?
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 176
Posts: 12283
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


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

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 549
Posts: 46111
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
#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.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 549
Posts: 46111
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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).
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

That's documentation. smiley-wink
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 549
Posts: 46111
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pages: [1]   Go Up
Jump to: