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.
Dependencies: RoboClaw StepperMotor mbed
Fork of Robot2016_2-0 by
AX12.cpp
00001 /* mbed AX-12+ Servo Library 00002 * 00003 * Copyright (c) 2010, cstyles (http://mbed.org) 00004 * 00005 * Permission is hereby granted, free of charge, to any person obtaining a copy 00006 * of this software and associated documentation files (the "Software"), to deal 00007 * in the Software without restriction, including without limitation the rights 00008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 * copies of the Software, and to permit persons to whom the Software is 00010 * furnished to do so, subject to the following conditions: 00011 * 00012 * The above copyright notice and this permission notice shall be included in 00013 * all copies or substantial portions of the Software. 00014 * 00015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00021 * THE SOFTWARE. 00022 */ 00023 00024 #include "AX12.h" 00025 #include "mbed.h" 00026 00027 extern Serial logger; 00028 00029 AX12::AX12(PinName tx, PinName rx, int ID, int baud) 00030 : _ax12(tx,rx) { 00031 _baud = baud; 00032 _ID = ID; 00033 _ax12.baud(_baud); 00034 00035 } 00036 00037 // set the mode of the servo 00038 // 0 = Positional (0-300 degrees) 00039 // 1 = Rotational -1 to 1 speed 00040 int AX12::setMode(int mode) { 00041 00042 if (mode == 1) { // set CR 00043 setCWLimit(0); 00044 setCCWLimit(0); 00045 setCRSpeed(0.0); 00046 } else { 00047 setCWLimit(0); 00048 setCCWLimit(300); 00049 setCRSpeed(0.0); 00050 } 00051 return(0); 00052 } 00053 00054 00055 // if flag[0] is set, were blocking 00056 // if flag[1] is set, we're registering 00057 // they are mutually exclusive operations 00058 int AX12::setGoal(int degrees, int flags) { 00059 00060 char reg_flag = 0; 00061 char data[2]; 00062 _goal = degrees; 00063 00064 // set the flag is only the register bit is set in the flag 00065 if (flags == 0x2) { 00066 reg_flag = 1; 00067 } 00068 00069 // 1023 / 300 * degrees 00070 short goal = (1023 * degrees) / 300; 00071 #ifdef AX12_DEBUG 00072 logger.printf("setGoal to 0x%x\n",goal); 00073 #endif 00074 00075 data[0] = goal & 0xff; // bottom 8 bits 00076 data[1] = goal >> 8; // top 8 bits 00077 00078 // write the packet, return the error code 00079 int rVal = write(_ID, AX12_REG_GOAL_POSITION, 2, data, reg_flag); 00080 00081 if (flags == 1) { 00082 // block until it comes to a halt 00083 while (isMoving()) {} 00084 } 00085 return(rVal); 00086 } 00087 00088 int AX12::setMaxTorque(int maxTorque) 00089 { 00090 char data[2]; 00091 00092 data[0] = maxTorque & 0xFF; 00093 data[1] = maxTorque >> 8; 00094 00095 // write the packet, return the error code 00096 int rVal = write(_ID, 0x22, 2, data); 00097 00098 return(rVal); 00099 } 00100 00101 00102 // set continuous rotation speed from -1 to 1 00103 int AX12::setCRSpeed(float speed) { 00104 00105 // bit 10 = direction, 0 = CCW, 1=CW 00106 // bits 9-0 = Speed 00107 char data[2]; 00108 00109 int goal = (0x3ff * abs(speed)); 00110 00111 // set direction CW if we have a negative speed 00112 if (speed < 0) { 00113 goal |= (0x1 << 10); 00114 } 00115 00116 data[0] = goal & 0xff; // bottom 8 bits 00117 data[1] = goal >> 8; // top 8 bits 00118 00119 // write the packet, return the error code 00120 int rVal = write(_ID, 0x20, 2, data); 00121 00122 return(rVal); 00123 } 00124 00125 00126 int AX12::setCWLimit (int degrees) { 00127 00128 char data[2]; 00129 00130 // 1023 / 300 * degrees 00131 short limit = (1023 * degrees) / 300; 00132 00133 #ifdef AX12_DEBUG 00134 logger.printf("setCWLimit to 0x%x\n",limit); 00135 #endif 00136 00137 data[0] = limit & 0xff; // bottom 8 bits 00138 data[1] = limit >> 8; // top 8 bits 00139 00140 // write the packet, return the error code 00141 return (write(_ID, AX12_REG_CW_LIMIT, 2, data)); 00142 00143 } 00144 00145 int AX12::setCCWLimit (int degrees) { 00146 00147 char data[2]; 00148 00149 // 1023 / 300 * degrees 00150 short limit = (1023 * degrees) / 300; 00151 00152 #ifdef AX12_DEBUG 00153 logger.printf("setCCWLimit to 0x%x\n",limit); 00154 #endif 00155 00156 data[0] = limit & 0xff; // bottom 8 bits 00157 data[1] = limit >> 8; // top 8 bits 00158 00159 // write the packet, return the error code 00160 return (write(_ID, AX12_REG_CCW_LIMIT, 2, data)); 00161 } 00162 00163 00164 int AX12::setID (int CurrentID, int NewID) { 00165 00166 char data[1]; 00167 data[0] = NewID; 00168 00169 #ifdef AX12_DEBUG 00170 logger.printf("setting ID from 0x%x to 0x%x\n",CurrentID,NewID); 00171 #endif 00172 00173 return (write(CurrentID, AX12_REG_ID, 1, data)); 00174 00175 } 00176 00177 00178 int AX12::setBaud (int baud) { 00179 00180 char data[1]; 00181 data[0] = baud; 00182 00183 #ifdef AX12_DEBUG 00184 logger.printf("setting Baud rate to %d\n",baud); 00185 #endif 00186 00187 return (write(0xFE, AX12_REG_BAUD, 1, data)); 00188 00189 } 00190 00191 00192 00193 // return 1 is the servo is still in flight 00194 int AX12::isMoving(void) { 00195 00196 char data[1]; 00197 read(_ID,AX12_REG_MOVING,1,data); 00198 return(data[0]); 00199 } 00200 00201 00202 void AX12::trigger(void) { 00203 00204 char TxBuf[16]; 00205 char sum = 0; 00206 00207 #ifdef AX12_TRIGGER_DEBUG 00208 // Build the TxPacket first in RAM, then we'll send in one go 00209 logger.printf("\nTriggered\n"); 00210 logger.printf("\nTrigger Packet\n Header : 0xFF, 0xFF\n"); 00211 #endif 00212 00213 TxBuf[0] = 0xFF; 00214 TxBuf[1] = 0xFF; 00215 00216 // ID - Broadcast 00217 TxBuf[2] = 0xFE; 00218 sum += TxBuf[2]; 00219 00220 #ifdef AX12_TRIGGER_DEBUG 00221 logger.printf(" ID : %d\n",TxBuf[2]); 00222 #endif 00223 00224 // Length 00225 TxBuf[3] = 0x02; 00226 sum += TxBuf[3]; 00227 00228 #ifdef AX12_TRIGGER_DEBUG 00229 logger.printf(" Length %d\n",TxBuf[3]); 00230 #endif 00231 00232 // Instruction - ACTION 00233 TxBuf[4] = 0x04; 00234 sum += TxBuf[4]; 00235 00236 #ifdef AX12_TRIGGER_DEBUG 00237 logger.printf(" Instruction 0x%X\n",TxBuf[5]); 00238 #endif 00239 00240 // Checksum 00241 TxBuf[5] = 0xFF - sum; 00242 #ifdef AX12_TRIGGER_DEBUG 00243 logger.printf(" Checksum 0x%X\n",TxBuf[5]); 00244 #endif 00245 00246 // Transmit the packet in one burst with no pausing 00247 for (int i = 0; i < 6 ; i++) { 00248 _ax12.putc(TxBuf[i]); 00249 } 00250 00251 // This is a broadcast packet, so there will be no reply 00252 return; 00253 } 00254 00255 00256 float AX12::getPosition(void) { 00257 00258 #ifdef AX12_DEBUG 00259 logger.printf("\ngetPosition(%d)",_ID); 00260 #endif 00261 00262 char data[2]; 00263 00264 int ErrorCode = read(_ID, AX12_REG_POSITION, 2, data); 00265 short position = data[0] + (data[1] << 8); 00266 float angle = (position * 300)/1024; 00267 00268 return (angle); 00269 } 00270 00271 00272 float AX12::getTemp (void) { 00273 00274 #ifdef AX12_DEBUG 00275 logger.printf("\ngetTemp(%d)",_ID); 00276 #endif 00277 00278 char data[1]; 00279 int ErrorCode = read(_ID, AX12_REG_TEMP, 1, data); 00280 float temp = data[0]; 00281 return(temp); 00282 } 00283 00284 00285 float AX12::getVolts (void) { 00286 00287 #ifdef AX12_DEBUG 00288 logger.printf("\ngetVolts(%d)",_ID); 00289 #endif 00290 00291 char data[1]; 00292 int ErrorCode = read(_ID, AX12_REG_VOLTS, 1, data); 00293 float volts = data[0]/10.0; 00294 return(volts); 00295 } 00296 00297 00298 int AX12::read(int ID, int start, int bytes, char* data) { 00299 00300 char PacketLength = 0x4; 00301 char TxBuf[16]; 00302 char sum = 0; 00303 char Status[16]; 00304 00305 Status[4] = 0xFE; // return code 00306 00307 #ifdef AX12_READ_DEBUG 00308 logger.printf("\nread(%d,0x%x,%d,data)\n",ID,start,bytes); 00309 #endif 00310 00311 // Build the TxPacket first in RAM, then we'll send in one go 00312 #ifdef AX12_READ_DEBUG 00313 logger.printf("\nInstruction Packet\n Header : 0xFF, 0xFF\n"); 00314 #endif 00315 00316 TxBuf[0] = 0xff; 00317 TxBuf[1] = 0xff; 00318 00319 // ID 00320 TxBuf[2] = ID; 00321 sum += TxBuf[2]; 00322 00323 #ifdef AX12_READ_DEBUG 00324 logger.printf(" ID : %d\n",TxBuf[2]); 00325 #endif 00326 00327 // Packet Length 00328 TxBuf[3] = PacketLength; // Length = 4 ; 2 + 1 (start) = 1 (bytes) 00329 sum += TxBuf[3]; // Accululate the packet sum 00330 00331 #ifdef AX12_READ_DEBUG 00332 logger.printf(" Length : 0x%x\n",TxBuf[3]); 00333 #endif 00334 00335 // Instruction - Read 00336 TxBuf[4] = 0x2; 00337 sum += TxBuf[4]; 00338 00339 #ifdef AX12_READ_DEBUG 00340 logger.printf(" Instruction : 0x%x\n",TxBuf[4]); 00341 #endif 00342 00343 // Start Address 00344 TxBuf[5] = start; 00345 sum += TxBuf[5]; 00346 00347 #ifdef AX12_READ_DEBUG 00348 logger.printf(" Start Address : 0x%x\n",TxBuf[5]); 00349 #endif 00350 00351 // Bytes to read 00352 TxBuf[6] = bytes; 00353 sum += TxBuf[6]; 00354 00355 #ifdef AX12_READ_DEBUG 00356 logger.printf(" No bytes : 0x%x\n",TxBuf[6]); 00357 #endif 00358 00359 // Checksum 00360 TxBuf[7] = 0xFF - sum; 00361 #ifdef AX12_READ_DEBUG 00362 logger.printf(" Checksum : 0x%x\n",TxBuf[7]); 00363 #endif 00364 00365 // Transmit the packet in one burst with no pausing 00366 for (int i = 0; i<8 ; i++) { 00367 _ax12.putc(TxBuf[i]); 00368 } 00369 00370 // Wait for the bytes to be transmitted 00371 wait (0.00002); 00372 00373 // Skip if the read was to the broadcast address 00374 if (_ID != 0xFE) { 00375 00376 00377 00378 // response packet is always 6 + bytes 00379 // 0xFF, 0xFF, ID, Length Error, Param(s) Checksum 00380 // timeout is a little more than the time to transmit 00381 // the packet back, i.e. (6+bytes)*10 bit periods 00382 00383 int timeout = 0; 00384 int plen = 0; 00385 while ((timeout < ((6+bytes)*10)) && (plen<(6+bytes))) { 00386 00387 if (_ax12.readable()) { 00388 Status[plen] = _ax12.getc(); 00389 plen++; 00390 timeout = 0; 00391 } 00392 00393 // wait for the bit period 00394 wait (1.0/_baud); 00395 timeout++; 00396 } 00397 00398 if (timeout == ((6+bytes)*10) ) { 00399 return(-1); 00400 } 00401 00402 // Copy the data from Status into data for return 00403 for (int i=0; i < Status[3]-2 ; i++) { 00404 data[i] = Status[5+i]; 00405 } 00406 00407 #ifdef AX12_READ_DEBUG 00408 logger.printf("\nStatus Packet\n"); 00409 logger.printf(" Header : 0x%x\n",Status[0]); 00410 logger.printf(" Header : 0x%x\n",Status[1]); 00411 logger.printf(" ID : 0x%x\n",Status[2]); 00412 logger.printf(" Length : 0x%x\n",Status[3]); 00413 logger.printf(" Error Code : 0x%x\n",Status[4]); 00414 00415 for (int i=0; i < Status[3]-2 ; i++) { 00416 logger.printf(" Data : 0x%x\n",Status[5+i]); 00417 } 00418 00419 logger.printf(" Checksum : 0x%x\n",Status[5+(Status[3]-2)]); 00420 #endif 00421 00422 } // if (ID!=0xFE) 00423 00424 return(Status[4]); 00425 } 00426 00427 00428 int AX12::write(int ID, int start, int bytes, char* data, int flag) { 00429 // 0xff, 0xff, ID, Length, Intruction(write), Address, Param(s), Checksum 00430 00431 char TxBuf[16]; 00432 char sum = 0; 00433 char Status[6]; 00434 00435 #ifdef AX12_WRITE_DEBUG 00436 logger.printf("\nwrite(%d,0x%x,%d,data,%d)\n",ID,start,bytes,flag); 00437 #endif 00438 00439 // Build the TxPacket first in RAM, then we'll send in one go 00440 #ifdef AX12_WRITE_DEBUG 00441 logger.printf("\nInstruction Packet\n Header : 0xFF, 0xFF\n"); 00442 #endif 00443 00444 TxBuf[0] = 0xff; 00445 TxBuf[1] = 0xff; 00446 00447 // ID 00448 TxBuf[2] = ID; 00449 sum += TxBuf[2]; 00450 00451 #ifdef AX12_WRITE_DEBUG 00452 logger.printf(" ID : %d\n",TxBuf[2]); 00453 #endif 00454 00455 // packet Length 00456 TxBuf[3] = 3+bytes; 00457 sum += TxBuf[3]; 00458 00459 #ifdef AX12_WRITE_DEBUG 00460 logger.printf(" Length : %d\n",TxBuf[3]); 00461 #endif 00462 00463 // Instruction 00464 if (flag == 1) { 00465 TxBuf[4]=0x04; 00466 sum += TxBuf[4]; 00467 } else { 00468 TxBuf[4]=0x03; 00469 sum += TxBuf[4]; 00470 } 00471 00472 #ifdef AX12_WRITE_DEBUG 00473 logger.printf(" Instruction : 0x%x\n",TxBuf[4]); 00474 #endif 00475 00476 // Start Address 00477 TxBuf[5] = start; 00478 sum += TxBuf[5]; 00479 00480 #ifdef AX12_WRITE_DEBUG 00481 logger.printf(" Start : 0x%x\n",TxBuf[5]); 00482 #endif 00483 00484 // data 00485 for (char i=0; i<bytes ; i++) { 00486 TxBuf[6+i] = data[i]; 00487 sum += TxBuf[6+i]; 00488 00489 #ifdef AX12_WRITE_DEBUG 00490 logger.printf(" Data : 0x%x\n",TxBuf[6+i]); 00491 #endif 00492 00493 } 00494 00495 // checksum 00496 TxBuf[6+bytes] = 0xFF - sum; 00497 00498 #ifdef AX12_WRITE_DEBUG 00499 logger.printf(" Checksum : 0x%x\n",TxBuf[6+bytes]); 00500 #endif 00501 00502 // Transmit the packet in one burst with no pausing 00503 for (int i = 0; i < (7 + bytes) ; i++) { 00504 _ax12.putc(TxBuf[i]); 00505 } 00506 00507 // Wait for data to transmit 00508 wait (0.00002); 00509 00510 // make sure we have a valid return 00511 Status[4]=0x00; 00512 00513 // we'll only get a reply if it was not broadcast 00514 if (_ID!=0xFE) { 00515 00516 00517 // response packet is always 6 bytes 00518 // 0xFF, 0xFF, ID, Length Error, Param(s) Checksum 00519 // timeout is a little more than the time to transmit 00520 // the packet back, i.e. 60 bit periods, round up to 100 00521 int timeout = 0; 00522 int plen = 0; 00523 while ((timeout < 100) && (plen<6)) { 00524 00525 if (_ax12.readable()) { 00526 Status[plen] = _ax12.getc(); 00527 plen++; 00528 timeout = 0; 00529 } 00530 00531 // wait for the bit period 00532 wait (1.0/_baud); 00533 timeout++; 00534 } 00535 00536 00537 // Build the TxPacket first in RAM, then we'll send in one go 00538 #ifdef AX12_WRITE_DEBUG 00539 logger.printf("\nStatus Packet\n Header : 0x%X, 0x%X\n",Status[0],Status[1]); 00540 logger.printf(" ID : %d\n",Status[2]); 00541 logger.printf(" Length : %d\n",Status[3]); 00542 logger.printf(" Error : 0x%x\n",Status[4]); 00543 logger.printf(" Checksum : 0x%x\n",Status[5]); 00544 #endif 00545 00546 00547 } 00548 00549 return(Status[4]); // return error code 00550 }
Generated on Wed Jul 13 2022 04:42:26 by
1.7.2
