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.
Fork of command_AX12_gros_robot by
AX12/AX12.cpp
- Committer:
- SquirrelGod
- Date:
- 2017-05-11
- Revision:
- 5:740eb0f606c1
- Parent:
- 4:92d6a49cd2c5
File content as of revision 5:740eb0f606c1:
/* mbed AX-12+ Servo Library * * Copyright (c) 2010, cstyles (http://mbed.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "mbed.h" #include "AX12.h" #define MAX_TIMEOUT 500 extern Timer t; typedef struct { unsigned short Model_Number; unsigned char Firmware; unsigned char ID; unsigned char Baud_Rate; unsigned char Return_Delay_Time; unsigned short CW_Angle_Limit; unsigned short CCW_Angle_Limit; unsigned char Reserved1; unsigned char Highest_Limit_Temperature; unsigned char Lowest_Limit_voltage; unsigned char Highest_Limit_voltage; unsigned short Max_Torque; unsigned char Status_Return_Level; unsigned char Alarm_LED; unsigned char Alarm_Shutdown; unsigned char Reserved2; unsigned short Down_Calibration; unsigned short Up_Calibration; unsigned char Torque_Enable; unsigned char LED; unsigned char CW_Compliance_Margin; unsigned char CCW_Compliance_Margin; unsigned char CW_Compliance_Slope; unsigned char CCW_Compliance_Slope; unsigned short Goal_Position; unsigned short Moving_Speed; unsigned short Torque_Limit; unsigned short Present_Position; unsigned short Present_Speed; unsigned short Present_Load; unsigned char Present_Voltage; unsigned char Present_Temperature; unsigned char Registered_Instruction; unsigned char Reserved3; unsigned char Moving; unsigned char Lock; unsigned short Punch; } T_AX12; AX12::AX12(PinName tx, PinName rx, int ID, int baud) : _ax12(tx,rx) { _baud = baud; _ID = ID; _ax12.baud(_baud); } int AX12::Set_Secure_Goal(int degres) { int error = 0; int position = 0; int difference = 0; int timeout_secure = 0; int autorisation = 0; position = Get_Position(); error = Set_Goal(degres); while ((autorisation == 0) && (timeout_secure < 100) ) { position = Get_Position(); //printf("position : %d", position ); error = Set_Goal(degres); //printf("degres : %d", degres); difference = degres - position; //printf ("difference : %d", difference ); if (((difference < 2) && (difference > (-2) ))) autorisation = 1; timeout_secure++; } if ( timeout_secure == 100) { #ifdef AX12_DEBUG printf (" timeout secure error "); #endif return(-1); } return(error); } int AX12::Get_Return_Delay_Time(void) { char data[1]; int ErrorCode = read(_ID, AX12_REG_DELAY_TIME, 1, data); int time = data[0]; time = 2.0 * time; return(time); } int AX12::Get_Baud_Rate(void) { char data[1]; int ErrorCode = read(_ID, AX12_REG_BAUD, 1, data); int baud = data[0]; baud = 2000000 / ( baud + 1 ); return(baud); } /** Reglage du courant minimum necessaire au bon fonctionnement de l'actionneur // minimum >> Ox000 >> decimal 0 // maximum >> 0x3FF >> decimal 1023 // deflaut >> 0x20 >> decimal 32 */ int AX12::Set_Punch(int punch) { char data[2]; data[0] = punch & 0xff; // bottom 8 bits data[1] = punch >> 8; // top 8 bits // write the packet, return the error code return (write(_ID, AX12_REG_PUNCH, 2, data)); } /** Reset */ int AX12::Reset(int punch) { char data[2]; data[0] = punch & 0xff; // bottom 8 bits data[1] = punch >> 8; // top 8 bits // write the packet, return the error code return (write(_ID, 0x06, 1,data)); } int AX12::Get_Punch (void) { char data[2]; int ErrorCode = read(_ID, AX12_REG_PUNCH, 2, data); int punch = data[0] | (data[1]<<8); return(punch); } int AX12::Get_Load_Direction (void) { char data[2]; int ErrorCode = read(_ID, AX12_REG_PRESENT_LOAD, 2, data); int direction = (data[1]>>2) & 0x01; return(direction); } int AX12::Get_Load_Value (void) { char data[2]; int ErrorCode = read(_ID, AX12_REG_PRESENT_LOAD, 2, data); int Load = (data[0] | (data[1]<<8)) & 0x3FF; return(Load); } int AX12::Get_Present_Speed (void) { char data[2]; int ErrorCode = read(_ID, AX12_REG_PRESENT_SPEED, 2, data); int speed = data[0] | (data[1]<<8); return(speed); } int AX12::Get_CCW_Angle_Limit (void) { char data[2]; int ErrorCode = read(_ID, AX12_REG_CCW_LIMIT, 2, data); int angle = data[0] | (data[1]<<8); angle = (angle * 300) / 1023; return(angle); } int AX12::Get_CW_Angle_Limit (void) { char data[2]; int ErrorCode = read(_ID, AX12_REG_CW_LIMIT, 2, data); int angle = data[0] | (data[1]<<8); angle = (angle * 300) / 1023; return(angle); } int AX12::Get_Torque_Enable(void) { char data[1]; int ErrorCode = read(_ID, AX12_REG_TORQUE_ENABLE, 1, data); int enable = data[0]; return(enable); } int AX12::Set_Torque_Enable(int etat) { char data[1]; data [0] = etat; int error = write(_ID, AX12_REG_TORQUE_ENABLE, 1, data); return (error); } int AX12::Get_Up_Calibration (void) { char data[1]; int ErrorCode = read(_ID, AX12_REG_UP_CALIBRATION, 2, data); int Up_calibration = data[0] | (data[1]<<8); return(Up_calibration); } int AX12::Get_Down_Calibration (void) { char data[1]; int ErrorCode = read(_ID, AX12_REG_DOWN_CALIBRATION, 2, data); int Dowm_calibration = data[0] | (data[1]<<8); return(Dowm_calibration); } int AX12::Get_ID(void) { char data[1]={-1}; int ErrorCode = read(_ID, AX12_REG_ID, 1, data); int id = data[0]; return(id); } // Lecture du couple maximum ( retourne la valeur du registre Max Torque de l'AX12 ) int AX12::Get_Max_Torque (void) { char data[2]; int ErrorCode = read(_ID, AX12_REG_MAX_TORQUE, 2, data); int torque = data[0] | (data[1]<<8); return(torque); } /** Reglage du couple maximum de l'actionneur // minimum >> Ox000 >> decimal 0 // maximum >> 0x3FF >> decimal 1023 // deflaut >> >> decimal */ int AX12::Set_Max_Torque(int torque) { char data[2]; data[0] = torque & 0xff; // bottom 8 bits data[1] = torque >> 8; // top 8 bits // write the packet, return the error code return (write(_ID, AX12_REG_MAX_TORQUE, 2, data)); } /** Reglage de la desactivation des actionneurs si une erreur le concernant se produit Bit Function Bit 7 0 Bit 6 If set to 1, torque off when an Instruction Error occurs Bit 5 If set to 1, torque off when an Overload Error occurs Bit 4 If set to 1, torque off when a Checksum Error occurs Bit 3 If set to 1, torque off when a Range Error occurs Bit 2 If set to 1, torque off when an Overheating Error occurs Bit 1 If set to 1, torque off when an Angle Limit Error occurs Bit 0 If set to 1, torque off when an Input Voltage Error occurs */ int AX12::Set_Alarm_Shutdown(int valeur) { char data[1]; data [0] = valeur; int val_alarm_shutdown = write(_ID, AX12_REG_ALARM_SHUTDOWN, 1, data); return (val_alarm_shutdown); } /** Reglage de l'activation de l'alarme Bit Function Bit 7 0 Bit 6 If set to 1, the LED blinks when an Instruction Error occurs Bit 5 If set to 1, the LED blinks when an Overload Error occurs Bit 4 If set to 1, the LED blinks when a Checksum Error occurs Bit 3 If set to 1, the LED blinks when a Range Error occurs Bit 2 If set to 1, the LED blinks when an Overheating Error occurs Bit 1 If set to 1, the LED blinks when an Angle Limit Error occurs Bit 0 If set to 1, the LED blinks when an Input Voltage Error occurs */ int AX12::Set_Alarm_LED(int valeur) { char data[1]; data [0] = valeur; int val_alarmLED = write(_ID, AX12_REG_ALARM_LED, 1, data); return (val_alarmLED); } // Reglage de la réponse à une instruction // 0 >> ne repond a aucune instructions // 1 >> repond seulement aux instructions READ_DATA // 2 >> repond à toutes les instructions int AX12::Set_Status_Return_Level(int etat) { char data[1]; data [0] = etat; int val_return_lvl = write(_ID, AX12_REG_SATUS_RETURN, 1, data); return (val_return_lvl); } // Reglage de la tension minimale // minimum >> Ox32 >> decimal 50 // maximum >> 0xFA >> decimal 250 // deflaut >> 0x3C >> decimal 60 int AX12::Set_Lowest_Voltage(int val_lowest_voltage) { char data[1]; data [0] = val_lowest_voltage; int val_lowvolt = write(_ID, AX12_REG_LOWEST_VOLTAGE, 1, data); return (val_lowvolt); } // Reglage de la tension maximale // minimum >> Ox32 >> decimal 50 // maximum >> 0xFA >> decimal 250 // deflaut >> 0xBE >> decimal 190 int AX12::Set_Highest_Voltage(int val_highest_voltage) { char data[1]; data [0] = val_highest_voltage; int val_highvolt = write(_ID, AX12_REG_HIGHEST_VOLTAGE, 1, data); return (val_highvolt); } // Reglage du return time delay EN MICRO SECONDE 2uSec * val_delay_time // minimum >> 0 us // maximum >> 508 us // deflaut >> 125 us int AX12::Set_Delay_Time (int val_delay_time ) { char data[1]; data [0] = val_delay_time/2.0; int valdelay_time = write(_ID, AX12_REG_DELAY_TIME, 1, data); return (valdelay_time ); } // Reglage de la température max du cervo // minimum >> Ox00 >> decimal 0 // maximum >> 0x96 >> decimal 150 int AX12::Set_Temperature_Max (int val_temperature ) { char data[1]; data [0] = val_temperature; int valtemp_max = write(_ID, AX12_REG_TEMP_MAX, 1, data); return (valtemp_max ); } // Etat LED // 0 = off // 1 = on int AX12::Set_Etat_LED(int etat) { char data[1]; data [0] = etat; int valLED = write(_ID, AX12_REG_LED, 1, data); return (valLED); } // Set the mode of the servo // 0 = Positional (0-300 degrees) // 1 = Rotational -1 to 1 speed int AX12::Set_Mode(int mode) { if (mode == 1) { // set CR //wait(0.001); Set_CW_Angle_Limit(0); //wait(0.001); Set_CCW_Angle_Limit(0); //wait(0.001); Set_CR_Speed(0.0); //wait(0.001); } else { //wait(0.001); Set_CW_Angle_Limit(0); //wait(0.001); Set_CCW_Angle_Limit(300); //wait(0.001); Set_CR_Speed(0.0); //wait(0.001); } return(0); } int AX12::Set_Goal_speed(int speed, int flags) { char reg_flag = 0; char data[2]; // set the flag is only the register bit is set in the flag if (flags == 0x2) { reg_flag = 1; } data[0] = speed & 0xff; // bottom 8 bits data[1] = speed >> 8; // top 8 bits // write the packet, return the error code int rVal = write(_ID, AX12_REG_MOVING_SPEED, 2, data, reg_flag); /*if (flags == 1) { // block until it comes to a halt while (isMoving()) { } }*/ return(rVal); } // if flag[0] is set, were blocking // if flag[1] is set, we're registering // they are mutually exclusive operations int AX12::Set_Goal(int degrees, int flags) { char reg_flag = 0; char data[2]; // set the flag is only the register bit is set in the flag if (flags == 0x2) { reg_flag = 1; } // 1023 / 300 * degrees short goal = (1023 * degrees) / 300; #ifdef AX12_DEBUG printf("SetGoal to 0x%x\n",goal); #endif data[0] = goal & 0xff; // bottom 8 bits data[1] = goal >> 8; // top 8 bits // write the packet, return the error code int rVal = write(_ID, AX12_REG_GOAL_POSITION, 2, data, reg_flag); /*if (flags == 1) { // block until it comes to a halt while (isMoving()) { } }*/ return(rVal); } // Set continuous rotation speed from -1 to 1 int AX12::Set_CR_Speed(float speed) { // bit 10 = direction, 0 = CCW, 1=CW // bits 9-0 = Speed char data[2]; int goal = (0x3ff * abs(speed)); // Set direction CW if we have a negative speed if (speed < 0) { goal |= (0x1 << 10); } data[0] = goal & 0xff; // bottom 8 bits data[1] = goal >> 8; // top 8 bits // write the packet, return the error code int rVal = write(_ID, 0x20, 2, data); return(rVal); } int AX12::Set_CW_Angle_Limit (int degrees) { char data[2]; // 1023 / 300 * degrees short limit = (1023 * degrees) / 300; #ifdef AX12_DEBUG printf("SetCWLimit to 0x%x\n",limit); #endif data[0] = limit & 0xff; // bottom 8 bits data[1] = limit >> 8; // top 8 bits // write the packet, return the error code return (write(_ID, AX12_REG_CW_LIMIT, 2, data)); } int AX12::Set_CCW_Angle_Limit (int degrees) { char data[2]; // 1023 / 300 * degrees short limit = (1023 * degrees) / 300; #ifdef AX12_DEBUG printf("SetCCWLimit to 0x%x\n",limit); #endif data[0] = limit & 0xff; // bottom 8 bits data[1] = limit >> 8; // top 8 bits // write the packet, return the error code return (write(_ID, AX12_REG_CCW_LIMIT, 2, data)); } int AX12::Set_ID (int CurrentID, int NewID) { char data[1]; data[0] = NewID; #ifdef AX12_DEBUG printf("Setting ID from 0x%x to 0x%x\n",CurrentID,NewID); #endif return (write(CurrentID, AX12_REG_ID, 1, data)); } int AX12::Set_Baud (int baud) { char data[1]; data[0] = baud; #ifdef AX12_DEBUG printf("Setting Baud rate to %d\n",baud); #endif return (write(_ID, AX12_REG_BAUD, 1, data)); } // return 1 is the servo is still in flight int AX12::isMoving(void) { char data[1]; read(_ID,AX12_REG_MOVING,1,data); return(data[0]); } void AX12::reset() { unsigned char TxBuf[16]; unsigned char sum = 0; unsigned long debut=0; #ifdef AX12_TRIGGER_DEBUG // Build the TxPacket first in RAM, then we'll send in one go printf("\nreset\n"); printf("\nreset Packet\n Header : 0xFF, 0xFF\n"); #endif TxBuf[0] = 0xFF; TxBuf[1] = 0xFF; // ID - Broadcast TxBuf[2] =_ID; sum += TxBuf[2]; #ifdef AX12_TRIGGER_DEBUG printf(" ID : %d\n",TxBuf[2]); #endif // Length TxBuf[3] = 0x02; sum += TxBuf[3]; #ifdef AX12_TRIGGER_DEBUG printf(" Length %d\n",TxBuf[3]); #endif // Instruction - ACTION TxBuf[4] = 0x06; //reset sum += TxBuf[4]; #ifdef AX12_TRIGGER_DEBUG printf(" Instruction 0x%X\n",TxBuf[5]); #endif // Checksum TxBuf[5] = 0xFF - sum; //#ifdef AX12_TRIGGER_DEBUG printf(" Checksum 0x%X\n",TxBuf[5]); //#endif // Transmit the packet in one burst with no pausing for (int i = 0; i < 6 ; i++) { while(_ax12.writeable()==0); _ax12.putc(TxBuf[i]); } wait(0.001); debut=t.read_ms(); do { if (_ax12.readable()==-1) // reception du premier Header ( 0xFF ) printf("%02x",_ax12.getc()); } while((t.read_ms()-debut)<500); printf("\n"); return; } void AX12::read_all_info(unsigned char start, unsigned char longueur) { unsigned char TxBuf[16]; unsigned char sum = 0; unsigned long debut=0; #ifdef AX12_TRIGGER_DEBUG // Build the TxPacket first in RAM, then we'll send in one go printf("\nreset\n"); printf("\nreset Packet\n Header : 0xFF, 0xFF\n"); #endif TxBuf[0] = 0xFF; TxBuf[1] = 0xFF; // ID - Broadcast TxBuf[2] =_ID; sum += TxBuf[2]; #ifdef AX12_TRIGGER_DEBUG printf(" ID : %d\n",TxBuf[2]); #endif // Length TxBuf[3] = 0x04; sum += TxBuf[3]; #ifdef AX12_TRIGGER_DEBUG printf(" Length %d\n",TxBuf[3]); #endif // Instruction - ACTION TxBuf[4] = INST_READ; //reset sum += TxBuf[4]; #ifdef AX12_TRIGGER_DEBUG printf(" Instruction 0x%X\n",TxBuf[4]); #endif TxBuf[5] = start; //reset sum += TxBuf[5]; TxBuf[6] = longueur; //reset sum += TxBuf[6]; // Checksum TxBuf[7] = 0xFF - sum; //#ifdef AX12_TRIGGER_DEBUG //printf(" Checksum 0x%X\n\r",TxBuf[7]); //#endif // Transmit the packet in one burst with no pausing for (int i = 0; i < 8 ; i++) { while(_ax12.writeable()==0); _ax12.putc(TxBuf[i]); } debut=t.read_ms(); int i=0; do { if (_ax12.readable()) { // reception du premier Header ( 0xFF ) printf("%02d:%02x ",start+i,_ax12.getc()); i++; } } while((t.read_ms()-debut)<5000); printf("\n"); return; } void AX12::trigger(void) { char TxBuf[16]; char sum = 0; #ifdef AX12_TRIGGER_DEBUG // Build the TxPacket first in RAM, then we'll send in one go printf("\nTriggered\n"); printf("\nTrigger Packet\n Header : 0xFF, 0xFF\n"); #endif TxBuf[0] = 0xFF; TxBuf[1] = 0xFF; // ID - Broadcast TxBuf[2] = 0xFE; sum += TxBuf[2]; #ifdef AX12_TRIGGER_DEBUG printf(" ID : %d\n",TxBuf[2]); #endif // Length TxBuf[3] = 0x02; sum += TxBuf[3]; #ifdef AX12_TRIGGER_DEBUG printf(" Length %d\n",TxBuf[3]); #endif // Instruction - ACTION TxBuf[4] = 0x04; sum += TxBuf[4]; #ifdef AX12_TRIGGER_DEBUG printf(" Instruction 0x%X\n",TxBuf[5]); #endif // Checksum TxBuf[5] = 0xFF - sum; #ifdef AX12_TRIGGER_DEBUG printf(" Checksum 0x%X\n",TxBuf[5]); #endif // Transmit the packet in one burst with no pausing for (int i = 0; i < 6 ; i++) { _ax12.putc(TxBuf[i]); } // This is a broadcast packet, so there will be no reply return; } float AX12::Get_Position(void) { #ifdef AX12_DEBUG printf("\nGetPositionID(%d)",_ID); #endif char data[2]; int ErrorCode = read(_ID, AX12_REG_POSITION, 2, data); int position = data[0] | (data[1] << 8); float angle = ((float)position * 300.0)/1023.0; return (angle); } float AX12::Get_Temp () { #ifdef AX12_DEBUG printf("\nGetTemp(%d)",_ID); #endif char data[1]; int ErrorCode = read(_ID, AX12_REG_TEMP, 1, data); float temp = data[0]; return(temp); } float AX12::Get_Volts (void) { #ifdef AX12_DEBUG printf("\nGetVolts(%d)",_ID); #endif char data[1]; int ErrorCode = read(_ID, AX12_REG_VOLTS, 1, data); float volts = data[0]/10.0; return(volts); } int AX12::read(int ID, int start, int bytes, char* data) { char PacketLength = 0x3; char TxBuf[16]; char sum = 0; char Status[16]; int timeout = 0; int plen = 0; int flag_out = 0; int timeout_transmit = 0; int i = 0; int enable = 0; // int poubelle = 0; // int count = 0; // char vidage[50]; typedef enum {Header1, Header2, ident, length, erreur, reception, checksum} type_etat; type_etat etat = Header1; Status[4] = 0xFE; // return code /*********************************** CREATION DE LA TRAME A EVOYER *****************************************/ #ifdef AX12_READ_DEBUG printf("\nread(%d,0x%x,%d,data)\n",ID,start,bytes); #endif // Build the TxPacket first in RAM, then we'll send in one go #ifdef AX12_READ_DEBUG printf("\nInstruction Packet\n Header : 0xFF, 0xFF\n"); #endif TxBuf[0] = 0xff; TxBuf[1] = 0xff; // ID TxBuf[2] = ID; sum += TxBuf[2]; #ifdef AX12_READ_DEBUG printf(" ID : %d\n",TxBuf[2]); #endif // Packet Length TxBuf[3] = 4;//PacketLength+bytes; // Length = 4 ; 2 + 1 (start) = 1 (bytes) sum += TxBuf[3]; // Accululate the packet sum #ifdef AX12_READ_DEBUG printf(" Length : 0x%x\n",TxBuf[3]); #endif // Instruction - Read TxBuf[4] = 0x2; sum += TxBuf[4]; #ifdef AX12_READ_DEBUG printf(" Instruction : 0x%x\n",TxBuf[4]); #endif // Start Address TxBuf[5] = start; sum += TxBuf[5]; #ifdef AX12_READ_DEBUG printf(" Start Address : 0x%x\n",TxBuf[5]); #endif // Bytes to read TxBuf[6] = bytes; sum += TxBuf[6]; #ifdef AX12_READ_DEBUG printf(" No bytes : 0x%x\n",TxBuf[6]); #endif // Checksum TxBuf[7] = 0xFF - sum; #ifdef AX12_READ_DEBUG printf(" Checksum : 0x%x\n",TxBuf[7]); #endif /********************************************TRAME CONSTRUITE DANS TxBuf***************************************/ /* Transmission de la trame construite precedemment dans le tableau TxBuf */ while ((timeout_transmit<5000) && (i < (7+bytes))) { if (_ax12.writeable()) { _ax12.putc(TxBuf[i]); i++; timeout_transmit = 0; } else timeout_transmit++; } if (timeout_transmit == 5000 ) // dans le cas d'une sortie en timeout pour ne pas rester bloquer ! { #ifdef AX12_DEBUG printf ("timeout transmit erreur\r\n"); #endif return(-1); } /* Transmission effectuée on va ensuite récuperer la trame de retour renvoyer par le servomoteur */ // Wait for the bytes to be transmitted wait (0.001); // Skip if the read was to the broadcast address if (_ID != 0xFE) { /* Partie de reception de la trame de retour */ while ((flag_out != 1) && (timeout < (1000*bytes))) { // Les differents etats de l'automate on été créés au debut de la fonction write ! switch (etat) { case Header1: if (_ax12.readable()) // reception du premier Header ( 0xFF ) { Status[plen] = _ax12.getc(); timeout = 0; if (Status[plen] == 0xFF ) { etat = Header2; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else etat = Header1; } else timeout++; break; case Header2: if (_ax12.readable()) // reception du second Header ( 0xFF ) { Status[plen] = _ax12.getc(); timeout = 0; if (Status[plen] == 0xFF ) { etat = ident; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else if (Status[plen] == ID ) // PERMET D'EVITER CERTAINES ERREUR LORSQU'ON LIT PLUSIEURS REGISTRES !!!! { Status[plen] = 0; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; Status[plen] = ID; etat = length; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else { etat = Header1; plen = 0; } } else timeout++; break; case ident: if (_ax12.readable()) // reception de l'octet correspondant à l'ID du servomoteur { Status[plen] = _ax12.getc(); timeout = 0; if (Status[plen] == ID ) { etat = length; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else { etat = Header1; plen = 0; } } else timeout++; break; case length: if (_ax12.readable()) // reception de l'octet correspondant à la taille ( taille = 2 + nombre de paramètres ) { Status[plen] = _ax12.getc(); timeout = 0; if (Status[plen] == (bytes+2) ) { etat = erreur; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else { etat = Header1; plen = 0; } } else timeout++; break; case erreur: if (_ax12.readable()) //reception de l'octet correspondant au code d'erreurs eventuels ( 0 = pas d'erreur ) { Status[plen] = _ax12.getc(); timeout = 0; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; etat = reception; } else timeout++; case reception: while ( enable < bytes ) // reception du ou des octect(s) de donnés ( suivant la valeur de la variable length ) { if (_ax12.readable()) { Status[plen] = _ax12.getc(); timeout = 0; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; enable++; } else timeout++; } etat = checksum; break; case checksum: if (_ax12.readable()) // reception du dernier octet ( Checksum ) >>> checksum = NOT ( ID + length + somme des données ) >>>> dans le cas d'un retour d'un read!! { Status[plen] = _ax12.getc(); timeout = 0; flag_out = 1; etat = Header1; #ifdef AX12_DEBUG_READ printf("data[%d] : %d\r\n\n", plen, (int)Status[plen]); #endif } else timeout++; break; default: break; } } if (timeout == (1000*bytes) ) // permet d'afficher si il y a une erreur de timeout et de ne pas rester bloquer si il y a des erreurs de trames { #ifdef AX12_DEBUG printf ("timeout erreur\n"); #endif return(-1); } // copie des données dans le tableau data for (int i=0; i < Status[3]-2 ; i++) { data[i] = Status[5+i]; } } // toute la partie precedente ne s'effectue pas dans le cas d'un appel avec un broadcast ID (ID!=0xFE) return(Status[4]); // retourne le code d'erreur ( octect 5 de la trame de retour ) } void AX12::multiple_goal_and_speed(int number_ax12,char* tab) { char TxBuf[50]; char sum = 0; int timeout_transmit =0; int i=0, k=0, j=0; int L=4; // nombre instructions par paquets int bytes= ((L+1)*number_ax12)+4; typedef enum {Header1, Header2, ident, length, erreur, checksum} type_etat; type_etat etat= Header1; for(j=0; j<50; j++) { TxBuf[i]=0; } #ifdef AX12_WRITE_DEBUG //printf(" MULTIPLE_GOAL_AND_SPEED \n "); #endif // Build the TxPacket first in RAM, then we'll send in one go #ifdef AX12_WRITE_DEBUG //printf("\nInstruction Packet\n Header :%d, %d\n",TxBuf[0], TxBuf[1]); #endif TxBuf[0]=0xFF; // bit de start TxBuf[1]=0xFF; // bit de start TxBuf[2] = 0xFE; //ID broadcast sum += TxBuf[2]; #ifdef AX12_WRITE_DEBUG printf(" adresse de difusion : %d\n",TxBuf[2]); #endif TxBuf[3] =bytes; // longueur sum += TxBuf[3]; #ifdef AX12_WRITE_DEBUG printf(" Longueur : %d\n",TxBuf[3]); #endif TxBuf[4]=0x83; //SYNC_WRITE sum += TxBuf[4]; #ifdef AX12_WRITE_DEBUG printf(" Instruction : 0x%x\n",TxBuf[4]); #endif TxBuf[5] = 0x1E; // addresse "GOAL_POSITION" sum += TxBuf[5]; #ifdef AX12_WRITE_DEBUG printf(" Adresse de debut : 0x%x\n",TxBuf[5]); #endif TxBuf[6]=L; // Nombre instruction par paquets sum += TxBuf[6]; #ifdef AX12_WRITE_DEBUG printf(" nombre instruction/paquet : 0x%x\n",TxBuf[6]); #endif for(i=0; i<(number_ax12*5); i++) // Copie des data de TAB sur TxBuf { TxBuf[i+7]=tab[i]; sum += TxBuf[i+7]; } #ifdef AX12_WRITE_DEBUG for(i=0; i<(number_ax12*5); i++) { printf(" Data : 0x%x\n",TxBuf[i+7]); } #endif TxBuf[(number_ax12*5)+7] = 0xFF - sum ; // CHECKSUM #ifdef AX12_WRITE_DEBUG printf(" Checksum : 0x%x\n",TxBuf[(number_ax12*5)+9]); #endif for(k=0; k<((number_ax12*5)+8); k++) // TRANSMISSION DE LA TRAME { _ax12.putc(TxBuf[k]); #ifdef AX12_WRITE_DEBUG printf(" transmission : 0x%x\n",TxBuf[k]); #endif } } float AX12::read_and_test(float angle,char* Tab) { int k=0; unsigned short val_angle=0, val_reche=0; #ifdef AX12_DEBUG printf("\nread_and_test"); #endif if( _ID==0x12) { k=1;} else if( _ID==0x04) { k=6;} else if( _ID==0x07) { k=11;} else if( _ID==0x0F) { k=16;} val_angle = (unsigned short) (angle/0.3); val_reche = (unsigned short) Tab[k] + ((unsigned short)Tab[k+1]<<8); if((val_angle < (val_reche+(28))) && (val_angle > (val_reche-(28)))) { #ifdef AX12_DEBUG printf("\nreturn1"); #endif return 1; } else { #ifdef AX12_DEBUG printf("\nreturn0"); #endif return 0; } } int AX12::write(int ID, int start, int bytes, char* data, int flag) { // 0xff, 0xff, ID, Length, Intruction(write), Address, Param(s), Checksum char TxBuf[16]; char sum = 0; char Status[6]; int timeout = 0; int plen = 0; int flag_out = 0; int timeout_transmit = 0; int i = 0; int poubelle = 0; int count = 0; char vidage[50]; typedef enum {Header1, Header2, ident, length, erreur, checksum} type_etat; type_etat etat = Header1; #ifdef AX12_WRITE_DEBUG printf("\nwrite(%d,0x%x,%d,data,%d)\n",ID,start,bytes,flag); #endif // Build the TxPacket first in RAM, then we'll send in one go #ifdef AX12_WRITE_DEBUG printf("\nInstruction Packet\n Header : 0xFF, 0xFF\n"); #endif TxBuf[0] = 0xff; TxBuf[1] = 0xff; // ID TxBuf[2] = ID; sum += TxBuf[2]; #ifdef AX12_WRITE_DEBUG printf(" ID : %d\n",TxBuf[2]); #endif // packet Length TxBuf[3] = 3+bytes; sum += TxBuf[3]; #ifdef AX12_WRITE_DEBUG printf(" Length : %d\n",TxBuf[3]); #endif // Instruction if (flag == 1) { TxBuf[4]=0x04; sum += TxBuf[4]; } else { TxBuf[4]=0x03; sum += TxBuf[4]; } #ifdef AX12_WRITE_DEBUG printf(" Instruction : 0x%x\n",TxBuf[4]); #endif // Start Address TxBuf[5] = start; sum += TxBuf[5]; #ifdef AX12_WRITE_DEBUG printf(" Start : 0x%x\n",TxBuf[5]); #endif // data for (char i=0; i<bytes ; i++) { TxBuf[6+i] = data[i]; sum += TxBuf[6+i]; #ifdef AX12_WRITE_DEBUG printf(" Data : 0x%x\n",TxBuf[6+i]); #endif } // checksum TxBuf[6+bytes] = 0xFF - sum; #ifdef AX12_WRITE_DEBUG printf(" Checksum : 0x%x\n",TxBuf[6+bytes]); #endif /* Transmission de la trame construite precedemment dans le tableau TxBuf */ while ((timeout_transmit<100) && (i < (7+bytes))) { if (_ax12.writeable()) { _ax12.putc(TxBuf[i]); i++; timeout_transmit = 0; } else timeout_transmit++; } if (timeout_transmit == 100 ) // dans le cas d'une sortie en timeout pour ne pas rester bloquer ! { #ifdef AX12_DEBUG printf ("TIMEOUT TRANSMIT ERROR\r\n"); #endif return(-1); } /* Transmission effectuée on va ensuite récuperer la trame de retour renvoyer par le servomoteur */ // Wait for data to transmit wait (0.005); // make sure we have a valid return Status[4]=0x00; // we'll only get a reply if it was not broadcast if (_ID!=0xFE) { /* Partie de reception de la trame de retour */ while ((flag_out != 1) && (timeout < MAX_TIMEOUT)) { // Les differents etats de l'automate on été créés au debut de la fonction write ! switch (etat) { case Header1: if (_ax12.readable()) // reception du premier Header ( 0xFF ) { Status[plen] = _ax12.getc(); timeout = 0; if (Status[plen] == 0xFF ) { etat = Header2; #ifdef AX12_DEBUG_WRITE printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else etat = Header1; } else timeout++; break; case Header2: if (_ax12.readable()) // reception du second Header ( 0xFF ) { Status[plen] = _ax12.getc(); timeout = 0; if (Status[plen] == 0xFF ) { etat = ident; #ifdef AX12_DEBUG_WRITE printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else { etat = Header1; plen = 0; } } else timeout++; break; case ident: if (_ax12.readable()) // reception de l'octet correspondant à l'ID du servomoteur { Status[plen] = _ax12.getc(); timeout = 0; if (Status[plen] == ID ) { etat = length; #ifdef AX12_DEBUG_WRITE printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else { etat = Header1; plen = 0; } } else timeout++; break; case length: if (_ax12.readable()) // reception de l'octet correspondant à la taille ( taille = 2 + nombre de paramètres ) { Status[plen] = _ax12.getc(); timeout = 0; if (Status[plen] == 2 ) // dans la trame de retour d'un write il n'y a pas de paramètre la taille vaudra donc 2!! { etat = erreur; #ifdef AX12_DEBUG_WRITE printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; } else { etat = Header1; plen = 0; } } else timeout++; break; case erreur: if (_ax12.readable()) //reception de l'octet correspondant au code d'erreurs eventuels ( 0 = pas d'erreur ) { Status[plen] = _ax12.getc(); timeout = 0; #ifdef AX12_DEBUG_WRITE printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif plen++; etat = checksum; } else timeout++; case checksum: if (_ax12.readable()) // recpetion du dernier octet ( Checksum ) >>> checksum = NOT ( ID + length ) >>>> dans le cas de la reception d'un write { Status[plen] = _ax12.getc(); timeout = 0; flag_out = 1; etat = Header1; #ifdef AX12_DEBUG_WRITE printf("data[%d] : %d\r\n\n", plen, (int)Status[plen]); #endif } else timeout++; break; } } if ( Status[4] != 0 ) { #ifdef AX12_DEBUG printf ("erreur ! \r\n"); #endif for (int i = 0; i<5; i++) { #ifdef AX12_DEBUG printf("data[%d] : %d\r\n", plen, (int)Status[plen]); #endif } } if (timeout == MAX_TIMEOUT ) // permet d'afficher si il y a une erreur de timeout et de ne pas rester bloquer si il y a des erreurs de trames { #ifdef AX12_DEBUG printf ("timeout erreur\n\r"); #endif return(-1); } // Build the TxPacket first in RAM, then we'll send in one go } return(Status[4]); // retourne le code d'erreur ( octect 5 de la trame de retour ) }