Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
/****************************************************************
Core header file for all the various RedBot functions.
There is additional license info below regarding the use of the
SoftwareSerial library from Arduino 1.0.5; I had good and sound
reasons for creating a derivative class rather than asking users
to simply use the existing library, which are documented below.
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.
****************************************************************/
#ifndef RedBot_h
#define RedBot_h
#include <Arduino.h>
// Pin aliases for the motor controller.
#define L_CTRL_1 2
#define L_CTRL_2 4
#define PWM_L 5
#define R_CTRL_1 7
#define R_CTRL_2 8
#define PWM_R 6
// PCINT functionality aliases. Each PCINT has a value set up when the
// class member gets created, and the PCINT service routine will handle
// the choosing the appropriate response to the interrupt.
#define NOT_IN_USE 0
#define WHISKER 1
#define LENCODER 2
#define RENCODER 3
#define SW_SERIAL 4
#define PCINT_A0 0
#define PCINT_A1 1
#define PCINT_A2 2
#define PCINT_A3 3
#define PCINT_A4 4
#define PCINT_A5 5
#define PCINT_3 6
#define PCINT_9 7
#define PCINT_10 8
#define PCINT_11 9
enum WHEEL {LEFT, RIGHT, BOTH}; // Variable for which wheel you're interested in
// when you do things in the encoder class.
// These three functions need to work from within multiple classes, so we keep
// them separate and add them as friend functions where appropriate.
void setPinChangeInterrupt(int pin, byte role); // The "role" of each pin is
// stored in an array which is accessed in the interrupt
// handler to determine what should be done on a falling edge
// PC interrupt.
void pinFunctionHandler(byte pinIndex); // This is the function which actually
// handles the legwork after the interrupt has identified
// which pin caught the interrupt.
void brake(void); // Globally accessible motor brake. I couldn't figure out how
// to set a function pointer to the RedBotMotors class
// function, and it's a small function, so I just made a
// global in the library.
void PC0Handler(byte PBTemp);
void PC1Handler(byte PCTemp);
void PC2Handler(byte PDTemp);
// This class handles motor functionality. I expect one instance of this at the
// start of a piece of RedBot code.
class RedBotMotors
{
public:
RedBotMotors(); // Constructor. Mainly sets up pins.
void drive(int speed); // Drive in direction given by sign, at speed given
// by magnitude of the parameter.
void drive(int speed, int duration); // drive(), but with a delay(duration)
void pivot(int speed); // Pivot more or less in place. Turns motors in
void pivot(int speed, int duration); // pivot() with a delay(duration)
void rightMotor(int speed); // Drive just the right motor. speed > 0 CW, speed < 0 CCW.
void leftMotor(int speed); // Drive just the left motor. speed > 0 CW, speed < 0 CCW.
void rightMotor(int speed, int duration); // Drive just the right motor. speed > 0 CW, speed < 0 CCW. delay(duration)
void leftMotor(int speed, int duration); // Drive just the left motor. speed > 0 CW, speed < 0 CCW. delay(duration)
void rightDrive(int speed); // Drive just the right motor. speed > 0 CW, speed < 0 CCW.
void leftDrive(int speed); // Drive just the left motor. speed > 0 CCW, speed < 0 CW.
void stop(); // Stop motors, but allow them to coast to a halt.
void coast(); // Stop motors, but allow them to coast to a halt.
void brake(); // Quick-stop the motors, shorting the leads.
void rightStop(); // Stop right motor, as with stop().
void leftStop(); // Stop left motor, as with stop().
void rightCoast(); // Stop right motor, as with stop().
void leftCoast(); // Stop left motor, as with stop().
void leftBrake(); // Quick-stop left motor, as with brake().
void rightBrake(); // Quick-stop right motor, as with brake().
private:
void leftFwd(byte speed); // These functions are pretty self-explanatory,
void leftRev(byte speed); // and are called by the above functions once
void rightFwd(byte speed);// sign has been used to determine direction.
void rightRev(byte speed);
};
// Handler for encoder sensors. Assume only one of this class is present.
// When a negative going edge happens on an encoder pin, a counter is
// incremented (or decremented), depending on the direction last determined
// by one of the motor direction commands.
class RedBotEncoder
{
// We declare a couple of friends, so they can have access to the private
// members of this class.
friend class RedBotMotors; // Needs access to lDir and rDir.
friend void pinFunctionHandler(byte pinIndex); // Called from within the
// ISRs, this function increments the counts
// by calling wheelTick().
public:
RedBotEncoder(int lPin, int rPin); // Constructor. Assigns pins, pin
// functions, zeroes counters, and adds a
// reference to the new encoder object for other
// library members to access.
void clearEnc(WHEEL wheel); // Zaps the encoder count for a given wheel (or
// for both wheels).
long getTicks(WHEEL wheel); // Returns the encoder count for a wheel.
private:
void wheelTick(WHEEL wheel); // Increment or decrement a wheel's counts,
// depending on which way the motor is turning.
long lCounts; // Holds the number of ticks for that wheel's
long rCounts; // encoder.
char lDir; // Direction is set by the motor class, according
char rDir; // to what the most recent motion direction for
// the given wheel was.
};
// This is a simple class to handle the button object on the robot. It has only one
// method, read(). This returns a boolean value for whether the button is pressed.
class RedBotButton
{
public:
RedBotButton(); // Constructor. Mainly sets up pins.
boolean read(); // Drive in direction given by sign, at speed given
};
// This is the reflectance sensor used for eg line following and table edge
// detection. It's pretty crude, but since they're analog sensors, they're
// kind of hard to work with.
class RedBotSensor
{
public:
RedBotSensor(int pin); // Configure a pin as a sensor.
int read(); // Return the current value of the pin.
boolean check(); // In theory, this will be true if a deviation from
// detectLevel is found; false otherwise.
int setBGLevel(); // You can calibrate the sensor to detect a deviation
int setDetectLevel(); // from detectLevel; these functions allow for that.
boolean calStatus(); // Have both calibrated levels been set yet?
private:
int _pin;
int _BGLevel;
int _detectLevel;
};
// This handles the physical wire-whisker type bumper.
class RedBotBumper
{
public:
RedBotBumper(int pin); // Simple constructor; when the bumper gets hit, the
// motors will stop.
RedBotBumper(int pin, void(*functionPointer)(void)); // If the user wishes
// to do something other than stop on a whisker,
// bump, they can write a function to do so, and
// use this constructor.
boolean read();
private:
int _pin;
void setBumpFunction(int pin, void(*functionPointer)(void));
};
// We have a bunch of stuff associated with the accelerometer here. We're going
// to implement our own I2C functions, too, to make things easy on ourselves.
#define XL_ADDR 0x1D // I2C address of the MMA8452Q accelerometer
#define I2C_READ 0x01 // I2C read bit set
// Some values we'll load into TWCR a lot
#define START_COND 0xA4 // (1<<TWINT) | (1<<TWSTA) | (1<<TWEN)
#define STOP_COND 0x94 // (1<<TWINT) | (1<<TWSTO) | (1<<TWEN)
#define CLEAR_TWINT 0x84 // (1<<TWINT) | (1<<TWEN)
#define NEXT_BYTE 0xC4 // (1<<TWINT) | (1<<TWEA) | (1<<TWEN)
class RedBotAccel
{
public:
RedBotAccel(); // Constructor...doesn't do much, since we re-configure
// the TWI registers on each send/receive.
void read(); // Puts the current readings of the accelerometer into
// the x, y, and z variables to be checked by user.
void enableBump(); // Put the accelerometer into a bump detection mode.
// Useful for tap-input to the robot.
boolean checkBump(); // Check to see if a tap has occurreed since the last
// time this function was called.
void setBumpThresh(int xThresh); // Adjust the threshold at which a bump
// is detected. Too low and motion will set it off, too
// high and it won't trigger when you want it to.
int x; // Rather than forcing users to grok pointers to read
int y; // the three axes, we just populate this variables and
int z; // let them be read as normal variables.
float angleXZ;
float angleXY;
float angleYZ;
private:
void xlWriteBytes(byte addr, byte *buffer, byte len); // addr is the
// memory location on the device to be written to; buffer
// and len are fairly self explanatory. Note that the
// address in the device auto-increments after each
// written, allowing consecutive registers to be written
// with only one command.
void xlReadBytes(byte addr, byte *buffer, byte len); // The same as the
// write command, but with reading. Same rules apply.
};
// This is lifted from the SoftwareSerial version that shipped with Arduino
// v1.0.5. I needed to rework that rather than use the existing SoftwareSerial
// library because I need to share the pin change ISRs with other classes in
// this library. Also, because I'm constraining the environment, I can make
// some optimizations to the code. I'm leaving in the full history, for
// citation's sake. People should know I didn't do all this.
/*
SoftwareSerial.h (formerly NewSoftSerial.h) -
Multi-instance software serial library for Arduino/Wiring
-- Interrupt-driven receive and other improvements by ladyada
(http://ladyada.net)
-- Tuning, circular buffer, derivation from class Print/Stream,
multi-instance support, porting to 8MHz processors,
various optimizations, PROGMEM delay tables, inverse logic and
direct port writing by Mikal Hart (http://www.arduiniana.org)
-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
The latest version of this library can always be found at
http://arduiniana.org.
*/
#include <inttypes.h>
#include <Stream.h>
/******************************************************************************
* Definitions
******************************************************************************/
#define _SS_MAX_RX_BUFF 64 // RX buffer size
#ifndef GCC_VERSION
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
class RedBotSoftwareSerial : public Stream
{
friend void pinFunctionHandler(byte pinIndex);
public:
// public methods
RedBotSoftwareSerial();
~RedBotSoftwareSerial();
void begin(long speed);
void end();
bool overflow() { bool ret = _buffer_overflow; _buffer_overflow = false; return ret; }
int peek();
virtual size_t write(uint8_t byte);
virtual int read();
virtual int available();
virtual void flush();
using Print::write;
private:
// per object data
uint8_t _receivePin;
uint8_t _receiveBitMask;
volatile uint8_t *_receivePortRegister;
uint8_t _transmitBitMask;
volatile uint8_t *_transmitPortRegister;
uint16_t _rx_delay_centering;
uint16_t _rx_delay_intrabit;
uint16_t _rx_delay_stopbit;
uint16_t _tx_delay;
uint16_t _buffer_overflow:1;
// static data
static char _receive_buffer[_SS_MAX_RX_BUFF];
static volatile uint8_t _receive_buffer_tail;
static volatile uint8_t _receive_buffer_head;
static RedBotSoftwareSerial *active_object;
// private methods
void recv();
uint8_t rx_pin_read();
void tx_pin_write(uint8_t pin_state);
void setTX(uint8_t transmitPin);
void setRX(uint8_t receivePin);
// private static method for timing
static inline void tunedDelay(uint16_t delay);
};
// We're going to create a special class now, to interface with the onboard
// XBee header. Since we've got the option of either software or hardware serial,
// I'm going to allow the user to choose between modes.
class RedBotRadio
{
public:
RedBotRadio(); // Constructor.
private:
};
#endif9a9ef921bThis file is pinned to the selected release. Download the original to open it in your design tool.