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);
- }
-}