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
diff -r 000000000000 -r 511d65ef1276 CRC7.cpp
--- /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);
+ }
+}
+
diff -r 000000000000 -r 511d65ef1276 CRC7.h
--- /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_ */
diff -r 000000000000 -r 511d65ef1276 PololuQik2.cpp
--- /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();
+}
diff -r 000000000000 -r 511d65ef1276 PololuQik2.h
--- /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_ */