Basic Information:
Printer Model: Custom
MCU / Printerboard: Costom STM32H723
Host / SBC : Raspberry Pi4
klippy.log
Describe your issue:
I made a custom 600x600 printer and I made a custom controller board that is based on STM32H723.
I’m more of a safety orientated guy so my board includes two safety relays (one for the hot ends and one for the bed), they are connected to a small MCU that acts as a watchdog timer. It needs kicking from the STM32H723 if Klipper is not in shutdown mode. The purpose is to protect the printer (and maybe my house) from freezes, lockups, and even shorted Mosfets or Tirac.
currently I made it woerking with macros but the problem is that they freeze when homing or heating up. I got an Idea to have a custom python script that runs in the background all the time if klipper is not in shutdown mode. I tried chatGPT and I got some code but it is not toggling the pin on the MCU. And I can’t see any errors in klippy log. Cane someone else help me out. Or any other ideas?
import logging
class WatchdogToggle:
def __init__(self, config):
logging.info("Starting watchdog")
self.printer = config.get_printer()
self.reactor = self.printer.get_reactor()
self.current_state = 0
self.toggle_interval = config.getfloat('toggle_interval', 1.0) # Toggle every 1 second
ppins = self.printer.lookup_object('pins')
self.is_pwm = config.getboolean('pwm', False)
if self.is_pwm:
self.mcu_pin = ppins.setup_pin('pwm', config.get('pin'))
max_duration = self.mcu_pin.get_mcu().max_nominal_duration()
cycle_time = config.getfloat('cycle_time', 0.100, above=0.,
maxval=max_duration)
hardware_pwm = config.getboolean('hardware_pwm', False)
self.mcu_pin.setup_cycle_time(cycle_time, hardware_pwm)
self.scale = config.getfloat('scale', 1., above=0.)
else:
self.mcu_pin = ppins.setup_pin('digital_out', config.get('pin'))
self.scale = 1.
self.mcu_pin.setup_max_duration(0.)
self.timer = self.reactor.register_timer(self._toggle_pin, self.reactor.NEVER)
self.printer.register_event_handler('klippy:ready', self._start_timer)
self.printer.register_event_handler('klippy:shutdown', self._handle_shutdown)
self.last_value = config.getfloat(
'value', 0., minval=0., maxval=self.scale) / self.scale
self.shutdown_value = config.getfloat(
'shutdown_value', 0., minval=0., maxval=self.scale) / self.scale
self.mcu_pin.setup_start_value(self.last_value, self.shutdown_value)
def get_status(self, eventtime):
return {'value': self.last_value}
def _start_timer(self):
try:
print_time = self.reactor.monotonic() + 0.1
self.current_state = 0
logging.info("Initialized pin to low at print_time %f", print_time)
self.reactor.update_timer(self.timer, self.reactor.NOW)
logging.info("Watchdog toggle timer started for pin")
except Exception as e:
logging.error("Error starting timer: %s", str(e))
raise
def _handle_shutdown(self):
try:
print_time = self.reactor.monotonic() + 0.1
self.output_pin.set_digital(print_time, 0)
logging.info("Shutdown detected, set to low at print_time %f and stopped timer", print_time)
self.reactor.update_timer(self.timer, self.reactor.NEVER)
except Exception as e:
logging.error("Error in handle_shutdown: %s", str(e))
def _toggle_pin(self, eventtime):
try:
idle_timeout = self.printer.lookup_object('idle_timeout')
printer_state = idle_timeout.get_status(eventtime)['state']
logging.debug("Printer state: %s", printer_state)
if printer_state == "Shutdown":
print_time = eventtime + 0.1
self.mcu_pin.set_digital(print_time, 0)
logging.info("Printer in shutdown, stopping toggle and setting to low at print_time %f", print_time)
return self.reactor.NEVER
self.current_state = 1 - self.current_state
print_time = eventtime + 0.1
self.mcu_pin.set_digital(print_time, self.current_state)
logging.info("Toggled to %d at eventtime %f, print_time %f", self.current_state, eventtime, print_time)
return eventtime + self.toggle_interval
except Exception as e:
logging.error("Error in toggle_pin for pin: %s", str(e))
return self.reactor.NEVER
def _set_pin(self, print_time, value):
if value == self.last_value:
return "discard", 0.
self.last_value = value
if self.is_pwm:
self.mcu_pin.set_pwm(print_time, value)
else:
self.mcu_pin.set_digital(print_time, value)
def _template_update(self, text):
try:
value = float(text)
except ValueError as e:
logging.exception("output_pin template render error")
value = 0.
def load_config_prefix(config):
return WatchdogToggle(config)
Thank you