Trouble with Objects

I am working on a robotics project for a class I am teaching. I want to use the Arduino with a robot base that we have access to. I am trying to write a library that the students can use so that they do not need to worry about the low level control of the motors and sensors on the robot ie. myRobot.driveForward(10) drives the robot forward at speed 10.

I have created a library for a single motor and have it working when I test it on its own. These motors are modified servo motors that can continually rotate 360 degrees. In testing I have found that if I send the motor 180 it spins at full speed in one direction, if I send 0 it spins at full speed in the other direction, and if I send it 93 the motor stops. The speed of rotation decreases in either direction the closer the number is to 93. This is why I’m using 93 as my pivot point or _stopPoint as I’ve named it in the code.

Motor.h:

#ifndef MOTOR_H
#define MOTOR_H
/*
This class represents a single motor on the BlueERS robot base.
 This class will allow the user to define where the motor is attached and to send signal to the motor.
 */
class Motor
{

  public:
    Motor(bool l);
    Motor();
    void Attach(int pin);
    void Detach();
    void driveMotor();
    void setMotorSpeed(int s);
    
  private:
    Servo _servo;              // the servo
    int _pos;              // current servo position
    bool _leftMotor;  //true if this is the left drive motor
    int _attachPin;  // pin where the motor is attached to the arduino
    bool _forward;   // when forward is true the motor moves forward in relation to the robot
    // when false the motor moves backwards.
    int _motorSpeed;  // speed can be a number between 0 and 90.  0 is full stop. 90 is full speed
    // in the direction defined by the boolean forward.
    static const int _stopPoint = 93;
};
#endif /* Motor class */

Motor.cpp:

#include "Motor.h"
#include <Servo.h>
#include "Arduino.h"


Motor::Motor(bool l)
{
  _leftMotor = l;
  _forward = true;  // default direction is forward.
  _motorSpeed = 0;  // default speed is full stop.
}

Motor::Motor(){
	_motorSpeed = 0;
}
void Motor::Attach(int pin)
{
  _servo.attach(pin);
}

void Motor::Detach()
{
  _servo.detach();
}

// Drive the motor
// -90 is full back
// 0 is full stop
// +90 is full forward
void Motor::driveMotor() {
  _pos = _stopPoint + _motorSpeed;
  _servo.write(_pos);  

  // REMOVE AFTER TESTING
  Serial.print("Pos = ");
  Serial.println(_pos);
}

// setMotorSpeed
// sets the speed variable of the motor to input if s is a valid value.
// -90 is full back
// 0 is full stop
// +90 is full forward
void Motor::setMotorSpeed(int s) {
  if (s >= -90 && s <= 90)
    _motorSpeed = s;
}

I have then started another object, BlueERS, in my main sketch that I will convert into a library once I have it working properly. BlueERS is the name of the robot chassis I am using.

Main Sketch:

#include <Servo.h>
#include <Motor.h>
/*
C. Whittington
 Oct. 2 2014
 */


/* BLUEERS CLASS
 TODO - Convert to library once fully debugged.
      - void driveForward()
      - void driveForward(int s)
      - void driveBackward()
      - void driveBackward(int s)
      - void turnRight(int time)
      - void turnLeft(int time)
      - void stopDrive()
      - int getDistance()
      - void setSpeed(int s)
*/

class BlueERS {
  public:
    BlueERS(int leftMotorPin, int rightMotorPin);
    void driveForward();
    void Update();
    //    void driveForward(int s);
    //    void driveBackwards();
    //    void driveBackwards(int s);
    //    void turnRight(int t);
    //    void turnLeft(int t);
    //    void stopDrive();
    //    int getDistance();
    void setRobotSpeed(int s);

  private:
    Motor _leftMotor = new Motor();
    Motor _rightMotor = new Motor();
    int _robotSpeed;
};

BlueERS::BlueERS(int leftMotorPin, int rightMotorPin) {
  _leftMotor.Attach(leftMotorPin);
 // _rightMotor.Attach(rightMotorPin);
  _robotSpeed = 0; // default speed is stopped.
  _leftMotor.setMotorSpeed(_robotSpeed);
 // _rightMotor.setMotorSpeed(_robotSpeed);
}
void BlueERS::driveForward() {
  _leftMotor.setMotorSpeed(_robotSpeed);
 // _rightMotor.setMotorSpeed(-_robotSpeed);
}
void BlueERS::setRobotSpeed(int s){
  _robotSpeed = s;
}
void BlueERS::Update(){
  _leftMotor.driveMotor();
  //_rightMotor.driveMotor();
}

//Motor leftMotor(true);
//Motor rightMotor(false);
const int switchPin = 3;
const int leftMotorPin = 9;
const int rightMotorPin = 8;
int robotSpeed;
BlueERS myRobot(leftMotorPin, rightMotorPin);

void setup()
{
  //leftMotor.Attach(leftMotorPin);
  //rightMotor.Attach(rightMotorPin);
  Serial.begin(9600);
  pinMode (switchPin, INPUT);
  myRobot.setRobotSpeed(0);
}


void loop()
{
  myRobot.driveForward();
  myRobot.Update();
// leftMotor.setMotorSpeed(0);
 //leftMotor.driveMotor();

}

The problem is that the Motors do not seem to be attaching properly. When I connect the BlueERS robot that I have named myRobot the motors spin even though I am sending it a 0 for speed. When I directly attach the motors using leftMotor and I send 0 to that motor the motor stops. I’m sure that I’m doing something stupid but I’m not sure what I’m missing. My guess is that I’m not using objects correctly in C++ or in Wire. I have a Java background so I understand objects but I’m not sure that I’m understanding the nuance of C++ or the Arduino platform. Any suggestions that you could give would be very helpful. My head is getting sore from bashing it against the wall :slight_smile:

When I connect the BlueERS robot that I have named myRobot the motors spin even though I am sending it a 0 for speed.

Why would you send 0 for the speed, and expect the motor to stop, when you KNOW that 93 means stop?

I am trying to make the control simpler to understand for my students. As it stands now if I send the instance of motor (ie. leftMotor) a speed of 0 it is converted to 93. In this way from the user's perspective motor rotation forward is 90, rotation backward is -90, and stop is 0. This way the user of the library need not know that the particular motor being used has a stop point of 93. This also means that if I ever change to different motors I only need to make some changes to the math in the Motor library for the new motors to behave in the same way as the old motors. This is all done in the following code from Motor.cpp in the driveMotor method:

_pos = _stopPoint + _motorSpeed;
_servo.write(_pos);

_stopPoint is a constant which is set to 93 in Motor.h. Therefore, if _motorSpeed is set to 0 then _pos which is sent to the motor is 93. If it is 90 the output to the motor is 183 (effectively the same as 180) or full forward. If it is -90 the output to the motor is 3 (effectively the same as 0) or full back.

I know that this is a bit messy but it cleans up what the end user is seeing.