Lazy sunday, so I decided to answer some of this myself
@owend said in daemon.g usage "rules" clarification:
What hasn't been covered (to my knowledge) is the implications of creating a loop which lasts longer than 10 seconds.
I presume RRF checks if the daemon process/thread is running before attempting to start a new one?
I.e "there can only be one"
This seems to be the case. The daemon does not try to re-open if an instance already exists in memory.
If an infinite loop were created, would it still be possible to rename daemon.g in order to modify?
Yes, you can rename it in order to edit the contents. However your revision won't take effect until the runnning instance of daemon.g is stopped (which will allow the new file to be loaded from disk)
Or would we need to do something like set a variable (which we can modify from the console) which we check before the loop for cases where we need to modify the daemon ?
I chose to do this as a fail safe. Restarting would load the new file, but I wanted a way to ensure I wasn't stuck in a loop.
So I made a couple of global variable in config.g
Are there any other implications of running the daemon in an infinite loop?
This question I haven't fully answered. More variables = more memory taken from the stack.
I guess it'll depend on what you do in daemon.g as to whether it could have effect on printing.
For those interested here's what I did.
In config.g I added
if !exists(global.RunDaemon)
global RunDaemon=true
else
set global.RunDaemon=true
; Global Variables for heater checking routine in daemon.g
if !exists(global.HeaterCheckInterval)
global HeaterCheckInterval=10 ; variable for use in daemon.g sets interval of heater checks
else
set global.HeaterCheckInterval=10 ; variable for use in daemon.g sets interval of heater checks
I then created two macros for "starting" and "stopping" the daemon
StartDaemon.g
;0:/macros/Daemon control/StartDaemon.g
set global.RunDaemon = true
M38 "0:/sys/daemon.g" ; check if dameon.g exists by trying to calculate hash
if result = 2 ; file not found
M38 "0:/sys/daemon.g.bak" ; check if dameon.g.bak exists by trying to calculate hash
if result = 0
M291 P"No daemon.g found" R"Daemon.g not found but daemon.g.bak found. Rename now?" S3
M471 S"0:/sys/daemon.g.bak" T"0:/sys/daemon.g" ; rename dameon.g.bak to daemon.g
if result = 0
echo "Daemon successfully renamed. Hit F5 on browser to refresh"
else
M291 P"Error" R"Unable to rename file" S2
else
M291 P"No daemon found" R"Daemon.g not found." S2
StopDaemon.g
set global.RunDaemon = false
M471 S"0:/sys/daemon.g" T"0:/sys/daemon.g.bak" ; rename dameon.g
if result = 0
M291 R"Daemon.g stopped" P"Daemon.g has been stopped and renamed. Hit F5 to refresh browser" S2
else
M291 R"Error" P"Could not rename daemon.g" S2
My daemon.g was then modified so that I had an infinite loop
I could use G4 to set the timing of this, however I have broken down sections which I can run at selected intervals
As it turns out, I wanted to check my heaters at 10 second intervals (which I was doing when daemon.g ran at 1Hz)
Note that anything not contained inside the infinite loop would only ever get run at the first loading of daemon.g and only then if the code was placed BEFORE the infinite loop.
daemon.g
; 0:/sys/daemon.g
; runs continually in background at approximately 10 second intervals
; We have initiated an infinite loop at the start so that we can do things at intervals less than 10 seconds
; daemon.g won't be opened again if it it still running
; everything must be indented by 2 x tabs becasue of the infinite loop at the start to allow checks at intervals less than 10 seconds
; We have created a global variable in config.g called RunDaemon
; If RunDaemon is set to "false" nothing inside the infinite loop will run, however daemon.g will still be run every 10 seconds if it exists.
; Any code outside the infinite loop would run at 10 second intervals provided it came before the loop
while true
if global.RunDaemon == false
M99 ; exit the macro
else
;add code that must be run at less than 10 second intervals here
;HEATER CHECKS
; this section of daemon.g checks for heater faults
; RRF doesn't currently check for faults when idle but by default will shut down during printing if temperature excursion is > 15 degrees.
; Note: temp excursion value and time may be manually set using M570
; checking if temp is rising requires a variable.
; G4 could be used but would also delay anything else in daemon.g
; this way allows other checks to run more frequently if needed however the G4 delays inside the loop will affect the frequency of daemon.g
; will be updated when variables are available in RRF.
; everything must be indented by 2 x tabs becasue of the infinite loop at the start to allow checks at intervals less than 10 seconds
while iterations < #heat.heaters ; loop through all configured heaters
set global.LastTemp=heat.heaters[1].current ; Set variable to current extruder temp.
if state.upTime < 60
break; If uptime is < 60 seconds, break out so all fans etc have time to stabilise.
if ((global.LastCheckTime + global.HeaterCheckInterval) > state.upTime) ; if checked in last 10 seconds escape loop and go to rest of daemon.g if present. offset will be zero at startup via config.g
;echo "skipping loop " ^ " " ^ state.upTime ^ " " ^ global.LastCheckTime+10
if global.LastCheckTime-state.upTime > 60 ; uptime must have rolled over so reset off set to zero
G10 P2 Y0
echo "upTime has rolled over. Heater checking reset"
break
else
;echo "checking heater " ^ iterations ^ " " ^ state.upTime ^ " " ^ global.LastCheckTime+10
if heat.heaters[iterations].state="tuning"
;echo "heater " ^ iterations ^ " is tuning - no check carried out"
continue ; don't check this heater as it is PID auto tuning
if (heat.heaters[iterations].current) > (heat.heaters[iterations].max) ; temp is over max so emergency shutdown required
;M41 P5 S1 ; activate output connected to externally powered latching relay here to sound alarm
M118 P0 S"heater over max temp fault detected in daemon.g. - shutting down" L1
M112; emergency shutdown
M81 S1 ; turn off power when fans have turned off
if (heat.heaters[iterations].current > 45) && (heat.heaters[iterations].active > 45); no real danger at below this temp as ambient may be close to this
;echo "heater " ^ iterations ^ " is above 45 degrees"
if (heat.heaters[iterations].state!="off") && (heat.heaters[iterations].current > heat.heaters[iterations].active + 15) ; temp is > 15 degrees above target.
;echo "heater " ^ iterations ^ " is on or in standby - checking if temp is rising"
set global.LastTemp=heat.heaters[iterations].current ; set the last check temp
;echo "heater " ^ iterations ^ " temp: " ^ heat.heaters[iterations].current
G4 S3 ; wait 3 seconds
if (heat.heaters[iterations].current > global.LastTemp + 0.5) ; heat is rising by more than 0.5 degrees in 3 seconds
echo "heater runaway fault detected in daemon.g. - shutting down"
if (state.status=="processing")
M25 ; pause print so you might be able to save it using M119
;M41 P5 S1 ; activate output connected to externally powered latching relay here to sound alarm
M0 ; unconditional stop. If axes are homed and a print is being canceled will run cancel.g otherwise will run stop.g
M81 S1 ; turn off power when fans have turned off
else
;echo "heater is on or standby but temp is falling on heater " ^ iterations ^ " - no action needed"
elif (heat.heaters[iterations].state="off") && ((heat.heaters[iterations].current) >= (fans[1].thermostatic.lowTemperature+0)) ; if heater is off and temp is greater than 50 there could be an issue
set global.LastTemp=heat.heaters[iterations].current;
;echo "heater " ^ iterations ^ " is off but checking if temp is rising"
G4 S3 ; wait 3 seconds
if (heat.heaters[iterations].current > global.LastTemp + 0.5) ; heat is rising by more than 0.5 degrees in 3 seconds
echo "heater is off but temp is rising on heater " ^ iterations ^ "emergency shutdown"
;M41 P5 S1 ; activate output connected to externally powered latching relay here to sound alarm
echo "heater runaway fault detected in daemon.g. - shutting down"
M112; emergency shutdown
M81 S1 ; turn off power when fans have turned off
else
;echo "heater " ^ iterations ^ " is off & temp is falling or stable on heater " ^ iterations ^ " - no action needed"
else
;echo "heater " ^ iterations ^ " is below 45 degrees so check thermistor" ;"heater is below 45 degrees so only other fault may be an open circuit thermistor which should show -275 degrees"
if heat.heaters[iterations].current < 0 ; we probably have a thermistor fault if heater is less than 0 degrees
M112 ; emergency shutdown
M81 S1 ; turn off power when fans have turned off
;Check if water pump is running correctly
if (iterations=1) && ((heat.heaters[1].current) > (fans[1].thermostatic.lowTemperature+0))
if fans[1].rpm <= 500 ; Coolant pump RPM off or low
G4 S3 ; check again in 3 seconds in case it's just spinning up
if fans[1].rpm <= 500
echo "Water pump fault - shutting down heaters - RPM : " ^ fans[1].rpm
M25 ; pause print so you might be able to save it using M119
M0 ; unconditional stop. If axes are homed and a print is being canceled will run cancel.g otherwise will run stop.g
M81 S1 ; turn off power when fans have turned off
elif (fans[1].rpm > 500) && (fans[1].rpm < 1400)
G4 S3 ; check again in 3 seconds in case it's just spinning up
if (fans[1].rpm > 500) && (fans[1].rpm < 1400)
echo "WARNING: Water pump RPM low - RPM : " ^ fans[1].rpm
if (state.status=="processing")
M25 ; pause print so you might be able to save it using M119
;M41 P5 S1 ; activate output connected to externally powered latching relay here to sound alarm
M0 ; unconditional stop. If axes are homed and a print is being canceled will run cancel.g otherwise will run stop.g
M81 S1 ; turn off power when fans have turned off
else
;echo "Coolant OK - RPM : " ^ fans[1].rpm
if fans[2].rpm <=1000
echo "WARNING: Water pump FAN RPM low - RPM : " ^ fans[2].rpm
if (state.status=="processing")
M25 ; pause print so you might be able to save it using M119
;M41 P5 S1 ; activate output connected to externally powered latching relay here to sound alarm
M0 ; unconditional stop. If axes are homed and a print is being canceled will run cancel.g otherwise will run stop.g
M81 S1 ; turn off power when fans have turned off
if iterations == #heat.heaters-1 ; all heaters have been checked
set global.LastCheckTime=state.upTime ; set the new time to check
; END HEATER CHECKS
; BEGIN OTHER CHECKS AT INTERVALS LESS THAN 10 SECONDS
; run other checks - don't forget to add 2 x tabs
;echo state.upTime ^ ":" ^ state.msUpTime ; should run very fast
;G4 P500