Team DIANA / AX12_v2

Dependents:   MX106-custom

Fork of AX12 by Chris Styles

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AX12.cpp Source File

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