Build a Robot, Part II

Tom Jacobs
4 min readMay 5, 2024

--

Ok, so we’ve got the giant motors motoring along.

Now it’s time to build a robot with them. Maybe something like this:

StrongArm wants to smash things

Let’s attach the two motors together, quick, CAD up a motor adaptor:

Will it be blue? Nope.

A quick three hour print later with my trusty Monoprice Voxel 3D printer, we have two motors joined together:

With added terminating resistor on CAN port

Ok, now what goes on the end of it? How about an inanimate carbon rod:

In Rod We Trust

Ok, how about we make a classic tube adaptor:

Now we’re adaptin’.

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:

Rod goes up, rod goes down. Rod falls off.

Let’s try both motors at once:

Probably could do with that rod adaptor being printed by now

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

Stay tuned for part III, where it all comes together into a magical useful STRONG ARM.

--

--