Implementing MOVE Command Firmware
By Jose Alcantar, Electronics and Controls Engineer
Introduction:
The pathfinder is controlled using the direction pad on both the control panel and through RC mode on the Arxterra app. When using the D-pad, the MOVE command is called from the 3Dotlibrary which is used to control the movement of the motors. Through the design of the 3Dotlibrary, pins 5,6,10 and 13 on the Arduino Leonardo are tied to the MOVE command. Because of how are system is designed, firmware was written to take advantage of the data from the D-pad and MOVE command, without using the dedicated pins.
When a button is pressed on the D-pad a packet is sent through Bluetooth and is decoded by the Arduino. The packet data is sent in the following format:
{A5, (packetlength), 01 (command id), 01 80 01 80, (checksum)};
The first value after the command id specifies the direction for the left set of wheels on the pathfinder followed by the second byte which is the PWM value to control the speed of those motors. The last next two bytes are used to control the right set of motors.
The following is a brief description of how the index values are interpreted
/***********************************
* motion command = 0x01
* motordata[3] left run (FORWARD = index 1, BACKWARD = index 2,
BRAKE = index 3, RELEASE = index 4)
* motordata[4] left speed 0 – 255
* motordata[5] right run (FORWARD, BACKWARD, BRAKE, RELEASE)
* motordata[6] right speed 0 – 255
* example
* forward half speed 0x01, 0x01, 0x80, 0x01, 0x80 0101800180
***********************************/
Firmware:
Understanding the data being sent from the D-pad, firmware was written for the motor controls. A series of if-else statements were used to account for the different data packets that the Arxterra app transmits:
void moveHandler (uint8_t cmd, uint8_t param[], uint8_t n)
{
Serial.write(cmd); // move command = 0x01
Serial.write(n); // number of param = 4
for (int i=0;i<n;i++) // param = 01 80 01 80
{
Serial.write (param[i]);
}
if(param[0] == 1 && param[2] == 1)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
left_forward();
right_forward();
}
else if( param[0] == 2 && param[2] == 2)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
left_reverse();
right_reverse();
}
else if( param[0] == 1 && param[2] == 2)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
right_turn();
}
else if(param[0] == 2 && param[2] == 1)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
left_turn();
}
else if( param[0] == 1 && param[2] == 4)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
left_forward();
right_release();
}
else if(param[0] == 2 && param[2] == 4)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
left_forward();
right_release();
}
else if(param[0] == 4 && param[2] == 1)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
left_release();
right_forward();
}
else if(param[0] == 4 && param[2] == 2)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
left_release();
right_reverse();
}
else if(param[0] == 4 && param[2] == 4)
{
input_pwm1 = param[1];
input_pwm2 = param[3];
left_release();
right_release();
}
Conclusion:
Following this code format, the motors can be controlled to move forward, reverse, brake, and release. Depending on the values being transmitted, the functions to drive the motors are called. The PWM values are then extracted from the packet and stored onto a variable to control the speed.