Pololu Quk Motor Controller Driver
Revision 0:511d65ef1276, committed 2014-03-03
- Comitter:
- srsmitherman
- Date:
- Mon Mar 03 19:34:13 2014 +0000
- Commit message:
- Pololu Qik Motor Controller;
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CRC7.cpp Mon Mar 03 19:34:13 2014 +0000 @@ -0,0 +1,46 @@ +/** + * @file CRC7.cpp + * @author Edward Wilson (edwilson1989@gmail.com) + * @date Dec 16, 2010 + * @brief The CRC7 checksum code. + * + * + */ + +#include "CRC7.h" + +CRC7::CRC7() +{ + GenerateCRCTable(); + +} + +unsigned char CRC7::GetCRC(unsigned char val) +{ + int j; + for (j = 0; j < 8; j++) { + if (val & 1) + val ^= CRC7_POLY; + val >>= 1; + } + return val; +} + +unsigned char CRC7::CRC(unsigned char message[], unsigned int length) +{ + unsigned char i, crc = 0; + + for (i = 0; i < length; i++) + crc = CRCTable[crc ^ message[i]]; + return crc; +} + +void CRC7::GenerateCRCTable() +{ + int i; + // generate a table value for all 256 possible byte values + for (i = 0; i < 256; i++) { + CRCTable[i] = GetCRC(i); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CRC7.h Mon Mar 03 19:34:13 2014 +0000 @@ -0,0 +1,66 @@ +/** + * @file CRC7.h + * @author Edward Wilson (edwilson1989@gmail.com) + * @date Dec 16, 2010 + * @brief Cyclic Redundancy Check Class. This class computes a CRC7 of the provided data. + * + * + */ + +#ifndef CRC7_H_ +#define CRC7_H_ + +#define CRC7_POLY 0x91 /**< The Chosen Polynomial for CRC7. This is a standard value */ + + +/** + * This is a CRC7 implementation for checking validity of messages. It will compute + * a checksum which can be used to determine if a message has been recieved unaltered. + * This is used particularly over wireless tranmission or noisy serial lines. + * + * This implements a stored CRC table. This will taken up 256 bytes of RAM when the object + * is instantiated. The reason for using a stored CRC table is speed. This is a compromise + * between speed and storage spaces. + * + * This could possibly be static object. + */ +class CRC7 +{ +public: + /** + * Default constructor. This method sets up the CRC table with pre-hashed values. + */ + CRC7(); + /** + * this method will generate the CRC7 checksum for the supplied message. It will be returned + * from this method. + * + * @param message[] the message to be hashed. + * @param length the length of the message to be hashed in characters. + * @return the checksum computed. + */ + unsigned char CRC(unsigned char message[], unsigned int length); + +private: + /** + * Used to retrieve the value from the CRCTable. + * + * @see GenerateCRCTable() + * @param val the character which the hash is required for. + * @return the precomputed hash. + */ + unsigned char GetCRC(unsigned char val); + /** + * Generates the CRC table which is used for lookups during operation. + * This method is faster than having to compute the hash code each time + * however it comes at a cost of using up valuable RAM. + */ + void GenerateCRCTable(); + + /** + * The array of characters which stores the precomputed hash codes. + */ + unsigned char CRCTable[256]; +}; + +#endif /* CRC7_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PololuQik2.cpp Mon Mar 03 19:34:13 2014 +0000 @@ -0,0 +1,143 @@ +/** + * @file PololuQik2.cpp + * @author Edward Wilson (edwilson1989@gmail.com) + * @date Aug 6, 2010 + * @brief PololuQik2 motor drivers + */ + +/************************************************************* + PololuQik2 - basic class to control Pololu's Qik2s9v1 + motor controller (http://www.pololu.com/catalog/product/1110) + + This uses the default settings for the motor controller and the + Compact Protocol to communicate to it. + + 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 + + Author: Edward Wilson (edwilson1989@gmail.com) + History: + Version: 1.0 August 6, 2010 Initial code + 1.1 December 28, 2010 Composition constructor added + 1.3 April 22, 2011 Ported for MBED +************************************************************/ + +#include "PololuQik2.h" + +PololuQik2::PololuQik2(PinName TxPin, PinName RxPin, PinName RSTPin, PinName errPin, void (*ErrorFunction)(void), bool enCRC):CRC(), resetPin(RSTPin), errorPin(errPin), serialConnection(TxPin,RxPin) { + serialConnection.baud(38400); + enableCRC = enCRC; + errorPin.rise(ErrorFunction); +} + +void PololuQik2::begin() { + serialConnection.baud(38400); + wait_ms(100); // Allow Serial baud rate to propagate + resetPin = 0; + wait_ms(100); + resetPin = 1; + wait_ms(10); + unsigned char message[] = { INITIALPACKET }; + sendMessage(message, 1); + wait_ms(100); +} + +void PololuQik2::setMotor0Speed(int8_t speed) { + if (speed < 0) { + unsigned char message[] = {MOTOR0REVERSEPACKET, (-1*speed)}; + sendMessage(message , 2); + } else if (speed > 0) { + unsigned char message[] = {MOTOR0FORWARDPACKET, speed}; + sendMessage(message , 2); + } else { + unsigned char message[] = {MOTOR0REVERSEPACKET, 0}; + sendMessage(message , 2); + } +} + +void PololuQik2::setMotor1Speed(int8_t speed) { + if (speed < 0) { + unsigned char message[] = {MOTOR1REVERSEPACKET, (-1*speed)}; + sendMessage(message , 2); + } else if (speed > 0) { + unsigned char message[] = {MOTOR1FORWARDPACKET, speed}; + sendMessage(message , 2); + } else { + unsigned char message[] = {MOTOR1REVERSEPACKET, 0}; + sendMessage(message , 2); + } +} + +void PololuQik2::stopBothMotors() { + setMotor0Speed(0); + setMotor1Speed(0); +} + +void PololuQik2::sendMessage(unsigned char message[], uint8_t length) { + if (enableCRC) { + uint8_t chk = CRC.CRC(message, length); + for (int8_t i = 0; i < length; i++) + sendByte(message[i]); + + sendByte(chk); + } else { + for (int8_t i = 0; i < length; i++) + sendByte(message[i]); + } +} + +uint8_t PololuQik2::readByte() { + while (!serialConnection.readable()); + return serialConnection.getc(); +} + +void PololuQik2::sendByte(uint8_t byte) { + serialConnection.putc(byte); +} + +uint8_t PololuQik2::getFirmwareVersion() { + unsigned char message[] = { FWVERSIONPACKET }; + sendMessage(message, 1); + return readByte(); +} + +bool PololuQik2::hasCRCError() { + return errorBitSet(CRCERRORBIT); +} + +bool PololuQik2::errorBitSet(uint8_t bitToCheck) { + return (1 << bitToCheck) & errByte; +} + +bool PololuQik2::hasFrameError() { + return errorBitSet(FRAMEERRORBIT); +} + +bool PololuQik2::hasDataOverrunError() { + return errorBitSet(DATAOVERRUNERRORBIT); +} + +bool PololuQik2::hasFormatError() { + return errorBitSet(FORMATERRORBIT); +} + +bool PololuQik2::hasTimeoutError() { + return errorBitSet(TIMEOUTERRORBIT); +} + +uint8_t PololuQik2::getError() { + unsigned char message[] = { ERRORPACKET }; + sendMessage(message, 1); + return readByte(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PololuQik2.h Mon Mar 03 19:34:13 2014 +0000 @@ -0,0 +1,228 @@ +/** + * @file PololuQik2.h + * @author Edward Wilson (edwilson1989@gmail.com) + * @author Eric Fialkowski (eric.fialkowski@gmail.com) + * @date Aug 6, 2010 + * @brief PololuQik2 motor drivers. + * + * @details This class is a derivative work based on work of Mr Fialkowski. + * + * PololuQik2 - basic class to control Pololu's Qik2s9v1 + * motor controller (http://www.pololu.com/catalog/product/1110) + * + * This uses the default settings for the motor controller and the + * Compact Protocol to communicate to it. + * + * 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 + * + * @version 1.0 August 6, 2010 Initial code + * @version 1.2 December 28, 2010 Composition constructor added + * @version 1.3 April 22, 2011 Ported for MBED + */ + +#ifndef POLOLUQIK2_H_ +#define POLOLUQIK2_H_ + +#include "CRC7.h" +#include "mbed.h" +#include <inttypes.h> + +#define INITIALPACKET 0xAA /**< The packet used to initialise the motor controller*/ +#define MOTOR0FORWARDPACKET 0x88 /**< The packet used to set motor 0 forward */ +#define MOTOR1FORWARDPACKET 0x8C /**< The packet used to set motor 1 forward */ +#define MOTOR0REVERSEPACKET 0x8A /**< The packet used to set motor 0 in reverse */ +#define MOTOR1REVERSEPACKET 0x8E /**< The packet used to set motor 1 in reverse */ +#define MOTOR0COASTPACKET 0x86 /**< The packet used to all motor 0 to coast */ +#define MOTOR1COASTPACKET 0x87 /**< The packet used to all motor 1 to coast */ +#define FWVERSIONPACKET 0x81 /**< The packet to query the firmware version of the motor controller */ +#define ERRORPACKET 0x82 /**< The packet to request the error state from the motor controller */ + +#define DATAOVERRUNERRORBIT 3 /**< The bit which signifies a data over run error */ +#define FRAMEERRORBIT 4 /**< The bit which signifies a frame error */ +#define CRCERRORBIT 5 /**< The bit which signifies CRC error */ +#define FORMATERRORBIT 6 /**< The bit which signifies a format error */ +#define TIMEOUTERRORBIT 7 /**< The bit which signifies time out error */ + +/** + * This is the driver for the motor controller. This is to control a Qik2s9v1. + * It will not control multiple motor and it does not support daisy chaining motor controllers. + * + * The specification for the motor controller can be found http://www.pololu.com/catalog/product/1110/ + * + * This motor controller is based on the work of Mr Fialkowski. + * This motor controller requires the newSoftSerial library be installed on the build path. + * This motor controller also requires the CRC7 class. + * + * @see CRC7 + */ +class PololuQik2 { +public: + + /** + * The parameterised constructor for the pololuQik2 motor controller. + * + * @attention It is important to call the begin() method as this initialises the controller. + * @see begin() + * + * @param txPin the pin on the controller to use for transmitting serial bytes. + * @param rxPin the pin on the controller to use for recieving serial bytes. + * @param errPin the digital output pin to use to reset the motor controller. + * @param EnableCRC true if CRC should be used when communicating with the motor controller. + * @param reset the pin on the controller to use to reset the motor controller. + */ + PololuQik2::PololuQik2(PinName TxPin, PinName RxPin, PinName RSTPin, PinName errPin, void (*errorFunction)(void), bool enCRC); + + /** + * This method initialises and begins communication with the motor controller. + * This method is also called when an error is exhibited. + * + * @see PololuQik2() + */ + void begin(); + + /** + * sets the speed of motor 0. This command has superseded motor0Forwards and motor0Reverse. + * If the speed is less than 0 then the motor will reverse. + * If the speed is greater than 0 then the motor will run forward + * If the speed is 0 then the motor will be stopped. + * + * The bound for the speed are -127 to 127. + * @since 1.2 + * @param speed the speed of the motor. If this value is negative the motor will reverse to the + * appropriate speed. + */ + void setMotor0Speed(int8_t speed); + + /** + * sets the speed of motor 1. This command has superseded motor1Forwards and motor1Reverse. + * If the speed is less than 0 then the motor will reverse. + * If the speed is greater than 0 then the motor will run forward + * If the speed is 0 then the motor will be stopped. + * + * The bound for the speed are -127 to 127. + * @since 1.2 + * @param speed the speed of the motor. If this value is negative the motor will reverse to the + * appropriate speed. + */ + void setMotor1Speed(int8_t speed); + + /** + * instructs the motor controller to halt both motors. + * This is equivalent to called any of the forward or reverse methods + * with the speed as zero (0). + */ + void stopBothMotors(); + + /** + * retrieves the firmware version from the motor controller. This will return one of two values. + * Either the ASCII representation of 1 or the ASCII representation of 2. + * + * The return from this method will be either 49 or 50. If otherwise there is an error. + * + * @return the firmware version of the motor controller. + */ + uint8_t getFirmwareVersion(); + + /** + * Checks if the motor controller has a Data over run error + * + * returns true if it has a data over run error + */ + bool hasDataOverrunError(); + + /** + * Checks if the motor controller has a Frame error + * + * returns true if it has a Frame error + */ + bool hasFrameError(); + + /** + * Checks if the motor controller has a CRC error + * + * returns true if it has a CRC error + */ + bool hasCRCError(); + + /** + * Checks if the motor controller has a Format error + * + * returns true if it has a Format error + */ + bool hasFormatError(); + + /** + * Checks if the motor controller has a time out error + * + * returns true if it has a time out error + */ + bool hasTimeoutError(); + +private: + + void errorCall(); + + /** + * This actually sends the data to the motor controller. + * + * @param message[] the message to be sent + * @param length the length of the message to be sent + */ + void sendMessage(unsigned char message[], uint8_t length); + + /** + * Checks if a specific bit in the error byte is set. + * @param bitToCheck the bit number to check. Assume that the least significant bit is bit 1. + * @return true if the bit is set. + */ + bool errorBitSet(uint8_t bitToCheck); + + /** + * retrieves the error value from the motor controller and stores it in the + * class internal workings. + * + * @see errorBitSet() + * @see error() + */ + uint8_t getError(); + + /** + * sends a single byte to the motor controller + * + * @param byte the byte of data to send + */ + void sendByte(uint8_t byte); + + /** + * Reads a byte from the motor controller. This is a blocking call. + * If the motor controller is not sending anything then the program will + * halt indefinitely. + * + * @return the byte from the motor controller. + * @bug There is a suspected bug in this method. + */ + uint8_t readByte(); + + Serial serialConnection; /**< Serial connection to the motor controller */ + DigitalOut resetPin; /**< The digital output on the controller which is connected to the motor controllers reset pin. */ + InterruptIn errorPin; /**< The digital output on the controller which is connected to the motor controllers error pin. This must be an interrrupt pin on the controller */ + uint8_t errByte; /**< A temporary store for the error code received from the motor controller. */ + uint8_t firmwareVersion; /**< The motor controller firmware version */ + bool enableCRC; /**< this value will be true if CRCs are expected by the motor controller. */ + CRC7 CRC; /**< The CRC object used to generate the CRC checksums */ + +}; + +#endif /* POLOLUQIK2_H_ */