diff --git a/examples/evalboards/MAX22216/ramdebug.py b/examples/evalboards/MAX22216/ramdebug.py index 27c6b290..431f3845 100644 --- a/examples/evalboards/MAX22216/ramdebug.py +++ b/examples/evalboards/MAX22216/ramdebug.py @@ -20,7 +20,7 @@ debug.set_trigger_threshold(50) debug.start_measurement() - while(not debug.is_measurement_done()): + while not debug.is_measurement_done(): pass samples = debug.get_samples() diff --git a/examples/evalboards/TMC2660/rotate_demo.py b/examples/evalboards/TMC2660/rotate_demo.py index 2098f748..393f7616 100644 --- a/examples/evalboards/TMC2660/rotate_demo.py +++ b/examples/evalboards/TMC2660/rotate_demo.py @@ -16,7 +16,7 @@ motor = eval_board.motors[0] print("Rotating...") - motor.rotate(10*25600) + motor.rotate(51200) time.sleep(2) print("Stopping...") diff --git a/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder.py b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder.py index 10307e18..79d2b336 100644 --- a/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder.py +++ b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder.py @@ -1,4 +1,5 @@ import time +import statistics import pytrinamic from pytrinamic.connections import ConnectionManager from pytrinamic.evalboards import TMC4671_eval, TMC6100_eval @@ -18,6 +19,9 @@ # Configure TMC4671 for a BLDC motor with ABN-Encoder + # Switch to stopped mode + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, TMC4671.ENUM.MOTION_MODE_STOPPED) + # Motor type & PWM configuration mc_eval.write_register_field(TMC4671.FIELD.MOTOR_TYPE, TMC4671.ENUM.MOTOR_TYPE_BLDC) mc_eval.write_register_field(TMC4671.FIELD.N_POLE_PAIRS, 4) @@ -33,11 +37,21 @@ mc_eval.write_register(TMC4671.REG.dsADC_MCLK_A, 0x20000000) mc_eval.write_register(TMC4671.REG.dsADC_MCLK_B, 0x00000000) mc_eval.write_register(TMC4671.REG.dsADC_MDEC_B_MDEC_A, int(0x014E014E)) - mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF00826D) - mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF0081F8) + # ADC offset compensation + adc_i0_samples = [] + adc_i1_samples = [] + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000) + for _ in range(50): + adc_i0_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i1_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i0_offset = statistics.mean(adc_i0_samples) + adc_i1_offset = statistics.mean(adc_i1_samples) + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000 + int(adc_i0_offset)) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000 + int(adc_i1_offset)) # ABN encoder settings - mc_eval.write_register(TMC4671.REG.ABN_DECODER_MODE, 0x00001000) + mc_eval.write_register(TMC4671.REG.ABN_DECODER_MODE, 0x00000000) mc_eval.write_register(TMC4671.REG.ABN_DECODER_PPR, 4096) mc_eval.write_register(TMC4671.REG.ABN_DECODER_PHI_E_PHI_M_OFFSET, 0) diff --git a/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder_position_mode_linear_ramp.py b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder_position_mode_linear_ramp.py new file mode 100644 index 00000000..93090dce --- /dev/null +++ b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder_position_mode_linear_ramp.py @@ -0,0 +1,133 @@ +import time +import dataclasses +import statistics +from pytrinamic.connections import ConnectionManager +from pytrinamic.evalboards import TMC4671_eval, TMC6100_eval +from pytrinamic.ic import TMC4671, TMC6100 +import matplotlib.pyplot as plt + + +with ConnectionManager().connect() as my_interface: + + # Create TMC4671-EVAL and TMC6100-EVAL class which communicate over the Landungsbrücke via TMCL + mc_eval = TMC4671_eval(my_interface) + drv_eval = TMC6100_eval(my_interface) + motor = mc_eval.motors[0] + + # Configure TMC6100 pwm for use with TMC4671 (disable singleline) + drv_eval.write_register_field(TMC6100.FIELD.SINGLELINE, 0) + + # Configure TMC4671 for a BLDC motor with ABN-Encoder + + # Motor type & PWM configuration + mc_eval.write_register_field(TMC4671.FIELD.MOTOR_TYPE, TMC4671.ENUM.MOTOR_TYPE_BLDC) + mc_eval.write_register_field(TMC4671.FIELD.N_POLE_PAIRS, 4) + mc_eval.write_register(TMC4671.REG.PWM_POLARITIES, 0x00000000) + mc_eval.write_register(TMC4671.REG.PWM_MAXCNT, int(0x00000F9F)) + mc_eval.write_register(TMC4671.REG.PWM_BBM_H_BBM_L, 0x00000019) + mc_eval.write_register_field(TMC4671.FIELD.PWM_CHOP, TMC4671.ENUM.PWM_CENTERED_FOR_FOC) + mc_eval.write_register_field(TMC4671.FIELD.PWM_SV, 1) + + # ADC configuration + mc_eval.write_register(TMC4671.REG.ADC_I_SELECT, 0x24000100) + mc_eval.write_register(TMC4671.REG.dsADC_MCFG_B_MCFG_A, 0x00100010) + mc_eval.write_register(TMC4671.REG.dsADC_MCLK_A, 0x20000000) + mc_eval.write_register(TMC4671.REG.dsADC_MCLK_B, 0x00000000) + mc_eval.write_register(TMC4671.REG.dsADC_MDEC_B_MDEC_A, int(0x014E014E)) + # ADC offset compensation + adc_i0_samples = [] + adc_i1_samples = [] + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000) + for _ in range(50): + adc_i0_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i1_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i0_offset = statistics.mean(adc_i0_samples) + adc_i1_offset = statistics.mean(adc_i1_samples) + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000 + int(adc_i0_offset)) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000 + int(adc_i1_offset)) + + # ABN encoder settings + mc_eval.write_register(TMC4671.REG.ABN_DECODER_MODE, 0x00000000) + mc_eval.write_register(TMC4671.REG.ABN_DECODER_PPR, 4096) + mc_eval.write_register(TMC4671.REG.ABN_DECODER_PHI_E_PHI_M_OFFSET, 0) + + # Limits + mc_eval.write_register(TMC4671.REG.PID_TORQUE_FLUX_LIMITS, 1000) + + # PI settings for Torque/Flux regulator + mc_eval.write_register(TMC4671.REG.PID_TORQUE_P_TORQUE_I, 1279 << 16 | 193 << 0) + mc_eval.write_register(TMC4671.REG.PID_FLUX_P_FLUX_I, 1279 << 16 | 193 << 0) + + # Init encoder (mode 0) + print("Initializing Encoder...") + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, 0x00000008) + mc_eval.write_register(TMC4671.REG.ABN_DECODER_PHI_E_PHI_M_OFFSET, 0x00000000) + mc_eval.write_register(TMC4671.REG.PHI_E_SELECTION, TMC4671.ENUM.PHI_E_EXTERNAL) + mc_eval.write_register(TMC4671.REG.PHI_E_EXT, 0x00000000) + mc_eval.write_register(TMC4671.REG.UQ_UD_EXT, 1150) + time.sleep(1) + # Clear abn_decoder_count + mc_eval.write_register(TMC4671.REG.ABN_DECODER_COUNT, 0) + print("...done") + + # Commutation Feedback selection + mc_eval.write_register(TMC4671.REG.PHI_E_SELECTION, TMC4671.ENUM.PHI_E_ABN) + + # ===== ABN encoder test drive ===== + @dataclasses.dataclass + class Sample: + timestamp: float + position: int + # Limits + mc_eval.write_register(TMC4671.REG.PID_TORQUE_FLUX_LIMITS, 8000) + + # PI settings for velocity and position regulator + mc_eval.write_register(TMC4671.REG.PID_VELOCITY_P_VELOCITY_I, 6219 << 16 | 2047 << 0) + mc_eval.write_register(TMC4671.REG.PID_POSITION_P_POSITION_I, 8 << 16 | 0 << 0) + + # Velocity Feedback selection + mc_eval.write_register(TMC4671.REG.VELOCITY_SELECTION, TMC4671.ENUM.VELOCITY_PHI_M_ABN) + # Position Feedback selection + mc_eval.write_register(TMC4671.REG.POSITION_SELECTION, TMC4671.ENUM.VELOCITY_PHI_M_ABN) + + # Switch to velocity mode + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, TMC4671.ENUM.MOTION_MODE_POSITION) + + # motion settings + motor.linear_ramp.max_velocity = 2000 + motor.linear_ramp.max_acceleration = 1000 + motor.linear_ramp.enabled = 1 + print(motor.linear_ramp) + + samples = [] + + motor.set_actual_position(0) + time.sleep(1) + + # Rotate right + print("Rotate right!") + targetPos = 409600 + motor.set_axis_parameter(motor.AP.TargetPosition, targetPos) + start_time = time.time() + while time.time() - start_time < 5: + samples.append(Sample(time.perf_counter(), motor.get_axis_parameter(motor.AP.ActualPosition, True))) + + # Stop + print("Stop!") + targetPos = 0 + motor.set_axis_parameter(motor.AP.TargetPosition, targetPos) + start_time = time.time() + while time.time() - start_time < 3: + samples.append(Sample(time.perf_counter(), motor.get_axis_parameter(motor.AP.ActualPosition, True))) + + fig, ax = plt.subplots() + t = [s.timestamp - samples[0].timestamp for s in samples] + pos = [s.position for s in samples] + ax.plot(t, pos, label='Position') + ax.legend() + plt.show() + + # Switch to stop mode + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, TMC4671.ENUM.MOTION_MODE_STOPPED) + diff --git a/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder_velocity.py b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder_velocity.py new file mode 100644 index 00000000..2199e175 --- /dev/null +++ b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_ABN_encoder_velocity.py @@ -0,0 +1,103 @@ +import time +import statistics +from pytrinamic.connections import ConnectionManager +from pytrinamic.evalboards import TMC4671_eval, TMC6100_eval +from pytrinamic.ic import TMC4671, TMC6100 + + +with ConnectionManager().connect() as my_interface: + + # Create TMC4671-EVAL and TMC6100-EVAL class which communicate over the Landungsbrücke via TMCL + mc_eval = TMC4671_eval(my_interface) + drv_eval = TMC6100_eval(my_interface) + + # Configure TMC6100 pwm for use with TMC4671 (disable singleline) + drv_eval.write_register_field(TMC6100.FIELD.SINGLELINE, 0) + + # Configure TMC4671 for a BLDC motor with ABN-Encoder + + # Switch to stopped mode + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, TMC4671.ENUM.MOTION_MODE_STOPPED) + + # Motor type & PWM configuration + mc_eval.write_register_field(TMC4671.FIELD.MOTOR_TYPE, TMC4671.ENUM.MOTOR_TYPE_BLDC) + mc_eval.write_register_field(TMC4671.FIELD.N_POLE_PAIRS, 4) + mc_eval.write_register(TMC4671.REG.PWM_POLARITIES, 0x00000000) + mc_eval.write_register(TMC4671.REG.PWM_MAXCNT, int(0x00000F9F)) + mc_eval.write_register(TMC4671.REG.PWM_BBM_H_BBM_L, 0x00001414) + mc_eval.write_register_field(TMC4671.FIELD.PWM_CHOP, TMC4671.ENUM.PWM_CENTERED_FOR_FOC) + mc_eval.write_register_field(TMC4671.FIELD.PWM_SV, 1) + + # ADC configuration + mc_eval.write_register(TMC4671.REG.ADC_I_SELECT, 0x24000100) + mc_eval.write_register(TMC4671.REG.dsADC_MCFG_B_MCFG_A, 0x00100010) + mc_eval.write_register(TMC4671.REG.dsADC_MCLK_A, 0x20000000) + mc_eval.write_register(TMC4671.REG.dsADC_MCLK_B, 0x00000000) + mc_eval.write_register(TMC4671.REG.dsADC_MDEC_B_MDEC_A, int(0x014E014E)) + # ADC offset compensation + adc_i0_samples = [] + adc_i1_samples = [] + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000) + for _ in range(50): + adc_i0_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i1_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i0_offset = statistics.mean(adc_i0_samples) + adc_i1_offset = statistics.mean(adc_i1_samples) + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000 + int(adc_i0_offset)) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000 + int(adc_i1_offset)) + + # ABN encoder settings + mc_eval.write_register(TMC4671.REG.ABN_DECODER_MODE, 0x00000000) + mc_eval.write_register(TMC4671.REG.ABN_DECODER_PPR, 4096) + mc_eval.write_register(TMC4671.REG.ABN_DECODER_PHI_E_PHI_M_OFFSET, 0) + + # Limits + mc_eval.write_register(TMC4671.REG.PID_TORQUE_FLUX_LIMITS, 1000) + + # PI settings for Torque/Flux regulator + mc_eval.write_register(TMC4671.REG.PID_TORQUE_P_TORQUE_I, 0x01000100) + mc_eval.write_register(TMC4671.REG.PID_FLUX_P_FLUX_I, 0x01000100) + + # Init encoder (mode 0) + print("Initializing Encoder...") + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, 0x00000008) + mc_eval.write_register(TMC4671.REG.ABN_DECODER_PHI_E_PHI_M_OFFSET, 0x00000000) + mc_eval.write_register(TMC4671.REG.PHI_E_SELECTION, TMC4671.ENUM.PHI_E_EXTERNAL) + mc_eval.write_register(TMC4671.REG.PHI_E_EXT, 0x00000000) + mc_eval.write_register(TMC4671.REG.UQ_UD_EXT, 1000) + time.sleep(1) + # Clear abn_decoder_count + mc_eval.write_register(TMC4671.REG.ABN_DECODER_COUNT, 0) + print("...done") + + # Commutation Feedback selection + mc_eval.write_register(TMC4671.REG.PHI_E_SELECTION, TMC4671.ENUM.PHI_E_ABN) + + # ===== ABN encoder test drive ===== + + # Limits + mc_eval.write_register(TMC4671.REG.PID_TORQUE_FLUX_LIMITS, 2000) + + # PI settings for velocity regulator + mc_eval.write_register(TMC4671.REG.PID_VELOCITY_P_VELOCITY_I, 400 << 16 | 100 << 0) + + # Velocity Feedback selection + mc_eval.write_register(TMC4671.REG.VELOCITY_SELECTION, TMC4671.ENUM.VELOCITY_PHI_M_ABN) + + # Switch to velocity mode + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, TMC4671.ENUM.MOTION_MODE_VELOCITY) + + # Rotate right + print("Rotate right!") + mc_eval.write_register(TMC4671.REG.PID_VELOCITY_TARGET, 500) + time.sleep(3) + + # Stop + print("Stop!") + mc_eval.write_register(TMC4671.REG.PID_VELOCITY_TARGET, 0) + time.sleep(1) + + # Switch to stop mode + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, TMC4671.ENUM.MOTION_MODE_STOPPED) + diff --git a/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_README.md b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_README.md new file mode 100644 index 00000000..4b031461 --- /dev/null +++ b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_README.md @@ -0,0 +1,59 @@ + +# Setup + +## Hardware + +``` + + |-----------------------------------------------------| + | | + | |---------------------------------------------| | + | | | | + | | | | ++---------------+ +----------|-|--+ +---------------+ | | +| | | | | | | | |----------------| | +| | | | | | | | | | | +| | | | | | | | +-|-----------------+ +| | | | | | | +-|--+| | +| | | | | | | | || | +| | | | | --------| | || |--- +| | | | | | | || | +| | | | | | +----+| | +| | | | | | TMCS-28-5-1024-AT01 +-------------------+ +| | | | | | QBL4208-61-04-013-DS +| | | | | | +| | | | | | ++---------------+ +---------------+ +---------------+ + Landungsbruecke TMC-4761-EVAL TMC6100-EVAL +``` + +## Wiring + +### Motor + +| Cable Color | TMC6100 | +|-------------|---------| +| Black | U | +| Red | V | +| Yellow | W | + +### ABN Encoder + +| Cable Color | TMC4671 | +|-------------|---------| +| Red | +5V | +| Black | GND | +| Withe | ENC1_A | +| Green | ENC1_B | +| Yellow | ENC1_N | + +### Digital Hall + +| Cable Color | TMC4671 | +|-------------|---------| +| Red | +5V | +| Black | GND | +| Blue | HALL_UX | +| Green | HALL_V | +| Withe | HALL_WY | + diff --git a/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_digital_hall_velocity.py b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_digital_hall_velocity.py new file mode 100644 index 00000000..252b7add --- /dev/null +++ b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_digital_hall_velocity.py @@ -0,0 +1,86 @@ +import time +import statistics +from pytrinamic.connections import ConnectionManager +from pytrinamic.evalboards import TMC4671_eval, TMC6100_eval +from pytrinamic.ic import TMC4671, TMC6100 + + +with ConnectionManager().connect() as my_interface: + + # Create TMC4671-EVAL and TMC6100-EVAL class which communicate over the Landungsbrücke via TMCL + mc_eval = TMC4671_eval(my_interface) + drv_eval = TMC6100_eval(my_interface) + + # Configure TMC6100 pwm for use with TMC4671 (disable singleline) + drv_eval.write_register_field(TMC6100.FIELD.SINGLELINE, 0) + + # Configure TMC4671 for a BLDC motor with digital hall + + # Motor type & PWM configuration + mc_eval.write_register_field(TMC4671.FIELD.MOTOR_TYPE, TMC4671.ENUM.MOTOR_TYPE_BLDC) + mc_eval.write_register_field(TMC4671.FIELD.N_POLE_PAIRS, 4) + mc_eval.write_register(TMC4671.REG.PWM_POLARITIES, 0x00000000) + mc_eval.write_register(TMC4671.REG.PWM_MAXCNT, int(0x00000F9F)) + mc_eval.write_register(TMC4671.REG.PWM_BBM_H_BBM_L, 0x00001414) + mc_eval.write_register_field(TMC4671.FIELD.PWM_CHOP, TMC4671.ENUM.PWM_CENTERED_FOR_FOC) + mc_eval.write_register_field(TMC4671.FIELD.PWM_SV, 1) + + # ADC configuration + mc_eval.write_register(TMC4671.REG.ADC_I_SELECT, 0x24000100) + mc_eval.write_register(TMC4671.REG.dsADC_MCFG_B_MCFG_A, 0x00100010) + mc_eval.write_register(TMC4671.REG.dsADC_MCLK_A, 0x20000000) + mc_eval.write_register(TMC4671.REG.dsADC_MCLK_B, 0x00000000) + mc_eval.write_register(TMC4671.REG.dsADC_MDEC_B_MDEC_A, int(0x014E014E)) + # ADC offset compensation + adc_i0_samples = [] + adc_i1_samples = [] + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000) + for _ in range(50): + adc_i0_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i1_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i0_offset = statistics.mean(adc_i0_samples) + adc_i1_offset = statistics.mean(adc_i1_samples) + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000 + int(adc_i0_offset)) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000 + int(adc_i1_offset)) + + # Limits + mc_eval.write_register(TMC4671.REG.PID_TORQUE_FLUX_LIMITS, 1000) + + # PI settings for Torque/Flux regulator + mc_eval.write_register(TMC4671.REG.PID_TORQUE_P_TORQUE_I, 0x01000100) + mc_eval.write_register(TMC4671.REG.PID_FLUX_P_FLUX_I, 0x01000100) + + # hall settings + mc_eval.write_register_field(TMC4671.FIELD.HALL_DIRECTION, 1) + mc_eval.write_register_field(TMC4671.FIELD.HALL_PHI_E_OFFSET, 9500) + + # Commutation Feedback selection + mc_eval.write_register(TMC4671.REG.PHI_E_SELECTION, TMC4671.ENUM.PHI_E_HALL) + + # ===== Digital hall test drive ===== + + # Limits + mc_eval.write_register(TMC4671.REG.PID_TORQUE_FLUX_LIMITS, 2000) + + # PI settings for velocity regulator + mc_eval.write_register(TMC4671.REG.PID_VELOCITY_P_VELOCITY_I, 400 << 16 | 100 << 0) + + # Velocity Feedback selection + mc_eval.write_register(TMC4671.REG.VELOCITY_SELECTION, TMC4671.ENUM.VELOCITY_PHI_M_HAL) + + # Switch to velocity mode + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, TMC4671.ENUM.MOTION_MODE_VELOCITY) + + # Rotate right + print("Rotate right!") + mc_eval.write_register(TMC4671.REG.PID_VELOCITY_TARGET, 500) + time.sleep(3) + + # Stop + print("Stop!") + mc_eval.write_register(TMC4671.REG.PID_VELOCITY_TARGET, 0) + time.sleep(1) + + # Switch to stop mode + mc_eval.write_register(TMC4671.REG.MODE_RAMP_MODE_MOTION, TMC4671.ENUM.MOTION_MODE_STOPPED) diff --git a/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_open_loop.py b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_open_loop.py index 1f306a26..cedd967a 100644 --- a/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_open_loop.py +++ b/examples/evalboards/TMC4671/TMC4671_eval_TMC6100_eval_BLDC_open_loop.py @@ -1,4 +1,5 @@ import time +import statistics import pytrinamic from pytrinamic.connections import ConnectionManager from pytrinamic.evalboards import TMC4671_eval, TMC6100_eval @@ -33,8 +34,18 @@ mc_eval.write_register(TMC4671.REG.dsADC_MCLK_A, 0x20000000) mc_eval.write_register(TMC4671.REG.dsADC_MCLK_B, 0x00000000) mc_eval.write_register(TMC4671.REG.dsADC_MDEC_B_MDEC_A, int(0x014E014E)) - mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF00826D) - mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF0081F8) + # ADC offset compensation + adc_i0_samples = [] + adc_i1_samples = [] + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000) + for _ in range(50): + adc_i0_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i1_samples.append(mc_eval.read_register_field(TMC4671.FIELD.ADC_I0_RAW)) + adc_i0_offset = statistics.mean(adc_i0_samples) + adc_i1_offset = statistics.mean(adc_i1_samples) + mc_eval.write_register(TMC4671.REG.ADC_I0_SCALE_OFFSET, 0xFF000000 + int(adc_i0_offset)) + mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF000000 + int(adc_i1_offset)) # Open loop settings mc_eval.write_register(TMC4671.REG.OPENLOOP_MODE, 0x00000000) diff --git a/examples/evalboards/TMC4671/TMC4671_eval_adc_offset_calibration.py b/examples/evalboards/TMC4671/TMC4671_eval_adc_offset_calibration.py index b1404182..aae944bd 100644 --- a/examples/evalboards/TMC4671/TMC4671_eval_adc_offset_calibration.py +++ b/examples/evalboards/TMC4671/TMC4671_eval_adc_offset_calibration.py @@ -9,20 +9,20 @@ from pytrinamic.ic import TMC4671 pytrinamic.show_info() -my_interface = ConnectionManager().connect() -print(my_interface) - -if isinstance(my_interface, UartIcInterface): - # Create an TMC4671 IC class which communicates directly over UART - mc = TMC4671(my_interface) - # Use IC like an "EVAL" to use this example for both access variants - eval_board = mc -else: - # Create an TMC4671 IC class which communicates over the Landungsbrücke via TMCL - eval_board = TMC4671_eval(my_interface) - mc = eval_board.ics[0] - -with my_interface: + +with ConnectionManager().connect() as my_interface: + + print(my_interface) + + if isinstance(my_interface, UartIcInterface): + # Create an TMC4671 IC class which communicates directly over UART + mc = TMC4671(my_interface) + # Use IC like an "EVAL" to use this example for both access variants + eval_board = mc + else: + # Create an TMC4671 IC class which communicates over the Landungsbrücke via TMCL + eval_board = TMC4671_eval(my_interface) + mc = eval_board.ics[0] # Configure TMC4671 for a BLDC motor in open loop mode diff --git a/examples/modules/TMCM1231/CANopen/StallGuard2_demo_using_sdo.py b/examples/modules/TMCM1231/CANopen/StallGuard2_demo_using_sdo.py deleted file mode 100644 index ee39a5e6..00000000 --- a/examples/modules/TMCM1231/CANopen/StallGuard2_demo_using_sdo.py +++ /dev/null @@ -1,71 +0,0 @@ -""" -Sets the StallGuard2 threshold such that the stall guard value (i.e SG value) is zero -when the motor comes close to stall and also sets the stop on stall velocity to a value -one less than the actual velocity of the motor -""" -import time -import canopen -from pytrinamic.modules.canopen_node import TmcmNode - -def stallguard2_init(init_velocity): - # Resetting SG2 threshold and stop on stall velocity to zero - tmcm_1231.sdo['Stall Guard2 Threshold 1'].raw = 0 - tmcm_1231.sdo['Stop On Stall 1'].raw = 0 - print("Rotating...") - tmcm_1231.sdo['Target Velocity 1'].raw = init_velocity - sgthresh = 0 - sgt = 0 - load_samples = [] - while (sgt == 0) and (sgthresh < 64): - load_samples = [] - tmcm_1231.sdo['Stall Guard2 Threshold 1'].raw = sgthresh - time.sleep(0.2) - sgthresh += 1 - for i in range(50): - load_samples.append(tmcm_1231.sdo['Actual Load Value 1'].raw ) - if not any(load_samples): - sgt = 0 - else: - sgt = max(load_samples) - while 1: - load_samples = [] - for i in range(50): - load_samples.append(tmcm_1231.sdo['Actual Load Value 1'].raw ) - if 0 in load_samples: - tmcm_1231.sdo['Absolute Max Current 1'].raw = tmcm_1231.sdo['Absolute Max Current 1'].raw - 1 - else: - break - - tmcm_1231.sdo['Stop On Stall 1'].raw = tmcm_1231.sdo['Velocity Actual Value 1'].raw - 1 - -def main(): - with canopen.Network() as network: - network.connect(channel='PCAN_USBBUS1', bustype='pcan', bitrate=1_000_000) - - global tmcm_1231 - tmcm_1231 = TmcmNode(1, 'TMCM-1231.eds') - network.add_node(tmcm_1231) - tmcm_1231.sdo['Modes of Operation 1'].raw = tmcm_1231.ModeOfOperation.PROFILE_VELOCITY_MODE - - tmcm_1231.load_configuration() - tmcm_1231.nmt.state = 'OPERATIONAL' - - tmcm_1231.go_to_operation_enabled() - tmcm_1231.sdo['Absolute Max Current 1'].raw = 20 - tmcm_1231.sdo['Standby Current 1'].raw = 8 - tmcm_1231.sdo['Microstep Resolution 1'].raw = 8 - - # set up StallGuard2 - print("Configuring StallGuard2 parameters...") - stallguard2_init(init_velocity = 10000) - print("Apply load and try to stall the motor...") - motor_activity_flag_mask = 0x4000 - while tmcm_1231.sdo['Statusword 1'].raw & motor_activity_flag_mask != 0: - pass - print("Motor stopped by StallGuard2!") - - tmcm_1231.nmt.state = 'PRE-OPERATIONAL' - tmcm_1231.shutdown() - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/examples/modules/TMCM1231/CANopen/rotate_demo_using_pdo.py b/examples/modules/TMCM1231/CANopen/rotate_demo_using_pdo.py deleted file mode 100644 index 1cc08936..00000000 --- a/examples/modules/TMCM1231/CANopen/rotate_demo_using_pdo.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Run a TMCM-1231 in "Profile Velocity Mode" using PDOs. - -Includes the recording and plotting of actual velocity. - -Tested with: -* Firmware version 3.26 -* Using the Python canopen package version 2.0.0 -""" -import time -import dataclasses -import canopen -import matplotlib.pyplot as plt -from pytrinamic.modules.canopen_node import TmcmNode - - -samples = [] - - -@dataclasses.dataclass -class Sample: - timestamp: float - velocity: int - - -def tpdo4_callback(message): - global samples - velocity = message['Velocity Actual Value 1'].raw - timestamp = message.timestamp - samples.append(Sample(timestamp=timestamp, velocity=velocity)) - - -with canopen.Network() as network: - network.connect(channel='PCAN_USBBUS1', bustype='pcan', bitrate=1_000_000) - - tmcm_1231 = TmcmNode(1, 'TMCM-1231.eds') - network.add_node(tmcm_1231) - - # Reconfiguration - tmcm_1231.sdo[0x1403][1].raw = 0x8000_0381 # disable the RPDO4 - tmcm_1231.sdo[0x1603][0].raw = 0 # write the number of entries into subindex 0 - tmcm_1231.sdo[0x1603][1].raw = 0x60400010 - tmcm_1231.sdo[0x1603][2].raw = 0x60FF0020 - tmcm_1231.sdo[0x1603][3].raw = 0x60600008 - tmcm_1231.sdo[0x1603][0].raw = 3 # write the number of entries into subindex 0 - tmcm_1231.sdo[0x1403][1].raw = 0x4000_0381 # enable the RPDO4 - - tmcm_1231.load_configuration() - tmcm_1231.nmt.state = 'OPERATIONAL' - - tmcm_1231.go_to_operation_enabled() - - tmcm_1231.tpdo[4].add_callback(tpdo4_callback) - - tmcm_1231.sdo['Absolute Max Current 1'].raw = 50 - tmcm_1231.sdo['Stop On Stall 1'].raw = 0 - - target_velocity = 10000 - # Profile Velocity Mode - tmcm_1231.rpdo[4]['Modes of Operation 1'].raw = tmcm_1231.ModeOfOperation.PROFILE_VELOCITY_MODE - tmcm_1231.rpdo[4]['Controlword 1'].raw = tmcm_1231.Cmd.ENABLE_OPERATION - tmcm_1231.rpdo[4]['Target Velocity 1'].raw = target_velocity - tmcm_1231.rpdo[4].transmit() - print("Motor rotating...") - time.sleep(5) - tmcm_1231.rpdo[4]['Target Velocity 1'].raw = 0 - tmcm_1231.rpdo[4].transmit() - print("Motor stopped!") - time.sleep(2) - tmcm_1231.nmt.state = 'PRE-OPERATIONAL' - tmcm_1231.shutdown() - -fig, ax = plt.subplots() -t = [s.timestamp for s in samples] -v = [s.velocity for s in samples] -ax.plot(t, v) -ax.set_xlabel('Time') -ax.set_ylabel('Velocity') -plt.show() - - diff --git a/examples/modules/TMCM1231/CANopen/rotate_demo_using_sdo.py b/examples/modules/TMCM1231/CANopen/rotate_demo_using_sdo.py deleted file mode 100644 index c88bb30f..00000000 --- a/examples/modules/TMCM1231/CANopen/rotate_demo_using_sdo.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Uses SDO to rotate the motor for 5 seconds in profile velocity mode. -""" -import time -import canopen -from pytrinamic.modules.canopen_node import TmcmNode - -with canopen.Network() as network: - network.connect(channel='PCAN_USBBUS1', bustype='pcan', bitrate=1_000_000) - - tmcm_1231 = TmcmNode(1, 'TMCM-1231.eds') - network.add_node(tmcm_1231) - # Profile Velocity Mode - tmcm_1231.sdo['Modes of Operation 1'].raw = tmcm_1231.ModeOfOperation.PROFILE_VELOCITY_MODE - - tmcm_1231.load_configuration() - tmcm_1231.nmt.state = 'OPERATIONAL' - - tmcm_1231.go_to_operation_enabled() - tmcm_1231.sdo['Absolute Max Current 1'].raw = 50 - tmcm_1231.sdo['Stop On Stall 1'].raw = 0 - - - target_velocity = 10000 - print("Rotating the motor...") - tmcm_1231.sdo['Target Velocity 1'].raw = target_velocity - time.sleep(5) - tmcm_1231.sdo['Target Velocity 1'].raw = 0 - print("Motor stopped!") - - tmcm_1231.nmt.state = 'PRE-OPERATIONAL' - tmcm_1231.shutdown() - - - diff --git a/examples/modules/TMCM1231/CANopen/six_point_ramp_demo_using_pdo.py b/examples/modules/TMCM1231/CANopen/six_point_ramp_demo_using_pdo.py deleted file mode 100644 index 35835e11..00000000 --- a/examples/modules/TMCM1231/CANopen/six_point_ramp_demo_using_pdo.py +++ /dev/null @@ -1,118 +0,0 @@ -"""Run a TMCM-1231 in "Profile Position Mode" using PDOs to configure Six-Point Ramp - -Includes the recording and plotting of the actual velocity along with the actual position. - -""" -import time -import dataclasses -import canopen -import matplotlib.pyplot as plt -from pytrinamic.modules.canopen_node import TmcmNode - - -samples = [] - - -@dataclasses.dataclass -class Sample: - timestamp: float - position: int - velocity: int - - -def tpdo4_callback(message): - global samples - position = message['Position Actual Value 1'].raw - velocity = message['Velocity Actual Value 1'].raw - timestamp = message.timestamp - samples.append(Sample(timestamp=timestamp, position=position, velocity=velocity)) - - -with canopen.Network() as network: - network.connect(channel='PCAN_USBBUS1', bustype='pcan', bitrate=1_000_000) - - tmcm_1231 = TmcmNode(1, 'TMCM-1231.eds') - network.add_node(tmcm_1231) - - # Reconfiguration of TPDO4 - tmcm_1231.sdo[0x1803][1].raw = 0x8000_0381 # disable the TPDO4 - tmcm_1231.sdo[0x1a03][0].raw = 0 # write the number of entries into subindex 0 - tmcm_1231.sdo[0x1a03][1].raw = 0x60640020 - tmcm_1231.sdo[0x1a03][2].raw = 0x606C0020 - tmcm_1231.sdo[0x1a03][0].raw = 2 # write the number of entries into subindex 0 - tmcm_1231.sdo[0x1803][1].raw = 0x4000_0381 # enable the TPDO4 - - # Reconfiguration of RPDO4 - tmcm_1231.sdo[0x1403][1].raw = 0x8000_0381 # disable the RPDO4 - tmcm_1231.sdo[0x1603][0].raw = 0 # write the number of entries into subindex 0 - tmcm_1231.sdo[0x1603][1].raw = 0x60400010 - tmcm_1231.sdo[0x1603][2].raw = 0x607a0020 - tmcm_1231.sdo[0x1603][0].raw = 2 # write the number of entries into subindex 0 - tmcm_1231.sdo[0x1403][1].raw = 0x4000_0381 # enable the RPDO4 - - tmcm_1231.load_configuration() - tmcm_1231.nmt.state = 'OPERATIONAL' - - tmcm_1231.go_to_operation_enabled() - tmcm_1231.tpdo[4].add_callback(tpdo4_callback) - - tmcm_1231.sdo['Absolute Max Current 1'].raw = 50 - tmcm_1231.sdo['Stop On Stall 1'].raw = 0 - - # Setting axis parameters for configuring SixPoint ramp - tmcm_1231.sdo['Profile start velocity 1'].raw = 5000 # V_Start - tmcm_1231.sdo['Profile start acceleration 1'].raw = 5000 # A1 - tmcm_1231.sdo['Profile Acceleration 1'].raw = 30000 # max acceleration - tmcm_1231.sdo['Profile Deceleration 1'].raw = 20000 # max deceleration - tmcm_1231.sdo['Profile break velocity 1'].raw = 10000 # V1 - tmcm_1231.sdo['Profile final deceleration 1'].raw = 5000 # D1 - tmcm_1231.sdo['Profile Velocity in pp-mode 1'].raw = 40000 # V_max - - # Need to set V_stop and ramp_wait_time with an appropriate value - tmcm_1231.sdo['End velocity 1'].raw = 5000 # V_Stop? - # tmcm_1231.sdo['Profile stop deceleration 1'].raw = 5000 - tmcm_1231.sdo['Bow scaling factor 1'].raw = 255 # ramp_wait_time? - - # Profile Velocity Mode - tmcm_1231.sdo['Modes of Operation 1'].raw = tmcm_1231.ModeOfOperation.PROFILE_POSITION_MODE - - tmcm_1231.rpdo[4]['Controlword 1'].raw = tmcm_1231.Cmd.ENABLE_OPERATION - tmcm_1231.rpdo[4]['Target Position 1'].raw = 0 - tmcm_1231.rpdo[4].transmit() - - time.sleep(0.2) - - for target_position in [100000, 0]: - tmcm_1231.rpdo[4]['Target Position 1'].raw = target_position - tmcm_1231.rpdo[4]['Controlword 1'].raw = tmcm_1231.Cmd.ENABLE_OPERATION + tmcm_1231.Cmd.NEW_SET_POINT - tmcm_1231.rpdo[4].transmit() - - tmcm_1231.rpdo[4]['Controlword 1'].raw = tmcm_1231.Cmd.ENABLE_OPERATION - tmcm_1231.rpdo[4].transmit() - - target_reached_flag_mask = 0x0400 - while tmcm_1231.sdo['Statusword 1'].raw & target_reached_flag_mask == 0: - pass - - print("Reached Target Position: {target_position}" .format(target_position=target_position)) - - tmcm_1231.nmt.state = 'PRE-OPERATIONAL' - tmcm_1231.shutdown() - -fig, ax = plt.subplots(2) -t = [float(s.timestamp - samples[0].timestamp) for s in samples] -pos = [float(s.position) for s in samples] -vel = [float(s.velocity) for s in samples] -ax[0].plot(t, pos, label='Position') -ax[0].set_title('Pos vs Time') -ax[0].set_xlabel('Time') -ax[0].set_ylabel('Pos') -ax[0].legend() -ax[0].grid() -ax[1].plot(t, vel, label='Velocity') -ax[1].set_title('Vel vs Time') -ax[1].set_xlabel('Time') -ax[1].set_ylabel('Vel') -ax[1].legend() -ax[1].grid() -plt.show() \ No newline at end of file diff --git a/examples/modules/TMCM123x_0_1/CANopen/StallGuard2_demo_using_sdo.py b/examples/modules/TMCM123x_0_1/CANopen/StallGuard2_demo_using_sdo.py new file mode 100644 index 00000000..5f526884 --- /dev/null +++ b/examples/modules/TMCM123x_0_1/CANopen/StallGuard2_demo_using_sdo.py @@ -0,0 +1,71 @@ +""" +Sets the StallGuard2 threshold such that the stall guard value (i.e SG value) is zero +when the motor comes close to stall and also sets the stop on stall velocity to a value +one less than the actual velocity of the motor +""" +import time +import canopen +from pytrinamic.modules.canopen_node import TmcmNode + +def stallguard2_init(init_velocity): + # Resetting SG2 threshold and stop on stall velocity to zero + tmcm_123x_0_1.sdo['Stall Guard2 Threshold 1'].raw = 0 + tmcm_123x_0_1.sdo['Stop On Stall 1'].raw = 0 + print("Rotating...") + tmcm_123x_0_1.sdo['Target Velocity 1'].raw = init_velocity + sgthresh = 0 + sgt = 0 + load_samples = [] + while (sgt == 0) and (sgthresh < 64): + load_samples = [] + tmcm_123x_0_1.sdo['Stall Guard2 Threshold 1'].raw = sgthresh + time.sleep(0.2) + sgthresh += 1 + for i in range(50): + load_samples.append(tmcm_123x_0_1.sdo['Actual Load Value 1'].raw ) + if not any(load_samples): + sgt = 0 + else: + sgt = max(load_samples) + while 1: + load_samples = [] + for i in range(50): + load_samples.append(tmcm_123x_0_1.sdo['Actual Load Value 1'].raw ) + if 0 in load_samples: + tmcm_123x_0_1.sdo['Absolute Max Current 1'].raw = tmcm_123x_0_1.sdo['Absolute Max Current 1'].raw - 1 + else: + break + + tmcm_123x_0_1.sdo['Stop On Stall 1'].raw = tmcm_123x_0_1.sdo['Velocity Actual Value 1'].raw - 1 + +def main(): + with canopen.Network() as network: + network.connect(channel='0', bustype='kvaser', bitrate=1_000_000) + + global tmcm_123x_0_1 + tmcm_123x_0_1 = TmcmNode(1, 'TMCM-1230.eds') + network.add_node(tmcm_123x_0_1) + tmcm_123x_0_1.sdo['Modes of Operation 1'].raw = tmcm_123x_0_1.ModeOfOperation.PROFILE_VELOCITY_MODE + + tmcm_123x_0_1.load_configuration() + tmcm_123x_0_1.nmt.state = 'OPERATIONAL' + + tmcm_123x_0_1.go_to_operation_enabled() + tmcm_123x_0_1.sdo['Absolute Max Current 1'].raw = 20 + tmcm_123x_0_1.sdo['Standby Current 1'].raw = 8 + tmcm_123x_0_1.sdo['Microstep Resolution 1'].raw = 8 + + # set up StallGuard2 + print("Configuring StallGuard2 parameters...") + stallguard2_init(init_velocity = 10000) + print("Apply load and try to stall the motor...") + motor_activity_flag_mask = 0x4000 + while tmcm_123x_0_1.sdo['Statusword 1'].raw & motor_activity_flag_mask != 0: + pass + print("Motor stopped by StallGuard2!") + + tmcm_123x_0_1.nmt.state = 'PRE-OPERATIONAL' + tmcm_123x_0_1.shutdown() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/examples/modules/TMCM123x_0_1/CANopen/TMCM-1230.eds b/examples/modules/TMCM123x_0_1/CANopen/TMCM-1230.eds new file mode 100644 index 00000000..92fceb30 --- /dev/null +++ b/examples/modules/TMCM123x_0_1/CANopen/TMCM-1230.eds @@ -0,0 +1,2222 @@ + +; This EDS file was created by the CANopen Design Tool 2.3.36.0. +; port GmbH Halle/Saale Germany, http://www.port.de, mailto:service@port.de + +[FileInfo] +FileName=TMCM-1230.eds +FileVersion=1 +FileRevision=3 +EDSVersion=4.0 +Description=Slot type stepper controller module. +CreationTime=03:02PM +CreationDate=07-16-2020 +CreatedBy=Mr. Kahlbaum +ModificationTime=02:02PM +ModificationDate=12-02-2021 +ModifiedBy=Mr. Kahlbaum + +[DeviceInfo] +VendorName=Trinamic Motion Control GmbH +VendorNumber=0x286 +ProductName=TMCM-1230 +ProductNumber=0x4CE +RevisionNumber=0x0003001A +OrderCode=TMCM-1230 +BaudRate_10=0 +BaudRate_20=1 +BaudRate_50=1 +BaudRate_125=1 +BaudRate_250=1 +BaudRate_500=1 +BaudRate_800=1 +BaudRate_1000=1 +DynamicChannelsSupported=0 +GroupMessaging=0 +LSS_Supported=0 +Granularity=8 +SimpleBootUpSlave=1 +SimpleBootUpMaster=0 +NrOfRXPDO=4 +NrOfTXPDO=4 + +[Comments] +Lines=0 + +[DummyUsage] +Dummy0001=0 +Dummy0002=0 +Dummy0003=0 +Dummy0004=0 +Dummy0005=0 +Dummy0006=0 +Dummy0007=0 + +[MandatoryObjects] +SupportedObjects=3 +1=0x1000 +2=0x1001 +3=0x1018 + +[OptionalObjects] +SupportedObjects=69 +1=0x1005 +2=0x1008 +3=0x1009 +4=0x100A +5=0x100C +6=0x100D +7=0x1010 +8=0x1011 +9=0x1014 +10=0x1015 +11=0x1016 +12=0x1017 +13=0x1023 +14=0x1029 +15=0x1400 +16=0x1401 +17=0x1402 +18=0x1403 +19=0x1600 +20=0x1601 +21=0x1602 +22=0x1603 +23=0x1800 +24=0x1801 +25=0x1802 +26=0x1803 +27=0x1A00 +28=0x1A01 +29=0x1A02 +30=0x1A03 +31=0x6040 +32=0x6041 +33=0x605A +34=0x605B +35=0x605C +36=0x605D +37=0x605E +38=0x6060 +39=0x6061 +40=0x6062 +41=0x6063 +42=0x6064 +43=0x6065 +44=0x6067 +45=0x6068 +46=0x606A +47=0x606C +48=0x607A +49=0x607C +50=0x607D +51=0x6081 +52=0x6082 +53=0x6083 +54=0x6084 +55=0x6085 +56=0x6086 +57=0x608F +58=0x6098 +59=0x6099 +60=0x609A +61=0x60A4 +62=0x60B0 +63=0x60B1 +64=0x60C2 +65=0x60F2 +66=0x60FD +67=0x60FF +68=0x6502 +69=0x67FF + +[ManufacturerObjects] +SupportedObjects=59 +1=0x2000 +2=0x2001 +3=0x2002 +4=0x2003 +5=0x2004 +6=0x2005 +7=0x200A +8=0x200B +9=0x200C +10=0x200F +11=0x2010 +12=0x2011 +13=0x2012 +14=0x2013 +15=0x2014 +16=0x2015 +17=0x204E +18=0x2089 +19=0x208C +20=0x208E +21=0x2092 +22=0x2093 +23=0x2094 +24=0x2095 +25=0x2096 +26=0x2097 +27=0x2098 +28=0x2099 +29=0x209A +30=0x209B +31=0x209C +32=0x209D +33=0x209E +34=0x20A1 +35=0x20A4 +36=0x20A5 +37=0x20A7 +38=0x20B0 +39=0x20B1 +40=0x20B2 +41=0x2100 +42=0x2101 +43=0x2102 +44=0x2107 +45=0x2123 +46=0x2700 +47=0x2701 +48=0x2702 +49=0x2703 +50=0x2704 +51=0x2705 +52=0x2706 +53=0x2707 +54=0x2708 +55=0x270B +56=0x270C +57=0x270E +58=0x270F +59=0x5FFF + +[1000] +ParameterName=Device Type +ObjectType=0x07 +DataType=0x0007 +AccessType=const +DefaultValue=0xFFFF0192 +PDOMapping=0 + +[1001] +ParameterName=Error Register +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[1005] +ParameterName=COB-ID SYNC +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000080 +PDOMapping=0 + +[1008] +ParameterName=Manufacturer Device Name +ObjectType=0x07 +DataType=0x0009 +AccessType=const +PDOMapping=0 + +[1009] +ParameterName=Manufacturer Hardware Version +ObjectType=0x07 +DataType=0x0009 +AccessType=const +PDOMapping=0 + +[100A] +ParameterName=Manufacturer Software Version +ObjectType=0x07 +DataType=0x0009 +AccessType=const +PDOMapping=0 + +[100C] +ParameterName=Guard Time +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[100D] +ParameterName=Life Time Factor +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[1010] +SubNumber=6 +ParameterName=Store Parameter Field +ObjectType=0x08 + +[1010sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=5 +AccessType=ro +DefaultValue=0x05 +PDOMapping=0 + +[1010sub1] +ParameterName=Save all Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1010sub2] +ParameterName=Save Communication Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1010sub3] +ParameterName=Save Device Profile Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1010sub4] +ParameterName=Save Axis 0 Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1010sub5] +ParameterName=Save Device Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1011] +SubNumber=6 +ParameterName=Restore Default Parameters +ObjectType=0x08 + +[1011sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=5 +AccessType=ro +DefaultValue=0x05 +PDOMapping=0 + +[1011sub1] +ParameterName=Restore all Default Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1011sub2] +ParameterName=Restore Communication Default Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1011sub3] +ParameterName=Restore Device Profile Default Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1011sub4] +ParameterName=Restore Axis 0 Default Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1011sub5] +ParameterName=Restore Device Default Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1014] +ParameterName=COB-ID EMCY +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x80 +PDOMapping=0 + +[1015] +ParameterName=Inhibit Time Emergency +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0000 +PDOMapping=0 + +[1016] +SubNumber=2 +ParameterName=Heartbeat Consumer Entries +ObjectType=0x08 + +[1016sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=5 +AccessType=ro +DefaultValue=0x1 +PDOMapping=0 + +[1016sub1] +ParameterName=Consumer Heartbeat Time 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[1017] +ParameterName=Producer Heartbeat Time +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[1018] +SubNumber=5 +ParameterName=Identity Object +ObjectType=0x09 + +[1018sub0] +ParameterName=number of entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x4 +PDOMapping=0 + +[1018sub1] +ParameterName=Vendor Id +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +DefaultValue=0x286 +PDOMapping=0 + +[1018sub2] +ParameterName=Product Code +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +DefaultValue=0x4CE +PDOMapping=0 + +[1018sub3] +ParameterName=Revision number +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[1018sub4] +ParameterName=Serial number +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[1023] +SubNumber=4 +ParameterName=OS Command +ObjectType=0x09 + +[1023sub0] +ParameterName=NumOfEntries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x3 +PDOMapping=0 + +[1023sub1] +ParameterName=Command +ObjectType=0x07 +DataType=0x000A +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[1023sub2] +ParameterName=Status +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[1023sub3] +ParameterName=Reply +ObjectType=0x07 +DataType=0x000A +AccessType=ro +PDOMapping=0 + +[1029] +SubNumber=3 +ParameterName=Error Behaviour +ObjectType=0x08 + +[1029sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=5 +AccessType=ro +DefaultValue=0x2 +PDOMapping=0 + +[1029sub1] +ParameterName=Communication Error +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[1029sub2] +ParameterName=Application Error +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x1 +PDOMapping=0 + +[1400] +SubNumber=3 +ParameterName=Receive PDO Communication Parameter 1 +ObjectType=0x09 + +[1400sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x02 +PDOMapping=0 + +[1400sub1] +ParameterName=COB-ID +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x40000200 +PDOMapping=0 + +[1400sub2] +ParameterName=Transmission Type +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0xFF +PDOMapping=0 + +[1401] +SubNumber=3 +ParameterName=Receive PDO Communication Parameter 2 +ObjectType=0x09 + +[1401sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x02 +PDOMapping=0 + +[1401sub1] +ParameterName=COB-ID +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x40000300 +PDOMapping=0 + +[1401sub2] +ParameterName=Transmission Type +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0xFF +PDOMapping=0 + +[1402] +SubNumber=3 +ParameterName=Receive PDO Communication Parameter 3 +ObjectType=0x09 + +[1402sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x02 +PDOMapping=0 + +[1402sub1] +ParameterName=COB-ID +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x40000400 +PDOMapping=0 + +[1402sub2] +ParameterName=Transmission Type +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0xFF +PDOMapping=0 + +[1403] +SubNumber=3 +ParameterName=Receive PDO Communication Parameter 4 +ObjectType=0x09 + +[1403sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x02 +PDOMapping=0 + +[1403sub1] +ParameterName=COB-ID +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x40000500 +PDOMapping=0 + +[1403sub2] +ParameterName=Transmission Type +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0xFE +PDOMapping=0 + +[1600] +SubNumber=4 +ParameterName=Receive PDO Mapping Parameter 1 +ObjectType=0x09 + +[1600sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x01 +PDOMapping=0 + +[1600sub1] +ParameterName=Mapping Entry 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60400010 +PDOMapping=0 + +[1600sub2] +ParameterName=Mapping Entry 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1600sub3] +ParameterName=Mapping Entry 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1601] +SubNumber=4 +ParameterName=Receive PDO Mapping Parameter 2 +ObjectType=0x09 + +[1601sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x02 +PDOMapping=0 + +[1601sub1] +ParameterName=Mapping Entry 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60400010 +PDOMapping=0 + +[1601sub2] +ParameterName=Mapping Entry 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60600008 +PDOMapping=0 + +[1601sub3] +ParameterName=Mapping Entry 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1602] +SubNumber=4 +ParameterName=Receive PDO Mapping Parameter 3 +ObjectType=0x09 + +[1602sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x02 +PDOMapping=0 + +[1602sub1] +ParameterName=Mapping Entry 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60400010 +PDOMapping=0 + +[1602sub2] +ParameterName=Mapping Entry 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x607A0020 +PDOMapping=0 + +[1602sub3] +ParameterName=Mapping Entry 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1603] +SubNumber=4 +ParameterName=Receive PDO Mapping Parameter 4 +ObjectType=0x09 + +[1603sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x02 +PDOMapping=0 + +[1603sub1] +ParameterName=Mapping Entry 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60400010 +PDOMapping=0 + +[1603sub2] +ParameterName=Mapping Entry 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60FF0020 +PDOMapping=0 + +[1603sub3] +ParameterName=Mapping Entry 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1800] +SubNumber=6 +ParameterName=Transmit PDO Communication Parameter 1 +ObjectType=0x09 + +[1800sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x05 +PDOMapping=0 + +[1800sub1] +ParameterName=COB-ID +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x40000180 +PDOMapping=0 + +[1800sub2] +ParameterName=Transmission Type +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0xFF +PDOMapping=0 + +[1800sub3] +ParameterName=Inhibit Time +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[1800sub4] +ParameterName=Compatibility Entry +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[1800sub5] +ParameterName=Event Timer +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[1801] +SubNumber=6 +ParameterName=Transmit PDO Communication Parameter 2 +ObjectType=0x09 + +[1801sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x05 +PDOMapping=0 + +[1801sub1] +ParameterName=COB-ID +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x40000280 +PDOMapping=0 + +[1801sub2] +ParameterName=Transmission Type +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0xFF +PDOMapping=0 + +[1801sub3] +ParameterName=Inhibit Time +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0000 +PDOMapping=0 + +[1801sub4] +ParameterName=Compatibility Entry +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[1801sub5] +ParameterName=Event Timer +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0000 +PDOMapping=0 + +[1802] +SubNumber=6 +ParameterName=Transmit PDO Communication Parameter 3 +ObjectType=0x09 + +[1802sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x05 +PDOMapping=0 + +[1802sub1] +ParameterName=COB-ID +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x40000380 +PDOMapping=0 + +[1802sub2] +ParameterName=Transmission Type +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x1 +PDOMapping=0 + +[1802sub3] +ParameterName=Inhibit Time +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0000 +PDOMapping=0 + +[1802sub4] +ParameterName=Compatibility Entry +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[1802sub5] +ParameterName=Event Timer +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0000 +PDOMapping=0 + +[1803] +SubNumber=6 +ParameterName=Transmit PDO Communication Parameter 4 +ObjectType=0x09 + +[1803sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +DefaultValue=0x05 +PDOMapping=0 + +[1803sub1] +ParameterName=COB-ID +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=$NODEID+0x40000480 +PDOMapping=0 + +[1803sub2] +ParameterName=Transmission Type +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0xFE +PDOMapping=0 + +[1803sub3] +ParameterName=Inhibit Time +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[1803sub4] +ParameterName=Compatibility Entry +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[1803sub5] +ParameterName=Event Timer +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[1A00] +SubNumber=4 +ParameterName=Transmit PDO Mapping Parameter 1 +ObjectType=0x09 + +[1A00sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x01 +PDOMapping=0 + +[1A00sub1] +ParameterName=Mapping Entry 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60410010 +PDOMapping=0 + +[1A00sub2] +ParameterName=Mapping Entry 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1A00sub3] +ParameterName=Mapping Entry 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1A01] +SubNumber=4 +ParameterName=Transmit PDO Mapping Parameter 2 +ObjectType=0x09 + +[1A01sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x02 +PDOMapping=0 + +[1A01sub1] +ParameterName=Mapping Entry 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60410010 +PDOMapping=0 + +[1A01sub2] +ParameterName=Mapping Entry 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60610008 +PDOMapping=0 + +[1A01sub3] +ParameterName=Mapping Entry 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1A02] +SubNumber=4 +ParameterName=Transmit PDO Mapping Parameter 3 +ObjectType=0x09 + +[1A02sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x02 +PDOMapping=0 + +[1A02sub1] +ParameterName=Mapping Entry 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60410010 +PDOMapping=0 + +[1A02sub2] +ParameterName=Mapping Entry 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60640020 +PDOMapping=0 + +[1A02sub3] +ParameterName=Mapping Entry 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[1A03] +SubNumber=4 +ParameterName=Transmit PDO Mapping Parameter 4 +ObjectType=0x09 + +[1A03sub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x02 +PDOMapping=0 + +[1A03sub1] +ParameterName=Mapping Entry 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x60410010 +PDOMapping=0 + +[1A03sub2] +ParameterName=Mapping Entry 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x606C0020 +PDOMapping=0 + +[1A03sub3] +ParameterName=Mapping Entry 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00000000 +PDOMapping=0 + +[2000] +ParameterName=Microstep Resolution 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2001] +ParameterName=Fullstep Resolution 1 +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0xC8 +PDOMapping=0 + +[2002] +SubNumber=3 +ParameterName=Brake Delay Time 1 +ObjectType=0x08 + +[2002sub0] +ParameterName=highest sub-index supported +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x2 +PDOMapping=0 + +[2002sub1] +ParameterName=apply +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +PDOMapping=0 + +[2002sub2] +ParameterName=release +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +PDOMapping=0 + +[2003] +ParameterName=Absolute Max Current 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2004] +ParameterName=Standby Current 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2005] +ParameterName=Switch Parameters 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[200A] +ParameterName=Enable drive delay time 1 +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[200B] +SubNumber=4 +ParameterName=Encoder Parameters 1 +ObjectType=0x09 + +[200Bsub0] +ParameterName=NumOfEntries +ObjectType=0x07 +DataType=0x0005 +AccessType=const +DefaultValue=0x3 +PDOMapping=0 + +[200Bsub1] +ParameterName=polarity +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[200Bsub2] +ParameterName=direction +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[200Bsub3] +ParameterName=initPosition +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[200C] +SubNumber=3 +ParameterName=Brake Current Feed 1 +ObjectType=0x08 + +[200Csub0] +ParameterName=Highest sub-index supported +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x2 +PDOMapping=0 + +[200Csub1] +ParameterName=applied +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[200Csub2] +ParameterName=released +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[200F] +SubNumber=4 +ParameterName=Encoder N Channel Latch 1 +ObjectType=0x09 + +[200Fsub0] +ParameterName=NumOfEntries +ObjectType=0x07 +DataType=0x0005 +AccessType=const +DefaultValue=0x3 +PDOMapping=0 + +[200Fsub1] +ParameterName=mode +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[200Fsub2] +ParameterName=latchedInternalPosition +ObjectType=0x07 +DataType=0x0004 +AccessType=ro +DefaultValue=0x00000000 +PDOMapping=0 + +[200Fsub3] +ParameterName=latchedEncoderPosition +ObjectType=0x07 +DataType=0x0004 +AccessType=ro +DefaultValue=0x00000000 +PDOMapping=0 + +[2010] +ParameterName=Profile start velocity 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[2011] +ParameterName=Profile start acceleration 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[2012] +ParameterName=Profile break velocity 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[2013] +ParameterName=Profile final deceleration 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[2014] +ParameterName=Profile stop deceleration 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[2015] +ParameterName=Bow scaling factor 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x1 +PDOMapping=0 + +[204E] +ParameterName=Boost current 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[2089] +ParameterName=Standby delay 1 +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[208C] +ParameterName=Velocity Dimension Index 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[208E] +ParameterName=Acceleration Dimension Index 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[2092] +ParameterName=Chopper Blank Time 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2093] +ParameterName=Chopper Mode 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2094] +ParameterName=Chopper Disable Fast Decay Comparator 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2095] +ParameterName=Chopper Hysteresis End 1 +ObjectType=0x07 +DataType=0x0002 +AccessType=rw +PDOMapping=0 + +[2096] +ParameterName=Chopper Hysteresis Start 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2097] +ParameterName=Chopper Off Time 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2098] +ParameterName=Smart Energy Current Minimum 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2099] +ParameterName=Smart Energy CurrentDown Step 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[209A] +ParameterName=Smart Energy Hysteresis 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[209B] +ParameterName=Smart Energy Current Up Step 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[209C] +ParameterName=Smart Energy Hysteresis Start 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[209D] +ParameterName=Stall Guard2 Filter Enable 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[209E] +ParameterName=Stall Guard2 Threshold 1 +ObjectType=0x07 +DataType=0x0002 +AccessType=rw +PDOMapping=0 + +[20A1] +ParameterName=Short Protection Disable 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[20A4] +ParameterName=Stop On Stall 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[20A5] +ParameterName=SmartEnergy Threshold Speed 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[20A7] +ParameterName=Stop On Stall Option Code 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[20B0] +ParameterName=PWM Threshold Speed 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[20B1] +ParameterName=PWM Gradient 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[20B2] +ParameterName=PWM Amplitude 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[2100] +ParameterName=Home Offset Display 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=ro +DefaultValue=0x0 +PDOMapping=0 + +[2101] +ParameterName=Actual Load Value 1 +ObjectType=0x07 +DataType=0x0006 +AccessType=ro +PDOMapping=0 + +[2102] +ParameterName=Driver Error Flags 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[2107] +ParameterName=Microstep Resolution Display 1 +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[2123] +ParameterName=PWM Mode +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[2700] +ParameterName=TMCL Direct Communication +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[2701] +ParameterName=PDO Disabling +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[2702] +ParameterName=Device Digital Inputs +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[2703] +SubNumber=3 +ParameterName=Device Digital Outputs +ObjectType=0x08 + +[2703sub0] +ParameterName=Highest sub-index supported +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x2 +PDOMapping=0 + +[2703sub1] +ParameterName=Physical Outputs +ObjectType=0x07 +DataType=0x0007 +AccessType=rww +DefaultValue=0x0 +PDOMapping=1 + +[2703sub2] +ParameterName=Output Mask +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[2704] +ParameterName=CAN Bit Rate +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000003 + +[2705] +ParameterName=Node-ID +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +PDOMapping=0 + +[2706] +SubNumber=2 +ParameterName=Store +ObjectType=0x08 + +[2706sub0] +ParameterName=Highest sub-index supported +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x1 +PDOMapping=0 + +[2706sub1] +ParameterName=Save all Parameters +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 +ObjFlags=0x00000001 + +[2707] +ParameterName=CAN Bit Rate Load +ObjectType=0x07 +DataType=0x0006 +AccessType=ro +PDOMapping=0 +ObjFlags=0x00000002 + +[2708] +ParameterName=Node-ID Load +ObjectType=0x07 +DataType=0x0005 +AccessType=ro +PDOMapping=0 + +[270B] +ParameterName=HAL version +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[270C] +SubNumber=7 +ParameterName=CL Information +ObjectType=0x08 + +[270Csub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x6 +PDOMapping=0 + +[270Csub1] +ParameterName=info 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[270Csub2] +ParameterName=info 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[270Csub3] +ParameterName=info 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[270Csub4] +ParameterName=info 4 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[270Csub5] +ParameterName=info 5 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[270Csub6] +ParameterName=info 6 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=0 + +[270E] +SubNumber=9 +ParameterName=Device Analog Inputs +ObjectType=0x08 + +[270Esub0] +ParameterName=Number of Entries +ObjectType=0x07 +DataType=5 +AccessType=ro +DefaultValue=0x8 +PDOMapping=0 + +[270Esub1] +ParameterName=AIN0 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[270Esub2] +ParameterName=AIN1 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[270Esub3] +ParameterName=AIN2 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[270Esub4] +ParameterName=AIN3 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[270Esub5] +ParameterName=AIN4 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[270Esub6] +ParameterName=AIN5 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[270Esub7] +ParameterName=AIN6 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[270Esub8] +ParameterName=AIN7 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[270F] +ParameterName=Service Period +ObjectType=0x07 +DataType=0x0004 +AccessType=rw +PDOMapping=0 + +[5FFF] +ParameterName=Enter Boot Mode +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[6040] +ParameterName=Controlword 1 +ObjectType=0x07 +DataType=0x0006 +AccessType=rww +PDOMapping=1 + +[6041] +ParameterName=Statusword 1 +ObjectType=0x07 +DataType=0x0006 +AccessType=ro +PDOMapping=1 + +[605A] +ParameterName=Quick Stop Option Code 1 +ObjectType=0x07 +DataType=0x0003 +AccessType=rw +DefaultValue=0x0002 +PDOMapping=0 + +[605B] +ParameterName=Shutdown Option Code 1 +ObjectType=0x07 +DataType=0x0003 +AccessType=ro +DefaultValue=0x0000 +PDOMapping=0 + +[605C] +ParameterName=Disable Operation Option Code 1 +ObjectType=0x07 +DataType=0x0003 +AccessType=ro +DefaultValue=0x0001 +PDOMapping=0 + +[605D] +ParameterName=Halt Option Code 1 +ObjectType=0x07 +DataType=0x0003 +AccessType=rw +DefaultValue=0x0001 +PDOMapping=0 + +[605E] +ParameterName=Fault Reaction Option Code 1 +ObjectType=0x07 +DataType=0x0003 +AccessType=ro +DefaultValue=0x0002 +PDOMapping=0 + +[6060] +ParameterName=Modes of Operation 1 +ObjectType=0x07 +DataType=0x0002 +AccessType=rww +DefaultValue=0x00 +PDOMapping=1 + +[6061] +ParameterName=Modes of Operation Display 1 +ObjectType=0x07 +DataType=0x0002 +AccessType=ro +PDOMapping=1 + +[6062] +ParameterName=Position Demand Value 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=ro +PDOMapping=1 + +[6063] +ParameterName=Position Actual Internal Value 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=ro +PDOMapping=1 + +[6064] +ParameterName=Position Actual Value 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=ro +PDOMapping=1 + +[6065] +ParameterName=Following Error Window 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[6067] +ParameterName=Position Window 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0xFFFFFFFF +PDOMapping=0 + +[6068] +ParameterName=Position Window Time 1 +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x0000 +PDOMapping=0 + +[606A] +ParameterName=Sensor Selection Code 1 +ObjectType=0x07 +DataType=0x0003 +AccessType=rw +PDOMapping=0 + +[606C] +ParameterName=Velocity Actual Value 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=ro +PDOMapping=1 + +[607A] +ParameterName=Target Position 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=rww +DefaultValue=0x0 +PDOMapping=1 + +[607C] +ParameterName=Home Offset 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[607D] +SubNumber=3 +ParameterName=Software Position Limit 1 +ObjectType=0x08 + +[607Dsub0] +ParameterName=Highest sub-index supported +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x2 +PDOMapping=0 + +[607Dsub1] +ParameterName=Min Software Position Limit +ObjectType=0x07 +DataType=0x0004 +AccessType=rw +DefaultValue=0x80000001 +PDOMapping=0 + +[607Dsub2] +ParameterName=Max Software Position Limit +ObjectType=0x07 +DataType=0x0004 +AccessType=rw +DefaultValue=0x7FFFFFFF +PDOMapping=0 + +[6081] +ParameterName=Profile Velocity in pp-mode 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rww +PDOMapping=1 + +[6082] +ParameterName=End velocity 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[6083] +ParameterName=Profile Acceleration 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rww +PDOMapping=1 + +[6084] +ParameterName=Profile Deceleration 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rww +PDOMapping=1 + +[6085] +ParameterName=Quick Stop Deceleration 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[6086] +ParameterName=Motion Profile Type 1 +ObjectType=0x07 +DataType=0x0003 +AccessType=rw +DefaultValue=0x0000 +PDOMapping=0 + +[608F] +SubNumber=3 +ParameterName=Position Encoder Resolution 1 +ObjectType=0x08 + +[608Fsub0] +ParameterName=Highest sub-index supported +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x2 +PDOMapping=0 + +[608Fsub1] +ParameterName=Encoder Increments +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[608Fsub2] +ParameterName=Motor Revolutions +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +DefaultValue=0x00000001 +PDOMapping=0 + +[6098] +ParameterName=Homing Method 1 +ObjectType=0x07 +DataType=0x0002 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[6099] +SubNumber=3 +ParameterName=Homing Speeds 1 +ObjectType=0x08 + +[6099sub0] +ParameterName=Highest sub-index supported +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x2 +PDOMapping=0 + +[6099sub1] +ParameterName=Fast Homing Speed +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[6099sub2] +ParameterName=Slow Homing Speed +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[609A] +ParameterName=Homing Acceleration 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +PDOMapping=0 + +[60A4] +SubNumber=5 +ParameterName=Profile Jerk 1 +ObjectType=0x08 + +[60A4sub0] +ParameterName=Highest sub-index supported +ObjectType=0x07 +DataType=5 +AccessType=const +DefaultValue=0x4 +PDOMapping=0 + +[60A4sub1] +ParameterName=Profile Jerk 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[60A4sub2] +ParameterName=Profile Jerk 2 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[60A4sub3] +ParameterName=Profile Jerk 3 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[60A4sub4] +ParameterName=Profile Jerk 4 +ObjectType=0x07 +DataType=0x0007 +AccessType=rw +DefaultValue=0x0 +PDOMapping=0 + +[60B0] +ParameterName=Position Offset 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=rww +DefaultValue=0x0 +PDOMapping=1 + +[60B1] +ParameterName=Velocity Offset 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=rww +DefaultValue=0x00 +PDOMapping=1 + +[60C2] +SubNumber=3 +ParameterName=Interpolation Time Period 1 +ObjectType=0x09 + +[60C2sub0] +ParameterName=NumOfEntries +ObjectType=0x07 +DataType=0x0005 +AccessType=const +DefaultValue=0x02 +PDOMapping=0 + +[60C2sub1] +ParameterName=timeUnits +ObjectType=0x07 +DataType=0x0005 +AccessType=rw +DefaultValue=0x1 +PDOMapping=0 + +[60C2sub2] +ParameterName=timeIndex +ObjectType=0x07 +DataType=0x0002 +AccessType=rw +DefaultValue=0xFD +PDOMapping=0 + +[60F2] +ParameterName=Positioning Option Code 1 +ObjectType=0x07 +DataType=0x0006 +AccessType=rw +DefaultValue=0x00 +PDOMapping=0 + +[60FD] +ParameterName=Digital Inputs 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +PDOMapping=1 + +[60FF] +ParameterName=Target Velocity 1 +ObjectType=0x07 +DataType=0x0004 +AccessType=rw +DefaultValue=0x0 +PDOMapping=1 + +[6502] +ParameterName=Supported Drive Modes 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +DefaultValue=0x000001A5 +PDOMapping=0 + +[67FF] +ParameterName=Single Device Type 1 +ObjectType=0x07 +DataType=0x0007 +AccessType=ro +DefaultValue=0x00040192 +PDOMapping=0 + diff --git a/examples/modules/TMCM1231/CANopen/TMCM-1231.eds b/examples/modules/TMCM123x_0_1/CANopen/TMCM-1231.eds similarity index 100% rename from examples/modules/TMCM1231/CANopen/TMCM-1231.eds rename to examples/modules/TMCM123x_0_1/CANopen/TMCM-1231.eds diff --git a/examples/modules/TMCM123x_0_1/CANopen/rotate_demo_using_pdo.py b/examples/modules/TMCM123x_0_1/CANopen/rotate_demo_using_pdo.py new file mode 100644 index 00000000..8efb0ec8 --- /dev/null +++ b/examples/modules/TMCM123x_0_1/CANopen/rotate_demo_using_pdo.py @@ -0,0 +1,81 @@ +"""Run a TMCM-123x_0_1 in "Profile Velocity Mode" using PDOs. + +Includes the recording and plotting of actual velocity. + +Tested with: +* Firmware version 3.26 +* Using the Python canopen package version 2.0.0 +""" +import time +import dataclasses +import canopen +import matplotlib.pyplot as plt +from pytrinamic.modules.canopen_node import TmcmNode + + +samples = [] + + +@dataclasses.dataclass +class Sample: + timestamp: float + velocity: int + + +def tpdo4_callback(message): + global samples + velocity = message['Velocity Actual Value 1'].raw + timestamp = message.timestamp + samples.append(Sample(timestamp=timestamp, velocity=velocity)) + + +with canopen.Network() as network: + #network.connect(channel='PCAN_USBBUS1', bustype='pcan', bitrate=1_000_000) + network.connect(channel=0, bustype='kvaser', bitrate=1_000_000) + + tmcm_123x_0_1 = TmcmNode(1, 'TMCM-1230.eds') + network.add_node(tmcm_123x_0_1) + + # Reconfiguration + tmcm_123x_0_1.sdo[0x1403][1].raw = 0x8000_0381 # disable the RPDO4 + tmcm_123x_0_1.sdo[0x1603][0].raw = 0 # write the number of entries into subindex 0 + tmcm_123x_0_1.sdo[0x1603][1].raw = 0x60400010 + tmcm_123x_0_1.sdo[0x1603][2].raw = 0x60FF0020 + tmcm_123x_0_1.sdo[0x1603][3].raw = 0x60600008 + tmcm_123x_0_1.sdo[0x1603][0].raw = 3 # write the number of entries into subindex 0 + tmcm_123x_0_1.sdo[0x1403][1].raw = 0x4000_0381 # enable the RPDO4 + + tmcm_123x_0_1.load_configuration() + tmcm_123x_0_1.nmt.state = 'OPERATIONAL' + + tmcm_123x_0_1.go_to_operation_enabled() + + tmcm_123x_0_1.tpdo[4].add_callback(tpdo4_callback) + + tmcm_123x_0_1.sdo['Absolute Max Current 1'].raw = 50 + tmcm_123x_0_1.sdo['Stop On Stall 1'].raw = 0 + + target_velocity = 10000 + # Profile Velocity Mode + tmcm_123x_0_1.rpdo[4]['Modes of Operation 1'].raw = tmcm_123x_0_1.ModeOfOperation.PROFILE_VELOCITY_MODE + tmcm_123x_0_1.rpdo[4]['Controlword 1'].raw = tmcm_123x_0_1.Cmd.ENABLE_OPERATION + tmcm_123x_0_1.rpdo[4]['Target Velocity 1'].raw = target_velocity + tmcm_123x_0_1.rpdo[4].transmit() + print("Motor rotating...") + time.sleep(5) + tmcm_123x_0_1.rpdo[4]['Target Velocity 1'].raw = 0 + tmcm_123x_0_1.rpdo[4].transmit() + print("Motor stopped!") + time.sleep(2) + tmcm_123x_0_1.nmt.state = 'PRE-OPERATIONAL' + tmcm_123x_0_1.shutdown() + +fig, ax = plt.subplots() +t = [s.timestamp for s in samples] +v = [s.velocity for s in samples] +ax.plot(t, v) +ax.set_xlabel('Time') +ax.set_ylabel('Velocity') +plt.show() + + diff --git a/examples/modules/TMCM123x_0_1/CANopen/rotate_demo_using_sdo.py b/examples/modules/TMCM123x_0_1/CANopen/rotate_demo_using_sdo.py new file mode 100644 index 00000000..6be115be --- /dev/null +++ b/examples/modules/TMCM123x_0_1/CANopen/rotate_demo_using_sdo.py @@ -0,0 +1,35 @@ +""" +Uses SDO to rotate the motor for 5 seconds in profile velocity mode. +""" +import time +import canopen +from pytrinamic.modules.canopen_node import TmcmNode + +with canopen.Network() as network: + network.connect(channel='0', bustype='kvaser', bitrate=1_000_000) + + tmcm_123x_0_1 = TmcmNode(1, 'TMCM-1230.eds') + network.add_node(tmcm_123x_0_1) + # Profile Velocity Mode + tmcm_123x_0_1.sdo['Modes of Operation 1'].raw = tmcm_123x_0_1.ModeOfOperation.PROFILE_VELOCITY_MODE + + tmcm_123x_0_1.load_configuration() + tmcm_123x_0_1.nmt.state = 'OPERATIONAL' + + tmcm_123x_0_1.go_to_operation_enabled() + tmcm_123x_0_1.sdo['Absolute Max Current 1'].raw = 50 + tmcm_123x_0_1.sdo['Stop On Stall 1'].raw = 0 + + + target_velocity = 10000 + print("Rotating the motor...") + tmcm_123x_0_1.sdo['Target Velocity 1'].raw = target_velocity + time.sleep(5) + tmcm_123x_0_1.sdo['Target Velocity 1'].raw = 0 + print("Motor stopped!") + + tmcm_123x_0_1.nmt.state = 'PRE-OPERATIONAL' + tmcm_123x_0_1.shutdown() + + + diff --git a/examples/modules/TMCM123x_0_1/CANopen/six_point_ramp_demo_using_pdo.py b/examples/modules/TMCM123x_0_1/CANopen/six_point_ramp_demo_using_pdo.py new file mode 100644 index 00000000..ac3365db --- /dev/null +++ b/examples/modules/TMCM123x_0_1/CANopen/six_point_ramp_demo_using_pdo.py @@ -0,0 +1,118 @@ +"""Run a TMCM-123x_0_1 in "Profile Position Mode" using PDOs to configure Six-Point Ramp + +Includes the recording and plotting of the actual velocity along with the actual position. + +""" +import time +import dataclasses +import canopen +import matplotlib.pyplot as plt +from pytrinamic.modules.canopen_node import TmcmNode + + +samples = [] + + +@dataclasses.dataclass +class Sample: + timestamp: float + position: int + velocity: int + + +def tpdo4_callback(message): + global samples + position = message['Position Actual Value 1'].raw + velocity = message['Velocity Actual Value 1'].raw + timestamp = message.timestamp + samples.append(Sample(timestamp=timestamp, position=position, velocity=velocity)) + + +with canopen.Network() as network: + network.connect(channel='0', bustype='kvaser', bitrate=1_000_000) + + tmcm_123x_0_1 = TmcmNode(1, 'TMCM-1230.eds') + network.add_node(tmcm_123x_0_1) + + # Reconfiguration of TPDO4 + tmcm_123x_0_1.sdo[0x1803][1].raw = 0x8000_0381 # disable the TPDO4 + tmcm_123x_0_1.sdo[0x1a03][0].raw = 0 # write the number of entries into subindex 0 + tmcm_123x_0_1.sdo[0x1a03][1].raw = 0x60640020 + tmcm_123x_0_1.sdo[0x1a03][2].raw = 0x606C0020 + tmcm_123x_0_1.sdo[0x1a03][0].raw = 2 # write the number of entries into subindex 0 + tmcm_123x_0_1.sdo[0x1803][1].raw = 0x4000_0381 # enable the TPDO4 + + # Reconfiguration of RPDO4 + tmcm_123x_0_1.sdo[0x1403][1].raw = 0x8000_0381 # disable the RPDO4 + tmcm_123x_0_1.sdo[0x1603][0].raw = 0 # write the number of entries into subindex 0 + tmcm_123x_0_1.sdo[0x1603][1].raw = 0x60400010 + tmcm_123x_0_1.sdo[0x1603][2].raw = 0x607a0020 + tmcm_123x_0_1.sdo[0x1603][0].raw = 2 # write the number of entries into subindex 0 + tmcm_123x_0_1.sdo[0x1403][1].raw = 0x4000_0381 # enable the RPDO4 + + tmcm_123x_0_1.load_configuration() + tmcm_123x_0_1.nmt.state = 'OPERATIONAL' + + tmcm_123x_0_1.go_to_operation_enabled() + tmcm_123x_0_1.tpdo[4].add_callback(tpdo4_callback) + + tmcm_123x_0_1.sdo['Absolute Max Current 1'].raw = 50 + tmcm_123x_0_1.sdo['Stop On Stall 1'].raw = 0 + + # Setting axis parameters for configuring SixPoint ramp + tmcm_123x_0_1.sdo['Profile start velocity 1'].raw = 5000 # V_Start + tmcm_123x_0_1.sdo['Profile start acceleration 1'].raw = 5000 # A1 + tmcm_123x_0_1.sdo['Profile Acceleration 1'].raw = 30000 # max acceleration + tmcm_123x_0_1.sdo['Profile Deceleration 1'].raw = 20000 # max deceleration + tmcm_123x_0_1.sdo['Profile break velocity 1'].raw = 10000 # V1 + tmcm_123x_0_1.sdo['Profile final deceleration 1'].raw = 5000 # D1 + tmcm_123x_0_1.sdo['Profile Velocity in pp-mode 1'].raw = 40000 # V_max + + # Need to set V_stop and ramp_wait_time with an appropriate value + tmcm_123x_0_1.sdo['End velocity 1'].raw = 5000 # V_Stop? + # tmcm_123x_0_1.sdo['Profile stop deceleration 1'].raw = 5000 + tmcm_123x_0_1.sdo['Bow scaling factor 1'].raw = 255 # ramp_wait_time? + + # Profile Velocity Mode + tmcm_123x_0_1.sdo['Modes of Operation 1'].raw = tmcm_123x_0_1.ModeOfOperation.PROFILE_POSITION_MODE + + tmcm_123x_0_1.rpdo[4]['Controlword 1'].raw = tmcm_123x_0_1.Cmd.ENABLE_OPERATION + tmcm_123x_0_1.rpdo[4]['Target Position 1'].raw = 0 + tmcm_123x_0_1.rpdo[4].transmit() + + time.sleep(0.2) + + for target_position in [100000, 0]: + tmcm_123x_0_1.rpdo[4]['Target Position 1'].raw = target_position + tmcm_123x_0_1.rpdo[4]['Controlword 1'].raw = tmcm_123x_0_1.Cmd.ENABLE_OPERATION + tmcm_123x_0_1.Cmd.NEW_SET_POINT + tmcm_123x_0_1.rpdo[4].transmit() + + tmcm_123x_0_1.rpdo[4]['Controlword 1'].raw = tmcm_123x_0_1.Cmd.ENABLE_OPERATION + tmcm_123x_0_1.rpdo[4].transmit() + + target_reached_flag_mask = 0x0400 + while tmcm_123x_0_1.sdo['Statusword 1'].raw & target_reached_flag_mask == 0: + pass + + print("Reached Target Position: {target_position}" .format(target_position=target_position)) + + tmcm_123x_0_1.nmt.state = 'PRE-OPERATIONAL' + tmcm_123x_0_1.shutdown() + +fig, ax = plt.subplots(2) +t = [float(s.timestamp - samples[0].timestamp) for s in samples] +pos = [float(s.position) for s in samples] +vel = [float(s.velocity) for s in samples] +ax[0].plot(t, pos, label='Position') +ax[0].set_title('Pos vs Time') +ax[0].set_xlabel('Time') +ax[0].set_ylabel('Pos') +ax[0].legend() +ax[0].grid() +ax[1].plot(t, vel, label='Velocity') +ax[1].set_title('Vel vs Time') +ax[1].set_xlabel('Time') +ax[1].set_ylabel('Vel') +ax[1].legend() +ax[1].grid() +plt.show() \ No newline at end of file diff --git a/examples/modules/TMCM1231/TMCL/StallGuard2_demo.py b/examples/modules/TMCM123x_0_1/TMCL/StallGuard2_demo.py similarity index 94% rename from examples/modules/TMCM1231/TMCL/StallGuard2_demo.py rename to examples/modules/TMCM123x_0_1/TMCL/StallGuard2_demo.py index 36077618..9aa95793 100644 --- a/examples/modules/TMCM1231/TMCL/StallGuard2_demo.py +++ b/examples/modules/TMCM123x_0_1/TMCL/StallGuard2_demo.py @@ -5,7 +5,7 @@ """ import pytrinamic from pytrinamic.connections import ConnectionManager -from pytrinamic.modules import TMCM1231 +from pytrinamic.modules import TMCM123x_0_1 import time def stallguard2_init(motor, init_velocity): @@ -47,9 +47,9 @@ def main(): pytrinamic.show_info() # This example is using PCAN, if you want to use another connection please change the next line. - connection_manager = ConnectionManager("--interface pcan_tmcl") + connection_manager = ConnectionManager("--interface kvaser_tmcl") with connection_manager.connect() as my_interface: - module = TMCM1231(my_interface) + module = TMCM123x_0_1(my_interface) motor = module.motors[0] print("Preparing parameters") diff --git a/examples/modules/TMCM1231/TMCL/rotate_demo.py b/examples/modules/TMCM123x_0_1/TMCL/rotate_demo.py similarity index 93% rename from examples/modules/TMCM1231/TMCL/rotate_demo.py rename to examples/modules/TMCM123x_0_1/TMCL/rotate_demo.py index c4eeed1f..93122659 100644 --- a/examples/modules/TMCM1231/TMCL/rotate_demo.py +++ b/examples/modules/TMCM123x_0_1/TMCL/rotate_demo.py @@ -1,14 +1,13 @@ import pytrinamic from pytrinamic.connections import ConnectionManager -from pytrinamic.modules import TMCM1231 +from pytrinamic.modules import TMCM123x_0_1 import time pytrinamic.show_info() - # This example is using PCAN, if you want to use another connection please change the next line. -connectionManager = ConnectionManager("--interface pcan_tmcl") +connectionManager = ConnectionManager("--interface kvaser_tmcl") with connectionManager.connect() as myInterface: - module = TMCM1231(myInterface) + module = TMCM123x_0_1(myInterface) motor = module.motors[0] # Please be sure not to use a too high current setting for your motor. diff --git a/examples/modules/TMCM123x_0_1/readme.txt b/examples/modules/TMCM123x_0_1/readme.txt new file mode 100644 index 00000000..e03c2522 --- /dev/null +++ b/examples/modules/TMCM123x_0_1/readme.txt @@ -0,0 +1,5 @@ +"These examples are compatible with both TMCM1230 and TMCM1231 stepper motor drivers and +can be used without any modification to the code except for CANopen examples, where the right eds file +needs to be added to the script." +However, it is important for the user to ensure that they provide the required voltage and +current to the board based on its hardware specifications to prevent any damage to the module." \ No newline at end of file diff --git a/pytrinamic/RAMDebug.py b/pytrinamic/RAMDebug.py index 50a34f4c..94c52bf9 100644 --- a/pytrinamic/RAMDebug.py +++ b/pytrinamic/RAMDebug.py @@ -1,6 +1,7 @@ from pytrinamic.tmcl import TMCLCommand, TMCLReplyStatusError, TMCLStatus from enum import IntEnum + class RAMDebug_Command(IntEnum): INIT = 0 SET_SAMPLE_COUNT = 1 @@ -25,6 +26,7 @@ class RAMDebug_Command(IntEnum): SET_TRIGGER_EVAL_CHANNEL = 20 SET_TRIGGER_ADDRESS = 21 + class RAMDebug_Channel(IntEnum): CHANNEL_CAPTURE_DISABLED = 0 CHANNEL_AXIS_PARAMETER = 1 @@ -34,12 +36,14 @@ class RAMDebug_Channel(IntEnum): CHANNEL_MEMORY_ADDRESS = 5 CHANNEL_ANALOG_INPUT = 6 + class RAMDebug_Info(IntEnum): INFO_MAX_CHANNELS = 0 INFO_BUFFER_ELEMENTS = 1 INFO_SAMPLING_FREQUENCY = 2 INFO_CAPTURED_SAMPLES = 3 + class RAMDebug_Trigger(IntEnum): TRIGGER_UNCONDITIONAL = 0 TRIGGER_RISING_EDGE_SIGNED = 1 @@ -49,6 +53,7 @@ class RAMDebug_Trigger(IntEnum): TRIGGER_FALLING_EDGE_UNSIGNED = 5 TRIGGER_DUAL_EDGE_UNSIGNED = 6 + class RAMDebug_State(IntEnum): IDLE = 0 TRIGGER = 1 @@ -62,6 +67,7 @@ class RAMDebug_State(IntEnum): def _missing_(cls, value): return cls.UNKNOWN_STATUS + class Channel(): def __init__(self, channel_type, value, address = 0, signed = False, mask = 0xFFFF_FFFF, shift = 0): #TODO: add signed self.value = value @@ -119,6 +125,7 @@ def analog_input(cls, number): # Error if value is bigger than 8 bits return cls(channel_type, number) + class RAMDebug(): def __init__(self, connection): self._connection = connection @@ -313,7 +320,6 @@ def get_total_samples(self): else: return self._sample_count * self.channel_count() - def channel_count(self): return len(self.channels) diff --git a/pytrinamic/connections/tmcl_interface.py b/pytrinamic/connections/tmcl_interface.py index 5f1b6543..87081d41 100644 --- a/pytrinamic/connections/tmcl_interface.py +++ b/pytrinamic/connections/tmcl_interface.py @@ -1,7 +1,7 @@ import logging from abc import ABC from ..tmcl import TMCL, TMCLRequest, TMCLCommand, TMCLReply, TMCLReplyChecksumError, TMCLReplyStatusError -from ..helpers import TMC_helpers +from ..helpers import to_signed_32 class TmclInterface(ABC): @@ -142,7 +142,7 @@ def get_version_string(self, module_id=None): # General parameter access functions def get_parameter(self, p_command, p_type, p_axis, p_value, module_id=None, signed=False): value = self.send(p_command, p_type, p_axis, p_value, module_id).value - return TMC_helpers.to_signed_32(value) if signed else value + return to_signed_32(value) if signed else value def set_parameter(self, p_command, p_type, p_axis, p_value, module_id=None): return self.send(p_command, p_type, p_axis, p_value, module_id) @@ -150,7 +150,7 @@ def set_parameter(self, p_command, p_type, p_axis, p_value, module_id=None): # Axis parameter access functions def get_axis_parameter(self, command_type, axis, module_id=None, signed=False): value = self.send(TMCLCommand.GAP, command_type, axis, 0, module_id).value - return TMC_helpers.to_signed_32(value) if signed else value + return to_signed_32(value) if signed else value def set_axis_parameter(self, command_type, axis, value, module_id=None): return self.send(TMCLCommand.SAP, command_type, axis, value, module_id) @@ -165,7 +165,7 @@ def set_and_store_axis_parameter(self, command_type, axis, value, module_id=None # Global parameter access functions def get_global_parameter(self, command_type, bank, module_id=None, signed=False): value = self.send(TMCLCommand.GGP, command_type, bank, 0, module_id).value - return TMC_helpers.to_signed_32(value) if signed else value + return to_signed_32(value) if signed else value def set_global_parameter(self, command_type, bank, value, module_id=None): return self.send(TMCLCommand.SGP, command_type, bank, value, module_id) @@ -200,7 +200,7 @@ def read_register(self, register_address, command, channel, module_id=None, sign tmcl_motor = (channel & 0x0F) | ((register_address & 0x0F00) >> 4) tmcl_type = register_address & 0xFF value = self.send(command, tmcl_type, tmcl_motor, 0, module_id).value - return TMC_helpers.to_signed_32(value) if signed else value + return to_signed_32(value) if signed else value def write_register(self, register_address, command, channel, value, module_id=None): tmcl_motor = (channel & 0x0F) | ((register_address & 0x0F00) >> 4) diff --git a/pytrinamic/evalboards/MAX22216_eval.py b/pytrinamic/evalboards/MAX22216_eval.py index 9e1bf822..2ae86827 100644 --- a/pytrinamic/evalboards/MAX22216_eval.py +++ b/pytrinamic/evalboards/MAX22216_eval.py @@ -1,6 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import MAX22216 -from pytrinamic.helpers import TMC_helpers + class MAX22216_eval(TMCLEval): """ diff --git a/pytrinamic/evalboards/TMC2100_eval.py b/pytrinamic/evalboards/TMC2100_eval.py index 03b55a19..21ebf8c1 100644 --- a/pytrinamic/evalboards/TMC2100_eval.py +++ b/pytrinamic/evalboards/TMC2100_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2100 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2100_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC2130_eval.py b/pytrinamic/evalboards/TMC2130_eval.py index 8f782297..6f06bf04 100644 --- a/pytrinamic/evalboards/TMC2130_eval.py +++ b/pytrinamic/evalboards/TMC2130_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2130 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2130_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC2160_eval.py b/pytrinamic/evalboards/TMC2160_eval.py index 7451f954..e43f4c05 100644 --- a/pytrinamic/evalboards/TMC2160_eval.py +++ b/pytrinamic/evalboards/TMC2160_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2160 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2160_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC2208_eval.py b/pytrinamic/evalboards/TMC2208_eval.py index 6fc48141..a3688914 100644 --- a/pytrinamic/evalboards/TMC2208_eval.py +++ b/pytrinamic/evalboards/TMC2208_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2208 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2208_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC2209_eval.py b/pytrinamic/evalboards/TMC2209_eval.py index 92ec2a4f..0d726588 100644 --- a/pytrinamic/evalboards/TMC2209_eval.py +++ b/pytrinamic/evalboards/TMC2209_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2209 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2209_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC2224_eval.py b/pytrinamic/evalboards/TMC2224_eval.py index da39a9d7..4286742d 100644 --- a/pytrinamic/evalboards/TMC2224_eval.py +++ b/pytrinamic/evalboards/TMC2224_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2224 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2224_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC2225_eval.py b/pytrinamic/evalboards/TMC2225_eval.py index 67cd2e62..3f73b71b 100644 --- a/pytrinamic/evalboards/TMC2225_eval.py +++ b/pytrinamic/evalboards/TMC2225_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2225 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2225_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC2240_eval.py b/pytrinamic/evalboards/TMC2240_eval.py index c3091265..75248ad5 100644 --- a/pytrinamic/evalboards/TMC2240_eval.py +++ b/pytrinamic/evalboards/TMC2240_eval.py @@ -1,7 +1,7 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2240 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers +from pytrinamic.helpers import BitField class TMC2240_eval(TMCLEval): @@ -41,11 +41,11 @@ def read_register(self, register_address, signed=False): return self._connection.read_drv(register_address, self._module_id, signed) def write_register_field(self, field, value): - return self.write_register(field[0], TMC_helpers.field_set(self.read_register(field[0]), - field[1], field[2], value)) + return self.write_register(field[0], BitField.field_set(self.read_register(field[0]), + field[1], field[2], value)) def read_register_field(self, field): - return TMC_helpers.field_get(self.read_register(field[0]), field[1], field[2]) + return BitField.field_get(self.read_register(field[0]), field[1], field[2]) # Motion control functions diff --git a/pytrinamic/evalboards/TMC2300_eval.py b/pytrinamic/evalboards/TMC2300_eval.py index ea00900d..eeb9ac74 100644 --- a/pytrinamic/evalboards/TMC2300_eval.py +++ b/pytrinamic/evalboards/TMC2300_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2300 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2300_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC2590_eval.py b/pytrinamic/evalboards/TMC2590_eval.py index 4173e20e..b29be276 100644 --- a/pytrinamic/evalboards/TMC2590_eval.py +++ b/pytrinamic/evalboards/TMC2590_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2590 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2590_eval(TMCLEval): @@ -53,7 +52,7 @@ def move_to(self, motor, position, velocity=None): if velocity and velocity != 0: # Set maximum positioning velocity self.motors[motor].set_axis_parameter(self.motors[motor].AP.MaxVelocity, velocity) - self._connection.move(motor, position, self._module_id) + self._connection.move_to(motor, position, self._module_id) class _MotorTypeA(MotorControlModule): def __init__(self, eval_board, axis): diff --git a/pytrinamic/evalboards/TMC2660_eval.py b/pytrinamic/evalboards/TMC2660_eval.py index 1f10e9f5..21d269bb 100644 --- a/pytrinamic/evalboards/TMC2660_eval.py +++ b/pytrinamic/evalboards/TMC2660_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC2660 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC2660_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC4361_eval.py b/pytrinamic/evalboards/TMC4361_eval.py index 6e535cd7..ba4113f5 100644 --- a/pytrinamic/evalboards/TMC4361_eval.py +++ b/pytrinamic/evalboards/TMC4361_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC4361 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC4361_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC4671_eval.py b/pytrinamic/evalboards/TMC4671_eval.py index b9a3b313..f28e85cf 100644 --- a/pytrinamic/evalboards/TMC4671_eval.py +++ b/pytrinamic/evalboards/TMC4671_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC4671 -from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers +from pytrinamic.features import MotorControlModule, LinearRampModule class TMC4671_eval(TMCLEval): @@ -14,6 +13,15 @@ def __init__(self, connection, module_id=1): self.ics = [TMC4671(connection)] # Use the motion controller channel for register access + def move_to(self, axis, position, velocity=None): + if velocity: + self.motors[axis].linear_ramp.max_velocity = velocity + self.connection.move_to(axis, position, self.module_id) + + def move_by(self, axis, difference, velocity=None): + if velocity: + self.motors[axis].linear_ramp.max_velocity = velocity + self.connection.move_by(axis, difference, self.module_id) def write_register(self, register_address, value): return self._connection.write_mc(register_address, value, self._module_id) @@ -24,12 +32,15 @@ def read_register(self, register_address, signed=False): class _MotorTypeA(MotorControlModule): def __init__(self, eval_board, axis): MotorControlModule.__init__(self, eval_board, axis, self.AP) + self.linear_ramp = LinearRampModule(eval_board, axis, self.AP) + class AP: MaxVelocity = 4 - Acceleration = 11 + MaxAcceleration = 11 EnableRamp = 12 RampVelocity = 13 + LinearTargetPosition = 25 TargetTorque = 171 PID_FLUX_TARGET = 172 PID_VELOCITY_TARGET = 173 diff --git a/pytrinamic/evalboards/TMC5031_eval.py b/pytrinamic/evalboards/TMC5031_eval.py index 18936f98..b83adb67 100644 --- a/pytrinamic/evalboards/TMC5031_eval.py +++ b/pytrinamic/evalboards/TMC5031_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC5031 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC5031_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC5041_eval.py b/pytrinamic/evalboards/TMC5041_eval.py index ff05843e..46fd3fae 100644 --- a/pytrinamic/evalboards/TMC5041_eval.py +++ b/pytrinamic/evalboards/TMC5041_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC5041 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC5041_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC5062_eval.py b/pytrinamic/evalboards/TMC5062_eval.py index b0166e15..c2289e5f 100644 --- a/pytrinamic/evalboards/TMC5062_eval.py +++ b/pytrinamic/evalboards/TMC5062_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC5062 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC5062_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC5072_eval.py b/pytrinamic/evalboards/TMC5072_eval.py index b3d8f909..a7951a5b 100644 --- a/pytrinamic/evalboards/TMC5072_eval.py +++ b/pytrinamic/evalboards/TMC5072_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC5072 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers # from pytrinamic.features.linear_ramp_module import LinearRampModule # from pytrinamic.features.stallguard2_module import StallGuard2Module diff --git a/pytrinamic/evalboards/TMC5130_eval.py b/pytrinamic/evalboards/TMC5130_eval.py index 2f85ff25..32e9cff9 100644 --- a/pytrinamic/evalboards/TMC5130_eval.py +++ b/pytrinamic/evalboards/TMC5130_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC5130 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers # from pytrinamic.features.linear_ramp_module import LinearRampModule # from pytrinamic.features.stallguard2_module import StallGuard2Module diff --git a/pytrinamic/evalboards/TMC5160_eval.py b/pytrinamic/evalboards/TMC5160_eval.py index 88f87555..0a758c0f 100644 --- a/pytrinamic/evalboards/TMC5160_eval.py +++ b/pytrinamic/evalboards/TMC5160_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC5160 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC5160_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC5160_shield.py b/pytrinamic/evalboards/TMC5160_shield.py index ac4f9dc2..b5e59e7c 100644 --- a/pytrinamic/evalboards/TMC5160_shield.py +++ b/pytrinamic/evalboards/TMC5160_shield.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC5160 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers from pytrinamic.tmcl import TMCLCommand diff --git a/pytrinamic/evalboards/TMC5240_eval.py b/pytrinamic/evalboards/TMC5240_eval.py index 533f55c8..30db36f1 100644 --- a/pytrinamic/evalboards/TMC5240_eval.py +++ b/pytrinamic/evalboards/TMC5240_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC5240 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC5240_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC6100_eval.py b/pytrinamic/evalboards/TMC6100_eval.py index 225db58a..fee99c5d 100644 --- a/pytrinamic/evalboards/TMC6100_eval.py +++ b/pytrinamic/evalboards/TMC6100_eval.py @@ -1,6 +1,5 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC6100 -from pytrinamic.helpers import TMC_helpers class TMC6100_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC6200_eval.py b/pytrinamic/evalboards/TMC6200_eval.py index 3fa1bcb4..92fa5907 100644 --- a/pytrinamic/evalboards/TMC6200_eval.py +++ b/pytrinamic/evalboards/TMC6200_eval.py @@ -1,6 +1,5 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC6200 -from pytrinamic.helpers import TMC_helpers class TMC6200_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC6300_eval.py b/pytrinamic/evalboards/TMC6300_eval.py index 9bfde29f..535b9019 100644 --- a/pytrinamic/evalboards/TMC6300_eval.py +++ b/pytrinamic/evalboards/TMC6300_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC6300 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC6300_eval(TMCLEval): diff --git a/pytrinamic/evalboards/TMC7300_eval.py b/pytrinamic/evalboards/TMC7300_eval.py index e8f23d99..9bc3fb74 100644 --- a/pytrinamic/evalboards/TMC7300_eval.py +++ b/pytrinamic/evalboards/TMC7300_eval.py @@ -1,7 +1,6 @@ from pytrinamic.evalboards import TMCLEval from pytrinamic.ic import TMC7300 from pytrinamic.features import MotorControlModule -from pytrinamic.helpers import TMC_helpers class TMC7300_eval(TMCLEval): diff --git a/pytrinamic/evalboards/tmcl_eval.py b/pytrinamic/evalboards/tmcl_eval.py index 1d3f524e..73624537 100644 --- a/pytrinamic/evalboards/tmcl_eval.py +++ b/pytrinamic/evalboards/tmcl_eval.py @@ -1,4 +1,5 @@ -from pytrinamic.helpers import TMC_helpers +from pytrinamic.helpers import BitField, to_signed_32 + class TMCLEval(object): @@ -44,11 +45,11 @@ def get_axis_parameter(self, ap_type, axis, signed=False): return self._connection.get_axis_parameter(ap_type, axis, self._module_id, signed=signed) def write_register_field(self, field, value): - return self.write_register(field[0], TMC_helpers.field_set(self.read_register(field[0]), - field[1], field[2], value)) + return self.write_register(field[0], BitField.field_set(self.read_register(field[0]), + field[1], field[2], value)) def read_register_field(self, field): - return TMC_helpers.field_get(self.read_register(field[0]), field[1], field[2]) + return BitField.field_get(self.read_register(field[0]), field[1], field[2]) def write_axis_field(self, axis, field, value): """ @@ -76,7 +77,7 @@ def read_axis_field(self, axis, field, signed=False): Returns: Value of the target register field for the given axis. """ value = self.read_register_field(field[axis] if type(field) == list else field) - return TMC_helpers.to_signed_32(value) if signed else value + return BitField.to_signed_32(value) if signed else value def __str__(self): return "{} {}".format( diff --git a/pytrinamic/features/motor_control_ic.py b/pytrinamic/features/motor_control_ic.py index 6287e263..afb89cd9 100644 --- a/pytrinamic/features/motor_control_ic.py +++ b/pytrinamic/features/motor_control_ic.py @@ -1,5 +1,5 @@ from ..features.motor_control import MotorControl -from ..helpers import TMC_helpers +from ..helpers import to_signed_32 class MotorControlIc(MotorControl): @@ -163,7 +163,7 @@ def read_axis_field(self, field, signed=False): Returns: Value of the target register field for the given axis. """ value = self._parent.read_register_field(field[self._axis] if type(field) == list else field) - return TMC_helpers.to_signed_32(value) if signed else value + return to_signed_32(value) if signed else value # Properties target_position = property(get_target_position, set_target_position) diff --git a/pytrinamic/features/stallguard2_module.py b/pytrinamic/features/stallguard2_module.py index d396df04..82976468 100644 --- a/pytrinamic/features/stallguard2_module.py +++ b/pytrinamic/features/stallguard2_module.py @@ -23,7 +23,7 @@ def set_filter(self, enable_filter): 0 - Disable StallGuard2 filter 1 - Enable StallGuard2 filter """ - self._parent.set_axis_parameter(self._aps.SG2FilterEnable, self._axis, filter) + self._parent.set_axis_parameter(self._aps.SG2FilterEnable, self._axis, enable_filter) def get_filter(self): """ diff --git a/pytrinamic/helpers.py b/pytrinamic/helpers.py index c61e95e6..873d1839 100644 --- a/pytrinamic/helpers.py +++ b/pytrinamic/helpers.py @@ -1,7 +1,5 @@ -from . import name, desc - -class TMC_helpers(object): +class BitField: @staticmethod def field_get(data, mask, shift): @@ -11,14 +9,10 @@ def field_get(data, mask, shift): def field_set(data, mask, shift, value): return (data & (~mask)) | ((value << shift) & mask) - @staticmethod - def to_signed_32(x): - m = x & 0xffffffff - return (m ^ 0x80000000) - 0x80000000 - @staticmethod - def show_info(): - print(name + " - " + desc) +def to_signed_32(x): + m = x & 0xffffffff + return (m ^ 0x80000000) - 0x80000000 class EEPROM: diff --git a/pytrinamic/ic/MAX22216.py b/pytrinamic/ic/MAX22216.py index c8585397..6ade2c7d 100644 --- a/pytrinamic/ic/MAX22216.py +++ b/pytrinamic/ic/MAX22216.py @@ -3,6 +3,7 @@ from ..features.solenoid_ic import SolenoidIC from ..features.solenoid_control_ic import SolenoidControlIC + class MAX22216(TMCIc): """ QUAD SERIAL PROGRAMMABLE 2A HALF BRIDGE DRIVER diff --git a/pytrinamic/ic/TMC2660.py b/pytrinamic/ic/TMC2660.py index 1393bd05..ad33592f 100644 --- a/pytrinamic/ic/TMC2660.py +++ b/pytrinamic/ic/TMC2660.py @@ -68,6 +68,8 @@ class FIELD: SG = (0x02, 0x00000001, 0) # DRVCTRL + Register_Address_Bits = (0x08, 0x000C0000, 18) # For register variant: S/D mode + # Register_Address_Bits = ( 0x08, 0x000E0000, 17 ) # For register variant: SPI Mode INTPOL = (0x08, 0x00000200, 9) DEDGE = (0x08, 0x00000100, 8) MRES = (0x08, 0x0000000F, 0) @@ -84,12 +86,14 @@ class FIELD: RNDTF = (0x0C, 0x00002000, 13) HDEC = (0x0C, 0x00001800, 11) HEND = (0x0C, 0x00000780, 7) - HDEC1 = (0x0C, 0x00002000, 12) + HDEC1 = (0x0C, 0x00001000, 12) + HDEC0 = (0x0C, 0x00000800, 11) HEND = (0x0C, 0x00000780, 7) - HSTRT = (0x0C, 0x00000070, 3) + HSTRT = (0x0C, 0x00000070, 4) TOFF = (0x0C, 0x0000000F, 0) # SMARTEN + Register_Address_Bits = (0x0D, 0x000E0000, 17 ) SEIMIN = (0x0D, 0x00008000, 15) SEDN = (0x0D, 0x00006000, 13) SEUP = (0x0D, 0x00000060, 5) @@ -97,11 +101,13 @@ class FIELD: SEMIN = (0x0D, 0x0000000F, 0) # SGCSCONF + Register_Address_Bits = (0x0E, 0x000E0000, 17 ) SFILT = (0x0E, 0x00010000, 16) SGT = (0x0E, 0x00007F00, 8) CS = (0x0E, 0x0000001F, 0) # DRVCONF + Register_Address_Bits = (0x0F, 0x000E0000, 17 ) TST = (0x0F, 0x00010000, 16) SLPH = (0x0F, 0x0000C000, 14) SLPL = (0x0F, 0x00003000, 12) diff --git a/pytrinamic/ic/TMC4671.py b/pytrinamic/ic/TMC4671.py index ac9adb4a..2131fc81 100644 --- a/pytrinamic/ic/TMC4671.py +++ b/pytrinamic/ic/TMC4671.py @@ -1,6 +1,6 @@ import struct from ..ic.tmc_ic import TMCIc -from ..helpers import TMC_helpers +from ..helpers import BitField, to_signed_32 DATAGRAM_FORMAT = ">BI" DATAGRAM_LENGTH = 5 @@ -26,14 +26,14 @@ def read_register(self, register_address, signed=False): reply = self._connection.send_datagram(datagram, DATAGRAM_LENGTH) values = struct.unpack(DATAGRAM_FORMAT, reply) value = values[1] - return TMC_helpers.to_signed_32(value) if signed else value + return to_signed_32(value) if signed else value def write_register_field(self, field, value): - return self.write_register(field[0], TMC_helpers.field_set(self.read_register(field[0]), - field[1], field[2], value)) + return self.write_register(field[0], BitField.field_set(self.read_register(field[0]), + field[1], field[2], value)) def read_register_field(self, field): - return TMC_helpers.field_get(self.read_register(field[0]), field[1], field[2]) + return BitField.field_get(self.read_register(field[0]), field[1], field[2]) class REG: """ diff --git a/pytrinamic/ic/TMC7300.py b/pytrinamic/ic/TMC7300.py index 6c67d97f..a8d4056a 100644 --- a/pytrinamic/ic/TMC7300.py +++ b/pytrinamic/ic/TMC7300.py @@ -1,6 +1,6 @@ import struct from ..ic.tmc_ic import TMCIc -from ..helpers import TMC_helpers +from ..helpers import BitField, to_signed_32 DATAGRAM_FORMAT = ">BI" DATAGRAM_LENGTH = 5 @@ -26,14 +26,14 @@ def read_register(self, register_address, signed=False): reply = self._connection.send_datagram(datagram, DATAGRAM_LENGTH) values = struct.unpack(DATAGRAM_FORMAT, reply) value = values[1] - return TMC_helpers.to_signed_32(value) if signed else value + return to_signed_32(value) if signed else value def write_register_field(self, field, value): - return self.write_register(field[0], TMC_helpers.field_set(self.read_register(field[0]), - field[1], field[2], value)) + return self.write_register(field[0], BitField.field_set(self.read_register(field[0]), + field[1], field[2], value)) def read_register_field(self, field): - return TMC_helpers.field_get(self.read_register(field[0]), field[1], field[2]) + return BitField.field_get(self.read_register(field[0]), field[1], field[2]) class REG: GCONF = 0x00 diff --git a/pytrinamic/modules/TMCM1231.py b/pytrinamic/modules/TMCM123x_0_1.py similarity index 97% rename from pytrinamic/modules/TMCM1231.py rename to pytrinamic/modules/TMCM123x_0_1.py index 68042100..0c8c3a43 100644 --- a/pytrinamic/modules/TMCM1231.py +++ b/pytrinamic/modules/TMCM123x_0_1.py @@ -5,13 +5,13 @@ from ..features import StallGuard2Module, CoolStepModule -class TMCM1231(TMCLModule): +class TMCM123x_0_1(TMCLModule): """ - The TMCM-1231 is a single axis controller/driver module for 2-phase bipolar stepper motors. + The TMCM-123x_0_1 represents TMCM-1230 and TMCM-1231. They are single axis controller/driver modules for 2-phase bipolar stepper motors. """ def __init__(self, connection, module_id=1): super().__init__(connection, module_id) - self.name = "TMCM-1231" + self.name = "TMCM-123x_0_1" self.desc = self.__doc__ self.motors = [self._MotorTypeA(self, 0)] diff --git a/pytrinamic/modules/TMCM1617.py b/pytrinamic/modules/TMCM1617.py index d75305c1..5c01836a 100644 --- a/pytrinamic/modules/TMCM1617.py +++ b/pytrinamic/modules/TMCM1617.py @@ -2,7 +2,7 @@ from ..ic import TMC4671, TMC6200 from ..features import MotorControlModule, DriveSettingModule, LinearRampModule from ..features import ABNEncoderModule, DigitalHallModule, PIDModule -from ..helpers import TMC_helpers +from ..helpers import BitField class TMCM1617(TMCLModule): @@ -41,11 +41,11 @@ def read_register(self, ic_id, register_address, signed=False): return self.connection.read_mc_by_id(ic_id, register_address, self.module_id, signed) def write_register_field(self, ic_id, field, value): - return self.write_register(ic_id, field[0], TMC_helpers.field_set(self.read_register(ic_id, field[0]), - field[1], field[2], value)) + return self.write_register(ic_id, field[0], BitField.field_set(self.read_register(ic_id, field[0]), + field[1], field[2], value)) def read_register_field(self, ic_id, field): - return TMC_helpers.field_get(self.read_register(ic_id, field[0]), field[1], field[2]) + return BitField.field_get(self.read_register(ic_id, field[0]), field[1], field[2]) class _MotorTypeA(MotorControlModule): diff --git a/pytrinamic/modules/__init__.py b/pytrinamic/modules/__init__.py index c0babf3b..9bfbd082 100644 --- a/pytrinamic/modules/__init__.py +++ b/pytrinamic/modules/__init__.py @@ -23,4 +23,4 @@ from .TMCM6110 import TMCM6110 from .TMCM6212 import TMCM6212 from .TMCM6214 import TMCM6214 -from .TMCM1231 import TMCM1231 \ No newline at end of file +from .TMCM123x_0_1 import TMCM123x_0_1