mirror of
https://github.com/sinseman44/PyCNC.git
synced 2026-07-16 08:37:09 +00:00
reorganise project
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
import logging
|
||||
import time
|
||||
|
||||
import rpgpio
|
||||
|
||||
from cnc.pulses import PulseGeneratorLinear
|
||||
from cnc.coordinates import Coordinates
|
||||
from cnc.config import *
|
||||
|
||||
# Stepper motors channel for RPIO
|
||||
STEPPER_CHANNEL = 0
|
||||
# Since there is no way to add pulses and then start cycle in RPIO,
|
||||
# use this delay to start adding pulses to cycle. It can be easily
|
||||
# solved by modifying RPIO in a way of adding method to start cycle
|
||||
# explicitly.
|
||||
RPIO_START_DELAY_US = 200000
|
||||
# Since RPIO generate cycles in loop, use this delay to stop RPIO
|
||||
# It can be removed if RPIO would allow to run single shot cycle.
|
||||
RPIO_STOP_DELAY_US = 5000000
|
||||
|
||||
US_IN_SECONDS = 1000000
|
||||
|
||||
gpio = rpgpio.GPIO()
|
||||
dma = rpgpio.DMAGPIO()
|
||||
|
||||
STEP_PIN_MASK_X = 1 << STEPPER_STEP_PIN_X
|
||||
STEP_PIN_MASK_Y = 1 << STEPPER_STEP_PIN_Y
|
||||
STEP_PIN_MASK_Z = 1 << STEPPER_STEP_PIN_Z
|
||||
|
||||
def init():
|
||||
""" Initialize GPIO pins and machine itself, including callibration if
|
||||
needed. Do not return till all procedure is completed.
|
||||
"""
|
||||
gpio.init(STEPPER_STEP_PIN_X, rpgpio.GPIO.MODE_OUTPUT)
|
||||
gpio.init(STEPPER_STEP_PIN_Y, rpgpio.GPIO.MODE_OUTPUT)
|
||||
gpio.init(STEPPER_STEP_PIN_Z, rpgpio.GPIO.MODE_OUTPUT)
|
||||
gpio.init(STEPPER_DIR_PIN_X, rpgpio.GPIO.MODE_OUTPUT)
|
||||
gpio.init(STEPPER_DIR_PIN_Y, rpgpio.GPIO.MODE_OUTPUT)
|
||||
gpio.init(STEPPER_DIR_PIN_Z, rpgpio.GPIO.MODE_OUTPUT)
|
||||
gpio.init(ENDSTOP_PIN_X, rpgpio.GPIO.MODE_INPUT_PULLUP)
|
||||
gpio.init(ENDSTOP_PIN_X, rpgpio.GPIO.MODE_INPUT_PULLUP)
|
||||
gpio.init(ENDSTOP_PIN_X, rpgpio.GPIO.MODE_INPUT_PULLUP)
|
||||
|
||||
# calibration
|
||||
gpio.set(STEPPER_DIR_PIN_X)
|
||||
gpio.set(STEPPER_DIR_PIN_Y)
|
||||
gpio.set(STEPPER_DIR_PIN_Z)
|
||||
pins = STEP_PIN_MASK_X | STEP_PIN_MASK_Y | STEP_PIN_MASK_Z
|
||||
dma.clear()
|
||||
dma.add_pulse(pins, STEPPER_PULSE_LINGTH_US)
|
||||
while True:
|
||||
if (STEP_PIN_MASK_X & pins) != 0 and gpio.read(ENDSTOP_PIN_X) == 0:
|
||||
pins &= ~STEP_PIN_MASK_X
|
||||
dma.clear()
|
||||
dma.add_pulse(pins, STEPPER_PULSE_LINGTH_US)
|
||||
if (STEP_PIN_MASK_Y & pins) != 0 and gpio.read(ENDSTOP_PIN_Y) == 0:
|
||||
pins &= ~STEP_PIN_MASK_Y
|
||||
dma.clear()
|
||||
dma.add_pulse(pins, STEPPER_PULSE_LINGTH_US)
|
||||
if (STEP_PIN_MASK_Z & pins) != 0 and gpio.read(ENDSTOP_PIN_Z) == 0:
|
||||
pins &= ~STEP_PIN_MASK_Z
|
||||
dma.clear()
|
||||
dma.add_pulse(pins, STEPPER_PULSE_LINGTH_US)
|
||||
if pins == 0:
|
||||
break
|
||||
dma.run(False)
|
||||
# limit velocity at ~10% of top velocity
|
||||
time.sleep((1 / 0.10) / (STEPPER_MAX_VELOCITY_MM_PER_MIN
|
||||
/ 60 * STEPPER_PULSES_PER_MM))
|
||||
|
||||
|
||||
def spindle_control(percent):
|
||||
""" Spindle control implementation.
|
||||
:param percent: Spindle speed in percent.
|
||||
"""
|
||||
# TODO spindle control.
|
||||
logging.info("TODO spindle control: {}%".format(percent))
|
||||
|
||||
|
||||
def move_linear(delta, velocity):
|
||||
""" Move head to specified position
|
||||
:param delta: Coordinated object, delta position in mm
|
||||
:param velocity: velocity in mm per min
|
||||
"""
|
||||
logging.info("move {} with velocity {}".format(delta, velocity))
|
||||
# initialize generator
|
||||
generator = PulseGeneratorLinear(delta, velocity)
|
||||
# wait if previous command still works
|
||||
while dma.is_active():
|
||||
time.sleep(0.001)
|
||||
|
||||
# set direction pins
|
||||
if delta.x > 0.0:
|
||||
gpio.clear(STEPPER_DIR_PIN_X)
|
||||
else:
|
||||
gpio.set(STEPPER_DIR_PIN_X)
|
||||
if delta.y > 0.0:
|
||||
gpio.clear(STEPPER_DIR_PIN_Y)
|
||||
else:
|
||||
gpio.set(STEPPER_DIR_PIN_Y)
|
||||
if delta.z > 0.0:
|
||||
gpio.clear(STEPPER_DIR_PIN_Z)
|
||||
else:
|
||||
gpio.set(STEPPER_DIR_PIN_Z)
|
||||
|
||||
# prepare and run dma
|
||||
dma.clear()
|
||||
prev = 0
|
||||
is_ran = False
|
||||
st = time.time()
|
||||
for tx, ty, tz in generator:
|
||||
pins = 0
|
||||
k = int(round(min(x for x in (tx, ty, tz) if x is not None)
|
||||
* US_IN_SECONDS))
|
||||
if tx is not None:
|
||||
pins |= STEP_PIN_MASK_X
|
||||
if ty is not None:
|
||||
pins |= STEP_PIN_MASK_Y
|
||||
if tz is not None:
|
||||
pins |= STEP_PIN_MASK_Z
|
||||
if k - prev > 0:
|
||||
dma.add_delay(k - prev)
|
||||
dma.add_pulse(pins, STEPPER_PULSE_LINGTH_US)
|
||||
# TODO not a precise way! pulses will set in queue, instead of crossing
|
||||
# if next pulse start during pulse length. Though it almost doesn't
|
||||
# matter for pulses with 1-2us length.
|
||||
prev = k + STEPPER_PULSE_LINGTH_US
|
||||
# instant run handling
|
||||
if not is_ran and INSTANT_RUN:
|
||||
if k > 500000: # wait at least 500 ms is uploaded
|
||||
if time.time() - st > 0.5:
|
||||
# may be instant run should be canceled here?
|
||||
logging.warn("Buffer preparing for instant run took more "
|
||||
"time then buffer time")
|
||||
dma.run_stream()
|
||||
is_ran = True
|
||||
pt = time.time()
|
||||
if not is_ran:
|
||||
dma.run(False)
|
||||
else:
|
||||
dma.finalize_stream()
|
||||
|
||||
logging.info("prepared in " + str(round(pt - st, 2)) + "s, estimated in "
|
||||
+ str(round(generator.total_time_s(), 2)) + "s")
|
||||
|
||||
|
||||
def join():
|
||||
""" Wait till motors work.
|
||||
"""
|
||||
# wait till dma works
|
||||
while dma.is_active():
|
||||
time.sleep(0.01)
|
||||
Reference in New Issue
Block a user