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.
Diff: MX12.cpp
- Revision:
- 31:61f9fca504dd
- Parent:
- 30:4e7cf52ac2dd
--- a/MX12.cpp Fri Feb 04 09:22:50 2022 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,527 +0,0 @@ -/** - * @file MX12.ccp - * @brief This file contains all the methods of the MX12 class - * whose prototypes are in the MX12.h header file - */ - -#include "MX12.h" -#include "math.h" - -MX12::MX12(PinName tx, PinName rx, int baud) - : _mx12(tx, rx) // initializes UnbufferedSerial object -{ - /* Serial bus setup - */ - // // Set desired properties (baud-8-N-1) - _mx12.baud(baud); /* modulation speed */ - _mx12.format( - 8, /* bits */ - SerialBase::None, /* parity */ - 1 /* stop bit */ - ); - // Register a callback to process a Rx (receive) interrupt. - _mx12.attach(callback(this, &MX12::_Rx_interrupt), SerialBase::RxIrq); - - // variable used for message reception - _status_pck = {.raw = "", - .n_byte = 0, - .servo_id = 0, - .length = 0, - .error = 0, - .n_param = 0, - .param = "", - .received_checksum = 0, - .calculated_checksum = 0, - .parsed = false, - .valid = false - }; - - _parser_state = {.expected_field = PacketField::Header1, - .byte_index = 0, - .param_index = 0 - }; - - // Internal defaults states - _bus_state = SerialState::Idle; - -} - -void MX12::SetSpeed(unsigned char mot_id, float speed) -{ - char data[2]; - - // Speed absolute value - int goal = (0x3ff * abs(speed)); - - // Spin direction (CW is negative) - if (speed < 0) { - goal |= (0x1 << 10); - } - - data[0] = goal & 0xff; - data[1] = goal >> 8; - - // Send instruction - _bus_state = SerialState::Writing; - rw(mot_id, CONTROL_TABLE_MOVING_SPEED, 2, data); -} - -void MX12::SetSpeed_rad_s(unsigned char mot_id, float speed) -{ - if (speed > MX12_ABSOLUTE_MAX_SPEED_RAD_S) { - SetSpeed(mot_id, 1); - } else if (speed < -MX12_ABSOLUTE_MAX_SPEED_RAD_S) { - SetSpeed(mot_id, -1); - } else { - SetSpeed(mot_id, speed / MX12_ABSOLUTE_MAX_SPEED_RAD_S); - } -} - -char MX12::IsAvailable(void) -{ - return (_bus_state == SerialState::Idle); -} - -void MX12::rw(unsigned char mot_id, char address, char len, char *data) -{ - - /* Set variables for reception from servovotor */ - _answer = 0; - _status_pck = {.raw = "", - .n_byte = 0, - .servo_id = 0, - .length = 0, - .error = 0, - .n_param = 0, - .param = "", - .received_checksum = 0, - .calculated_checksum = 0, - .parsed = false, - .valid = false - }; - _parser_state = {.expected_field = PacketField::Header1, - .byte_index = 0, - .param_index = 0 - }; - - - /* Initialise instruction packet to forge. - * Instruction Packet is the command data sent to the servomotor. - * - * |Header1|Header2|Packet ID|Length|Instruction|Param1...ParamN|Checksum| - * |-------|-------|---------|------|-----------|---------------|--------| - * | 0xFF | 0xFF |Packet ID|Length|Instruction|Param1...ParamN| CHKSUM | - * | cmd[0]| cmd[1]| cmd[2] |cmd[3]| cmd[4] |cmd[5]... | | - * \__ ___/ \_ _/ \__ __/ - * \/ | \/ \/ | - * mot_id | address data | - * | (len = N-1) | - * \__________________ ________________/ - * \/ - * Length ( cmd[3] ) - */ - char packet[16]; - unsigned char packet_length; - - /* Initialise checksum to calculate - * It is used to check if packet is damaged during communication. - * Status Checksum is calculated according to the following formula: - * - * Status Checksum = ~( ID + Length + Error + Parameter1 + … Parameter N ) - */ - char checksum = 0x00; - - /* header 1 = 0xFF (dynamixel protocol 1.0) */ - packet[0] = 0xff; - - /* header 2 = 0xFF (dynamixel protocol 1.0) */ - packet[1] = 0xff; - - /* packet ID i.e. servomotor id (dynamixel protocol 1.0) */ - packet[2] = mot_id; - checksum += packet[2]; - - /* Guess instruction type. NULL for read, not NULL for write */ - if(data == NULL) { // read instruction - /* byte length of the instruction: parameter and checksum field. */ - /* for read instruction: 1 INSTR + */ - /* 2 PARAM (starting address, length of data) + 1 CHKSUM */ - packet[3] = 4; - checksum += packet[3]; - - /* set write instruction */ - packet[4] = PROTOCOL_INSTRUCTION_READ; - checksum += packet[4]; - - /* Param 1: address to read in the Control Table of RAM Area */ - packet[5] = address; - checksum += packet[5]; - - /* Param 2: number of bytes to read in the Control Table of RAM Area */ - packet[6] = len; - checksum += packet[6]; - - /* Checksum = ~( ID + Length + Instruction + Param1 + … Param N ) */ - packet[7] = ~checksum; - - packet_length = 8; - } else { // write instruction - /* byte length of the instruction: parameter and checksum field */ - /* For write instruction: 1 INSTR + */ - /* (1+len)PARAM (starting Address, bytes to write) + 1 CHKSUM */ - packet[3] = 3 + len; - checksum += packet[3]; - - /* set read instruction */ - packet[4] = PROTOCOL_INSTRUCTION_WRITE; - checksum += packet[4]; - - /* Param 1: address to write in the "Control Table of RAM Area" */ - packet[5] = address; - checksum += packet[5]; - - /* Param 2 to N: data to write in the Control Table of RAM Area */ - for(char i = 0; i < len; i++) { - packet[6 + i] = data[i]; - checksum += data[i]; - } - - /* Checksum = ~( ID + Length + Instruction + Param1 + … Param N ) */ - packet[6 + len] = ~checksum; - - packet_length = 7 + len; - } - - // Send packet - if(mot_id != 0xFE) { - for(char i = 0; i < packet_length; i++) { - _mx12.write(&packet[i], 1); - } - } -} - -// Debug function to print Serial read -void MX12::PrintSerial() -{ - for(int i = 0; i < _status_pck.n_byte; i++) { - printf("%x ", _status_pck.raw[i]); - } - printf("\n"); -} - -char MX12::ReadSerial() -{ - char data; - for(int i = 0; i < _status_pck.n_byte; i++) { - } - return data; -} - -MX12::Status MX12::GetStatus() -{ - // Return the corresponding status code - switch(_status_pck.error) { - case 0: - return Ok; - break; - case 1 << 0: - return InputVoltageError; - break; - case 1 << 1: - return AngleLimitError; - break; - case 1 << 2: - return OverheatingError; - break; - case 1 << 3: - return RangeError; - break; - case 1 << 4: - return ChecksumError; - break; - case 1 << 5: - return OverloadError; - break; - case 1 << 6: - return InstructionError; - break; - default: - return Unknown; - } -} - -void MX12::_Rx_interrupt() -{ - - char c; - - // Try to read serial - if(_mx12.read(&c, 1)) { - - _status_pck.raw[(_parser_state.byte_index)++] = c; - - // State-machine parsing - switch(_parser_state.expected_field) { - - /* c char is interpreted as a Header1 field */ - case PacketField::Header1: - - /* do nothing and set next state to Header2 */ - _parser_state.expected_field = PacketField::Header2; - break; - - /* c char is interpreted as a Header2 field */ - case PacketField::Header2: - - /* do nothing and set next state to Id */ - _parser_state.expected_field = PacketField::Id; - break; - - /* c char is interpreted as ID field */ - case PacketField::Id: - - /* store ID, update checksum and set next state to Length */ - _status_pck.servo_id = c; - _status_pck.calculated_checksum += c; - _parser_state.expected_field = PacketField::Length; - break; - - /* c char is interpreted as length of message data field - * Length = number of Parameters + 2 - * where 2 stands for Length field (1 byte) + Error filed (1 byte) - */ - case PacketField::Length: - - /* store number of param into _status_pck.n_param, - * update calculated_checksum and set next state to Error - */ - _status_pck.n_param = c - 2; - _status_pck.calculated_checksum += c; - _parser_state.expected_field = PacketField::Error; - break; - - /* c char is interpreted as error status field */ - case PacketField::Error: - - /* store error status, update checksum - * and set next state to Data - */ - _status_pck.error = c; - _status_pck.calculated_checksum += c; - _parser_state.expected_field = PacketField::Data; - break; - - /* c char is interpreted as a param field */ - case PacketField::Data: - - /* store current param, increase param_index - * and update checksum */ - _status_pck.param[(_parser_state.param_index)++] = c; - _status_pck.received_checksum += c; - - /* increase param index (_parser_state.dataCount) - * and test if it is the last param to read - */ - if(_parser_state.param_index > _status_pck.n_param) { - /* reset param index and set next state to Checksum */ - _parser_state.param_index = 0; - _parser_state.expected_field = PacketField::Checksum; - } - break; - - /* c char is interpreted as Checksum field */ - case PacketField::Checksum: - - /* store received_checksum, set parsed, store n_byte, - * evalutate valid and set next state to Header1 */ - _status_pck.received_checksum = c; - _status_pck.parsed = true; - _status_pck.n_byte = _parser_state.byte_index; - _status_pck.valid = (_status_pck.received_checksum == c); - _parser_state.expected_field = PacketField::Header1; - - /* set seriel state to Idle */ - _bus_state = SerialState::Idle; - break; - - default: - - /* unexpected case. If it occurs it would be due to a - * code error of this class */ - break; - } - } -} - -/* Code from previous version of the class */ - -/* -void MX12::ReadPosition(unsigned char mot_id) { - // Make a request, interrupt takes care of everything else - _state = State::ReadingPosition; - rw(mot_id, 0x24, 2, NULL); -} - -float MX12::GetPosition(unsigned char mot_id) { - return _angle[mot_id]; -} -*/ - - - - - - -void MX12::cmd_moteur(float Vavance, float Vlat, float Wz) -{ - // mettre en mode wh - char data[2]; - data[1] = 0; - data[0] = 0; - _bus_state = SerialState::Writing; - rw(1, CONTROL_TABLE_CW_ANGLE_LIMIT, 2, data); - rw(2, CONTROL_TABLE_CW_ANGLE_LIMIT, 2, data); - rw(3, CONTROL_TABLE_CW_ANGLE_LIMIT, 2, data); - - - _bus_state = SerialState::Writing; - rw(1, CONTROL_TABLE_CCW_ANGLE_LIMIT, 2, data); - rw(2, CONTROL_TABLE_CCW_ANGLE_LIMIT, 2, data); - rw(3, CONTROL_TABLE_CCW_ANGLE_LIMIT, 2, data); - - float W1; - float W2; - float W3; - float Rc; - float R; - float x1; - float x2; - float x3; - float y1; - float y2; - float y3; - float a1; - float a2; - float a3; - Rc=0.08; // rayon du chassis*10 - R=0.019; // rayon de la roue*10 - W1=0; - W2=0; - W3=0; - a1 = 4.74 ; - a2 = 0.5; - a3 = 2.64; - x1 = -0.0024; - x2 = 0.0625; - x3 = -0.0643; - y1 = -0.073; - y2 = 0.0361; - y3 = 0.037; - //Vtm_smax=0.8; //sert pour calculer valeurs -999->999 - //Vnm_smax=0.9; - //Wcrd_smax=2.9; - //if (Vtm_s>Vtm_smax) - // {Vtm_s=Vtm_smax;} - //if (Vnm_s>Vnm_smax) - // {Vnm_s=Vnm_smax;} - //if (Wcrd_s>Wcrd_smax) - // {Wcrd_s=Wcrd_smax;} - //if (Wcrd_s<-Wcrd_smax) - // {Wcrd_s=-Wcrd_smax;} - - W1=1/R*(-cosf(a1)*Vavance + sinf(a1)*y1*Wz - sinf(a1)*Vlat + cosf(a1)*x1*Wz); //loi de commande moteur 1 - W2=1/R*(-cosf(a2)*Vavance + sinf(a2)*y2*Wz - sinf(a2)*Vlat + cosf(a2)*x2*Wz); - W3=1/R*(-cosf(a3)*Vavance + sinf(a3)*y3*Wz - sinf(a3)*Vlat + cosf(a3)*x3*Wz); - printf("%d %d %dn\r",(int)(1000*W1),(int)(1000*W2),(int)(1000*W3)); - - - SetSpeed_rad_s(1,W1); // impose la vitesse au moteur 1 - SetSpeed_rad_s(2,W2); - SetSpeed_rad_s(3,W3); - - - -} - -void MX12::cmd_moteur_rampe_unitaire(int id_moteur, float w_moteur, int step, float time) -{ - -} - -void MX12::eteindre_moteurs() -{ - char data[1]; - - data[0] = 0; - - - // Send instruction - _bus_state = SerialState::Writing; - rw(1, CONTROL_TABLE_TORQUE_ENABLE, 1, data); - _bus_state = SerialState::Writing; - rw(2, CONTROL_TABLE_TORQUE_ENABLE, 1, data); - _bus_state = SerialState::Writing; - rw(3, CONTROL_TABLE_TORQUE_ENABLE, 1, data); -} - - - -void MX12::cmd_moteur_multiturn(float pos1, float pos2, float pos3) -{ - // eteindre les moteurs - eteindre_moteurs(); - // mettre en mode multiturn - char data[2]; - data[1] = 255; - data[0] = 15; - _bus_state = SerialState::Writing; - rw(1, CONTROL_TABLE_CW_ANGLE_LIMIT, 2, data); - rw(2, CONTROL_TABLE_CW_ANGLE_LIMIT, 2, data); - rw(3, CONTROL_TABLE_CW_ANGLE_LIMIT, 2, data); - - - _bus_state = SerialState::Writing; - rw(1, CONTROL_TABLE_CCW_ANGLE_LIMIT, 2, data); - rw(2, CONTROL_TABLE_CCW_ANGLE_LIMIT, 2, data); - rw(3, CONTROL_TABLE_CCW_ANGLE_LIMIT, 2, data); - - //relever la position - int pas1 = pos1-28672/60; - int pas2 = pos2-28672/60; - int pas3 = pos3-28672/60; - - for (int i = 0; i < 61; i++) { - int goal_position1 = i * pas1 - 28672; - if (goal_position1 < 0) { - goal_position1 = goal_position1 + 28627 + 36864; - } - char data1[2]; - data1[1] = goal_position1%256; - data1[0] = goal_position1/256; - - int goal_position2 = i * pas2 - 28672; - if (goal_position2 < 0) { - goal_position2 = goal_position2 + 28627 + 36864; - } - char data2[2]; - data2[1] = goal_position2%256; - data2[0] = goal_position2/256; - - int goal_position3 = i * pas3 - 28672; - if (goal_position3 < 0) { - goal_position3 = goal_position3 + 28627 + 36864; - } - char data3[2]; - data3[1] = goal_position3%256; - data3[0] = goal_position3/256; - - rw(1, CONTROL_TABLE_GOAL_POSITION, 2, data1); - thread_sleep_for(60); - rw(2, CONTROL_TABLE_GOAL_POSITION, 2, data2); - thread_sleep_for(60); - rw(3, CONTROL_TABLE_GOAL_POSITION, 2, data3); - thread_sleep_for(60); - - thread_sleep_for(1000); - } -}