[Solved] Upgrade from Halls to Rotary Encoders, no. vel or .pos movement yet

Hello world! Thanks for taking time to help solve an tricky issue. I get stuck trying to spin BLDC wheel after
odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION followed by the cursory .save and .reboot. Encoding revs w Halls worked ok but now I’m hungry for some better resolution with $10 rotary encoder used in Getting Started example and seen below. Now I can only get as far as being able to read encoder counts on both wheel from rotary. A and B are working well as values go up and down in position counts as wheel is hand turned.

In [41]: odrv0.axis0.encoder.pos_estimate
Out[41]: 9577.0166015625

No Z available for rev INDEX. New encoders ordered for INDEX option. Am I missing something in this upgrade? If you have experience with this issue please do drop a line. Thanks a mint!
Hardware



2 - 350 W 10" hooverboard Outrunner style BLDC motors
2 - 400 p/r encoders (as seen in Odrive Doc example)
2 - planetary gear sets 32:8 (Inner wheel:encoder shaft)
Odrive 45V v3.5 w 36 V Li-ion. The motor Current level set a default 10 A.

Odrive Doc was followed on hooverboard cal and test with one change for encoder types: hall(90 cpr) to rotary (9600 cpr) cpr = 400 p/r * 4 quad. * 4 from gear set (32:8)

odrv0.axis0.encoder.config.mode = ENCODER_MODE_INCREMENTAL 
odrv0.axis0.encoder.config.cpr = 9600

In [66]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
…:

In [67]: odrv0.axis0.encoder
…:
Out[67]:
count_in_cpr = 0 (int)
vel_estimate = 0.0 (float)
phase = -0.05405902862548828 (float)
interpolation = 0.5 (float)
pos_estimate = 0.02437400072813034 (float)
is_ready = True (bool)
index_found = False (bool)
hall_state = 6 (int)
config:
mode = 0 (int)
zero_count_on_find_idx = True (bool)
calib_range = 0.019999999552965164 (float)
use_index = False (bool)
offset = 2565 (int)
bandwidth = 100.0 (float)
offset_float = 1.0066719055175781 (float)
idx_search_speed = 10.0 (float)
cpr = 9600 (int)
pre_calibrated = True (bool)
pos_cpr = 0.024843774735927582 (float)
shadow_count = 0 (int)
error = 0x0000 (int)

I tried this below and all the other modes I could find in Doc but no spin up like with Hall sensors from before upgrade. I have also tried to set up motor with
odrv0.axis0.motor.config.motor_type=MOTOR_TYPE_HIGH_CURRENT then
odrv0.erase_configuration() only to start try hooverboard with rotary encoder. Below is another attempt with said configuration. Fun stuff! I can’t wait to get back up and Odrivin’ again with the added cpr. Thank you kindly for any and all feedback :0)

In [17]: odrv0.axis0.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL

In [18]: odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

In [19]: odrv0.axis0.controller.vel_setpoint = 20

In [20]: odrv0.axis0.motor.current_control.Iq_measured
Out[20]: -0.18101319670677185

In [21]: odrv0.axis0.motor.current_control.Iq_setpoint
Out[21]: 0.2471545934677124

What errors are you getting? Are you running on odrivetool 0.4.8? If so, what does odrv0.dump_errors() output?

Hi Jalbob,
Thanks for your questions. We are running odrivetool 0.4.7 so the dump_errors(odrv0) is not an option yet. How does one uprade to odrivetool 0.4.8? Here is what dump_errors(odrv0) returned.


NameError Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/fibre/shell.py in
----> 1 dump_errors(odrv0)

NameError: name ‘dump_errors’ is not defined

In [9]: dump_errors(odrv0)

NameError Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/fibre/shell.py in <mod

Also I am concerned that .pos_estimate and .pos_cpr are different by a large margin. Is this normal?
odrv0.axis0.encoder.pos_estimate
Out[9]: -1843.98291015625

In [10]: odrv0.axis0.encoder.pos_cpr
Out[10]: 7756.0244140625

This link looks to be firmware updates and not odrivetool update.
Is there a command in linux to update utility odrive 0.4.7 to odrive 0.4.8?

This worked for me as im running pip3.5
$pip3.5 install odrive --upgrade

In [1]: dump_errors(odrv0)
Axis0:
axis: Error(s):
ERROR_INVALID_STATE
motor: no error
encoder: no error
controller: no error
Axis1:
axis: no error
motor: no error
encoder: no error
controller: no error

You’re still in Hall sensor mode I think. Try odrv0.erase_configuration() and then set everything up again according to the Getting Started guide.

Hi thanks for your response. Hope you had a nice weekend. We tried:
odrv0.erase_configuration()
then followed getting started hooverboard method changing only .mode from HALL to INCREMENTAL and cpr value. Still no spin up…

In [10]: odrv0.axis0.encoder.config.mode = ENCODER_MODE_INCREMENTAL

In [11]: odrv0.axis0.encoder.config.cpr = 9600

In [27]: dump_errors(odrv0)
Axis0:
axis: no error
motor: no error
encoder: no error
controller: no error
Axis1:
axis: no error
motor: no error
encoder: no error
controller: no error

In [28]: odrv0.axis0.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL
…:

In [29]: odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
…:

In [30]: odrv0.axis0.controller.vel_setpoint = 120
…:

In [31]: odrv0.axis0.controller.vel_setpoint = 0

In [32]: dump_errors(odrv0)
Axis0:
axis: Error(s):
ERROR_INVALID_STATE
motor: no error
encoder: no error
controller: no error
Axis1:
axis: no error
motor: no error
encoder: no error
controller: no error

------------------------------------ for kindiana 3/25/19 3 PM--------------------------

In [46]: odrv0.erase_configuration()

In [47]: odrv0.reboot()
Oh no odrv0 disappeared

ChannelBrokenException Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/fibre/shell.py in
----> 1 odrv0.reboot()

/usr/local/lib/python3.5/dist-packages/fibre/remote_object.py in call(self, *args)
160 for i in range(len(args)):
161 self._inputs[i].set_value(args[i])
–> 162 self._parent.channel.remote_endpoint_operation(self._trigger_id, None, True, 0)
163 if len(self._outputs) > 0:
164 return self._outputs[0].get_value()

/usr/local/lib/python3.5/dist-packages/fibre/protocol.py in remote_endpoint_operation(self, endpoint_id, input, expect_ack, output_length)
307 try:
308 if wait_any(self._resend_timeout, ack_event, self._channel_broken) != 0:
–> 309 raise ChannelBrokenException()
310 except TimeoutError:
311 attempt += 1

ChannelBrokenException:

Reconnected to ODrive 207D37943548 as odrv0
In [48]: odrv0.axis0.motor.config.pole_pairs = 15

In [49]: odrv0.axis0.motor.config.resistance_calib_max_voltage =4

In [50]: odrv0.save_configuration()
…:

In [51]: odrv0.reboot()
Oh no odrv0 disappeared

ChannelBrokenException Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/fibre/shell.py in
----> 1 odrv0.reboot()

/usr/local/lib/python3.5/dist-packages/fibre/remote_object.py in call(self, *args)
160 for i in range(len(args)):
161 self._inputs[i].set_value(args[i])
–> 162 self._parent.channel.remote_endpoint_operation(self._trigger_id, None, True, 0)
163 if len(self._outputs) > 0:
164 return self._outputs[0].get_value()

/usr/local/lib/python3.5/dist-packages/fibre/protocol.py in remote_endpoint_operation(self, endpoint_id, input, expect_ack, output_length)
307 try:
308 if wait_any(self._resend_timeout, ack_event, self._channel_broken) != 0:
–> 309 raise ChannelBrokenException()
310 except TimeoutError:
311 attempt += 1

ChannelBrokenException:

Reconnected to ODrive 207D37943548 as odrv0
In [52]: odrv0.axis0.motor.config.current_control_bandwidth = 100
…:

In [53]: odrv0.axis0.encoder.config.mode = ENCODER_MODE_INCREMENTAL

In [54]: odrv0.axis0.encoder.config.cpr = 9600

In [55]: odrv0.axis0.encoder.config.bandwidth = 100

In [56]: odrv0.axis0.controller.config.pos_gain = 1
…:

In [57]: odrv0.axis0.controller.config.vel_gain = 0.02
…:

In [58]: odrv0.axis0.controller.config.vel_integrator_gain = 0.1
…:

In [59]: odrv0.axis0.controller.config.vel_limit = 1000
…:

In [60]: odrv0.axis0.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL
…:

In [61]: odrv0.save_configuration()
…:

In [62]: odrv0.reboot()
…:
Oh no odrv0 disappeared

ChannelBrokenException Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/fibre/shell.py in
----> 1 odrv0.reboot()

/usr/local/lib/python3.5/dist-packages/fibre/remote_object.py in call(self, *args)
160 for i in range(len(args)):
161 self._inputs[i].set_value(args[i])
–> 162 self._parent.channel.remote_endpoint_operation(self._trigger_id, None, True, 0)
163 if len(self._outputs) > 0:
164 return self._outputs[0].get_value()

/usr/local/lib/python3.5/dist-packages/fibre/protocol.py in remote_endpoint_operation(self, endpoint_id, input, expect_ack, output_length)
307 try:
308 if wait_any(self._resend_timeout, ack_event, self._channel_broken) != 0:
–> 309 raise ChannelBrokenException()
310 except TimeoutError:
311 attempt += 1

ChannelBrokenException:

Reconnected to ODrive 207D37943548 as odrv0
In [63]: odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION
…:

