Skip to content

Instantly share code, notes, and snippets.

@astropika
Last active August 26, 2024 16:40
Show Gist options
  • Save astropika/dca7d5ebc62edbd3c6ee6f143526209d to your computer and use it in GitHub Desktop.
Save astropika/dca7d5ebc62edbd3c6ee6f143526209d to your computer and use it in GitHub Desktop.
Micropython TMC2130 control script for a simple variable speed turntable, used on an ESP32. Docs for registry values at https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2130_datasheet.pdf
import machine
from machine import Pin, SPI, PWM, ADC
import time
import struct
import sys
# for use with TMC2130
led = Pin(13, Pin.OUT)
enable = Pin(32, Pin.OUT)
switch = Pin(33, Pin.IN, Pin.PULL_UP)
cs = Pin(4, Pin.OUT)
cs.value(1)
step = PWM(Pin(14))
spi = SPI(-1,baudrate=100000,polarity=1,phase=1,firstbit=SPI.MSB, sck=Pin(5, Pin.OUT), mosi=Pin(18, Pin.OUT), miso=Pin(19, Pin.IN))
speed = ADC(Pin(36))
speed.atten(ADC.ATTN_11DB)
speed.width(ADC.WIDTH_10BIT)
# /2 because dedge enabled
RPS = 51200/2
WRITE_FLAG = 0x80 #write flag
READ_FLAG = 0x00 #read flag
REG_GCONF = 0x00
REG_GSTAT = 0x01
REG_IHOLD_IRUN = 0x10
REG_CHOPCONF = 0x6C
REG_COOLCONF = 0x6D
REG_DCCTRL = 0x6E
REG_DRVSTATUS = 0x6F
def pack_data(data,fmt='>L'):
pb = struct.pack(fmt,data)
buf = bytearray(pb)
return buf
def tmc_write(cmd, data):
cs.value(0)
cmdpack = pack_data(cmd,'B')
datapack = pack_data(data,'>L')
c = spi.write(cmdpack)
s = spi.write(datapack)
cs.value(1)
return s
def tmc_read(addr):
cs.value(0)
tmc_write(addr,0x00)
s = spi.write(pack_data(addr))
buf = struct.unpack('>L',spi.read(4,0x00))
cs.value(1)
return (s,buf)
def setup():
spi.init(baudrate=100000)
enable.value(1)
#voltage on AIN is current reference
s = tmc_write(WRITE_FLAG+REG_GCONF, 0x00000001)
print(parse_status(s))
#IHOLD=0x10, IRUN=0x10
s = tmc_write(WRITE_FLAG+REG_IHOLD_IRUN, 0x00001010)
print(parse_status(s))
#native 256 microsteps, MRES=0, TBL=1=24, TOFF=8
s = tmc_write(WRITE_FLAG+REG_CHOPCONF, 0x20008008)
#64 microsteps, MRES=0, TBL=1=24, TOFF=8
#s = tmc_write(WRITE_FLAG+REG_CHOPCONF, 0x02008008)
#1 microsteps, MRES=0, TBL=1=24, TOFF=8
#s = tmc_write(WRITE_FLAG+REG_CHOPCONF, 0x13008008)
print(parse_status(s))
def flash(num):
#esp32 doesn't have lots of fancy LEDs on the board
#connect some LEDs later to show externally
for i in range(num):
led.value(1)
time.sleep(.250)
led.value(0)
time.sleep(.250)
def error(num,e):
while True:
for i in range(num):
led.value(1)
time.sleep(.125)
led.value(0)
time.sleep(.125)
print(e)
sys.print_exception(e)
time.sleep(4.000)
def parse_status(s):
if s:
if (s & 0x01):
return("reset")
elif (s & 0x02):
return("error")
elif (s & 0x03):
return("sg2")
elif (s & 0x04):
return("standstill")
else:
return(s)
else:
return s
def speedsel(val):
if val > 50:
if val < 200:
# 6RPM
return int(RPS/10)
elif val < 400:
# 12RPM
return int(RPS/5)
elif val < 600:
#60RPM
return int(RPS)
else:
#120RPM
return int(RPS*2)
else:
return 1
def run():
try:
print("enabling")
enable.value(0)
s, data = tmc_read(REG_GSTAT)
goutput = "REG_GSTAT: "+ str(data[0]) + " " + str(parse_status(data[0]))
print(goutput)
s, data = tmc_read(REG_GCONF)
coutput = "REG_GCONF: "+ str(data[0]) + " " + str(parse_status(data[0]))
print(coutput)
s, data = tmc_read(REG_DRVSTATUS)
doutput = "DRVSTATUS: "+ str(data[0]) + " " + str(parse_status(data[0]))
print(doutput)
print(speed.read())
revs = speedsel(speed.read())
step.init(freq=revs)
while revs > 1:
if revs is not speedsel(speed.read()):
revs = speedsel(speed.read())
step.freq(revs)
time.sleep(0.25)
print(speed.read())
step.deinit()
enable.value(1)
print("disabling")
except Exception as e:
enable.value(1)
error(5,e)
def wait():
flash(4)
while True:
if not switch.value():
if speedsel(speed.read()) > 1:
run()
time.sleep(.5)
else:
print('speed at idle')
else:
print("switch off")
flash(1)
if __name__ == "__main__":
try:
setup()
wait()
except Exception as e:
enable.value(1)
error(3,e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment