Build a Robot, Part II
Ok, so we’ve got the giant motors motoring along.
Now it’s time to build a robot with them. Maybe something like this:
Let’s attach the two motors together, quick, CAD up a motor adaptor:
A quick three hour print later with my trusty Monoprice Voxel 3D printer, we have two motors joined together:
Ok, now what goes on the end of it? How about an inanimate carbon rod:
Ok, how about we make a classic tube adaptor:
Ok, how about some position control of the two motors. These motors come with a motor encoder, and support for a secondary output encoder, but the output encoder is not installed. So we’ll have to use the motor encoder.
In the motor protocol document, let’s take a look at the commands. There seem to be a few of them. Reading the single-turn position of the motor is not that helpful, because the actuator has a 35:1 gear ratio, so the motor rotates 35 times for every output rotation, so that doesn’t tell us much about the output position by itself. But the motor controller keeps track of the multi-turn position, i.e. the calculated position of the output shaft, based on how many times the motor has turned a full revolution. Let’s take a look at the multi-turn position readings, with these commands:
// Commands
#define COMMAND 0x20
#define GET_PID_PARAMS 0x30
#define GET_OUTPUT_ANGLE_ENCODER 0x60
#define GET_OUTPUT_ANGLE_ORIGINAL 0x61
#define GET_OUTPUT_ANGLE_ZERO 0x62
#define SET_OUTPUT_ZERO_VALUE 0x63
#define SET_OUTPUT_ZERO_CURRENT 0x64
#define GET_OUTPUT_ANGLE 0x92 // Multi-turn
#define SET_OUTPUT_ANGLE 0xA4 // Multi-turn
#define GET_MOTOR_ANGLE 0x94
#define SET_MOTOR_ANGLE 0xA6
#define SHUT_DOWN_MOTOR 0x80
#define STOP_MOTOR 0x81
#define RESET_MOTOR 0x76
#define SET_TORQUE 0xA1
#define GET_SET_ID 0x79
I’ve put this up on GitHub, so you can see these being used here: https://github.com/tjacobs/StrongArm/blob/main/motor/motor.ino#L15
After reading the multi-turn position with GET_OUTPUT_ANGLE, and setting to zero at the current position with SET_OUTPUT_ZERO_CURRENT, we can start to set an output position on the motor in a loop:
// Set action
static int angle = 0;
static int position = 1;
static int speed = 100;
static int t = 0;
t++;
if (t >= 2000) {
// Reset
t = 0;
// Flip
if (position == 1) position = -1;
else if (position == -1) position = 1;
angle = position * 2000;
// Do action
sendCANCommand(MOTOR + 2, SET_OUTPUT_ANGLE, angle, speed, 0);
}
Wow, we’re a wizard, we have a self waving magic wand:
Let’s try both motors at once:
How about drawing a square in the air:
// Set action
static int state = 1;
static int angle1 = 0;
static int angle2 = 0;
static int speed = 100;
static int t = 0;
t++;
if (t >= 500) {
// Reset
t = 0;
// Next state
if (state > 0) state++;
if (state > 4) state = 1;
// State
if (state == 1) angle1 = 2000;
else if (state == 2) angle2 = 2000;
else if (state == 3) angle1 = -2000;
else if (state == 4) angle2 = -2000;
// Do action
if (state >= 1) {
// Set output angle
sendCANCommand(MOTOR + 1, SET_OUTPUT_ANGLE, angle1, speed, 0);
delay(100);
sendCANCommand(MOTOR + 2, SET_OUTPUT_ANGLE, angle2, speed, 0);
delay(100);
}
}
Stay tuned for part III, where it all comes together into a magical useful STRONG ARM.