You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
5.4 KiB
Python
155 lines
5.4 KiB
Python
from pathlib import Path, PurePath
|
|
|
|
import click
|
|
import odrive
|
|
import yaml
|
|
|
|
# CONSTANTS
|
|
AXIS_STATE_UNDEFINED = 0
|
|
AXIS_STATE_IDLE = 1
|
|
AXIS_STATE_STARTUP_SEQUENCE = 2
|
|
AXIS_STATE_FULL_CALIBRATION_SEQUENCE = 3
|
|
AXIS_STATE_MOTOR_CALIBRATION = 4
|
|
AXIS_STATE_SENSORLESS_CONTROL = 5
|
|
AXIS_STATE_ENCODER_INDEX_SEARCH = 6
|
|
AXIS_STATE_ENCODER_OFFSET_CALIBRATION = 7
|
|
AXIS_STATE_CLOSED_LOOP_CONTROL = 8
|
|
|
|
INPUT_MODE_VEL_RAMP = 2
|
|
|
|
# OPTIONS
|
|
|
|
config_option = click.option(
|
|
'-c',
|
|
'--config',
|
|
default=PurePath(Path(__file__).parent, Path('odrive.yaml')),
|
|
type=Path,
|
|
help='A config file for the odrive. Defaults to odrive.yaml.'
|
|
)
|
|
|
|
|
|
@click.group()
|
|
def cli():
|
|
pass
|
|
|
|
|
|
@cli.command('config-encoder')
|
|
@config_option
|
|
def config_encoder(**options):
|
|
"""Configures an Odrive with a provided .yaml file of config values."""
|
|
odrv0 = odrive.find_any()
|
|
odrv0.axis0.encoder.config.calib_range = 0.05
|
|
odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
|
|
# Set negative to reverse index search direction
|
|
odrv0.axis1.encoder.config.calib_range = 0.05
|
|
odrv0.axis1.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
|
|
print("You're motor encoder should be configured.")
|
|
return 0
|
|
|
|
|
|
class RoboWheelConfig:
|
|
"""
|
|
Class for configuring an Odrive axis.
|
|
"""
|
|
|
|
# Motor KV
|
|
KV_RATING = 10.0
|
|
|
|
# min/max phase inductance of motor
|
|
MIN_PHASE_INDUCTANCE = 0.0 # ?
|
|
MAX_PHASE_INDUCTANCE = 0.001 # ?
|
|
|
|
# Min/Max phase resistance of motor
|
|
MIN_PHASE_RESISTANCE = 0.0 # ?
|
|
MAX_PHASE_RESISTANCE = 2.5 # ? I think my motor is 1.7 ohm...
|
|
|
|
ENCODER_COUNT_PER_REV = 3200.0
|
|
|
|
# Number of magnets in the motor divided by 2
|
|
POLE_PAIR_COUNT = 15.0
|
|
|
|
# See https://docs.odriverobotics.com/hoverboard
|
|
RESISTANCE_CALIB_MAX_VOLTAGE = 6.0 # HB motors are larger with more resistance so he doubled the 2.0 default
|
|
REQUESTED_CURRENT_RANGE = 35.0 # lower values are more sensitive default was 60
|
|
CURRENT_CONTROL_BANDWIDTH = 1000.0 # Motors are also high inductance so the bandwidth to 100 from the default 1000
|
|
TORQUE_CONSTANT = 8.27 / KV_RATING
|
|
CALIBRATION_CURRENT = 2
|
|
ENABLE_BRAKE_RESISTOR = True
|
|
|
|
|
|
# Encoder steps
|
|
"""
|
|
odrv0.config.enable_brake_resistor = True # Using included 2ohm resistor
|
|
odrv0.axis0.motor.config.calibration_current = 2 # highest integer value where I heard the square wave was 4
|
|
odrv0.axis0.motor.config.pole_pairs = 15
|
|
odrv0.axis0.motor.config.resistance_calib_max_voltage = 6 # motor config still worked with this set to 6
|
|
odrv0.axis0.motor.config.requested_current_range = 35 # 35 was the lowest value that produced and audible square wave.
|
|
odrv0.axis0.motor.config.current_control_bandwidth = 100.0
|
|
odrv0.axis0.motor.config.torque_constant = 8.27 / 10 # KV 10
|
|
odrv0.axis1.motor.config.calibration_current = 2 # highest integer value where I heard the square wave was 4
|
|
odrv0.axis1.motor.config.pole_pairs = 15
|
|
odrv0.axis1.motor.config.resistance_calib_max_voltage = 6 # motor config still worked with this set to 6
|
|
odrv0.axis1.motor.config.requested_current_range = 35 # 35 was the lowest value that produced and audible square wave.
|
|
odrv0.axis1.motor.config.current_control_bandwidth = 100.0
|
|
odrv0.axis1.motor.config.torque_constant = 8.27 / 10 # KV 10
|
|
|
|
# encoder
|
|
odrv0.axis0.encoder.config.mode = ENCODER_MODE_INCREMENTAL
|
|
odrv0.axis0.encoder.config.cpr = 3200
|
|
odrv0.axis0.encoder.config.bandwidth = 1000
|
|
odrv0.axis1.encoder.config.mode = ENCODER_MODE_INCREMENTAL
|
|
odrv0.axis1.encoder.config.cpr = 3200
|
|
odrv0.axis1.encoder.config.bandwidth = 1000
|
|
|
|
odrv0.axis0.controller.config.input_mode = INPUT_MODE_VEL_RAMP
|
|
odrv0.axis0.controller.config.control_mode = CONTROL_MODE_VELOCITY_CONTROL
|
|
odrv0.axis0.controller.config.pos_gain = 1
|
|
odrv0.axis0.controller.config.vel_gain = 0.002 * odrv0.axis0.motor.config.torque_constant * odrv0.axis0.encoder.config.cpr
|
|
odrv0.axis0.controller.config.vel_integrator_gain = 0.01 * odrv0.axis0.motor.config.torque_constant * odrv0.axis0.encoder.config.cpr
|
|
odrv0.axis0.controller.config.vel_limit = 5
|
|
odrv0.axis1.controller.config.input_mode = INPUT_MODE_VEL_RAMP
|
|
odrv0.axis1.controller.config.control_mode = CONTROL_MODE_VELOCITY_CONTROL
|
|
odrv0.axis1.controller.config.pos_gain = 1
|
|
odrv0.axis1.controller.config.vel_gain = 0.002 * odrv0.axis1.motor.config.torque_constant * odrv0.axis1.encoder.config.cpr
|
|
odrv0.axis1.controller.config.vel_integrator_gain = 0.01 * odrv0.axis1.motor.config.torque_constant * odrv0.axis1.encoder.config.cpr
|
|
odrv0.axis1.controller.config.vel_limit = 5
|
|
|
|
# BREAK HERE
|
|
odrv0.save_configuration()
|
|
odrv0.reboot()
|
|
|
|
odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION
|
|
|
|
dump_errors(odrv0)
|
|
|
|
odrv0.axis1.requested_state = AXIS_STATE_MOTOR_CALIBRATION
|
|
|
|
odrv0.axis0.motor.config.pre_calibrated = True
|
|
odrv0.axis1.motor.config.pre_calibrated = True
|
|
|
|
# BREAK HERE
|
|
odrv0.save_configuration()
|
|
odrv0.reboot()
|
|
|
|
|
|
# Encoder
|
|
odrv0.axis0.encoder.config.calib_range = 0.05
|
|
odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
|
|
odrv0.axis1.encoder.config.calib_range = 0.05
|
|
odrv0.axis1.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
|
|
|
|
# Movement
|
|
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
|
|
odrv0.axis1.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
|
|
odrv0.axis0.controller.input_vel = 0.5
|
|
odrv0.axis1.controller.input_vel = 0.5
|
|
# Your motor should spin here
|
|
odrv0.axis0.controller.input_vel = 0
|
|
odrv0.axis1.controller.input_vel = 0
|
|
odrv0.axis0.requested_state = AXIS_STATE_IDLE
|
|
odrv0.axis1.requested_state = AXIS_STATE_IDLE
|
|
"""
|
|
|
|
if __name__ == "__main__":
|
|
cli()
|