Loading files
b1065f773This file is pinned to the selected release. Download the original to open it in your design tool.
/****************************************************************
Main CPP for RedBot motor control.
This code is beerware; if you use it, please buy me (or any other
SparkFun employee) a cold beverage next time you run into one of
us at the local.
21 Jan 2014- Mike Hord, SparkFun Electronics
Code developed in Arduino 1.0.5, on an SparkFun Redbot v12.
****************************************************************/
#include "RedBot.h"
#include <Arduino.h>
extern RedBotEncoder *encoderObject; // Declared in RedBotEncoder.cpp
// Constructor. Mostly for pin setup; note that it's not necessary to configure
// PWM pins as they will be automatically configured with the analogWrite()
// function is called.
RedBotMotors::RedBotMotors()
{
// The interface to the motor driver is kind of ugly. It's three pins per
// channel: two that define role (forward, reverse, stop, brake) and one
// PWM input for speed.
pinMode(R_CTRL_1, OUTPUT);
pinMode(R_CTRL_2, OUTPUT);
pinMode(L_CTRL_1, OUTPUT);
pinMode(L_CTRL_2, OUTPUT);
}
// stop() allows the motors to coast to a stop, rather than trying to stop them
// quickly. As will be the case with functions affecting both motors, the
// global stop just calls the individual stop functions for each wheel.
void RedBotMotors::stop()
{
leftStop();
rightStop();
}
// coast() is the same as stop() -- but more descriptive of what this method does.
// it allows the motors to coast to a stop, rather than trying to stop them
// quickly. As will be the case with functions affecting both motors, the
// global stop just calls the individual stop functions for each wheel. This is
// exactly the same as the stop() method. stop() is retained for backwards compatibilty
void RedBotMotors::coast()
{
leftStop();
rightStop();
}
// brake() effectively shorts the two leads of the motor together, which causes
// the motor to resist being turned. It stops quite quickly.
void RedBotMotors::brake()
{
leftBrake();
rightBrake();
}
// drive() starts both motors. It figures out whether the motors should go
// forward or revers, then calls the appropriate individual functions. Note
// the use of a 16-bit integer for the speed input; an 8-bit integer doesn't
// have the range to reach full speed. The calls to the actual drive functions
// are only 8-bit, since we only have 8-bit PWM.
void RedBotMotors::drive(int speed)
{
if (speed > 0)
{
leftFwd((byte)(abs(speed)));
rightFwd((byte)(abs(speed)));
}
else
{
leftRev((byte)(abs(speed)));
rightRev((byte)(abs(speed)));
}
}
void RedBotMotors::drive(int speed, int duration)
{ // this variant of drive() integrates a delay duration to allow for single commmand instruction.
if (speed > 0)
{
leftFwd((byte)(abs(speed)));
rightFwd((byte)(abs(speed)));
}
else
{
leftRev((byte)(abs(speed)));
rightRev((byte)(abs(speed)));
}
delay(duration);
leftStop();
rightStop();
}
// pivot() is very much like drive(), except the motors are driven in opposite
// directions, so as to pivot the motor on it's central axis. Positive numbers
// turn / rotate the robot clockwise (to the right) -- assuming the motors are hooked up properly.
void RedBotMotors::pivot(int speed)
{
if (speed > 0)
{
leftFwd((byte)(abs(speed)));
rightRev((byte)(abs(speed)));
}
else
{
leftRev((byte)(abs(speed)));
rightFwd((byte)(abs(speed)));
}
}
void RedBotMotors::pivot(int speed, int duration)
{
if (speed > 0)
{
leftRev((byte)(abs(speed)));
rightFwd((byte)(abs(speed)));
}
else
{
leftFwd((byte)(abs(speed)));
rightRev((byte)(abs(speed)));
}
delay(duration);
leftStop();
rightStop();
}
// Basically the same as drive, but omitting the left motor.
void RedBotMotors::rightMotor(int speed)
{
if (speed > 0)
{
rightFwd((byte)(abs(speed)));
}
else
{
rightRev((byte)(abs(speed)));
}
}
void RedBotMotors::rightMotor(int speed, int duration)
{
if (speed > 0)
{
rightFwd((byte)(abs(speed)));
}
else
{
rightRev((byte)(abs(speed)));
}
delay(duration);
rightStop();
}
// Basically the same as drive(), but omitting the right motor.
void RedBotMotors::leftMotor(int speed)
{
if (speed > 0)
{
leftRev((byte)(abs(speed)));
}
else
{
leftFwd((byte)(abs(speed)));
}
}
void RedBotMotors::leftMotor(int speed, int duration)
{
if (speed > 0)
{
leftRev((byte)(abs(speed)));
}
else
{
leftFwd((byte)(abs(speed)));
}
delay(duration);
leftStop();
}
void RedBotMotors::rightDrive(int speed)
{
if (speed > 0)
{
rightFwd((byte)(abs(speed)));
}
else
{
rightRev((byte)(abs(speed)));
}
}void RedBotMotors::leftDrive(int speed)
{
if (speed > 0)
{
leftFwd((byte)(abs(speed)));
}
else
{
leftRev((byte)(abs(speed)));
}
}
// From here out, we deal with the nitty gritty details of telling the motor
// driver what to do. For more information about this, refer to the TB6612FNG
// datasheet.
void RedBotMotors::leftBrake()
{
digitalWrite(L_CTRL_1, HIGH);
digitalWrite(L_CTRL_2, HIGH);
analogWrite(PWM_L, 0);
}
void RedBotMotors::rightBrake()
{
digitalWrite(R_CTRL_1, HIGH);
digitalWrite(R_CTRL_2, HIGH);
analogWrite(PWM_R, 0);
}
void RedBotMotors::leftStop() // allows left motor to coast to a stop
{
digitalWrite(L_CTRL_1, LOW);
digitalWrite(L_CTRL_2, LOW);
analogWrite(PWM_L, 0);
}
void RedBotMotors::rightStop() // allows right motor to coast to a stop
{
digitalWrite(R_CTRL_1, LOW);
digitalWrite(R_CTRL_2, LOW);
analogWrite(PWM_R, 0);
}
void RedBotMotors::leftCoast() // same as rightStop()
{
digitalWrite(L_CTRL_1, LOW);
digitalWrite(L_CTRL_2, LOW);
analogWrite(PWM_L, 0);
}
void RedBotMotors::rightCoast() // same as leftStop()
{
digitalWrite(R_CTRL_1, LOW);
digitalWrite(R_CTRL_2, LOW);
analogWrite(PWM_R, 0);
}
/******************************************************************************
Private functions for RedBotMotor
******************************************************************************/
// These are the motor-driver level abstractions for turning a given motor the
// right direction. Users never see them, and *should* never see them, so we
// make them private.
void RedBotMotors::leftFwd(byte spd)
{
digitalWrite(L_CTRL_1, HIGH);
digitalWrite(L_CTRL_2, LOW);
analogWrite(PWM_L, spd);
// If we have an encoder in the system, we want to make sure that it counts
// in the right direction when ticks occur.
if (encoderObject != 0)
{
encoderObject->lDir = 1;
}
}
void RedBotMotors::leftRev(byte spd)
{
digitalWrite(L_CTRL_1, LOW);
digitalWrite(L_CTRL_2, HIGH);
analogWrite(PWM_L, spd);
// If we have an encoder in the system, we want to make sure that it counts
// in the right direction when ticks occur.
if (encoderObject != 0)
{
encoderObject->lDir = -1;
}
}
void RedBotMotors::rightFwd(byte spd)
{
digitalWrite(R_CTRL_1, HIGH);
digitalWrite(R_CTRL_2, LOW);
analogWrite(PWM_R, spd);
// If we have an encoder in the system, we want to make sure that it counts
// in the right direction when ticks occur.
if (encoderObject != 0)
{
encoderObject->rDir = 1;
}
}
void RedBotMotors::rightRev(byte spd)
{
digitalWrite(R_CTRL_1, LOW);
digitalWrite(R_CTRL_2, HIGH);
analogWrite(PWM_R, spd);
// If we have an encoder in the system, we want to make sure that it counts
// in the right direction when ticks occur.
if (encoderObject != 0)
{
encoderObject->rDir = -1;
}
}