Last active
August 26, 2024 16:40
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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