In [64]: odrv0.axis0.motor
…:
Out[64]:
is_calibrated = True (bool)
current_meas_phB = 0.03713488578796387 (float)
timing_log:
TIMING_LOG_IDX_SEARCH = 0 (int)
TIMING_LOG_ADC_CB_DC = 12886 (int)
TIMING_LOG_ENC_CALIB = 0 (int)
TIMING_LOG_ADC_CB_I = 2502 (int)
TIMING_LOG_MEAS_R = 7370 (int)
TIMING_LOG_FOC_CURRENT = 0 (int)
TIMING_LOG_FOC_VOLTAGE = 7306 (int)
TIMING_LOG_MEAS_L = 7366 (int)
TIMING_LOG_GENERAL = 0 (int)
current_control:
v_current_control_integral_d = 0.0 (float)
overcurrent_trip_level = 67.5 (float)
max_allowed_current = 60.75 (float)
final_v_alpha = 0.0 (float)
Ibus = 0.0 (float)
p_gain = 0.04346119984984398 (float)
final_v_beta = 0.0 (float)
Iq_setpoint = 0.0 (float)
v_current_control_integral_q = 0.0 (float)
i_gain = 20.24873924255371 (float)
Iq_measured = 0.0 (float)
error = 0x0000 (int)
DC_calib_phC = -1.480223298072815 (float)
phase_current_rev_gain = 0.02500000037252903 (float)
DC_calib_phB = -1.326115369796753 (float)
current_meas_phC = -0.050664544105529785 (float)
gate_driver:
drv_fault = 0 (int)
armed_state = 0 (int)
config:
current_control_bandwidth = 100.0 (float)
motor_type = 0 (int)
phase_resistance = 0.20248739421367645 (float)
phase_inductance = 0.0004346120113041252 (float)
resistance_calib_max_voltage = 4.0 (float)
pole_pairs = 15 (int)
calibration_current = 10.0 (float)
current_lim = 10.0 (float)
pre_calibrated = False (bool)
requested_current_range = 60.0 (float)
direction = 1 (int)

In [65]: odrv0.axis0.motor.config.pre_calibrated = True
…:

In [66]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
…:

In [67]: odrv0.axis0.encoder
Out[67]:
vel_estimate = 0.0 (float)
phase = -0.061758995056152344 (float)
is_ready = True (bool)
count_in_cpr = 0 (int)
error = 0x0000 (int)
interpolation = 0.5 (float)
config:
use_index = False (bool)
offset_float = 0.7908750176429749 (float)
zero_count_on_find_idx = True (bool)
idx_search_speed = 10.0 (float)
calib_range = 0.019999999552965164 (float)
bandwidth = 100.0 (float)
cpr = 9600 (int)
mode = 0 (int)
pre_calibrated = False (bool)
offset = 2566 (int)
index_found = False (bool)
shadow_count = 0 (int)
pos_estimate = 0.9972842931747437 (float)
hall_state = 4 (int)
pos_cpr = 0.9751157760620117 (float)

In [68]: odrv0.axis0.encoder.config.pre_calibrated = True
…:

In [69]: odrv0.save_configuration()
…:

In [70]: odrv0.reboot()
…:
Oh no odrv0 disappeared

ChannelBrokenException Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/fibre/shell.py in
----> 1 odrv0.reboot()

/usr/local/lib/python3.5/dist-packages/fibre/remote_object.py in call(self, *args)
160 for i in range(len(args)):
161 self._inputs[i].set_value(args[i])
–> 162 self._parent.channel.remote_endpoint_operation(self._trigger_id, None, True, 0)
163 if len(self._outputs) > 0:
164 return self._outputs[0].get_value()

/usr/local/lib/python3.5/dist-packages/fibre/protocol.py in remote_endpoint_operation(self, endpoint_id, input, expect_ack, output_length)
307 try:
308 if wait_any(self._resend_timeout, ack_event, self._channel_broken) != 0:
–> 309 raise ChannelBrokenException()
310 except TimeoutError:
311 attempt += 1

ChannelBrokenException:

Reconnected to ODrive 207D37943548 as odrv0
In [71]: dump_errors(odrv0)
Axis0:
axis: no error
motor: no error
encoder: no error
controller: no error
Axis1:
axis: no error
motor: no error
encoder: no error
controller: no error

In [72]: odrv0.axis0.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL
…:

In [73]: odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
…:

In [74]: odrv0.axis0.controller.vel_setpoint = 120
…:

In [75]: dump_errors(odrv0)
Axis0:
axis: Error(s):
ERROR_INVALID_STATE
motor: no error
encoder: no error
controller: no error
Axis1:
axis: no error
motor: no error
encoder: no error
controller: no error

1 Like

SOLVED -
The gains needed to scaled back due to new encoder resolution. Before with Halls - 90 cpr as seen in Odrive hooverboard Doc. After with rotary encoders - 9600 cpr
.pos_gain = 0.5, .vel_gain = 0.0005 and .vel_intergrator_gain = 0.0025. The current increase from 10 A to 20 A and we are back on the road. Special thanks to all!

1 Like

I have a doubt which arose while calibrating the Encoder, the command prompt kept showing name error. The command used was:
odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
The error was name error. Can anyone assist in this??

And, before executing this step, the motor config was assigned True, command used:
odrv0.axis0.motor.config.pre_calibrated = True