I can get a motor to spin, so this doesn’t qualify as “getting started” but I’m still quite a ways from “actually using”.
I’m re-purposing a cordless brushless power tool, specifically a Milwaukee 18V FUEL Mud Mixer (Milwaukee 2810-20). It’s a nice small package with an integrated planetary (52:1) gearset. Prior to disassembly I measured the output shaft at over 500 RPM (26,000 at the motor) and under near stall (measured 40NM), it was drawing 90amps from the battery pack. It has Hall sensors, but adding an encoder would be…very complicated. (tool only for about $150 US retail) Ultimately I’m looking to drive a leadscrew so I need trajectory/position control.
I mostly followed the setup for Hoverboard wheelmotors, adjusting polepairs to two (four magnets on the rotor) and encoder.config.cpr to 12. I had some trouble getting the encoder offset calibration to run, but I was able to get past it after setting motor.config.calibration_current much higher (40A) - this motor has a very high cogging torque.
At this point I have several issues:
I can put it in velocity mode and spin it at setpoints up to about 2000, beyond that it shuts down and hex(odrv0.axis0.error) gives me ‘0x60’. and odrv0.axis0.motor gives me an error 0x0400. At a setpoint of 2000 the unit is drawing about 2.5 amps from the battery pack.
I attempted to experiment with trajectory control, but odrv0.axis0.controller.config.control_mode = CTRL_MODE_TRAJECTORY_CONTROL gives me the error: NameError: name ‘CTRL_MODE_TRAJECTORY_CONTROL’ is not defined. What am I missing?
I’ve attempted to experiment with position control. I’ve had some limited success, but have at least two issues. I can only send it relatively short moves (under about 1000 counts) - longer moves seem to try to spin too fast and give me the same errors as above. And after it gets to destination, it “hunts”. Moving ± about 50 counts past the setpoint every few seconds. If I had to guess, I’d say that this is a combination of high inertial load and the cogging torque and could be improved with tuning, but I would have thought there should be some deadband?
The error 0x0400 seems to be ERROR_CURRENT_SENSE_SATURATION, which I think has something to do with the setting odrv0.axis0.motor.config.requested_current_range that was adjusted in the setup, but I don’t see any guidance of which way to adjust it based on what criteria or acceptable range?
Any help would be appreciated.
and just in case it helps…
In : odrv0.axis0.motor Out: error = 0x0400 (int) armed_state = 0 (int) is_calibrated = True (bool) current_meas_phB = 0.06314337253570557 (float) current_meas_phC = -0.03106069564819336 (float) DC_calib_phB = -1.210925817489624 (float) DC_calib_phC = -1.49945068359375 (float) phase_current_rev_gain = 0.012500000186264515 (float) current_control: p_gain = 0.0018225724343210459 (float) i_gain = 3.1034533977508545 (float) v_current_control_integral_d = -2.7737841606140137 (float) v_current_control_integral_q = -3.541830062866211 (float) Ibus = 6.324885845184326 (float) final_v_alpha = -4.412751197814941 (float) final_v_beta = -0.4657534062862396 (float) Iq_setpoint = 30.375 (float) Iq_measured = 3.320199966430664 (float) max_allowed_current = 30.375 (float) overcurrent_trip_level = 33.75 (float) gate_driver: drv_fault = 0 (int) timing_log: TIMING_LOG_GENERAL = 0 (int) TIMING_LOG_ADC_CB_I = 2526 (int) TIMING_LOG_ADC_CB_DC = 13062 (int) TIMING_LOG_MEAS_R = 0 (int) TIMING_LOG_MEAS_L = 0 (int) TIMING_LOG_ENC_CALIB = 0 (int) TIMING_LOG_IDX_SEARCH = 0 (int) TIMING_LOG_FOC_VOLTAGE = 0 (int) TIMING_LOG_FOC_CURRENT = 8130 (int) config: pre_calibrated = True (bool) pole_pairs = 2 (int) calibration_current = 40.0 (float) resistance_calib_max_voltage = 3.0 (float) phase_inductance = 1.822572448872961e-05 (float) phase_resistance = 0.03103453479707241 (float) direction = -1 (int) motor_type = 0 (int) current_lim = 50.0 (float) requested_current_range = 5.0 (float) current_control_bandwidth = 100.0 (float)
In : odrv0.axis0.controller Out: error = 0x0000 (int) pos_setpoint = -1.9750028848648071 (float) vel_setpoint = 0.0 (float) vel_integrator_current = 2.004138708114624 (float) current_setpoint = 0.0 (float) vel_ramp_target = 0.0 (float) vel_ramp_enable = False (bool) config: control_mode = 2 (int) pos_gain = 1.0 (float) vel_gain = 0.019999999552965164 (float) vel_integrator_gain = 0.10000000149011612 (float) vel_limit = 10000.0 (float) vel_limit_tolerance = 1.2000000476837158 (float) vel_ramp_rate = 10000.0 (float) setpoints_in_cpr = False (bool) set_pos_setpoint(pos_setpoint: float, vel_feed_forward: float, current_feed_forward: float) set_vel_setpoint(vel_setpoint: float, current_feed_forward: float) set_current_setpoint(current_setpoint: float) move_to_pos(goal_point: float) start_anticogging_calibration()
In : odrv0 Out: vbus_voltage = 20.126293182373047 (float) serial_number = 2084378C3548 (int) hw_version_major = 3 (int) hw_version_minor = 5 (int) hw_version_variant = 24 (int) fw_version_major = 0 (int) fw_version_minor = 4 (int) fw_version_revision = 7 (int) fw_version_unreleased = 0 (int) user_config_loaded = True (bool) brake_resistor_armed = True (bool) system_stats: uptime = 139304 (int) min_heap_space = 14264 (int) min_stack_space_axis0 = 7852 (int) min_stack_space_axis1 = 7860 (int) min_stack_space_comms = 3136 (int) min_stack_space_usb = 1332 (int) min_stack_space_uart = 3964 (int) min_stack_space_usb_irq = 1820 (int) min_stack_space_startup = 556 (int) usb: ... i2c: ... config: brake_resistance = 0.4699999988079071 (float) enable_uart = True (bool) enable_i2c_instead_of_can = False (bool) enable_ascii_protocol_on_usb = True (bool) dc_bus_undervoltage_trip_level = 8.0 (float) dc_bus_overvoltage_trip_level = 25.920001983642578 (float) gpio1_pwm_mapping: ... gpio2_pwm_mapping: ... gpio3_pwm_mapping: ... gpio4_pwm_mapping: ... axis0: error = 0x0020 (int) step_dir_active = False (bool) current_state = 1 (int) requested_state = 0 (int) loop_counter = 1101765 (int) config: ... get_temp() motor: ... controller: ... encoder: ... sensorless_estimator: ... trap_traj: ... axis1: error = 0x0000 (int) step_dir_active = False (bool) current_state = 1 (int) requested_state = 0 (int) loop_counter = 1101812 (int) config: ... get_temp() motor: ... controller: ... encoder: ... sensorless_estimator: ... trap_traj: ... can: node_id = 0 (int) TxMailboxCompleteCallbackCnt = 0 (int) TxMailboxAbortCallbackCnt = 0 (int) received_msg_cnt = 0 (int) received_ack = 0 (int) unexpected_errors = 0 (int) unhandled_messages = 0 (int) test_property = 0 (int) test_function(delta: int) get_oscilloscope_val(index: int) get_adc_voltage(gpio: int) save_configuration() erase_configuration() reboot() enter_dfu_mode()