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: mbed ADS1115 StepperMotor SRF05 TPA81new
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 AX12::AX12 (PinName tx, PinName rx, PinName tx_ena, int ID, int baud) : _ax12(tx,rx), _ena_tx(tx_ena) 00028 { 00029 _ena_tx = 1; 00030 _ax12.baud(baud); 00031 _baud_bit = 1000000/baud; 00032 _wait_sent = 20 * _baud_bit; 00033 _timeout_tick = 500 + 12 * _baud_bit; 00034 _ID = ID; 00035 _error_code = 0; 00036 _data[0] = 0; 00037 _reg_flag = 0; 00038 } 00039 00040 // Set the mode of the servo 00041 // 0 = Positional (0-300 degrees) 00042 // 1 = Rotational -1 to 1 speed 00043 int AX12::SetMode(int mode) 00044 { 00045 if (mode == 1) 00046 { // set CR 00047 SetCWLimit(0); 00048 SetCCWLimit(0); 00049 SetCRSpeed(0.0); 00050 } 00051 else 00052 { 00053 SetCWLimit(0); 00054 SetCCWLimit(300); 00055 SetCRSpeed(0.0); 00056 } 00057 return(0); 00058 } 00059 00060 // if flag[0] is set, were blocking 00061 // if flag[1] is set, we're registering 00062 // they are mutually exclusive operations 00063 int AX12::SetGoal(int degrees, int flags) 00064 { 00065 _reg_flag = 0; 00066 00067 // set the flag is only the register bit is set in the flag 00068 if (flags == 0x2) 00069 { 00070 _reg_flag = 1; 00071 } 00072 00073 // 1023 / 300 * degrees 00074 short goal = (1023 * degrees) / 300; 00075 00076 _data[0] = goal & 0xff; // bottom 8 bits 00077 _data[1] = goal >> 8; // top 8 bits 00078 00079 // write the packet, return the error code 00080 int rVal = write(_ID, AX12_REG_GOAL_POSITION, 2, _data, _reg_flag); 00081 00082 if (flags == 1) 00083 { 00084 // block until it comes to a halt 00085 while (isMoving()) 00086 { 00087 00088 } 00089 } 00090 return(rVal); 00091 } 00092 00093 void AX12::MultSetGoal(int degrees1, float speed1, 00094 int degrees2, float speed2, 00095 int degrees3, float speed3, 00096 int degrees4, float speed4, 00097 int degrees5, float speed5, 00098 int degrees6, float speed6, 00099 int degrees7, float speed7, 00100 int degrees8, float speed8, 00101 int degrees9, float speed9, 00102 int degrees10, float speed10, 00103 int degrees11, float speed11, 00104 int degrees12, float speed12, 00105 int degrees13, float speed13, 00106 int degrees14, float speed14, 00107 int degrees15, float speed15, 00108 int degrees16, float speed16, 00109 int degrees17, float speed17, 00110 int degrees18, float speed18) 00111 { 00112 char data[(total_ID*length_data) + 1]; 00113 00114 int goal; 00115 int goal_speed; 00116 00117 int alamat; 00118 00119 int degrees[19]; 00120 float speed[19]; 00121 00122 // assignment value from parameter to array 00123 00124 degrees[1] = degrees1; 00125 degrees[2] = degrees2; 00126 degrees[3] = degrees3; 00127 degrees[4] = degrees4; 00128 degrees[5] = degrees5; 00129 degrees[6] = degrees6; 00130 degrees[7] = degrees7; 00131 degrees[8] = degrees8; 00132 degrees[9] = degrees9; 00133 degrees[10] = degrees10; 00134 degrees[11] = degrees11; 00135 degrees[12] = degrees12; 00136 degrees[13] = degrees13; 00137 degrees[14] = degrees14; 00138 degrees[15] = degrees15; 00139 degrees[16] = degrees16; 00140 degrees[17] = degrees17; 00141 degrees[18] = degrees18; 00142 00143 speed[1] = speed1; 00144 speed[2] = speed2; 00145 speed[3] = speed3; 00146 speed[4] = speed4; 00147 speed[5] = speed5; 00148 speed[6] = speed6; 00149 speed[7] = speed7; 00150 speed[8] = speed8; 00151 speed[9] = speed9; 00152 speed[10] = speed10; 00153 speed[11] = speed11; 00154 speed[12] = speed12; 00155 speed[13] = speed13; 00156 speed[14] = speed14; 00157 speed[15] = speed15; 00158 speed[16] = speed16; 00159 speed[17] = speed17; 00160 speed[18] = speed18; 00161 00162 /* 00163 for (char k=1; k<=total_ID; k++) 00164 { 00165 degrees[k] = degrees1; 00166 speed[k] = speed1; 00167 } 00168 */ 00169 00170 for (int i=1; i<=total_ID; i++) 00171 { 00172 alamat = length_data*(i-1); 00173 00174 goal = (1023 * degrees[i]) / 300; 00175 00176 data[alamat+1] = goal & 0xff; // bottom 8 bits 00177 data[alamat+2] = goal >> 8; // top 8 bits 00178 00179 float temp = (speed[i]<0)? (-1)*speed[i]:speed[i]; 00180 goal_speed = (0x3ff * temp); 00181 00182 // Set direction CW if we have a negative speed 00183 if (speed[i] < 0) 00184 { 00185 goal_speed |= (0x1 << 10); 00186 } 00187 00188 data[alamat+3] = goal_speed & 0xff; // bottom 8 bits 00189 data[alamat+4] = goal_speed >> 8; // top 8 bits 00190 } 00191 00192 // Write 00193 sync_write(data); 00194 00195 return; 00196 } 00197 00198 // Set continuous rotation speed from -1 to 1 00199 int AX12::SetCRSpeed(float speed) 00200 { 00201 // bit 10 = direction, 0 = CCW, 1=CW 00202 // bits 9-0 = Speed 00203 float temp = (speed<0)? speed * (-1): speed; 00204 int goal = (0x3ff * temp); 00205 00206 // Set direction CW if we have a negative speed 00207 if (speed < 0) 00208 { 00209 goal |= (0x1 << 10); 00210 } 00211 00212 _data[0] = goal & 0xff; // bottom 8 bits 00213 _data[1] = goal >> 8; // top 8 bits 00214 00215 // write the packet, return the error code 00216 int rVal = write(_ID, AX12_REG_MOVING_SPEED, 2, _data); 00217 00218 return(rVal); 00219 } 00220 00221 int AX12::SetCWLimit (int degrees) 00222 { 00223 // 1023 / 300 * degrees 00224 short limit = (1023 * degrees) / 300; 00225 00226 _data[0] = limit & 0xff; // bottom 8 bits 00227 _data[1] = limit >> 8; // top 8 bits 00228 00229 // write the packet, return the error code 00230 return (write(_ID, AX12_REG_CW_LIMIT, 2, _data)); 00231 } 00232 00233 int AX12::SetCCWLimit (int degrees) 00234 { 00235 // 1023 / 300 * degrees 00236 short limit = (1023 * degrees) / 300; 00237 00238 _data[0] = limit & 0xff; // bottom 8 bits 00239 _data[1] = limit >> 8; // top 8 bits 00240 00241 // write the packet, return the error code 00242 return (write(_ID, AX12_REG_CCW_LIMIT, 2, _data)); 00243 } 00244 00245 void AX12::ControlID (int ID) 00246 { 00247 _ID = ID; 00248 00249 return; 00250 } 00251 00252 int AX12::SetID (int CurrentID, int NewID) 00253 { 00254 _data[0] = NewID; 00255 return (write(CurrentID, AX12_REG_ID, 1, _data)); 00256 } 00257 00258 int AX12::SetBaud (int baud) 00259 { 00260 _data[0] = baud; 00261 return (write(0xFE, AX12_REG_BAUD, 1, _data)); 00262 } 00263 00264 // return 1 is the servo is still in flight 00265 int AX12::isMoving(void) 00266 { 00267 read(_ID,AX12_REG_MOVING,1,_data); 00268 return(_data[0]); 00269 } 00270 00271 void AX12::trigger(void) 00272 { 00273 char TxBuf[16]; 00274 char sum = 0; 00275 00276 TxBuf[0] = 0xFF; 00277 TxBuf[1] = 0xFF; 00278 00279 // ID - Broadcast 00280 TxBuf[2] = 0xFE; 00281 sum += TxBuf[2]; 00282 00283 // Length 00284 TxBuf[3] = 0x02; 00285 sum += TxBuf[3]; 00286 00287 // Instruction - ACTION 00288 TxBuf[4] = 0x04; 00289 sum += TxBuf[4]; 00290 00291 // Checksum 00292 TxBuf[5] = 0xFF - sum; 00293 00294 // Transmit the packet in one burst with no pausing 00295 for (int i = 0; i < 6 ; i++) { 00296 _ax12.putc(TxBuf[i]); 00297 } 00298 00299 // This is a broadcast packet, so there will be no reply 00300 return; 00301 } 00302 00303 float AX12::GetPosition(void) 00304 { 00305 _error_code = read(_ID, AX12_REG_POSITION, 2, _data); 00306 return ((short)(_data[0] + (_data[1] << 8)) * 300.0f / 1024.0f); 00307 } 00308 00309 float AX12::GetTemp (void) 00310 { 00311 _error_code = read(_ID, AX12_REG_TEMP, 1, _data); 00312 return(_data[0]); 00313 } 00314 00315 float AX12::GetVolts (void) 00316 { 00317 _error_code = read(_ID, AX12_REG_VOLTS, 1, _data); 00318 return(_data[0]/10.0f); 00319 } 00320 00321 int AX12::read(int ID, int start, int bytes, char* data) 00322 { 00323 char PacketLength = 0x4; 00324 char TxBuf[8]; 00325 char sum = 0; 00326 // char Status[6 + bytes]; 00327 00328 Status[4] = 0xFE; // return code 00329 00330 // Build the TxPacket first in RAM, then we'll send in one go 00331 00332 TxBuf[0] = 0xff; 00333 TxBuf[1] = 0xff; 00334 00335 // ID 00336 TxBuf[2] = ID; 00337 sum += TxBuf[2]; 00338 00339 // Packet Length 00340 TxBuf[3] = PacketLength; // Length = 4 ; 2 + 1 (start) = 1 (bytes) 00341 sum += TxBuf[3]; // Accululate the packet sum 00342 00343 // Instruction - Read 00344 TxBuf[4] = 0x2; 00345 sum += TxBuf[4]; 00346 00347 // Start Address 00348 TxBuf[5] = start; 00349 sum += TxBuf[5]; 00350 00351 // Bytes to read 00352 TxBuf[6] = bytes; 00353 sum += TxBuf[6]; 00354 00355 // Checksum 00356 TxBuf[7] = 0xFF - sum; 00357 00358 // Transmit the packet in one burst with no pausing 00359 _ena_tx = 1; 00360 for (int i = 0; i<8 ; i++) 00361 { 00362 _ax12.putc(TxBuf[i]); 00363 } 00364 00365 // Wait for the bytes to be transmitted 00366 wait_us (_wait_sent); 00367 _ena_tx = 0; 00368 00369 // Skip if the read was to the broadcast address 00370 if (_ID != 0xFE) 00371 { 00372 // response packet is always 6 + bytes 00373 // 0xFF, 0xFF, ID, Length Error, Param(s) Checksum 00374 // timeout is a little more than the time to transmit 00375 // the packet back, i.e. (6+bytes)*10 bit periods 00376 int plen = 0; 00377 int timeout = 0; 00378 int state = 0; 00379 while ((timeout < _timeout_tick) && (plen < (bytes + 3))) 00380 { 00381 if (_ax12.readable()) 00382 { 00383 switch(state) 00384 { 00385 case 0: 00386 case 1: 00387 Status[state] = _ax12.getc(); 00388 if(Status[state] == 0xFF) 00389 { 00390 state++; 00391 timeout = 0; 00392 } 00393 else 00394 state = 0; 00395 break; 00396 case 2: 00397 Status[state] = _ax12.getc(); 00398 if(Status[state] == ID) 00399 { 00400 state++; 00401 timeout = 0; 00402 } 00403 else 00404 state = 0; 00405 break; 00406 case 3: 00407 Status[plen+state] = _ax12.getc(); 00408 plen++; 00409 timeout = 0; 00410 break; 00411 default: 00412 state = 0; 00413 } 00414 } 00415 00416 // wait for the bit period 00417 wait_us(1); 00418 timeout++; 00419 } 00420 00421 if (timeout == 550) 00422 { 00423 return(-1); 00424 } 00425 00426 // Copy the data from Status into data for return 00427 for (int i=0; i < Status[3]-2 ; i++) 00428 { 00429 data[i] = Status[5+i]; 00430 } 00431 } 00432 00433 // if (ID!=0xFE) 00434 return(Status[4]); 00435 } 00436 00437 int AX12::write(int ID, int start, int bytes, char* data, int flag) { 00438 // 0xff, 0xff, ID, Length, Intruction(write), Address, Param(s), Checksum 00439 00440 // char TxBuf[7+bytes]; 00441 char sum = 0; 00442 char Status[6]; 00443 00444 // Build the TxPacket first in RAM, then we'll send in one go 00445 00446 TxBuf[0] = 0xff; 00447 TxBuf[1] = 0xff; 00448 00449 // ID 00450 TxBuf[2] = ID; 00451 sum += TxBuf[2]; 00452 00453 // packet Length 00454 TxBuf[3] = 3+bytes; 00455 sum += TxBuf[3]; 00456 00457 // Instruction 00458 if (flag == 1) 00459 { 00460 TxBuf[4]=0x04; 00461 sum += TxBuf[4]; 00462 } 00463 else 00464 { 00465 TxBuf[4]=0x03; 00466 sum += TxBuf[4]; 00467 } 00468 00469 // Start Address 00470 TxBuf[5] = start; 00471 sum += TxBuf[5]; 00472 00473 // data 00474 for (uint8_t i=0; i<bytes ; i++) 00475 { 00476 TxBuf[6+i] = data[i]; 00477 sum += TxBuf[6+i]; 00478 } 00479 00480 // checksum 00481 TxBuf[6+bytes] = 0xFF - sum; 00482 00483 // Transmit the packet in one burst with no pausing 00484 _ena_tx = 1; 00485 for (int i = 0; i < (7 + bytes) ; i++) 00486 { 00487 _ax12.putc(TxBuf[i]); 00488 } 00489 00490 // Wait for data to transmit 00491 wait_us (_wait_sent); 00492 _ena_tx = 0; 00493 00494 // make sure we have a valid return 00495 Status[4]=0x00; 00496 00497 // we'll only get a reply if it was not broadcast 00498 if (_ID!=0xFE) 00499 { 00500 // response packet is always 6 bytes 00501 // 0xFF, 0xFF, ID, Length Error, Param(s) Checksum 00502 // timeout is a little more than the time to transmit 00503 // the packet back, i.e. 60 bit periods, round up to 100 00504 int timeout = 0; 00505 int state = 0; 00506 int plen = 0; 00507 while ((timeout < _timeout_tick) && (plen<3)) 00508 { 00509 if (_ax12.readable()) 00510 { 00511 switch(state) 00512 { 00513 case 0: 00514 case 1: 00515 Status[state] = _ax12.getc(); 00516 if(Status[state] == 0xFF) 00517 { 00518 state++; 00519 timeout = 0; 00520 } 00521 else 00522 state = 0; 00523 break; 00524 case 2: 00525 Status[state] = _ax12.getc(); 00526 if(Status[state] == ID) 00527 { 00528 state++; 00529 timeout = 0; 00530 } 00531 else 00532 state = 0; 00533 break; 00534 case 3: 00535 Status[plen+state] = _ax12.getc(); 00536 plen++; 00537 timeout = 0; 00538 break; 00539 default: 00540 state = 0; 00541 } 00542 } 00543 00544 // wait for the bit period 00545 wait_us (1); 00546 timeout++; 00547 } 00548 00549 // Build the TxPacket first in RAM, then we'll send in one go 00550 } 00551 return(Status[4]); // return error code 00552 } 00553 00554 int AX12::sync_write(char* data) 00555 { 00556 // 0xff, 0xff, ID, Length, Intruction(write), Address, Param(s), Checksum 00557 00558 char sum = 0; 00559 char Status[6]; 00560 char TxBuf[(total_ID*(length_data+1)) + 8]; 00561 00562 int pra_alamat, alamat; 00563 00564 // Set ID 00565 char ID[total_ID+1]; 00566 00567 for (uint8_t k=1; k<=total_ID; k++) 00568 { 00569 ID[k] = k; 00570 } 00571 00572 TxBuf[0] = 0xFF; 00573 TxBuf[1] = 0xFF; 00574 00575 // ID 00576 TxBuf[2] = 0xFE; 00577 sum += TxBuf[2]; 00578 00579 // packet Length 00580 TxBuf[3] = ((length_data+1) * total_ID) + 4; 00581 sum += TxBuf[3]; 00582 00583 // Instruction 00584 TxBuf[4]=0x83; 00585 sum += TxBuf[4]; 00586 00587 // Start Address 00588 TxBuf[5] = start_reg; 00589 sum += TxBuf[5]; 00590 00591 // Length of Data to Write 00592 TxBuf[6] = length_data; 00593 sum += TxBuf[6]; 00594 00595 for (uint8_t j=1; j<=total_ID; j++) 00596 { 00597 pra_alamat = length_data*(j-1); 00598 alamat = 6 + j + pra_alamat; 00599 00600 TxBuf[alamat] = ID[j]; 00601 sum += TxBuf[alamat]; 00602 00603 for (char i=1; i<=length_data; i++) 00604 { 00605 TxBuf[alamat+i] = data[pra_alamat+i]; 00606 sum += TxBuf[alamat+i]; 00607 } 00608 } 00609 00610 // checksum 00611 TxBuf[((total_ID*(length_data+1)) + 7)] = 0xFF - (sum & 0xFF); 00612 00613 // Transmit the packet in one burst with no pausing 00614 _ena_tx = 1; 00615 for (int i = 0; i <= ((total_ID*(length_data+1)) + 7) ; i++) 00616 { 00617 _ax12.putc(TxBuf[i]); 00618 } 00619 00620 // Wait for data to transmit 00621 wait_us (_wait_sent); 00622 _ena_tx = 0; 00623 00624 // make sure we have a valid return 00625 Status[4]=0x00; 00626 00627 return(Status[4]); // return error code 00628 } 00629 00630 void AX12::SetTorqueEnable(char val) { 00631 // write(int ID, int start, int length, char* data, int flag=0); 00632 char en = val; 00633 write(_ID, AX12_TORQUE_ENABLE, 1, &en, 0); 00634 }
Generated on Wed Jul 13 2022 00:38:51 by
1.7.2