1 /* 2 * Author: Jon Trulson <jtrulson@ics.com> 3 * Copyright (c) 2014 Intel Corporation. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 #pragma once 25 26 #include <stdint.h> 27 #include <sys/time.h> 28 #include <string> 29 #include <mraa/types.hpp> 30 #include <mraa/i2c.hpp> 31 32 #define GROVEMD_I2C_BUS 0 33 #define GROVEMD_DEFAULT_I2C_ADDR 0x0f 34 35 namespace upm { 36 /** 37 * @brief Grove I2C Motor Driver library 38 * @defgroup grovemd libupm-grovemd 39 * @ingroup seeed i2c motor robok 40 */ 41 42 /** 43 * @library grovemd 44 * @sensor grovemd 45 * @comname Grove I2C Motor Driver 46 * @type motor 47 * @man seeed 48 * @con i2c 49 * @kit robok 50 * 51 * @brief API for the Grove I2C Motor Driver 52 * 53 * This class implements support for the Grove I2C Motor Driver. 54 * This device can support a single 4-wire stepper motor, or two 55 * 2-wire DC motors. The device contains an Atmel* ATmega8L 56 * microcontroller that manages an L298N H-bridge driver chip. 57 * 58 * This device supports an I2C bus speed of 100Khz only. 59 * 60 * The module does not provide any telemetry or status - it only 61 * accepts I2C commands for its various operations. 62 * 63 * This module was tested with version 1.3 of the Grove I2C Motor 64 * Driver. 65 * 66 * For stepper operation, this driver can run in one of two modes - 67 * Mode 1, where this driver handles the stepping operation, and 68 * Mode 2, where this driver simply sends commands to the Grove 69 * Motor Driver, and it handles the stepping operation. Mode2 70 * requires updated (and working) firmware to be loaded onto the 71 * device. 72 * 73 * The default stepper operation mode is Mode1, which is generally 74 * more flexible and is supported on all firmware revisions. 75 * 76 * @image html grovemd.jpg 77 * An example showing the use of a DC motor 78 * @snippet grovemd.cxx Interesting 79 * An example showing the use of a 4-wire stepper 80 * @snippet grovemd-stepper.cxx Interesting 81 */ 82 class GroveMD { 83 84 public: 85 // GroveMD registers 86 typedef enum { SET_SPEED = 0x82, 87 SET_PWM_FREQ = 0x84, 88 SET_DIRECTION = 0xaa, 89 SET_MOTOR_A = 0xa1, // not documented 90 SET_MOTOR_B = 0xa5, // not documented 91 STEPPER_ENABLE = 0x1a, 92 STEPPER_DISABLE = 0x1b, 93 STEPPER_NUM_STEPS = 0x1c 94 } REG_T; 95 96 // legal directions for the stepper 97 typedef enum { STEP_DIR_CCW = 0x01, 98 STEP_DIR_CW = 0x00 99 } STEP_DIRECTION_T; 100 101 // legal directions for individual DC motors 102 typedef enum { DIR_CCW = 0x02, 103 DIR_CW = 0x01 104 } DC_DIRECTION_T; 105 106 // stepper modes 107 typedef enum { STEP_MODE1 = 0x00, 108 STEP_MODE2 = 0x01 109 } STEP_MODE_T; 110 111 /** 112 * GroveMD constructor 113 * 114 * @param bus I2C bus to use 115 * @param address I2C address to use 116 */ 117 GroveMD(int bus=GROVEMD_I2C_BUS, 118 uint8_t address=GROVEMD_DEFAULT_I2C_ADDR); 119 120 /** 121 * GroveMD destructor 122 */ 123 ~GroveMD(); 124 125 /** 126 * Composes and writes a 3-byte packet to the controller 127 * 128 * @param reg Register location 129 * @param data1 First byte of data 130 * @param data2 Second byte of data 131 * @return True if successful 132 */ 133 bool writePacket(REG_T reg, uint8_t data1, uint8_t data2); 134 135 /** 136 * To control DC motors, sets the speed of motors A & B. 137 * Valid values are 0-255. 138 * 139 * @param speedA Speed of motor A 140 * @param speedB Speed of motor B 141 * @return True if successful 142 */ 143 bool setMotorSpeeds(uint8_t speedA, uint8_t speedB); 144 145 /** 146 * To control DC motors, sets the PWM frequency prescale 147 * factor. Note: this register is not ducumented other than to say 148 * the default value is 0x03. Presumably, this is the timer 149 * prescale factor used on the ATMega MCU timer driving the PWM. 150 * 151 * @param freq PWM prescale frequency; default is 0x03 152 * @return True if successful 153 */ 154 bool setPWMFrequencyPrescale(uint8_t freq=0x03); 155 156 /** 157 * To control DC motors, sets the directions of motors A & B 158 * 159 * @param dirA Direction for motor A, DIR_CW or DIR_CCW 160 * @param dirB Direction for motor B, DIR_CW or DIR_CCW 161 * @return True if successful 162 */ 163 bool setMotorDirections(DC_DIRECTION_T dirA, DC_DIRECTION_T dirB); 164 165 /** 166 * To control a stepper motor, sets its direction and speed, and 167 * then starts operation. For Mode2, this method will return 168 * immediately. For Mode1 (the default) this method returns when 169 * the number of steps specified by setStepperSteps() has 170 * completed. 171 * 172 * @param dir Direction, STEP_DIR_CW or STEP_DIR_CCW 173 * @param speed Motor speed. Valid range is 1-255. For Mode 1 174 * (default), this specifies the speed in RPM's. For Mode 2, 175 * speed is multiplied by 4ms by the board, so higher numbers 176 * will mean a slower speed. 177 * @return True if successful 178 */ 179 bool enableStepper(STEP_DIRECTION_T dir, uint8_t speed); 180 181 /** 182 * To control a stepper motor, stops the stepper motor. 183 * 184 * @return True if successful 185 */ 186 bool disableStepper(); 187 188 /** 189 * To control a stepper motor, specifies the number of steps to 190 * execute. For Mode2, valid values are between 1-255, 255 means 191 * continuous rotation. 192 * 193 * For Mode1 (the default) steps can be any positive integer. 194 * 195 * @param steps Number of steps to execute. 255 (only in Mode2) 196 * means continuous rotation. 197 * @return True if successful 198 */ 199 bool setStepperSteps(unsigned int steps); 200 201 /** 202 * Configure the initial Stepper parameters. This should be 203 * called before any other stepper method. 204 * 205 * @param stepsPerRev The number of steps required to complete one 206 * full revolution. 207 * @param mode The stepper operating mode, default STEP_MODE1 208 * @return Elapsed milliseconds 209 */ 210 void configStepper(unsigned int stepsPerRev, STEP_MODE_T mode=STEP_MODE1); 211 212 protected: 213 mraa::I2c m_i2c; 214 uint8_t m_addr; 215 216 private: 217 // steps per revolution 218 int m_stepsPerRev; 219 int m_currentStep; 220 uint32_t m_stepDelay; 221 uint32_t m_totalSteps; 222 STEP_MODE_T m_stepMode; 223 224 /** 225 * Steps the motor one tick 226 * 227 */ 228 void stepperStep(); 229 230 // step direction: - 1 = forward, -1 = backward 231 int m_stepDirection; 232 233 // This is a NOOP value used to pad packets 234 static const uint8_t GROVEMD_NOOP = 0x01; 235 // our timer 236 struct timeval m_startTime; 237 238 /** 239 * Returns the number of milliseconds elapsed since initClock() 240 * was last called. 241 * 242 * @return Elapsed milliseconds 243 */ 244 uint32_t getMillis(); 245 246 /** 247 * Resets the clock 248 * 249 */ 250 void initClock(); 251 252 }; 253 } 254 255 256