Skip to content

Commit

Permalink
Examples: Some updates to the TMC4671 + TMC6100 eval system examples
Browse files Browse the repository at this point in the history
  • Loading branch information
trinamic-bp committed Jun 14, 2023
1 parent 36425de commit de222b2
Show file tree
Hide file tree
Showing 7 changed files with 305 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import time
import statistics
import pytrinamic
from pytrinamic.connections import ConnectionManager
from pytrinamic.evalboards import TMC4671_eval, TMC6100_eval
Expand All @@ -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)
Expand All @@ -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)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
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
Expand Down Expand Up @@ -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, 0xFF00835D)
mc_eval.write_register(TMC4671.REG.ADC_I1_SCALE_OFFSET, 0xFF0083B5)
# 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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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)

Original file line number Diff line number Diff line change
@@ -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 |

Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import time
import statistics
import pytrinamic
from pytrinamic.connections import ConnectionManager
from pytrinamic.evalboards import TMC4671_eval, TMC6100_eval
Expand Down Expand Up @@ -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)
Expand Down
28 changes: 14 additions & 14 deletions examples/evalboards/TMC4671/TMC4671_eval_adc_offset_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit de222b2

Please sign in to comment.