Skip to content

Commit

Permalink
m84 real implementation, refactoring: mostly line width
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolay-Kha committed Jul 9, 2017
1 parent 129d26e commit f549801
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 34 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ Video demo - [YouTube video](https://youtu.be/vcedo59raS4)

# Current gcode support
Commands G0, G1, G2, G3, G4, G17, G18, G19, G20, G21, G28, G53, G90, G91, G92,
M2, M3, M5, M30, M104, M105, M106, M107, M109, M114, M140, M190 are supported.
Commands can be easily added, see [gmachine.py](./cnc/gmachine.py) file.
M2, M3, M5, M30, M84, M104, M105, M106, M107, M109, M114, M140, M190 are
supported. Commands can be easily added, see [gmachine.py](./cnc/gmachine.py)
file.
Four axis are supported - X, Y, Z, E.
Circular interpolation for XY, ZX, YZ planes is supported.
Spindle with rpm control is supported.
Expand Down
2 changes: 2 additions & 0 deletions cnc/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
# -----------------------------------------------------------------------------
# Pins configuration.

# Enable pin for all steppers, low level is enabled.
STEPPERS_ENABLE_PIN = 26
STEPPER_STEP_PIN_X = 16
STEPPER_STEP_PIN_Y = 20
STEPPER_STEP_PIN_Z = 21
Expand Down
10 changes: 5 additions & 5 deletions cnc/gmachine.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ def _circular(self, delta, radius, velocity, direction):
logging.info("Moving circularly {} {} {} with radius {}"
" and velocity {}".format(self._plane, circle_end,
direction, radius, velocity))
gen = PulseGeneratorCircular(circle_end, radius, self._plane, direction,
velocity)
gen = PulseGeneratorCircular(circle_end, radius, self._plane,
direction, velocity)
self.__check_velocity(gen.max_velocity())
# if finish coords is not on circle, move some distance linearly
linear_delta = delta - circle_end
Expand Down Expand Up @@ -411,6 +411,8 @@ def do_command(self, gcode):
self._spindle(0)
elif c == 'M2' or c == 'M30': # program finish, reset everything.
self.reset()
elif c == 'M84': # disable motors
hal.disable_steppers()
# extruder and bed heaters control
elif c == 'M104' or c == 'M109' or c == 'M140' or c == 'M190':
if c == 'M104' or c == 'M109':
Expand Down Expand Up @@ -453,7 +455,7 @@ def do_command(self, gcode):
hal.join()
p = self.position()
answer = "X:{} Y:{} Z:{} E:{}".format(p.x, p.y, p.z, p.e)
elif c is None: # command not specified(for example, just F was passed)
elif c is None: # command not specified(ie just F was passed)
pass
# commands below are added just for compatibility
elif c == 'M82': # absolute mode for extruder
Expand All @@ -462,8 +464,6 @@ def do_command(self, gcode):
elif c == 'M83': # relative mode for extruder
if self._absoluteCoordinates:
raise GMachineException("Not supported, use G90/G91")
elif c == 'M84': # disable motors
pass # do not do anything
else:
raise GMachineException("unknown command")
# save parameters on success
Expand Down
10 changes: 10 additions & 0 deletions cnc/hal.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@
# """
# return measure()
#
#
# def disable_steppers():
# """ Disable all steppers until any movement occurs.
# """
# do_something()
#
#
# def calibrate(x, y, z):
# """ Move head to home position till end stop switch will be triggered.
# Do not return till all procedures are completed.
Expand All @@ -61,6 +68,7 @@
# """
# return do_something()
#
#
# def move(generator):
# """ Move head to according pulses in PulseGenerator.
# :param generator: PulseGenerator object
Expand Down Expand Up @@ -103,6 +111,8 @@
raise NotImplementedError("hal.get_extruder_temperature() not implemented")
if 'get_bed_temperature' not in locals():
raise NotImplementedError("hal.get_bed_temperature() not implemented")
if 'disable_steppers' not in locals():
raise NotImplementedError("hal.disable_steppers() not implemented")
if 'calibrate' not in locals():
raise NotImplementedError("hal.calibrate() not implemented")
if 'move' not in locals():
Expand Down
14 changes: 14 additions & 0 deletions cnc/hal_raspberry/hal.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ def init():
gpio.init(FAN_PIN, rpgpio.GPIO.MODE_OUTPUT)
gpio.init(EXTRUDER_HEATER_PIN, rpgpio.GPIO.MODE_OUTPUT)
gpio.init(BED_HEATER_PIN, rpgpio.GPIO.MODE_OUTPUT)
gpio.init(STEPPERS_ENABLE_PIN, rpgpio.GPIO.MODE_OUTPUT)
gpio.clear(SPINDLE_PWM_PIN)
gpio.clear(FAN_PIN)
gpio.clear(EXTRUDER_HEATER_PIN)
gpio.clear(BED_HEATER_PIN)
gpio.clear(STEPPERS_ENABLE_PIN)


def spindle_control(percent):
Expand Down Expand Up @@ -99,6 +101,13 @@ def get_bed_temperature():
return thermistor.get_temperature(BED_TEMPERATURE_SENSOR_CHANNEL)


def disable_steppers():
""" Disable all steppers until any movement occurs.
"""
logging.info("disable steppers")
gpio.set(STEPPERS_ENABLE_PIN)


def __calibrate_private(x, y, z, invert):
if invert:
stepper_inverted_x = not STEPPER_INVERTED_X
Expand Down Expand Up @@ -190,6 +199,8 @@ def calibrate(x, y, z):
:param z: boolean, True to calibrate Z axis.
:return: boolean, True if all specified end stops were triggered.
"""
# enable steppers
gpio.clear(STEPPERS_ENABLE_PIN)
logging.info("hal calibrate, x={}, y={}, z={}".format(x, y, z))
if not __calibrate_private(x, y, z, True): # move from endstop switch
return False
Expand All @@ -206,6 +217,8 @@ def move(generator):
# moving. In this case machine would safely paused between commands until
# calculation is done.

# enable steppers
gpio.clear(STEPPERS_ENABLE_PIN)
# 4 control blocks per 32 bytes
bytes_per_iter = 4 * dma.control_block_size()
# prepare and run dma
Expand Down Expand Up @@ -309,6 +322,7 @@ def deinit():
""" De-initialize hardware.
"""
join()
disable_steppers()
pwm.remove_all()
gpio.clear(SPINDLE_PWM_PIN)
gpio.clear(FAN_PIN)
Expand Down
19 changes: 10 additions & 9 deletions cnc/hal_raspberry/rpgpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class GPIO(object):

def __init__(self):
""" Create object which can control GPIO.
This class writes directly to CPU registers and doesn't use any libs
or kernel modules.
This class writes directly to CPU registers and doesn't use any
libs or kernel modules.
"""
self._mem = PhysicalMemory(PERI_BASE + GPIO_REGISTER_BASE)

Expand Down Expand Up @@ -191,26 +191,27 @@ def finalize_stream(self):
self._phys_memory.write_int(self.__current_address + 20
- self._DMA_CONTROL_BLOCK_SIZE, 0)
logging.info("DMA took {}MB of memory".
format(round(self.__current_address / 1024.0 / 1024.0, 2)))
format(round(self.__current_address / 1048576.0, 2)))

def run_stream(self):
""" Run DMA module in stream mode, i.e. does'n finalize last block
and do not check if there is anything to do.
"""
# configure PWM hardware module which will clocks DMA
self._pwm.write_int(PWM_CTL, 0)
self._clock.write_int(CM_PWM_CNTL, CM_PASSWORD | CM_SRC_PLLD) # disable
# disable
self._clock.write_int(CM_PWM_CNTL, CM_PASSWORD | CM_SRC_PLLD)
while (self._clock.read_int(CM_PWM_CNTL) & CM_CNTL_BUSY) != 0:
time.sleep(0.00001) # 10 us, wait until BUSY bit is clear
self._clock.write_int(CM_PWM_DIV,
CM_PASSWORD | CM_DIV_VALUE(5)) # 100MHz
# configure, 100 MHz
self._clock.write_int(CM_PWM_DIV, CM_PASSWORD | CM_DIV_VALUE(5))
self._clock.write_int(CM_PWM_CNTL,
CM_PASSWORD | CM_SRC_PLLD | CM_CNTL_ENABLE)

self._pwm.write_int(PWM_RNG1, 100)
self._pwm.write_int(PWM_DMAC, PWM_DMAC_ENAB
| PWM_DMAC_PANIC(15) | PWM_DMAC_DREQ(15))
self._pwm.write_int(PWM_DMAC, PWM_DMAC_ENAB | PWM_DMAC_PANIC(15)
| PWM_DMAC_DREQ(15))
self._pwm.write_int(PWM_CTL, PWM_CTL_CLRF)
# enable
self._pwm.write_int(PWM_CTL, PWM_CTL_USEF1 | PWM_CTL_PWEN1)
super(DMAGPIO, self)._run_dma()

Expand Down
6 changes: 6 additions & 0 deletions cnc/hal_virtual.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ def get_bed_temperature():
return BED_MAX_TEMPERATURE * 0.999


def disable_steppers():
""" Disable all steppers until any movement occurs.
"""
logging.info("hal disable steppers")


def calibrate(x, y, z):
""" Move head to home position till end stop switch will be triggered.
Do not return till all procedures are completed.
Expand Down
8 changes: 4 additions & 4 deletions cnc/heater.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ def run(self):
last_error = time.time()
else:
if time.time() - last_error > self.SENSOR_TIMEOUT_S:
logging.critical("No data from temperature sensor. Stop"
" heating.")
logging.critical("No data from temperature sensor."
" Stop heating.")
break
continue
last_error = None
Expand All @@ -87,8 +87,8 @@ def wait(self):
i = 0
while not self._pid.is_fixed():
if i % 8 == 0:
logging.info("Heating... current temperature {} C, power {}%"
.format(self._measure(), int(self._current_power)))
logging.info("Heating... current temperature {} C, power {}%".
format(self._measure(), int(self._current_power)))
i = 0
i += 1
time.sleep(0.25)
14 changes: 8 additions & 6 deletions cnc/pulses.py
Original file line number Diff line number Diff line change
Expand Up @@ -609,9 +609,10 @@ def __circular_find_time(self, a, b):
def __circular_a(self, i, pulses_per_mm):
if i >= self._iterations_a:
return self._dir_a, None
a, direction, side = self.__circular_helper(self._start_a_pulses, i + 1,
self._radius_a_pulses,
self._side_a, self._dir_a)
a, direction, side = \
self.__circular_helper(self._start_a_pulses, i + 1,
self._radius_a_pulses,
self._side_a, self._dir_a)
a /= pulses_per_mm
# first and last item can be slightly out of bound due float precision
if i + 1 == self._iterations_a:
Expand All @@ -624,9 +625,10 @@ def __circular_a(self, i, pulses_per_mm):
def __circular_b(self, i, pulses_per_mm):
if i >= self._iterations_b:
return self._dir_b, None
b, direction, side = self.__circular_helper(self._start_b_pulses, i + 1,
self._radius_b_pulses,
self._side_b, self._dir_b)
b, direction, side = \
self.__circular_helper(self._start_b_pulses, i + 1,
self._radius_b_pulses,
self._side_b, self._dir_b)
b /= pulses_per_mm
# first and last item can be slightly out of bound due float precision
if i + 1 == self._iterations_b:
Expand Down
10 changes: 6 additions & 4 deletions tests/test_gmachine.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ def test_feed_rate(self):
self.assertRaises(GMachineException,
m.do_command, GCode.parse_line("G1X1F-1"))
cl = "G1X1F" + str(MIN_VELOCITY_MM_PER_MIN - 0.0000001)
self.assertRaises(GMachineException, m.do_command, GCode.parse_line(cl))
self.assertRaises(GMachineException, m.do_command,
GCode.parse_line(cl))
m.do_command(GCode.parse_line("G1X100F"
+ str(MAX_VELOCITY_MM_PER_MIN_X)))
m.do_command(GCode.parse_line("G1Y100F"
Expand Down Expand Up @@ -120,7 +121,8 @@ def test_g2_g3(self):
m.do_command, GCode.parse_line("G2X99999999Y99999999"
"I1J1"))
self.assertRaises(GMachineException,
m.do_command, GCode.parse_line("G2X2Y2Z99999999I1J1"))
m.do_command,
GCode.parse_line("G2X2Y2Z99999999I1J1"))
self.assertEqual(m.position(), Coordinates(0, 0, 0, 0))
self.assertRaises(GMachineException,
m.do_command, GCode.parse_line("G2X4Y4I2J2"))
Expand Down Expand Up @@ -250,9 +252,9 @@ def test_m104_m109(self):
self.assertEqual(m.extruder_target_temperature(), 0)
self.assertRaises(GMachineException, m.do_command,
GCode.parse_line("M104S"+str(MIN_TEMPERATURE - 1)))
et = EXTRUDER_MAX_TEMPERATURE + 1
self.assertRaises(GMachineException, m.do_command,
GCode.parse_line("M109S"
+ str(EXTRUDER_MAX_TEMPERATURE + 1)))
GCode.parse_line("M109S" + str(et)))
self.assertRaises(GMachineException, m.do_command,
GCode.parse_line("M109"))

Expand Down
4 changes: 2 additions & 2 deletions tests/test_heater.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ def test_sync(self):
def test_fail(self):
# check if heater will not fix with incorrect temperature
self._control_counter = 0
he = Heater(self._target_temp, EXTRUDER_PID, self.__get_bad_temperature,
self.__control)
he = Heater(self._target_temp, EXTRUDER_PID,
self.__get_bad_temperature, self.__control)
j = 0
while self._control_counter < 10:
time.sleep(0.01)
Expand Down
4 changes: 2 additions & 2 deletions utils/heater_model_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@


"""
This executable module is looking for heating and cooling transfer coefficients.
Can be ran only on real hardware.
This executable module is looking for heating and cooling transfer
coefficients. Can be ran only on real hardware.
"""

# change settings below for your hardware/environment
Expand Down

0 comments on commit f549801

Please sign in to comment.