I’ve set odrv0.axis1.config.can.encoder_count_rate_ms = 10
and have confirmed manually that checking count_in_cpr
changes as I rotate the motor.
In [45]: odrv0.axis1.encoder.count_in_cpr
Out[45]: 88
Modifying the can_dbc_example script I’m printing the values of the encoders before and after spinning them up
for message in bus:
if message.arbitration_id == 0x0A | axisID << 5:
print(db.decode_message(f'{axis}_Get_Encoder_Count', msg.data))
break
Sweeping velocity between -4 and 4.
CTRL+C to stop
{'Shadow_Count': 1092616192, 'Count_in_CPR': 1092616192}
{'Shadow_Count': 1092616192, 'Count_in_CPR': 1092616192}
Velocity: -3.04
Velocity: -3.92
Velocity: -3.8
Velocity: -2.72
^C
Done! Setting to AXIS_STATE_IDLE
CLOSED_LOOP_CONTROL
CLOSED_LOOP_CONTROL
CLOSED_LOOP_CONTROL
CLOSED_LOOP_CONTROL
CLOSED_LOOP_CONTROL
CLOSED_LOOP_CONTROL
IDLE
Axis has returned to Idle state.
{'Shadow_Count': 0, 'Count_in_CPR': 2147483649}
I’m not sure how accurate those values are but what matters is they’re changing. My C++ code looks like this
int ODrive::get_encoder_estimates(axis axis){
struct can_frame rx_msg;
// Encoder estimates are sent every 10ms. Read for 100ms
auto start = std::chrono::high_resolution_clock::now();
while (std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start)
.count() < 100) {
int nbytes = read(sockfd, &rx_msg, sizeof(struct can_frame));
if (nbytes < 0) {
printf("Error in reading can frame\n");
return -1;
}
if (rx_msg.can_id == (axis.id << 5 | GET_ENCODER_COUNTS)) {
break;
}
}
// print raw values of rx_msg
printf("rx_msg.data: %d %d %d %d %d %d %d %d \n",rx_msg.data[0],rx_msg.data[1],rx_msg.data[2],rx_msg.data[3],rx_msg.data[4],rx_msg.data[5],rx_msg.data[6],rx_msg.data[7]);
// return float(position_estimate);
bytes2Float(rx_msg.data, &axis.encoder_position_estimate);
return 0;
}
where bytes2Float
just casts the raw int array to a float and assigns it to the pointer’s encoder position in the struct I’ve made, and GET_ENCODER_COUNTS
is const uint32_t GET_ENCODER_COUNTS = 10;
. Here’s the output of my test
Found heartbeat on Axis 0
Found heartbeat on Axis 1
Testing closed loop control...
rx_msg.data: 133 254 255 255 71 0 0 0
rx_msg.data: 231 37 0 0 73 0 0 0
Encoder counts: 6.12227e-41, -5.71949e+06
Closed loop control test passed // Motors move here for 1 second
rx_msg.data: 133 254 255 255 71 0 0 0
rx_msg.data: 231 37 0 0 73 0 0 0
Encoder counts: 6.12227e-41, -5.71949e+06
What am I missing here?