diff --git a/macros.cfg b/macros.cfg index 9f5b678..ff97a42 100644 --- a/macros.cfg +++ b/macros.cfg @@ -6,6 +6,7 @@ gcode: M117 start heating M140 S{BED_TEMP} # start bed heating M104 S{EXTRUDER_TEMP} # start extruder heating + NEOPIXEL_ON COLOR=green # set neopixel green G92 E0 # reset extruder G21 # set units to millimeters G90 # use absolute coordinates @@ -14,11 +15,14 @@ gcode: M117 home G28 # home the printer G1 Z5 F3000 # move the nozzle near the bed - G1 Z0.15 F300 # move the nozzle very close to the bed + G1 Z0.25 F300 # move the nozzle very close to the bed M117 wait for heating + NEOPIXEL_ON COLOR=red # set neopixel red + G92 E0 # reset extruder M190 S{BED_TEMP} # set and wait for bed temperature M109 S{EXTRUDER_TEMP} # set and wait for nozzle temperature # clean nozzle + NEOPIXEL_ON COLOR=blue # set neopixel blue M117 clean nozzle G0 Z5 F300 # move Z to travel height G0 X40 Y0 F5000 # move to start position @@ -26,7 +30,8 @@ gcode: G0 X150 Y0 Z0.2 E10 # draw line G0 X150 Y0.8 Z0.2 # move to the side little G0 X30 Y0.8 Z0.2 E5 # draw fine line - G0 Z5 F300 # move Z to travel height + # G0 Z5 F300 # move Z to travel height + NEOPIXEL_ON COLOR=white # set neopixel white M117 starting [gcode_macro END_PRINT] @@ -41,6 +46,7 @@ gcode: G1 Z10 F3000 # Raise nozzle by 10mm G90 # Use absolute coordinates M84 # Disable steppers + NEOPIXEL_OFF # Turn off NeoPixel [gcode_macro PREHEAT] description: set bed and extruder temperature diff --git a/neopixel.cfg b/neopixel.cfg new file mode 100644 index 0000000..e15b6f6 --- /dev/null +++ b/neopixel.cfg @@ -0,0 +1,62 @@ +## direct control of neopixel is not working on RPI +# [neopixel pixel] +# pin: rpi:gpio18 +# chain_count: 4 +# color_order: GRB +# initial_RED: 0.0 +# initial_GREEN: 0.0 +# initial_BLUE: 0.0 +# # initial_WHITE: 0.0 + +# [gcode_macro NEOPIXEL] +# description: control neopixel +# gcode: +# {% set R = params.R|default(0) %} +# {% set G = params.G|default(0) %} +# {% set B = params.B|default(0) %} +# SET_LED LED=pixel RED={R} GREEN={G} BLUE={B} + +## run script instead +[gcode_macro NEOPIXEL_ON] +description: turn neopixel on +gcode: + {% set COLOR = params.COLOR|default("white") %} + {% if COLOR == "white" %} + RUN_SHELL_COMMAND CMD=neopixel_white + {% elif COLOR == "red" %} + RUN_SHELL_COMMAND CMD=neopixel_red + {% elif COLOR == "green" %} + RUN_SHELL_COMMAND CMD=neopixel_green + {% elif COLOR == "blue" %} + RUN_SHELL_COMMAND CMD=neopixel_blue + {% endif %} + +[gcode_macro NEOPIXEL_OFF] +description: turn neopixel off +gcode: + RUN_SHELL_COMMAND CMD=neopixel_off + +[gcode_shell_command neopixel_white] +command: sudo /home/pi/klipper_config/scripts/pixel.py 255 +timeout: 3 +verbose: False + +[gcode_shell_command neopixel_red] +command: sudo /home/pi/klipper_config/scripts/pixel.py 255 0 0 +timeout: 3 +verbose: False + +[gcode_shell_command neopixel_green] +command: sudo /home/pi/klipper_config/scripts/pixel.py 0 255 0 +timeout: 3 +verbose: False + +[gcode_shell_command neopixel_blue] +command: sudo /home/pi/klipper_config/scripts/pixel.py 0 0 255 +timeout: 3 +verbose: False + +[gcode_shell_command neopixel_off] +command: sudo /home/pi/klipper_config/scripts/pixel.py 0 +timeout: 3 +verbose: False diff --git a/printer.cfg b/printer.cfg index bcfe878..d639a64 100644 --- a/printer.cfg +++ b/printer.cfg @@ -18,6 +18,9 @@ max_z_accel: 400 [virtual_sdcard] path: ~/gcode_files +## neopixel +[include neopixel.cfg] + ## macros [include macros.cfg] diff --git a/scripts/gcode_shell_command.py b/scripts/gcode_shell_command.py new file mode 100755 index 0000000..4138172 --- /dev/null +++ b/scripts/gcode_shell_command.py @@ -0,0 +1,83 @@ +# Run a shell command via gcode +# +# Copyright (C) 2019 Eric Callahan +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import os +import shlex +import subprocess +import logging + +class ShellCommand: + def __init__(self, config): + self.name = config.get_name().split()[-1] + self.printer = config.get_printer() + self.gcode = self.printer.lookup_object('gcode') + cmd = config.get('command') + cmd = os.path.expanduser(cmd) + self.command = shlex.split(cmd) + self.timeout = config.getfloat('timeout', 2., above=0.) + self.verbose = config.getboolean('verbose', True) + self.proc_fd = None + self.partial_output = "" + self.gcode.register_mux_command( + "RUN_SHELL_COMMAND", "CMD", self.name, + self.cmd_RUN_SHELL_COMMAND, + desc=self.cmd_RUN_SHELL_COMMAND_help) + + def _process_output(self, eventime): + if self.proc_fd is None: + return + try: + data = os.read(self.proc_fd, 4096) + except Exception: + pass + data = self.partial_output + data + if '\n' not in data: + self.partial_output = data + return + elif data[-1] != '\n': + split = data.rfind('\n') + 1 + self.partial_output = data[split:] + data = data[:split] + self.gcode.respond_info(data) + + cmd_RUN_SHELL_COMMAND_help = "Run a linux shell command" + def cmd_RUN_SHELL_COMMAND(self, params): + reactor = self.printer.get_reactor() + try: + proc = subprocess.Popen( + self.command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + except Exception: + logging.exception( + "shell_command: Command {%s} failed" % (self.name)) + raise self.gcode.error("Error running command {%s}" % (self.name)) + if self.verbose: + self.proc_fd = proc.stdout.fileno() + self.gcode.respond_info("Running Command {%s}...:" % (self.name)) + hdl = reactor.register_fd(self.proc_fd, self._process_output) + eventtime = reactor.monotonic() + endtime = eventtime + self.timeout + complete = False + while eventtime < endtime: + eventtime = reactor.pause(eventtime + .05) + if proc.poll() is not None: + complete = True + break + if not complete: + proc.terminate() + if self.verbose: + if self.partial_output: + self.gcode.respond_info(self.partial_output) + self.partial_output = "" + if complete: + msg = "Command {%s} finished\n" % (self.name) + else: + msg = "Command {%s} timed out" % (self.name) + self.gcode.respond_info(msg) + reactor.unregister_fd(hdl) + self.proc_fd = None + + +def load_config_prefix(config): + return ShellCommand(config) diff --git a/scripts/pixel.py b/scripts/pixel.py new file mode 100755 index 0000000..ef2ceb5 --- /dev/null +++ b/scripts/pixel.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import board +import neopixel +import sys + +np_pin = board.D18 +np_num = 16 +np_order = neopixel.GRB + +fname = "/tmp/pixel" +np = neopixel.NeoPixel(np_pin, np_num, auto_write=False, pixel_order=np_order) + +c = (0,0,0) +try: + if len(sys.argv) == 4: + c = (int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])) + elif len(sys.argv) == 2: + c = (int(sys.argv[1]), int(sys.argv[1]), int(sys.argv[1])) + + print(f"setting color to {c}") + np.fill(c) + np.show() +except Exception as ex: + print(f"ERROR: {ex}")