reorganise project

This commit is contained in:
Nikolay Khabarov
2017-05-13 03:52:36 +03:00
parent 82d0f5f016
commit 1391b03724
17 changed files with 69 additions and 34 deletions
+152
View File
@@ -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)