Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
MD25.cpp
00001 /******************************************************************** 00002 * @filename MD25.cpp 00003 * @author Thomas B. Joergensen (thomas.bal.jorgensen@gmail.com) 00004 * @date 06 FEB 2012 00005 * @version 1.0 00006 * @target mbed (NXP LPC1768 - ARM Cortex M3 - 32-bit) 00007 * 00008 * @desciption A library for interacting with the MD25 DC motor 00009 * controller. Find more at: 00010 * http://www.robot-electronics.co.uk/htm/md25tech.htm 00011 * http://www.robot-electronics.co.uk/htm/md25i2c.htm 00012 *******************************************************************/ 00013 00014 /* Includes */ 00015 #include "MD25.h" 00016 00017 /*** CONSTRUCTOR AND DESTRUCTOR ***/ 00018 00019 MD25::MD25(I2C *i2c_interface, char i2c_address) { 00020 this->i2c_interface = i2c_interface; 00021 this->i2c_address = i2c_address; 00022 00023 /* Default values */ 00024 mode = 0; 00025 } 00026 00027 MD25::~MD25(void) {}; 00028 00029 /*** GENERIC METHODS ***/ 00030 00031 /** 00032 * Write a number of bytes. 00033 * 00034 * @param reg_addr Address of register to access. 00035 * @param data Pointer to where data is stored. 00036 * @param bytes Number of bytes to write. 00037 */ 00038 int MD25::write(char reg_addr, char *data, int bytes) { 00039 /* Variables */ 00040 char data_out[bytes + 1]; 00041 00042 /* Add register address to char array */ 00043 data_out[0] = reg_addr; 00044 00045 /* Populate data array */ 00046 for (int i = 1; i < bytes + 1; i++) { 00047 data_out[i] = data[i - 1]; 00048 } 00049 00050 /* Write address and data */ 00051 if (i2c_interface->write(i2c_address + I2C_WRITE_BIT, &data_out[0], bytes + 1, true)) { 00052 return -1; 00053 } 00054 00055 /* Return success */ 00056 return 0; 00057 } 00058 00059 /** 00060 * Read a number of bytes. 00061 * 00062 * @param reg_addr Address of register to access. 00063 * @param data Pointer to where data it to be stored. 00064 * @param bytes Number of bytes to read. 00065 */ 00066 int MD25::read(char reg_addr, char *data, int bytes) { 00067 /* Setup register to read */ 00068 if (!i2c_interface->write(i2c_address + I2C_WRITE_BIT, ®_addr, 1, true)) { 00069 /* Read register */ 00070 if (i2c_interface->read(i2c_address + I2C_READ_BIT, data, bytes, false)) { 00071 return -1; 00072 } 00073 } else { 00074 return -1; 00075 } 00076 00077 /* Return success */ 00078 return 0; 00079 } 00080 00081 /** 00082 * Discover I2C devices. 00083 * 00084 * @return char containing indicator of i2c device presence in form of bits 00085 * i.e. if LSB of returned char is 1 then a device is present at I2C_START_ADDR. 00086 * If bit 2 of char is 1 then a device is present at I2C_START_ADDR + 2. 00087 */ 00088 char MD25::doDiscover() { 00089 /* Initialize device char */ 00090 char device = 0; 00091 00092 /* Check for devices */ 00093 for (int i = 0; i < 8; i++) { 00094 if (!i2c_interface->write(I2C_START_ADDR + (2 * i), NULL, 0)) { // 0 returned is ok 00095 device |= (1<<i); 00096 } 00097 } 00098 00099 /* Return device char */ 00100 return device; 00101 } 00102 00103 /*** CONTROL METHODS ***/ 00104 00105 /** 00106 * Set mode of operation. 00107 * 00108 * @param mode Set mode of operation (0 - 3) (default: 0). 00109 */ 00110 int MD25::mode_set(int mode) { 00111 /* Check input is valid */ 00112 if (mode < 0 || mode > 3) return -1; 00113 00114 /* Variables */ 00115 char data = (char)mode; 00116 00117 /* Set mode */ 00118 if (write(REG_MODE, &data, 1) == -1) return -1; 00119 00120 /* Check set */ 00121 data = mode_get(); 00122 if (data != mode) return -1; 00123 00124 /* Set mode variable */ 00125 this->mode = mode; 00126 00127 /* Return success */ 00128 return 0; 00129 } 00130 00131 /** 00132 * Get mode of operation. 00133 */ 00134 int MD25::mode_get() { 00135 /* Variables */ 00136 char data; 00137 00138 /* Get mode */ 00139 if (read(REG_MODE, &data, 1) == -1) return -1; 00140 00141 /* Return mode */ 00142 return data; 00143 } 00144 00145 /** 00146 * Reset the encoder registers. 00147 */ 00148 int MD25::encoder_reset() { 00149 /* Variables */ 00150 char data = CMD_ENCODER_RESET; 00151 00152 /* Reset encoders */ 00153 if (write(REG_COMMAND, &data, 1) == -1) return -1; 00154 00155 /* Return success */ 00156 return 0; 00157 } 00158 00159 /** 00160 * Enable/disable automatic speed regulation (default: enabled). 00161 * 00162 * @param enabled enable = 1 | disable = 0. 00163 */ 00164 int MD25::auto_speed_set(bool enabled) { 00165 /* Variables */ 00166 char data; 00167 00168 /* Set data */ 00169 if (enabled) { 00170 data = CMD_AUTO_SPEED_ENABLE; 00171 } else { 00172 data = CMD_AUTO_SPEED_DISABLE; 00173 } 00174 00175 /* Reset encoders */ 00176 if (write(REG_COMMAND, &data, 1) == -1) return -1; 00177 00178 /* Return success */ 00179 return 0; 00180 } 00181 00182 /** 00183 * Enable/disable 2 sec timeout of motors when no I2C comms (default: enabled). 00184 * 00185 * @param enabled enable = 1 | disable = 0. 00186 */ 00187 int MD25::timeout_set(bool enabled) { 00188 /* Variables */ 00189 char data; 00190 00191 /* Set data */ 00192 if (enabled) { 00193 data = CMD_TIMEOUT_ENABLE; 00194 } else { 00195 data = CMD_TIMEOUT_DISABLE; 00196 } 00197 00198 /* Reset encoders */ 00199 if (write(REG_COMMAND, &data, 1) == -1) return -1; 00200 00201 /* Return success */ 00202 return 0; 00203 } 00204 00205 /** 00206 * Set a new I2C device address (Default: 0xB0). 00207 * 00208 * @param address Address of device (B0 -> BE; inc: 2). 00209 */ 00210 int MD25::i2c_addr_set(char address) { 00211 /* Check input is valid */ 00212 if (address < I2C_START_ADDR || address > I2C_START_ADDR + 0x0F) return -1; 00213 if (address % 2 == 1) return -1; 00214 00215 /* Set data */ 00216 char data[4]; 00217 data[0] = CMD_CHANGE_I2C_ADDR_1; 00218 data[1] = CMD_CHANGE_I2C_ADDR_2; 00219 data[2] = CMD_CHANGE_I2C_ADDR_3; 00220 data[3] = address; 00221 00222 /* Set new address */ 00223 if (write(REG_COMMAND, &data[0], 4) == -1) return -1; 00224 00225 /* Set address variable */ 00226 i2c_address = address; 00227 00228 /* Return success */ 00229 return 0; 00230 } 00231 00232 /*** DATA METHODS ***/ 00233 00234 /** 00235 * Set the speed of motor 1. (Only mode 0 or 1). 00236 * 00237 * @param speed Faster the higher a number (mode 0: 0 -> 255 | mode 1: -128 to 127). 00238 */ 00239 int MD25::speed1_set(int speed) { 00240 /* Check input is valid */ 00241 if (mode == 0) { 00242 if (speed < 0 || speed >255) return -1; 00243 } else if (mode == 1) { 00244 if (speed < -128 || speed > 127) return -1; 00245 } else { 00246 return 0; 00247 } 00248 00249 /* Variable */ 00250 char data = (char)speed; 00251 00252 /* Set data */ 00253 if (mode == 1) data = (signed char)data; 00254 00255 /* Set speed */ 00256 if (write(REG_SPEED1, &data, 1) == -1) return -1; 00257 00258 /* Return success */ 00259 return 0; 00260 } 00261 00262 /** 00263 * Get the set speed of motor 1. (Only mode 0 or 1). 00264 * 00265 * @return Faster the higher a number (mode 0: 0 -> 255 | mode 1: -128 to 127). 00266 */ 00267 int MD25::speed1_get() { 00268 /* Check valid mode */ 00269 if (mode < 0 || mode > 1) return -1; 00270 00271 /* Variables */ 00272 char data; 00273 00274 /* Get speed */ 00275 if (read(REG_SPEED1, &data, 1) == -1) return -1; 00276 00277 /* Return speed */ 00278 if (mode == 1) return (signed char)data; 00279 return data; 00280 } 00281 00282 /** 00283 * Set the speed of motor 2. (Only mode 0 or 1). 00284 * 00285 * @param speed Faster the higher a number (mode 0: 0 -> 255 | mode 1: -128 to 127). 00286 */ 00287 int MD25::speed2_set(int speed) { 00288 /* Check input is valid */ 00289 if (mode == 0) { 00290 if (speed < 0 || speed >255) return -1; 00291 } else if (mode == 1) { 00292 if (speed < -128 || speed > 127) return -1; 00293 } else { 00294 return 0; 00295 } 00296 00297 /* Variable */ 00298 char data = (char)speed; 00299 00300 /* Set data */ 00301 if (mode == 1) data = (signed char)data; 00302 00303 /* Set speed */ 00304 if (write(REG_SPEED2, &data, 1) == -1) return -1; 00305 00306 /* Return success */ 00307 return 0; 00308 } 00309 00310 /** 00311 * Get the set speed of motor 2. (Only mode 0 or 1). 00312 * 00313 * @return Faster the higher a number (mode 0: 0 -> 255 | mode 1: -128 to 127). 00314 */ 00315 int MD25::speed2_get() { 00316 /* Check valid mode */ 00317 if (mode < 0 || mode > 1) return -1; 00318 00319 /* Variables */ 00320 char data; 00321 00322 /* Get speed */ 00323 if (read(REG_SPEED2, &data, 1) == -1) return -1; 00324 00325 /* Return speed */ 00326 if (mode == 1) return (signed char)data; 00327 return data; 00328 } 00329 00330 /** 00331 * Set the speed. (Only mode 2 or 3). 00332 * 00333 * @param speed Faster the higher a number (mode 2: 0 -> 255 | mode 3: -128 to 127). 00334 */ 00335 int MD25::speed_set(int speed) { 00336 /* Check input is valid */ 00337 if (mode == 2) { 00338 if (speed < 0 || speed > 255) return -1; 00339 } else if (mode == 3) { 00340 if (speed < -128 || speed > 127) return -1; 00341 } else { 00342 return 0; 00343 } 00344 00345 /* Set data */ 00346 char data = (char)speed; 00347 00348 /* Set speed */ 00349 if (write(REG_SPEED1, &data, 1) == -1) return -1; 00350 00351 /* Return success */ 00352 return 0; 00353 } 00354 00355 /** 00356 * Get the set speed. (Only mode 2 or 3). 00357 * 00358 * @return Faster the higher a number (mode 2: 0 -> 255 | mode 3: -128 to 127). 00359 */ 00360 int MD25::speed_get() { 00361 /* Check valid mode */ 00362 if (mode < 2 || mode > 3) return -1; 00363 00364 /* Variables */ 00365 char data; 00366 00367 /* Get speed */ 00368 if (read(REG_SPEED1, &data, 1) == -1) return -1; 00369 00370 /* Return speed */ 00371 return data; 00372 } 00373 00374 /** 00375 * Set the turn. (Only mode 2 or 3). 00376 * 00377 * @param turn Faster the higher a number (mode 2: 0 -> 255 | mode 3: -128 to 127). 00378 */ 00379 int MD25::turn_set(int turn) { 00380 /* Check input is valid */ 00381 if (mode == 2) { 00382 if (turn < 0 || turn > 255) return -1; 00383 } else if (mode == 3) { 00384 if (turn < -128 || turn > 127) return -1; 00385 } else { 00386 return 0; 00387 } 00388 00389 /* Set data */ 00390 char data = (char)turn; 00391 00392 /* Set turn */ 00393 if (write(REG_SPEED2, &data, 1) == -1) return -1; 00394 00395 /* Return success */ 00396 return 0; 00397 } 00398 00399 /** 00400 * Get the set turn. (Only mode 2 or 3). 00401 * 00402 * @return Faster the higher a number (mode 2: 0 -> 255 | mode 3: -128 to 127). 00403 */ 00404 int MD25::turn_get() { 00405 /* Check valid mode */ 00406 if (mode < 2 || mode > 3) return -1; 00407 00408 /* Variables */ 00409 char data; 00410 00411 /* Get turn */ 00412 if (read(REG_SPEED2, &data, 1) == -1) return -1; 00413 00414 /* Return turn */ 00415 return data; 00416 } 00417 00418 /** 00419 * Set the desired acceleration rate. 00420 * 00421 * if new speed > current speed: 00422 * steps = (new speed - current speed) / acceleration register 00423 * if new speed < current speed: 00424 * steps = (current speed - new speed) / acceleration register 00425 * time = steps * 25ms 00426 * Example: 00427 * Time/step: 25ms | Current speed: 0 | New speed: 255 | Steps: 255 | Acceleration time: 6.375s. 00428 * @param acceleration Faster the higher a number (default: 5). 00429 */ 00430 int MD25::acceleration_set(int acceleration) { 00431 /* Check input is valid */ 00432 if (acceleration < 0 || acceleration > 255) return -1; 00433 00434 /* Set data */ 00435 char data = (char)acceleration; 00436 00437 /* Set acceleration */ 00438 if (write(REG_ACCELERATION_RATE, &data, 1) == -1) return -1; 00439 00440 /* Return success */ 00441 return 0; 00442 } 00443 00444 /** 00445 * Get the set desired acceleration rate. 00446 * 00447 * if new speed > current speed: 00448 * steps = (new speed - current speed) / acceleration register 00449 * if new speed < current speed: 00450 * steps = (current speed - new speed) / acceleration register 00451 * time = steps * 25ms 00452 * Example: 00453 * Time/step: 25ms | Current speed: 0 | New speed: 255 | Steps: 255 | Acceleration time: 6.375s. 00454 * @return Faster the higher a number (default: 5). 00455 */ 00456 int MD25::acceleration_get() { 00457 /* Variables */ 00458 char data; 00459 00460 /* Get acceleration */ 00461 if (read(REG_ACCELERATION_RATE, &data, 1) == -1) return -1; 00462 00463 /* Return acceleration */ 00464 return data; 00465 } 00466 00467 /** 00468 * Get encoder 1 position. 00469 */ 00470 int MD25::encoder1_get() { 00471 /* Variables */ 00472 char data[4]; 00473 int position; 00474 00475 /* Get encoder bytes */ 00476 if (read(REG_ENC1A, &data[0], 4) == -1) return -1; 00477 00478 /* Combine the position bytes */ 00479 position = (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | data[3]; 00480 00481 /* Return position */ 00482 return position; 00483 } 00484 00485 /** 00486 * Get encoder 2 position. 00487 */ 00488 int MD25::encoder2_get() { 00489 /* Variables */ 00490 char data[4]; 00491 int position; 00492 00493 /* Get encoder bytes */ 00494 if (read(REG_ENC2A, &data[0], 4) == -1) return -1; 00495 00496 /* Combine the position bytes */ 00497 position = (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | data[3]; 00498 00499 /* Return position */ 00500 return position; 00501 } 00502 00503 /** 00504 * Get battery voltage. 00505 * It reads 10 times the voltage i.e. 121 for 12.1V. 00506 * 00507 * @return Normalized float. 00508 */ 00509 float MD25::bat_voltage_get() { 00510 /* Variables */ 00511 char data; 00512 00513 /* Get battery voltages */ 00514 if (read(REG_BATTERY_VOLTS, &data, 1) == -1) return -1; 00515 00516 /* Return battery voltage */ 00517 return (float)(data / 10.0); 00518 } 00519 00520 /** 00521 * Get current of motor 1. 00522 * It reads 10 times the current i.e. 25 for 2.5A. 00523 * 00524 * @return Normalized float. 00525 */ 00526 float MD25::motor1_current_get() { 00527 /* Variables */ 00528 char data; 00529 00530 /* Get motor current */ 00531 if (read(REG_MOTOR1_CURRENT, &data, 1) == -1) return -1; 00532 00533 /* Return motor current */ 00534 return (float)(data / 10.0); 00535 } 00536 00537 /** 00538 * Get current of motor 2. 00539 * It reads 10 times the current i.e. 25 for 2.5A. 00540 * 00541 * @return Normalized float. 00542 */ 00543 float MD25::motor2_current_get() { 00544 /* Variables */ 00545 char data; 00546 00547 /* Get motor current */ 00548 if (read(REG_MOTOR2_CURRENT, &data, 1) == -1) return -1; 00549 00550 /* Return motor current */ 00551 return (float)(data / 10.0); 00552 } 00553 00554 /** 00555 * Get the software revision number in the PIC16F873 controller. 00556 */ 00557 int MD25::software_rev_num_get() { 00558 /* Variables */ 00559 char data; 00560 00561 /* Get software revision number */ 00562 if (read(REG_SOFTWARE_REVISION, &data, 1) == -1) return -1; 00563 00564 /* Return software revision number */ 00565 return data; 00566 }
Generated on Tue Jul 12 2022 18:14:02 by
1.7.2