created v0.3 functional software prototype
This commit is contained in:
parent
b2597a60c7
commit
fafa874b43
228
Software/TMC2130.py
Normal file
228
Software/TMC2130.py
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
from machine import Pin, PWM, SPI
|
||||||
|
import time
|
||||||
|
import utime
|
||||||
|
from config import *
|
||||||
|
from led import *
|
||||||
|
from sTimer import sTimer_Start, sTimer_Stop
|
||||||
|
import sys
|
||||||
|
|
||||||
|
EN = Pin(13, Pin.OUT)
|
||||||
|
DIR = Pin(14, Pin.OUT)
|
||||||
|
STEP = Pin(15, Pin.OUT)
|
||||||
|
ENDSTOP = Pin(8, Pin.IN, Pin.PULL_UP)
|
||||||
|
DC_EN = Pin(11, Pin.OUT)
|
||||||
|
DC_IN = Pin(10, Pin.OUT)
|
||||||
|
DC_OUT = Pin(12, Pin.IN)
|
||||||
|
SPI_MODE = Pin(20, Pin.OUT)
|
||||||
|
spi_cs = Pin(17, Pin.OUT)
|
||||||
|
|
||||||
|
spi = SPI(0, baudrate=100000, polarity=1, phase=1, bits=8, firstbit=SPI.MSB, sck=Pin(18, Pin.OUT), mosi=Pin(19, Pin.OUT), miso=Pin(16, Pin.IN))
|
||||||
|
|
||||||
|
DC_EN(0)
|
||||||
|
DC_IN(0)
|
||||||
|
spi_cs(1)
|
||||||
|
EN(1) #0 = enabled
|
||||||
|
DIR(0)
|
||||||
|
STEP(0)
|
||||||
|
|
||||||
|
MM_PER_STEP = SCREW_PITCH / (MOTOR_STEPS * MICROSTEPPING)
|
||||||
|
FREQ_PER_STEP_INCREASE = (((MOTOR_STEPS * MICROSTEPPING) / SCREW_PITCH) * ACCELERATION) / 60
|
||||||
|
|
||||||
|
REG_GCONF = 0x00
|
||||||
|
REG_GSTAT = 0x01
|
||||||
|
REG_IHOLD_IRUN = 0x10
|
||||||
|
REG_CHOPCONF = 0x6C
|
||||||
|
REG_COOLCONF = 0x6D
|
||||||
|
REG_DCCTRL = 0x6E
|
||||||
|
REG_DRVSTATUS = 0x6F
|
||||||
|
|
||||||
|
step_cntr = 0
|
||||||
|
target_steps = 0
|
||||||
|
target_frequency = 0
|
||||||
|
current_frequency = 0
|
||||||
|
def step():
|
||||||
|
global STEP, step_cntr, current_frequency, target_frequency, target_steps, FREQ_PER_STEP_INCREASE
|
||||||
|
STEP.value(not STEP.value())
|
||||||
|
STEP.value(not STEP.value())
|
||||||
|
LED_ERR.value(not LED_ERR.value())
|
||||||
|
|
||||||
|
step_cntr += 1
|
||||||
|
if(current_frequency < target_frequency):
|
||||||
|
current_frequency += FREQ_PER_STEP_INCREASE
|
||||||
|
if(target_steps >= step_cntr):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def rotate_motor(steps, feedrate):
|
||||||
|
global current_frequency, step_cntr, target_steps, target_frequency
|
||||||
|
step_cntr = 0
|
||||||
|
target_steps = steps
|
||||||
|
target_frequency = ((feedrate / SCREW_PITCH) * MOTOR_STEPS * MICROSTEPPING) / 60 #steps/s = rpm * steps_per_rotation / 60
|
||||||
|
print(target_frequency)
|
||||||
|
print(FREQ_PER_STEP_INCREASE)
|
||||||
|
current_frequency = FREQ_PER_STEP_INCREASE
|
||||||
|
|
||||||
|
def timer_callback(counter):
|
||||||
|
if (counter % 1) == 0:
|
||||||
|
step()
|
||||||
|
|
||||||
|
def get_stats():
|
||||||
|
global STEP, step_cntr, current_frequency, target_frequency, target_steps, FREQ_PER_STEP_INCREASE
|
||||||
|
print(step_cntr, current_frequency, target_frequency, FREQ_PER_STEP_INCREASE)
|
||||||
|
|
||||||
|
def rotate_motor_test():
|
||||||
|
rotate_motor(32*200, 5)
|
||||||
|
sTimer_Start()
|
||||||
|
time.sleep(2)
|
||||||
|
sTimer_Stop()
|
||||||
|
|
||||||
|
def prepare_spi_msg(addr, d0, d1, d2, d3, rw):
|
||||||
|
msg = bytearray()
|
||||||
|
if rw == 'r':
|
||||||
|
msg.append(addr)
|
||||||
|
else:
|
||||||
|
msg.append(0x80 + addr)
|
||||||
|
msg.append(d0)
|
||||||
|
msg.append(d1)
|
||||||
|
msg.append(d2)
|
||||||
|
msg.append(d3)
|
||||||
|
|
||||||
|
return msg
|
||||||
|
|
||||||
|
def send_spi_msg(msg):
|
||||||
|
spi_cs(0)
|
||||||
|
rxdata = bytearray(5)
|
||||||
|
spi.write_readinto(msg, rxdata)
|
||||||
|
#print(rxdata.hex())
|
||||||
|
spi_cs(1)
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
def TMC2130_Rotate(dir, steps, speed): #speed in rpm
|
||||||
|
#1rmp = 200steps/min=3.333steps/s~150ms@50%duty
|
||||||
|
wait = (((1 / ((MOTOR_STEPS * MICROSTEPPING) / 60)) / 2) / speed) * 1000 * 1000
|
||||||
|
freq = 1 / ((wait / 1000000) * 2)
|
||||||
|
|
||||||
|
if AXIS_REVERSE:
|
||||||
|
if dir == 0:
|
||||||
|
dir = 1
|
||||||
|
else:
|
||||||
|
dir = 0
|
||||||
|
|
||||||
|
DIR(dir)
|
||||||
|
LED_DIR(dir)
|
||||||
|
|
||||||
|
STEP = PWM(Pin(15), freq=int(freq), duty_u16=32768)
|
||||||
|
time.sleep((1 / freq) * steps)
|
||||||
|
STEP.deinit()
|
||||||
|
|
||||||
|
homing = False
|
||||||
|
def TMC2130_Home():
|
||||||
|
global homing
|
||||||
|
|
||||||
|
dir = HOME_DIR
|
||||||
|
STEP = Pin(15, Pin.OUT)
|
||||||
|
|
||||||
|
steps_mm = (MOTOR_STEPS * MICROSTEPPING) / SCREW_PITCH
|
||||||
|
rpm = HOME_SPEED / SCREW_PITCH
|
||||||
|
wait = (((1 / ((MOTOR_STEPS * MICROSTEPPING) / 60)) / 2) / rpm) * 1000 * 1000
|
||||||
|
freq = 1 / ((wait / 1000000) * 2)
|
||||||
|
|
||||||
|
if AXIS_REVERSE:
|
||||||
|
if dir == 0:
|
||||||
|
dir = 1
|
||||||
|
else:
|
||||||
|
dir = 0
|
||||||
|
|
||||||
|
DIR(dir)
|
||||||
|
LED_DIR(dir)
|
||||||
|
|
||||||
|
sys.stdout.write('homing\r\n')
|
||||||
|
homing = True
|
||||||
|
STEP = PWM(Pin(15), freq=int(freq), duty_u16=32768)
|
||||||
|
while homing:
|
||||||
|
pass
|
||||||
|
STEP.deinit()
|
||||||
|
|
||||||
|
if HOME_DEBOUNCE == True:
|
||||||
|
sys.stdout.write('debouncing\r\n')
|
||||||
|
if dir == 0:
|
||||||
|
dir = 1
|
||||||
|
else:
|
||||||
|
dir = 0
|
||||||
|
|
||||||
|
DIR(dir)
|
||||||
|
LED_DIR(dir)
|
||||||
|
|
||||||
|
steps = steps_mm * abs(HOME_DEBOUNCE_DISTANCE)
|
||||||
|
|
||||||
|
TMC2130_Rotate(dir, steps, HOME_DEBOUNCE_SPEED)
|
||||||
|
|
||||||
|
rpm = HOME_DEBOUNCE_SPEED / SCREW_PITCH
|
||||||
|
wait = (((1 / ((MOTOR_STEPS * MICROSTEPPING) / 60)) / 2) / rpm) * 1000 * 1000
|
||||||
|
freq = 1 / ((wait / 1000000) * 2)
|
||||||
|
|
||||||
|
if dir == 0:
|
||||||
|
dir = 1
|
||||||
|
else:
|
||||||
|
dir = 0
|
||||||
|
|
||||||
|
DIR(dir)
|
||||||
|
LED_DIR(dir)
|
||||||
|
|
||||||
|
homing = True
|
||||||
|
STEP = PWM(Pin(15), freq=int(freq), duty_u16=32768)
|
||||||
|
while homing:
|
||||||
|
pass
|
||||||
|
STEP.deinit()
|
||||||
|
|
||||||
|
def TMC2130_Disable():
|
||||||
|
EN.value(1)
|
||||||
|
|
||||||
|
def TMC2130_Enable():
|
||||||
|
EN.value(0)
|
||||||
|
|
||||||
|
def endstop_callback(endstop):
|
||||||
|
global homing
|
||||||
|
|
||||||
|
homing = False
|
||||||
|
|
||||||
|
def TMC2130_Init():
|
||||||
|
SPI_MODE(1)
|
||||||
|
# setup coolstep
|
||||||
|
microstep = 0
|
||||||
|
if MICROSTEPPING == 128:
|
||||||
|
microstep = 1
|
||||||
|
elif MICROSTEPPING == 64:
|
||||||
|
microstep = 2
|
||||||
|
elif MICROSTEPPING == 32:
|
||||||
|
microstep = 3
|
||||||
|
elif MICROSTEPPING == 16:
|
||||||
|
microstep = 4
|
||||||
|
elif MICROSTEPPING == 8:
|
||||||
|
microstep = 5
|
||||||
|
elif MICROSTEPPING == 4:
|
||||||
|
microstep = 6
|
||||||
|
elif MICROSTEPPING == 2:
|
||||||
|
microstep = 7
|
||||||
|
elif MICROSTEPPING == 1:
|
||||||
|
microstep = 8
|
||||||
|
else:
|
||||||
|
microstep = 0
|
||||||
|
|
||||||
|
msg = prepare_spi_msg(REG_CHOPCONF, 0x00+microstep, 0x01, 0x00, 0xC3, 'w')
|
||||||
|
send_spi_msg(msg)
|
||||||
|
msg = prepare_spi_msg(REG_IHOLD_IRUN, 0x00, 0x06, I_RUN, I_HOLD, 'w')
|
||||||
|
send_spi_msg(msg)
|
||||||
|
msg = prepare_spi_msg(0x11, 0x00, 0x00, 0x00, 0x0A, 'w')
|
||||||
|
send_spi_msg(msg)
|
||||||
|
msg = prepare_spi_msg(REG_GCONF, 0x00, 0x00, 0x00, 0x04, 'w')
|
||||||
|
send_spi_msg(msg)
|
||||||
|
msg = prepare_spi_msg(0x13, 0x00, 0x00, 0x01, 0xF4, 'w')
|
||||||
|
send_spi_msg(msg)
|
||||||
|
msg = prepare_spi_msg(0x70, 0x00, 0x04, 0x01, 0xC8, 'w')
|
||||||
|
send_spi_msg(msg)
|
||||||
|
msg = prepare_spi_msg(REG_COOLCONF, 0x00, 0x00, 0x03, 0x01, 'w')
|
||||||
|
send_spi_msg(msg)
|
||||||
|
|
||||||
|
TMC2130_Enable()
|
||||||
|
|
||||||
|
ENDSTOP.irq(trigger=Pin.IRQ_FALLING, handler=endstop_callback)
|
66
Software/comms.py
Normal file
66
Software/comms.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import sys
|
||||||
|
import select
|
||||||
|
from config import *
|
||||||
|
from motion import Motion_Move
|
||||||
|
from TMC2130 import TMC2130_Home
|
||||||
|
import machine
|
||||||
|
|
||||||
|
poll_obj = ''
|
||||||
|
|
||||||
|
def Comms_Init():
|
||||||
|
global poll_obj
|
||||||
|
|
||||||
|
poll_obj = select.poll()
|
||||||
|
poll_obj.register(sys.stdin, select.POLLIN)
|
||||||
|
|
||||||
|
def Comms_Hello():
|
||||||
|
hello_str = 'Stepper motor driver\r\n'
|
||||||
|
hello_str += 'Software: v0.3\r\n'
|
||||||
|
hello_str += 'Hardware: v1.0\r\n'
|
||||||
|
hello_str += 'Author: Angoosh\r\n'
|
||||||
|
sys.stdout.write(hello_str)
|
||||||
|
|
||||||
|
def Comms_Reset():
|
||||||
|
machine.reset()
|
||||||
|
|
||||||
|
def Comms_GetInfo(info):
|
||||||
|
if info == 0:
|
||||||
|
sys.stdout.write(AXIS_ID+'\r\n')
|
||||||
|
|
||||||
|
def Comms_Read():
|
||||||
|
global poll_obj
|
||||||
|
|
||||||
|
poll_results = poll_obj.poll(1)
|
||||||
|
|
||||||
|
if poll_results:
|
||||||
|
rw = sys.stdin.readline().strip()
|
||||||
|
rw = rw.upper()
|
||||||
|
|
||||||
|
if 'G0' in rw:
|
||||||
|
if AXIS_ID in rw:
|
||||||
|
data = rw.split(' ')
|
||||||
|
for i in data:
|
||||||
|
if AXIS_ID in i:
|
||||||
|
motorics = i.split(':')
|
||||||
|
Motion_Move(int(motorics[1]), int(motorics[2]))
|
||||||
|
sys.stdout.write('OK\r\n')
|
||||||
|
elif 'G1' in rw:
|
||||||
|
if AXIS_ID in rw:
|
||||||
|
data = rw.split(' ')
|
||||||
|
for i in data:
|
||||||
|
if AXIS_ID in i:
|
||||||
|
motorics = i.split(':')
|
||||||
|
Motion_Move(int(motorics[1]), int(motorics[2]))
|
||||||
|
sys.stdout.write('OK\r\n')
|
||||||
|
elif 'G28' in rw:
|
||||||
|
TMC2130_Home()
|
||||||
|
elif 'RESET' in rw:
|
||||||
|
sys.stdout.write('OK\r\n')
|
||||||
|
Comms_Reset()
|
||||||
|
elif 'INFO' in rw:
|
||||||
|
data = rw.split(' ')
|
||||||
|
Comms_GetInfo(int(data[1]))
|
||||||
|
elif rw == '':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
sys.stdout.write('INVALID 1\r\n')
|
17
Software/config.py
Normal file
17
Software/config.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
MOTOR_STEPS = 200
|
||||||
|
MICROSTEPPING = 16
|
||||||
|
I_HOLD = 10 #hold current (1-31)
|
||||||
|
I_RUN = 10 #run current (1-31)
|
||||||
|
|
||||||
|
SCREW_PITCH = 5 #in mm/rotation
|
||||||
|
AXIS_LENGTH = 1000 #mm
|
||||||
|
AXIS_ID = 'X' #id of axis (X,Y,U,V)
|
||||||
|
AXIS_REVERSE = False
|
||||||
|
|
||||||
|
HOME_DIR = 0
|
||||||
|
HOME_SPEED = 600 #in mm/s
|
||||||
|
HOME_DEBOUNCE = True
|
||||||
|
HOME_DEBOUNCE_DISTANCE = 5 #in mm
|
||||||
|
HOME_DEBOUNCE_SPEED = 200
|
||||||
|
|
||||||
|
ACCELERATION = 1
|
6
Software/led.py
Normal file
6
Software/led.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from machine import Pin
|
||||||
|
|
||||||
|
LED_ERR = Pin(25, Pin.OUT)
|
||||||
|
LED_DIR = Pin(3, Pin.OUT)
|
||||||
|
LED_STOP = Pin(6, Pin.OUT)
|
||||||
|
LED_OK = Pin(7, Pin.OUT)
|
29
Software/main.py
Normal file
29
Software/main.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Example using PWM to fade an LED.
|
||||||
|
import time
|
||||||
|
from machine import Pin, PWM, Timer, SPI
|
||||||
|
from config import *
|
||||||
|
from led import *
|
||||||
|
from TMC2130 import TMC2130_Rotate, TMC2130_Init, rotate_motor_test
|
||||||
|
from motion import Motion_Init, Motion_Move
|
||||||
|
from comms import *
|
||||||
|
|
||||||
|
LED_OK.value(0)
|
||||||
|
LED_ERR.value(1)
|
||||||
|
time.sleep(0.5)
|
||||||
|
LED_ERR.value(0)
|
||||||
|
LED_DIR.value(1)
|
||||||
|
time.sleep(0.5)
|
||||||
|
LED_DIR.value(0)
|
||||||
|
LED_STOP.value(1)
|
||||||
|
time.sleep(0.5)
|
||||||
|
LED_STOP.value(0)
|
||||||
|
LED_OK.value(1)
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
TMC2130_Init()
|
||||||
|
Motion_Init()
|
||||||
|
Comms_Init()
|
||||||
|
|
||||||
|
Comms_Hello()
|
||||||
|
while True:
|
||||||
|
Comms_Read()
|
30
Software/motion.py
Normal file
30
Software/motion.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from TMC2130 import TMC2130_Rotate
|
||||||
|
from config import *
|
||||||
|
|
||||||
|
steps_mm = 0
|
||||||
|
|
||||||
|
def Motion_Init():
|
||||||
|
global steps_mm
|
||||||
|
|
||||||
|
steps_mm = (MOTOR_STEPS * MICROSTEPPING) / SCREW_PITCH
|
||||||
|
|
||||||
|
def Motion_Move(distance, speed): #distance in mm, speed in mm/min
|
||||||
|
global steps_mm
|
||||||
|
|
||||||
|
steps = steps_mm * abs(distance)
|
||||||
|
|
||||||
|
direction = 0
|
||||||
|
if distance < 0:
|
||||||
|
if AXIS_REVERSE == False:
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
direction = 1
|
||||||
|
else:
|
||||||
|
if AXIS_REVERSE == False:
|
||||||
|
direction = 1
|
||||||
|
else:
|
||||||
|
direction = 0
|
||||||
|
|
||||||
|
rpm = speed / SCREW_PITCH
|
||||||
|
|
||||||
|
TMC2130_Rotate(direction, steps, rpm)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
1
motor_driver/~motor_driver.kicad_pcb.lck
Normal file
1
motor_driver/~motor_driver.kicad_pcb.lck
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"hostname":"Oneill","username":"angoosh"}
|
Loading…
x
Reference in New Issue
Block a user