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.
Dependents: 2-FisherMan 2-FisherMan
Fork of AX12 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 #include "SerialHalfDuplex.h" 00027 00028 AX12::AX12(PinName tx, PinName rx, int ID, int baud) 00029 : _ax12(tx,rx) { 00030 _baud = baud; 00031 _ID = ID; 00032 _ax12.baud(_baud); 00033 00034 } 00035 00036 // Set the mode of the servo 00037 // 0 = Positional (0-300 degrees) 00038 // 1 = Rotational -1 to 1 speed 00039 int AX12::SetMode(int mode) { 00040 00041 if (mode == 1) { // set CR 00042 SetCWLimit(0); 00043 SetCCWLimit(0); 00044 SetCRSpeed(0.0); 00045 } else { 00046 SetCWLimit(0); 00047 SetCCWLimit(300); 00048 SetCRSpeed(0.0); 00049 } 00050 return(0); 00051 } 00052 00053 00054 // if flag[0] is set, were blocking 00055 // if flag[1] is set, we're registering 00056 // they are mutually exclusive operations 00057 int AX12::SetGoal(int degrees, int flags) { 00058 00059 char reg_flag = 0; 00060 char data[2]; 00061 00062 // set the flag is only the register bit is set in the flag 00063 if (flags == 0x2) { 00064 reg_flag = 1; 00065 } 00066 00067 // 1023 / 300 * degrees 00068 short goal = (1023 * degrees) / 300; 00069 #ifdef AX12_DEBUG 00070 printf("SetGoal to 0x%x\n",goal); 00071 #endif 00072 00073 data[0] = goal & 0xff; // bottom 8 bits 00074 data[1] = goal >> 8; // top 8 bits 00075 00076 // write the packet, return the error code 00077 int rVal = write(_ID, AX12_REG_GOAL_POSITION, 2, data, reg_flag); 00078 00079 if (flags == 1) { 00080 // block until it comes to a halt 00081 while (isMoving()) {} 00082 } 00083 return(rVal); 00084 } 00085 00086 // Set speed 00087 int AX12::SetSpeed(int speed) { 00088 char data[2]; 00089 00090 data[0] = speed & 0xff; // bottom 8 bits 00091 data[1] = speed >> 8; // top 8 bits 00092 00093 // write the packet, return the error code 00094 int rVal = write(_ID, AX12_REG_MOVING_SPEED, 2, data); 00095 return(rVal); 00096 } 00097 00098 // Set continuous rotation speed from -1 to 1 00099 int AX12::SetCRSpeed(float speed) { 00100 00101 // bit 10 = direction, 0 = CCW, 1=CW 00102 // bits 9-0 = Speed 00103 char data[2]; 00104 00105 int goal = (0x3ff * abs(speed)); 00106 00107 // Set direction CW if we have a negative speed 00108 if (speed < 0) { 00109 goal |= (0x1 << 10); 00110 } 00111 00112 data[0] = goal & 0xff; // bottom 8 bits 00113 data[1] = goal >> 8; // top 8 bits 00114 00115 // write the packet, return the error code 00116 int rVal = write(_ID, 0x20, 2, data); 00117 00118 return(rVal); 00119 } 00120 00121 00122 int AX12::SetCWLimit (int degrees) { 00123 00124 char data[2]; 00125 00126 // 1023 / 300 * degrees 00127 short limit = (1023 * degrees) / 300; 00128 00129 #ifdef AX12_DEBUG 00130 printf("SetCWLimit to 0x%x\n",limit); 00131 #endif 00132 00133 data[0] = limit & 0xff; // bottom 8 bits 00134 data[1] = limit >> 8; // top 8 bits 00135 00136 // write the packet, return the error code 00137 return (write(_ID, AX12_REG_CW_LIMIT, 2, data)); 00138 00139 } 00140 00141 int AX12::SetCCWLimit (int degrees) { 00142 00143 char data[2]; 00144 00145 // 1023 / 300 * degrees 00146 short limit = (1023 * degrees) / 300; 00147 00148 #ifdef AX12_DEBUG 00149 printf("SetCCWLimit to 0x%x\n",limit); 00150 #endif 00151 00152 data[0] = limit & 0xff; // bottom 8 bits 00153 data[1] = limit >> 8; // top 8 bits 00154 00155 // write the packet, return the error code 00156 return (write(_ID, AX12_REG_CCW_LIMIT, 2, data)); 00157 } 00158 00159 00160 int AX12::SetID (int CurrentID, int NewID) { 00161 00162 char data[1]; 00163 data[0] = NewID; 00164 00165 #ifdef AX12_DEBUG 00166 printf("Setting ID from 0x%x to 0x%x\n",CurrentID,NewID); 00167 #endif 00168 00169 return (write(CurrentID, AX12_REG_ID, 1, data)); 00170 00171 } 00172 00173 00174 int AX12::SetBaud (int baud) { 00175 00176 char data[1]; 00177 data[0] = baud; 00178 00179 #ifdef AX12_DEBUG 00180 printf("Setting Baud rate to %d\n",baud); 00181 #endif 00182 00183 return (write(0xFE, AX12_REG_BAUD, 1, data)); 00184 00185 } 00186 00187 00188 00189 // return 1 is the servo is still in flight 00190 int AX12::isMoving(void) { 00191 00192 char data[1]; 00193 read(_ID,AX12_REG_MOVING,1,data); 00194 return(data[0]); 00195 } 00196 00197 00198 void AX12::trigger(void) { 00199 00200 char TxBuf[16]; 00201 char sum = 0; 00202 00203 #ifdef AX12_TRIGGER_DEBUG 00204 // Build the TxPacket first in RAM, then we'll send in one go 00205 printf("\nTriggered\n"); 00206 printf("\nTrigger Packet\n Header : 0xFF, 0xFF\n"); 00207 #endif 00208 00209 TxBuf[0] = 0xFF; 00210 TxBuf[1] = 0xFF; 00211 00212 // ID - Broadcast 00213 TxBuf[2] = 0xFE; 00214 sum += TxBuf[2]; 00215 00216 #ifdef AX12_TRIGGER_DEBUG 00217 printf(" ID : %d\n",TxBuf[2]); 00218 #endif 00219 00220 // Length 00221 TxBuf[3] = 0x02; 00222 sum += TxBuf[3]; 00223 00224 #ifdef AX12_TRIGGER_DEBUG 00225 printf(" Length %d\n",TxBuf[3]); 00226 #endif 00227 00228 // Instruction - ACTION 00229 TxBuf[4] = 0x04; 00230 sum += TxBuf[4]; 00231 00232 #ifdef AX12_TRIGGER_DEBUG 00233 printf(" Instruction 0x%X\n",TxBuf[5]); 00234 #endif 00235 00236 // Checksum 00237 TxBuf[5] = 0xFF - sum; 00238 #ifdef AX12_TRIGGER_DEBUG 00239 printf(" Checksum 0x%X\n",TxBuf[5]); 00240 #endif 00241 00242 // Transmit the packet in one burst with no pausing 00243 for (int i = 0; i < 6 ; i++) { 00244 _ax12.putc(TxBuf[i]); 00245 } 00246 00247 // This is a broadcast packet, so there will be no reply 00248 return; 00249 } 00250 00251 00252 float AX12::GetPosition(void) { 00253 00254 #ifdef AX12_DEBUG 00255 printf("\nGetPosition(%d)",_ID); 00256 #endif 00257 00258 char data[2]; 00259 00260 int ErrorCode = read(_ID, AX12_REG_POSITION, 2, data); 00261 short position = data[0] + (data[1] << 8); 00262 float angle = (position * 300)/1024; 00263 00264 return (angle); 00265 } 00266 00267 00268 float AX12::GetTemp (void) { 00269 00270 #ifdef AX12_DEBUG 00271 printf("\nGetTemp(%d)",_ID); 00272 #endif 00273 00274 char data[1]; 00275 int ErrorCode = read(_ID, AX12_REG_TEMP, 1, data); 00276 float temp = data[0]; 00277 return(temp); 00278 } 00279 00280 00281 float AX12::GetVolts (void) { 00282 00283 #ifdef AX12_DEBUG 00284 printf("\nGetVolts(%d)",_ID); 00285 #endif 00286 00287 char data[1]; 00288 int ErrorCode = read(_ID, AX12_REG_VOLTS, 1, data); 00289 float volts = data[0]/10.0; 00290 return(volts); 00291 } 00292 00293 00294 int AX12::read(int ID, int start, int bytes, char* data) { 00295 00296 char PacketLength = 0x4; 00297 char TxBuf[16]; 00298 char sum = 0; 00299 char Status[16]; 00300 00301 Status[4] = 0xFE; // return code 00302 00303 #ifdef AX12_READ_DEBUG 00304 printf("\nread(%d,0x%x,%d,data)\n",ID,start,bytes); 00305 #endif 00306 00307 // Build the TxPacket first in RAM, then we'll send in one go 00308 #ifdef AX12_READ_DEBUG 00309 printf("\nInstruction Packet\n Header : 0xFF, 0xFF\n"); 00310 #endif 00311 00312 TxBuf[0] = 0xff; 00313 TxBuf[1] = 0xff; 00314 00315 // ID 00316 TxBuf[2] = ID; 00317 sum += TxBuf[2]; 00318 00319 #ifdef AX12_READ_DEBUG 00320 printf(" ID : %d\n",TxBuf[2]); 00321 #endif 00322 00323 // Packet Length 00324 TxBuf[3] = PacketLength; // Length = 4 ; 2 + 1 (start) = 1 (bytes) 00325 sum += TxBuf[3]; // Accululate the packet sum 00326 00327 #ifdef AX12_READ_DEBUG 00328 printf(" Length : 0x%x\n",TxBuf[3]); 00329 #endif 00330 00331 // Instruction - Read 00332 TxBuf[4] = 0x2; 00333 sum += TxBuf[4]; 00334 00335 #ifdef AX12_READ_DEBUG 00336 printf(" Instruction : 0x%x\n",TxBuf[4]); 00337 #endif 00338 00339 // Start Address 00340 TxBuf[5] = start; 00341 sum += TxBuf[5]; 00342 00343 #ifdef AX12_READ_DEBUG 00344 printf(" Start Address : 0x%x\n",TxBuf[5]); 00345 #endif 00346 00347 // Bytes to read 00348 TxBuf[6] = bytes; 00349 sum += TxBuf[6]; 00350 00351 #ifdef AX12_READ_DEBUG 00352 printf(" No bytes : 0x%x\n",TxBuf[6]); 00353 #endif 00354 00355 // Checksum 00356 TxBuf[7] = 0xFF - sum; 00357 #ifdef AX12_READ_DEBUG 00358 printf(" Checksum : 0x%x\n",TxBuf[7]); 00359 #endif 00360 00361 // Transmit the packet in one burst with no pausing 00362 for (int i = 0; i<8 ; i++) { 00363 _ax12.putc(TxBuf[i]); 00364 } 00365 00366 // Wait for the bytes to be transmitted 00367 wait (0.00002); 00368 00369 // Skip if the read was to the broadcast address 00370 if (_ID != 0xFE) { 00371 00372 00373 00374 // response packet is always 6 + bytes 00375 // 0xFF, 0xFF, ID, Length Error, Param(s) Checksum 00376 // timeout is a little more than the time to transmit 00377 // the packet back, i.e. (6+bytes)*10 bit periods 00378 00379 int timeout = 0; 00380 int plen = 0; 00381 while ((timeout < ((6+bytes)*10)) && (plen<(6+bytes))) { 00382 00383 if (_ax12.readable()) { 00384 Status[plen] = _ax12.getc(); 00385 plen++; 00386 timeout = 0; 00387 } 00388 00389 // wait for the bit period 00390 wait (1.0/_baud); 00391 timeout++; 00392 } 00393 00394 if (timeout == ((6+bytes)*10) ) { 00395 return(-1); 00396 } 00397 00398 // Copy the data from Status into data for return 00399 for (int i=0; i < Status[3]-2 ; i++) { 00400 data[i] = Status[5+i]; 00401 } 00402 00403 #ifdef AX12_READ_DEBUG 00404 printf("\nStatus Packet\n"); 00405 printf(" Header : 0x%x\n",Status[0]); 00406 printf(" Header : 0x%x\n",Status[1]); 00407 printf(" ID : 0x%x\n",Status[2]); 00408 printf(" Length : 0x%x\n",Status[3]); 00409 printf(" Error Code : 0x%x\n",Status[4]); 00410 00411 for (int i=0; i < Status[3]-2 ; i++) { 00412 printf(" Data : 0x%x\n",Status[5+i]); 00413 } 00414 00415 printf(" Checksum : 0x%x\n",Status[5+(Status[3]-2)]); 00416 #endif 00417 00418 } // if (ID!=0xFE) 00419 00420 return(Status[4]); 00421 } 00422 00423 00424 int AX12::write(int ID, int start, int bytes, char* data, int flag) { 00425 // 0xff, 0xff, ID, Length, Intruction(write), Address, Param(s), Checksum 00426 00427 char TxBuf[16]; 00428 char sum = 0; 00429 char Status[6]; 00430 00431 #ifdef AX12_WRITE_DEBUG 00432 printf("\nwrite(%d,0x%x,%d,data,%d)\n",ID,start,bytes,flag); 00433 #endif 00434 00435 // Build the TxPacket first in RAM, then we'll send in one go 00436 #ifdef AX12_WRITE_DEBUG 00437 printf("\nInstruction Packet\n Header : 0xFF, 0xFF\n"); 00438 #endif 00439 00440 TxBuf[0] = 0xff; 00441 TxBuf[1] = 0xff; 00442 00443 // ID 00444 TxBuf[2] = ID; 00445 sum += TxBuf[2]; 00446 00447 #ifdef AX12_WRITE_DEBUG 00448 printf(" ID : %d\n",TxBuf[2]); 00449 #endif 00450 00451 // packet Length 00452 TxBuf[3] = 3+bytes; 00453 sum += TxBuf[3]; 00454 00455 #ifdef AX12_WRITE_DEBUG 00456 printf(" Length : %d\n",TxBuf[3]); 00457 #endif 00458 00459 // Instruction 00460 if (flag == 1) { 00461 TxBuf[4]=0x04; 00462 sum += TxBuf[4]; 00463 } else { 00464 TxBuf[4]=0x03; 00465 sum += TxBuf[4]; 00466 } 00467 00468 #ifdef AX12_WRITE_DEBUG 00469 printf(" Instruction : 0x%x\n",TxBuf[4]); 00470 #endif 00471 00472 // Start Address 00473 TxBuf[5] = start; 00474 sum += TxBuf[5]; 00475 00476 #ifdef AX12_WRITE_DEBUG 00477 printf(" Start : 0x%x\n",TxBuf[5]); 00478 #endif 00479 00480 // data 00481 for (char i=0; i<bytes ; i++) { 00482 TxBuf[6+i] = data[i]; 00483 sum += TxBuf[6+i]; 00484 00485 #ifdef AX12_WRITE_DEBUG 00486 printf(" Data : 0x%x\n",TxBuf[6+i]); 00487 #endif 00488 00489 } 00490 00491 // checksum 00492 TxBuf[6+bytes] = 0xFF - sum; 00493 00494 #ifdef AX12_WRITE_DEBUG 00495 printf(" Checksum : 0x%x\n",TxBuf[6+bytes]); 00496 #endif 00497 00498 // Transmit the packet in one burst with no pausing 00499 for (int i = 0; i < (7 + bytes) ; i++) { 00500 _ax12.putc(TxBuf[i]); 00501 } 00502 00503 // Wait for data to transmit 00504 wait (0.00002); 00505 00506 // make sure we have a valid return 00507 Status[4]=0x00; 00508 00509 // we'll only get a reply if it was not broadcast 00510 if (_ID!=0xFE) { 00511 00512 00513 // response packet is always 6 bytes 00514 // 0xFF, 0xFF, ID, Length Error, Param(s) Checksum 00515 // timeout is a little more than the time to transmit 00516 // the packet back, i.e. 60 bit periods, round up to 100 00517 int timeout = 0; 00518 int plen = 0; 00519 while ((timeout < 100) && (plen<6)) { 00520 00521 if (_ax12.readable()) { 00522 Status[plen] = _ax12.getc(); 00523 plen++; 00524 timeout = 0; 00525 } 00526 00527 // wait for the bit period 00528 wait (1.0/_baud); 00529 timeout++; 00530 } 00531 00532 00533 // Build the TxPacket first in RAM, then we'll send in one go 00534 #ifdef AX12_WRITE_DEBUG 00535 printf("\nStatus Packet\n Header : 0x%X, 0x%X\n",Status[0],Status[1]); 00536 printf(" ID : %d\n",Status[2]); 00537 printf(" Length : %d\n",Status[3]); 00538 printf(" Error : 0x%x\n",Status[4]); 00539 printf(" Checksum : 0x%x\n",Status[5]); 00540 #endif 00541 00542 00543 } 00544 00545 return(Status[4]); // return error code 00546 }
Generated on Fri Jul 15 2022 14:23:46 by
 1.7.2
 1.7.2 
    