Pages: [1] 2   Go Down
Author Topic: Library for motor control  (Read 3794 times)
0 Members and 1 Guest are viewing this topic.
The Netherlands (Rotterdam)
Offline Offline
Full Member
***
Karma: 1
Posts: 169
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I have finally decided to make a separate library for controlling a motor. Now I've coded the control into a Arduino sketch but this is somewhat cumbersome... I have never written a library before so this is a big hurdle for me  :-[

The motors will be controlled using this motor carrier (http://www.pololu.com/catalog/product/713). It accept PWM values to set the speed and uses two digital inputs to determine the detection of the motor(s).

I will be creating a library that controls each motor separately.

I use this tutorial (http://www.arduino.cc/en/Hacking/LibraryTutorial) to make the library, but I think I'll need some help along the way.

First:

What software do you use to create the library? Currently I am using "Visual c++ Express Edition" but this is a very big software package with limited features.

I am looking for some software that will also "Check" the library (similar to the "verify" button in Arduino software, I am a beginning programmer....)? And some CTRL + T functionality to automatically format the code would also be great smiley

What software can you recommend me?

/me
« Last Edit: July 30, 2010, 02:51:52 pm by OpenSource » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46240
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What software do you use to create the library?
When developing the library, put the header and cpp files in the same directory as the sketch (the .pde file). When you open the sketch, each file in the same directory will be opened in a separate tab in the Arduino IDE.

When you verify the sketch, all the files in the directory are compiled, too.
Logged

The Netherlands (Rotterdam)
Offline Offline
Full Member
***
Karma: 1
Posts: 169
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi PaulS,

Thanks for the reply. This makes the development much easier smiley

A question:

Header file:
Code:
/*
      MotorControl.h Library for controlling a motor using PWM commands
       Created by OpenSource, July 30, 2010.
 */

#ifndef MotorControl_h
#define MotorControl_h

#include "WProgram.h"

class MotorControl
{
public:
  PinFwd(int pinFwd);

private:
  int _pinFwd;
};

#endif

Source file:
Code:
/*
      MotorControl.ccp Library for controlling a motor using PWM commands
       Created by OpenSource, July 30, 2010.
 */

#include "WProgram.h"
#include "MotorControl.h"

MotorControl::PinRev(int pinRev)
{
  pinMode(pinRev, OUTPUT);
  _pinRev = pinRev;
}


I get the error: MotorControl.h:14: error: ISO C++ forbids declaration of 'PinFwd' with no type

So there is a error in the header: PinFwd(int pinFwd); Why is this forbidden
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46240
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's not illegal to declare a function. It IS illegal to declare a function without a return type. If the function does not return a value, it's return type is void.
Logged

The Netherlands (Rotterdam)
Offline Offline
Full Member
***
Karma: 1
Posts: 169
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok,

I am confused.

According to this example it should work? http://www.arduino.cc/en/Hacking/LibraryTutorial

Header file:
Code:
/*
  Morse.h - Library for flashing Morse code.
  Created by David A. Mellis, November 2, 2007.
  Released into the public domain.
*/
#ifndef Morse_h
#define Morse_h

#include "WProgram.h"

class Morse
{
  public:
    Morse(int pin);
    void dot();
    void dash();
  private:
    int _pin;
};

#endif


I think part from the header file is similar to my example.

Code:
public:
    Morse(int pin);

Source file:
Code:
/*
  Morse.cpp - Library for flashing Morse code.
  Created by David A. Mellis, November 2, 2007.
  Released into the public domain.
*/

#include "WProgram.h"
#include "Morse.h"

Morse::Morse(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}

void Morse::dot()
{
  digitalWrite(_pin, HIGH);
  delay(250);
  digitalWrite(_pin, LOW);
  delay(250);  
}

void Morse::dash()
{
  digitalWrite(_pin, HIGH);
  delay(1000);
  digitalWrite(_pin, LOW);
  delay(250);
}

This is the part where the declaration is used:

Code:
Morse::Morse(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}

Is there something wrong in the example? I mean it is declared as a function but without a return type.

EDIT: I know that simply create a void solved the problem, but I just want to know what I an doing wrong....

Thanks in advance,

/me
« Last Edit: July 30, 2010, 04:41:04 pm by OpenSource » Logged

Phoenix, Arizona USA
Offline Offline
Faraday Member
**
Karma: 36
Posts: 5519
Where's the beer?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

When you declare a function with the same name as the class, that function is called the "constructor" - its return type is the object instantiated from the class.

You are declaring a completely different function named differently from the class; therefore it is not the constructor, and should have a declared return type.
Logged

I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

The Netherlands (Rotterdam)
Offline Offline
Full Member
***
Karma: 1
Posts: 169
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

Ok I have read the tutorial again and I get the function of the construct (and the difference between construct and function).

I think the library is almost finished. The funny thing is the "old" MotorControl code in my current sketch is approximately 4 times the code compared to the new library smiley

I would like to ask a forum member to review my library to see if the principle is good? I have placed comments in the header and source files on the places where I think there still is some optimization that has to be done.

Header file:
Code:
/*
    MotorControl.h Library for controlling a motor using PWM commands
 Created by OpenSource, July 30, 2010.
 Version 0.1
 
 This library is created to control a motor (or motors) using the "Pololu TB6612FNG Dual Motor Driver Carrier".
 This library let you define one motor and control certain parameters (multiple motors can be defined in a sketch).
 
 First the motor has to be defined. This is done using the following:
 
 MotorControl MotorLeft(5,6,7);
 
 In this case pin 5 and 6 are the pins to set the direction of the motor.
 -  If 5 = HIGH and 6 = LOW then the direction will be forward.
 -  If 6 = LOW and 6 = HIGH then the direction will be reverse.
 -  Pin 7 in this example is the PWM pin.
 
 The following parameters can be controlled after a motor has been defined:
 
 1. PwmWrite(int)
 This parameter let you write a PWM value (255 to -255) to the motor. PWM = 255 means full speed forward, PWM = -255 means full speed backwards and PWM = 0 means no speed.
 Normally PMW does not allow you to set negative value's, but this library does. It converts the negative value to a positive one using the asb() function. This value is used to write the PWM value (see code).
 
 2. PwmStepUp(int)
 -  This parameter let you speed up the motor in forward position.
 Example: If the PWM value is 20 anf PWmStepUp(20) is set the new PWM value will be: 20 + 20 = 40
 -  If the motor is in reverse it will slow down.
 Example: If the PWM value is -400 anf PWmStepUp(20) is set the new PWM value will be: -40 + 20 = -20
 
 3. PwmSetpDowm(int)
 -  This parameter let you speed up the motor in reverse position.
 -  If the motor is going forward it will slow down.
 
 4. PwmRead
 This parameter will let you read the currect PWM parameter.
 
 5. MotorDirection
 This parameter will let you read the currecnt direction of the motor
 - FWD = Forward
 - REV = Reverse
 - IDLE = Idle (PWM = 0)
 */

#ifndef MotorControl_h
#define MotorControl_h

#include "WProgram.h"

class MotorControl
{
public:
  MotorControl(int pinFwd,int pinRev,int pinPwm);

  void PwmWrite (int Pwm);
  void PwmStepUp (int PwmStepUp);
  void PwmStepDown (int PwmStepDown);

  //Is the usage of these char* data type correct? The problem is that the length changes (FWD, REV or IDLE). Any better suggestions?
  char* MotorDirection();
  char* Direction;
  char* _Direction;

  int PwmRead();

private:
  int _pinFwd;
  int _pinRev;
  int _pinPwm;
  int _Pwm;
  int _PwmStepUp;
  int _PwmStepDown;
};
#endif

Source file
Code:
#include "WProgram.h"
#include "MotorControl.h"

MotorControl::MotorControl(int pinFwd,int pinRev, int pinPwm)
{
  pinMode(pinFwd, OUTPUT);
  pinMode(pinRev, OUTPUT);
  _pinFwd = pinFwd;
  _pinRev = pinRev;
  _pinPwm = pinPwm;
}

void MotorControl::PwmWrite(int Pwm)
{
  _Pwm = Pwm;

  // Check if PWM value do not exceed the boundaries (-255 to 255). Better to use min, max or constrain?
  if (_Pwm > 255)
  {
    _Pwm = 255;
  }      
  else if (_Pwm < -255)
  {
    _Pwm = -255;
  }

  // Is the PWM value positive, if yes go forward.
  if (_Pwm <= 255 || _Pwm >= 1)
  {
    digitalWrite(_pinFwd, HIGH );
    digitalWrite(_pinRev, LOW);
    analogWrite (_pinFwd, _Pwm);
    _Direction = "FWD";
  }

  // Is the PWM value zero, if yes the motor is idle.
  else if (_Pwm == 0)
  {
    digitalWrite(_pinFwd, HIGH);
    digitalWrite(_pinRev, LOW);
    analogWrite (_pinFwd, _Pwm);
    _Direction = "IDLE";
  }

  // Is the PWM value negative, if yes go reverse.
  else if (_Pwm <= -255 || _Pwm >= -1)
  {
    digitalWrite(_pinFwd, LOW);
    digitalWrite(_pinRev, HIGH);
    analogWrite (_pinPwm, abs(_Pwm));
    _Direction = "REV";
  }
}

void MotorControl::PwmStepUp (int PwmStepUp)
{
  _PwmStepUp = PwmStepUp;

  _Pwm = _Pwm + _PwmStepUp;

  MotorControl::PwmWrite(_Pwm);
}

void MotorControl::PwmStepDown (int PwmStepDown)
{
  _PwmStepDown = PwmStepDown;

  _Pwm = _Pwm - _PwmStepDown;

  MotorControl::PwmWrite(_Pwm);
}

int MotorControl::PwmRead()
{
  int PwmReturn = _Pwm;
  return PwmReturn;
}

char* MotorControl::MotorDirection()
{
  _Direction = Direction;
  return Direction;
}

Thanks in advance,

/me
« Last Edit: July 30, 2010, 08:00:02 pm by OpenSource » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46240
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

One thing that I notice is that the range of valid values for PWM pins is 0 to 255, not -255 to 255.

In the PwmRead function, there is no reason to copy the member field, _Pwm into a local variable that you return. You can simply return _Pwm.

The same holds true for MotorDirection.

Why is there a member field called Direction and one called _Direction. This seems confusing. Direction could be stored simple as -1 for reverse, 0 for idle, and +1 for forward.

I don't see a way to set the motor direction. There is only a way to read it.
Logged

The Netherlands (Rotterdam)
Offline Offline
Full Member
***
Karma: 1
Posts: 169
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi PaulS,

Thanks for you useful advice.

Here is my updated version:

Header file:
Code:
/*
  MotorControl.h Library for controlling a motor using PWM commands
 Created by OpenSource, July 30, 2010.
 Version 0.2
 
 For a description of the library, check the MotorControl.ccp file.
 
 */

#ifndef MotorControl_h
#define MotorControl_h

#include "WProgram.h"

class MotorControl
{
public:
  MotorControl(int pinFwd,int pinRev,int pinPwm);

  void PwmWrite (int Pwm);
  void PwmStepUp (int PwmStepUp);
  void PwmStepDown (int PwmStepDown);

  //Is the usage of these char* datatype correct? The problem is that the legth changes (FWD, REV or IDLE). Any better suggestion?
  char* MotorDirection();
  char* _Direction;

  int PwmRead();

private:
  int _pinFwd;
  int _pinRev;
  int _pinPwm;
  int _Pwm;
  int _PwmStepUp;
  int _PwmStepDown;
  int _ConstrainPwm;
};
#endif

Source file:
Code:
/*
  MotorControl.h Library for controlling a motor using PWM commands
 Created by OpenSource, July 30, 2010.
 Version 0.2
 
 This library is created to control a motor (or motors) using the "Pololu TB6612FNG Dual Motor Driver Carrier" (or any other driver that uses the same principle).
 
 **Working principle of the motor driver:**
 
 The driver uses two digital pint to set the direction of the motor. DigitalWrite(_pinFwd, HIGH) and digitalWrite(_pinRev, LOW) will set the motor in forard direction.
 DigitalWrite(_pinFwd, LOW) and digitalWrite(_pinRev, HIGH) will set the motor in reverse direction.
 The driver uses one PWM pin to set the speed of the set direction.

 Something about the motor speed. The library accepts speed values from -255 to 255. -255 means full speed in reverse, 255 means full speed forward.
 The speed value is actually used to determine the direction where the car is going. Based on this direction the motor is set in foward or reverse.
 PWM does not accept negative values so the negitive speed values are converted to positive speed values using the abs() function AFTER the direction has been determined using the speed value.
 
**MotorControl properties:**

Create a instance of the MotorControl library:
 
 MotorControl MotorLeft(5,6,7);
 
 In this case pin 5 and 6 are the pins to set the direction of the motor.
 -  If 5 = HIGH and 6 = LOW then the direction will be forward.
 -  If 6 = LOW and 6 = HIGH then the direction will be reverse.
 -  Pin 7 in this example is the PWM pin.
 
 The following properties can be controlled after a motor instance has been created:
 
 1. PwmWrite(int)
 This parameter let you directly write a PWM value (255 to -255) to the motor. PWM = 255 means full speed forward, PWM = -255 means full speed backwards and PWM = 0 means no speed.
 Normally PMW does not allow you to set negative value's, but this library does. It converts the negative value to a positive one using the asb() function. This value is used to write the PWM value (see code).
 
 2. PwmStepUp(int)
 -  This parameter let you speed up the motor in forward position.
 Example: If the PWM value is 20 anf PWmStepUp(20) is set the new PWM value will be: 20 + 20 = 40
 -  If the motor is in reverse it will slow down.
 Example: If the PWM value is -400 anf PWmStepUp(20) is set the new PWM value will be: -40 + 20 = -20
 
 3. PwmSetpDowm(int)
 -  This parameter let you speed up the motor in reverse position.
 -  If the motor is going forward it will slow down.
 
 4. PwmRead
 This parameter will let you read the currect PWM parameter.
 
 5. MotorDirection
 This parameter will let you read the currecnt direction of the motor
 - FWD = Forward
 - REV = Reverse
 - IDLE = Idle (PWM = 0)
 */

#include "WProgram.h"
#include "MotorControl.h"

MotorControl::MotorControl(int pinFwd,int pinRev, int pinPwm)
{
  pinMode(pinFwd, OUTPUT);
  pinMode(pinRev, OUTPUT);
  _pinFwd = pinFwd;
  _pinRev = pinRev;
  _pinPwm = pinPwm;
}

void MotorControl::PwmWrite(int Pwm)
{
  _Pwm = Pwm;

  // Check if PWM value do not exceed the boundaries (-255 to 255).
  _Pwm = constrain(_Pwm, -255, 255);

  // Is the PWM value positive, if yes go forward.
  if (_Pwm <= 255 || _Pwm >= 1)
  {
    digitalWrite(_pinFwd, HIGH );
    digitalWrite(_pinRev, LOW);
    analogWrite (_pinFwd, _Pwm);
    _Direction = "FWD";
  }

  // Is the PWM value zero, if yes the motor is idle.
  else if (_Pwm == 0)
  {
    digitalWrite(_pinFwd, HIGH);
    digitalWrite(_pinRev, LOW);
    analogWrite (_pinFwd, _Pwm);
    _Direction = "IDLE";
  }

  // Is the PWM value negative, if yes go reverse.
  else if (_Pwm <= -255 || _Pwm >= -1)
  {
    digitalWrite(_pinFwd, LOW);
    digitalWrite(_pinRev, HIGH);
    analogWrite (_pinPwm, abs(_Pwm));
    _Direction = "REV";
  }
}

void MotorControl::PwmStepUp (int PwmStepUp)
{
  _PwmStepUp = PwmStepUp;

  _Pwm = _Pwm + _PwmStepUp;

  MotorControl::PwmWrite(_Pwm);
}

void MotorControl::PwmStepDown (int PwmStepDown)
{
  _PwmStepDown = PwmStepDown;

  _Pwm = _Pwm - _PwmStepDown;

  MotorControl::PwmWrite(_Pwm);
}

int MotorControl::PwmRead()
{
  return _Pwm;
}

char* MotorControl::MotorDirection()
{
  return _Direction;
}

About the speed value. I used a integer that is kept withing the range of -255 to 255 using the constrain function. This value is not the actual PWM value that is set. -255 is full speed in reverse and 255 is full speed forward.
The negative speed value is converted into a positive value using the abs() function.

There is no need to set the direction of the motor, this is done automatically by the library (see the code).

If the user wants to know the direction of the motor I think it is better to return a text instead of a value (from a users point of view).
If you want to know the direction and the speed you can print the direction and spreed value. So you would get something like:

Motor direction: FWD
Speed: 120

Instead of:

Motor direction: 1
Speed: 120

Cheers.
« Last Edit: July 31, 2010, 08:14:29 am by OpenSource » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46240
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you actually tested this class?

From MotorControl::PwmStepUp():
Code:
 MotorControl::PwmWrite(_Pwm);
Since PwmWrite is a member of the class, and PwmStepUp is called for an instance of the class, PwmWrite should be called for that same instance, either implicitly:
Code:
PwmWrite(_Pwm);
or explicitly:
Code:
this->PwmWrite(_Pwm);

The MotorControl::PwmWrite(_Pwm); would be used only if PwmWrite was a static method (which it is not).

Quote
-255 is full speed in reverse and 255 is full speed forward.
I missed that. However, you could use just a single character for direction (F, R, I), rather than FWD, REV, IDLE.

Read through your comments at the start of the cpp file. There are some typos that distract from the professional appearance of the code. Also, shorten the lines so that scrolling back and forth is not required. Please.

A couple more code corrections:
Code:
 if (_Pwm <= 255 || _Pwm >= 1)
This should be
Code:
 if (_Pwm <= 255 [glow]&&[/glow] _Pwm >= 1)
I'd also suggest swapping the order of the comparisons:
Code:
if(_Pwm >= 1 && _Pwm <= 255)
To me, this is more readable - if the value is greater than or equal to 1 and less than or equal to 255, do something.

Code:
 else if (_Pwm == 0)
This is correct. Stop if _Pwm is 0.

Code:
 else if (_Pwm <= -255 || _Pwm >= -1)
This is not, though. -400 is less than -255, but it is not a valid PWM value. The operator should be >=, noot <=.

The cases where _Pwm is greater than 0 have already been checked, so the second test is not required. If you want to keep it, the operator in the middle should be &&, as in the first if, and the operator between _Pwm and -1 should be <=.
Logged

The Netherlands (Rotterdam)
Offline Offline
Full Member
***
Karma: 1
Posts: 169
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi PaulS,

Thanks for your good advice once again smiley

I have modified the code a bit. The member names have been changed from "Pwm" to "Speed", this because speed values are used and not PWM values. I have spell checked the description, and changed your suggestions. I have also changed the MotorDirection names to F, I and R. This saves space (char instead of string).

I will test the code on my vehicle this afternoon. If it works,I will first think of some additional features and then upload it to the playground.

Header file:
Code:
/*
  MotorControl.h Library for controlling a motor using PWM commands
 Created by OpenSource, July 30, 2010.
 Version 0.2
 
 For a description of the library, check the MotorControl.ccp file.
 */

#ifndef MotorControl_h
#define MotorControl_h

#include "WProgram.h"

class MotorControl
{
public:
  MotorControl(int pinFwd,int pinRev,int pinPwm);

  void SpeedWrite(int Pwm);
  void SpeedStepUp(int PwmStepUp);
  void SpeedStepDown(int PwmStepDown);

  char MotorDirection();
  char _Direction;

  int SpeedRead();

private:
  int _pinFwd;
  int _pinRev;
  int _pinPwm;
  int _Pwm;
  int _PwmStepUp;
  int _PwmStepDown;
  int _ConstrainPwm;
};
#endif

Source file:
Code:
/*
**General:**
 This library is created to control a motor (or motors) using the "Pololu TB6612FNG Dual Motor Driver Carrier"
 This library can off course also be used for any other driver that uses the same principle.
 The library only controls one motor, but it is possible to create multiple instances of the MotorControl.
 
 Created by OpenSource, July 30, 2010.
 Version 0.3
 
 **Working principle of the motor driver:**
 The driver uses two digital pins to set the direction of one motor.
 DigitalWrite(_pinFwd, HIGH) and digitalWrite(_pinRev, LOW) will set the motor in forward direction.
 DigitalWrite(_pinFwd, LOW) and digitalWrite(_pinRev, HIGH) will set the motor in reverse direction.
 The driver uses one PWM pin to set the speed of the set direction for one motor.
 
 To summarize For one motor one instance of the library, two digital pins and one PWM pin is necessary.
 For the control of two motors, two instances of the library, 4 digital pins and2 PWM pins are necessary.
 
 **Create a MotorControl instance:**
 MotorControl MotorLeft(5,6,7);
 
 In this case pin 5 and 6 are the pins to set the direction of the motor (I used the Arduino Mega):
 -  If 5 = HIGH and 6 = LOW then the direction will be forward.
 -  If 6 = LOW and 6 = HIGH then the direction will be reverse.
 -  Pin 7 in this example is the PWM pin.
 
 **MotorControl members:**
 The MotorControl library consists of the following members::
 
 1. SpeedWrite(int);
 This parameter let you directly write a speed value (255 to -255) to the motor.
 Speed = 255 means full speed forward, Speed = -255 means full speed backwards and speed = 0 means no speed.
 
 The speed values are actually derived from PWM values but it is not allowed to set negative PWM value's.
 The speed values are converted into PWM values using the abs() function.
 This value is used to write the PWM value to the driver (see the SpeedWrite code on how this principle works).
 
 The SpeedWrite(int); member is used in the SpeedStepUp(int); and the SpeedStepDown(int); members.
 
 2. SpeedStepUp(int);
 -  This parameter let you step up the motor speed in forward position.
 Example: If the speed value is 20 and SpeedStepUp(20) is set the new speed value will be: 20 + 20 = 40
 -  If the motor is in reverse it will slow down.
 Example: If the speed value is -40 and SpeedStepUp(20) is set the new speed value will be: -40 + 20 = -20
 
 3. SpeedStepDown(int);
 -  This parameter let you speed up the motor in reverse position.
 -  If the motor is going forward it will slow down.
 
 4. SpeedRead();
 This parameter will let you read the current speed of the motor.
 
 5. MotorDirection();
 This parameter will let you read the current direction of the motor
 - F = Forward
 - R = Reverse
 - I = Idle (PWM/speed = 0)
 */

#include "WProgram.h"
#include "MotorControl.h"

MotorControl::MotorControl(int pinFwd,int pinRev, int pinPwm)
{
  pinMode(pinFwd, OUTPUT);
  pinMode(pinRev, OUTPUT);
  _pinFwd = pinFwd;
  _pinRev = pinRev;
  _pinPwm = pinPwm;
}

void MotorControl::SpeedWrite(int Pwm)
{
  _Pwm = Pwm;

  // Check if PWM value do not exceed the boundaries (-255 to 255).
  _Pwm = constrain(_Pwm, -255, 255);

  // Is the PWM value positive, if yes go forward.
  if (_Pwm >= 1 && _Pwm <= 255)
  {
    digitalWrite(_pinFwd, HIGH );
    digitalWrite(_pinRev, LOW);
    analogWrite (_pinFwd, _Pwm);
    _Direction = 'F';
  }

  // Is the PWM value zero, if yes the motor is idle.
  else if (_Pwm == 0)
  {
    digitalWrite(_pinFwd, HIGH);
    digitalWrite(_pinRev, LOW);
    analogWrite (_pinFwd, _Pwm);
    _Direction = 'I';
  }

  // Is the PWM value negative, if yes go reverse.
  else if (_Pwm >= -255 && _Pwm <= -1)
  {
    digitalWrite(_pinFwd, LOW);
    digitalWrite(_pinRev, HIGH);
    //Here the negative speed value is converted into a PWM value.
    analogWrite (_pinPwm, abs(_Pwm));
    _Direction = 'R';
  }
}

void MotorControl::SpeedStepUp(int PwmStepUp)
{
  _PwmStepUp = PwmStepUp;

  _Pwm = _Pwm + _PwmStepUp;

  this->SpeedWrite(_Pwm);
}

void MotorControl::SpeedStepDown(int PwmStepDown)
{
  _PwmStepDown = PwmStepDown;

  _Pwm = _Pwm - _PwmStepDown;

  this->SpeedWrite(_Pwm);
}

int MotorControl::SpeedRead()
{
  return _Pwm;
}

char MotorControl::MotorDirection()
{
  return _Direction;
}


Thanks,

/me
« Last Edit: August 01, 2010, 11:29:52 am by OpenSource » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46240
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks good. One final comment. In SpeedWrite(), you have this:
Code:
 else if (_Pwm >= -255 && _Pwm <= -1)
  {
    digitalWrite(_pinFwd, LOW);
    digitalWrite(_pinRev, HIGH);
    //Here the negative speed value is converted into a PWM value.
    analogWrite (_pinPwm, abs(_Pwm));
    _Direction = 'R';
  }
You already know that _Pwm is negative. The abs function is going to return the input value is the argument is positive or 0, and the input value times -1 if the input value is negative.

Save the overhead of a function call (time and memory) and simply use:
Code:
   analogWrite (_pinPwm, -_Pwm);
Logged

The Netherlands (Rotterdam)
Offline Offline
Full Member
***
Karma: 1
Posts: 169
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think this is the final version of the library smiley

If people think it is useful I will upload it to the playground.

I would like to thank PaulS for all the help, this is actually my first library.

Cheers.

Header file:

Code:
/*
  MotorControl.h Library for controlling a motor using PWM commands
 Created by OpenSource, July 30, 2010.
 Version 0.3
 
 For a description of the library, check the MotorControl.ccp file.
 */

#ifndef MotorControl_h
#define MotorControl_h

#include "WProgram.h"

class MotorControl
{
public:
  MotorControl(int pinFwd,int pinRev,int pinPwm);

  void SpeedWrite(int Speed);
  void SpeedStepUp(int PwmStepUp);
  void SpeedStepDown(int PwmStepDown);

  char Direction();
  char _Direction;

  int SpeedRead();

private:
  int _pinFwd;
  int _pinRev;
  int _pinPwm;
  int _Pwm;
  int _PwmStepUp;
  int _PwmStepDown;
  int _ConstrainPwm;
};
#endif

Cpp file:

Code:
/*
**General:**
 This library is created to control a motor (or motors) using the "Pololu TB6612FNG Dual Motor Driver Carrier"
 This library can off course also be used for any other driver that uses the same principle.
 The library only controls one motor, but it is possible to create multiple instances of the MotorControl.
 
 Created by OpenSource, July 30, 2010.
 Version 0.3
 
 **Working principle of the motor driver:**
 The driver uses two digital pins to set the direction of one motor.
 DigitalWrite(_pinFwd, HIGH) and digitalWrite(_pinRev, LOW) will set the motor in forward direction.
 DigitalWrite(_pinFwd, LOW) and digitalWrite(_pinRev, HIGH) will set the motor in reverse direction.
 The driver uses one PWM pin to set the speed of the set direction for one motor.
 
 To summarize: For one motor one instance of the library, two digital pins and one PWM pin is necessary.
 For the control of two motors, two instances of the library, 4 digital pins and 2 PWM pins are necessary.
 
 **Create a MotorControl instance:**
 MotorControl MotorLeft(5,6,7);
 
 In this case pin 5 and 6 are the pins to set the direction of the motor (I used the Arduino Mega):
 -  If 5 = HIGH and 6 = LOW then the direction will be forward.
 -  If 6 = LOW and 6 = HIGH then the direction will be reverse.
 -  Pin 7 in this example is the PWM pin.
 
 **MotorControl members:**
 The MotorControl library consists of the following members::
 
 1. SpeedWrite(int)
 This parameter let you directly write a speed value (255 to -255) to the motor.
 Speed = 255 means full speed forward, Speed = -255 means full speed backwards and speed = 0 means no speed.
 
 The speed values are actually derived from PWM values but it is not allowed to set negative PWM value's.
 The speed values are converted into PWM values.
 This value is used to write the PWM value to the driver (see the SpeedWrite code on how this principle works).
 
 The SpeedWrite(int) member is used in the SpeedStepUp(int) and the SpeedStepDown(int) members.
 
 2. SpeedStepUp(int)
 -  This parameter let you step up the motor speed in forward position.
 Example: If the speed value is 20 and SpeedStepUp(20) is set the new speed value will be: 20 + 20 = 40
 -  If the motor is in reverse it will slow down.
 Example: If the speed value is -40 and SpeedStepUp(20) is set the new speed value will be: -40 + 20 = -20
 
 3. SpeedStepDown(int)
 -  This parameter let you speed up the motor in reverse position.
 -  If the motor is going forward it will slow down.
 
 4. SpeedRead()
 This parameter will let you read the current speed of the motor.
 
 5. MotorDirection()
 This parameter will let you read the current direction of the motor
 - F = Forward
 - R = Reverse
 - I = Idle (PWM speed = 0)
 */

#include "WProgram.h"
#include "MotorControl.h"

MotorControl::MotorControl(int pinFwd,int pinRev, int pinPwm)
{
  pinMode(pinFwd, OUTPUT);
  pinMode(pinRev, OUTPUT);
  _pinFwd = pinFwd;
  _pinRev = pinRev;
  _pinPwm = pinPwm;
}

void MotorControl::SpeedWrite(int Pwm)
{
  _Pwm = Pwm;

  // Check if PWM value do not exceed the boundaries (-255 to 255).
  _Pwm = constrain(_Pwm, -255, 255);

  // Is the PWM value positive, if yes go forward.
  if (_Pwm >= 1 && _Pwm <= 255)
  {
    digitalWrite(_pinFwd, HIGH );
    digitalWrite(_pinRev, LOW);
    analogWrite (_pinFwd, _Pwm);
    _Direction = 'F';
  }

  // Is the PWM value zero, if yes the motor is idle.
  else if (_Pwm == 0)
  {
    digitalWrite(_pinFwd, HIGH);
    digitalWrite(_pinRev, LOW);
    analogWrite (_pinFwd, _Pwm);
    _Direction = 'I';
  }

  // Is the PWM value negative, if yes go reverse.
  else if (_Pwm >= -255 && _Pwm <= -1)
  {
    digitalWrite(_pinFwd, LOW);
    digitalWrite(_pinRev, HIGH);
    //Here the negative speed value is converted into a PWM value.
    analogWrite (_pinPwm, -_Pwm);
    _Direction = 'R';
  }
}

void MotorControl::SpeedStepUp(int PwmStepUp)
{
  _PwmStepUp = PwmStepUp;

  _Pwm = _Pwm + _PwmStepUp;

  this->SpeedWrite(_Pwm);
}

void MotorControl::SpeedStepDown(int PwmStepDown)
{
  _PwmStepDown = PwmStepDown;

  _Pwm = _Pwm - _PwmStepDown;

  this->SpeedWrite(_Pwm);
}

int MotorControl::SpeedRead()
{
  return _Pwm;
}

char MotorControl::Direction()
{
  return _Direction;
}

Usage in Arduino Project:
Code:

MotorControl MotorLeft(7,6,5);
MotorControl MotorRight(10,9,8);

void setup(){
MotorLeft.SpeedWrite(0);
MotorRight.SpeedWrite(0);
}

void loop(){

//Do other commands

}
« Last Edit: August 27, 2010, 12:17:30 pm by OpenSource » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for making this library!

I ordered a couple of these controllers, i'll give you submit feedback here.

Maybe you should consider uploading the lib to playground, it will increase visibility.

Cheers
Logged

The Netherlands (Rotterdam)
Offline Offline
Full Member
***
Karma: 1
Posts: 169
Arduino rocks!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

good to hear that you are trying the library. I've tried to keep it as simple as possible. I'll upload it to the playground asap. if you have a feature request please let me know.

cheers.
Logged

Pages: [1] 2   Go Up
Jump to: