Since I can't do any printing at the moment (printer is broken), I have put together a bit of a tutorial on "best practice" when creating conditional G code.
There will be many far more qualified people than I on the forum to do this, and I'm sure that there is better and more concise documentation coming, but some may find it useful.
It is far from a complete or even comprehensive treatise on the subject, nor is it meant to be.
Feel free to correct, disagree or ignore as you see fit.
Especially since the code therein is untested (printer broken remember)
Conditional G Code best practice.pdf

Best posts made by OwenD
-
Conditional G Code introduction "tutorial" (PDF)
-
RE: Baby Stepping.. can it, or can it not be permanent?
just run a macro. (assuming you're running RRF3)
You could either do it manually or put it in the stop gcode of your slicer;save_babystep.g ; Add babystep to Z offset and make "persistant" if move.axes[2].babystep !=0 echo {"Z trigger height altered by " ^ move.axes[2].babystep ^ "mm"} echo {"OLD: " ^ sensors.probes[0].triggerHeight ^ " new: " ^ sensors.probes[0].triggerHeight - move.axes[2].babystep} G31 Z{sensors.probes[0].triggerHeight - move.axes[2].babystep} M500 P10:31 ; save settings to config-overide.g - Must have M501 in config.g else echo "No babystepping set. Nothing to save"
EDIT: Original post incorrectly added baby steps to trigger height. It should subtract.
-
Pressure Advance Tuning file generator
Hi All,
In my quest to tune my various settings I decided I needed to be able to automatically generate a test file that would change the pressure advance at set intervals.
The only programming language I know is Delphi/Lazarus, so I created a windows application to carry out the task.Essentially that application creates a square box with two wall perimeters.
The inner wall prints at a constant speed and acts merely for support.
The outer wall alternates between a high and low speed with the transition point being mid way along the wall.
At the end of each layer a retraction is added.This allows you to see how the PA adjustments are affecting corners at the two speeds and how it is affecting the retraction settings.
A start and end G code section takes care of temps etc.
Here are some pics of tests starting a PA of zero and increasing by 0.05 every 5mm in height.
My printer runs about a 350mm bowden tube.Pic 1: PA range 0-0.35
Note the distinct thickness variations at the speed change point and the blobbing at the retraction/layer change point.
Pic2: PA Range 0.4-0.75
Transition line still faintly visible and some issues around retraction area
Pic3: PA range 0.8-1.15
Looks pretty good at about mid way
Pic4: PA range 1.2-1.55
Here we can see that pressure advance is starting to cause too much retraction.
I'd either have to reduce PA or try again with less retraction.
If anyone would like to try the application and provide feedback , I have put a link to my dropbox.
Download link:
https://www.dropbox.com/s/nolo5aca26e7fni/PaAdvanceTestInstall_v1-0.zip?dl=0BE WARNED!!
This should be considered very much beta software.
Use at your own risk.
I've only tested on Windows 10.I'm not sure my extrusion volume calculations are 100% accurate.
They seem close, but not identical to Cura's values.
At any rate it seems good enough for the test purposes. -
Macro for "automatic" calibration of BL Touch
This macro uses variables so needs RRF3.3b2 or later.
EDIT: Object model values for M558 are now stored in mm/min so no conversion necessary. - please used amended macro below which includes improvements and corrects some errors pointed out in this thread by other users.
It prompts you to jog the nozzle to the bed and then runs 10 probe offset tests (this number is configurable as a variable)
At the end, it discards the highest and lowest reading and averages the rest.
You can then choose to save the result in config-overide.g;Calibrate BL Touch ; Reprap firmware version 3.3b2 or later required! ; if two speed probing is configured in M558,we probably want to reduce the speed for this test var ProbeSpeedHigh = sensors.probes[0].speeds[0]*60 ; Speeds are saved in mm/sec in the object model but M558 uses mm/min var ProbeSpeedLow = sensors.probes[0].speeds[1]*60 M558 F60 ; reduce probe speed to 60mm/min for accuracy - adjust F parameter as required ;define some variables to store readings var NumTests=10 ; modify this value to define number of tests ; Do not change below this line var RunningTotal=0 var Average=0 var Lowest=0 var Highest=0 ; If the printer hasn't been homed, home it if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed G28 else G1 Z{sensors.probes[0].diveHeight} F360 ; if axes homed move to dive height M561 ; clear any bed transform M290 R0 S0 ; clear babystepping ; move nozzle to centre of bed G1 X{(move.axes[0].min + move.axes[0].max)/2} Y{(move.axes[1].min + move.axes[1].max)/2} M564 S0 H0 ; Allow movement beyond limits ;ensure you have room for the probe if move.axes[2].machinePosition < sensors.probes[0].diveHeight G1 Z{sensors.probes[0].diveHeight} M280 P0 S160 I1 ; reset BL Touch G4 S0.5 M98 P"0:/sys/retractprobe.g" ; Ensure probe is retracted & reset G4 S0.5 M561 ; clear any bed transform ; Jog head to position M291 P"Jog nozzle to touch bed" R"Set nozzle to zero" S3 Z1 G92 Z0 ; set Z position to zero M291 P"Press OK to begin" R"Ready?" S3; ; Move probe over top of same point that nozzle was when zero was set G1 Z{sensors.probes[0].diveHeight}; lift head G1 X{move.axes[0].machinePosition - sensors.probes[0].offsets[0]} Y{move.axes[1].machinePosition - sensors.probes[0].offsets[1]} F1800 echo "Current probe offset = " ^ sensors.probes[0].triggerHeight ^ "mm" ; carry out 10 probes (or what is set in NumTests variable) while iterations < var.NumTests G1 Z{sensors.probes[0].diveHeight} ; move to dive height if sensors.probes[0].value[0]=1000 ; if probe is in error state echo "Probe in error state- resetting" M280 P0 S160 I1 ; reset BL Touch G4 S0.5 M98 P"0:/sys/retractprobe.g" ; Ensure probe is retracted & reset G4 S0.5 G30 S-1 M118 P2 S{"Test # " ^ (iterations+1) ^ " Triggered @ " ^ move.axes[2].machinePosition ^ "mm"} ; send trigger height to Paneldue console M118 P3 S{"Test # " ^ (iterations+1) ^ " Triggered @ " ^ move.axes[2].machinePosition ^ "mm"} ; send trigger height to DWC console if iterations == 0 set var.Lowest={move.axes[2].machinePosition} ; set the new lowest reading to first probe height set var.Highest={move.axes[2].machinePosition} ; set the new highest reading to first probe height if move.axes[2].machinePosition < var.Lowest set var.Lowest={move.axes[2].machinePosition} ; set the new lowest reading ;M118 P3 S{"new low reading = " ^ move.axes[2].machinePosition} ; send trigger height to DWC console G4 S0.3 if move.axes[2].machinePosition > var.Highest set var.Highest={move.axes[2].machinePosition} ; set the new highest reading ;M118 P3 S{"new high reading = " ^ move.axes[2].machinePosition} ; send trigger height to DWC console G4 S0.3 set var.RunningTotal={var.RunningTotal + move.axes[2].machinePosition} ; set new running total ;M118 P3 S{"running total = " ^ var.RunningTotal} ; send running total to DWC console G4 S0.5 set var.Average = {(var.RunningTotal - var.Highest - var.Lowest) / (var.NumTests - 2)} ; calculate the average after discarding th ehigh & low reading ;M118 P3 S{"running total = " ^ var.RunningTotal} ; send running total to DWC console ;M118 P3 S{"low reading = " ^ var.Lowest} ; send low reading to DWC console ;M118 P3 S{"high reading = " ^ var.Highest} ; send high reading to DWC console M118 P2 S{"Average excluding high and low reading = " ^ var.Average} ; send average to PanelDue console M118 P3 S{"Average excluding high and low reading = " ^ var.Average} ; send average to DWC console G31 P500 Z{var.Average} ; set Z probe offset to the average reading M564 S0 H1 ; Reset limits M558 F{var.ProbeSpeedHigh}:{var.ProbeSpeedLow} ; reset probe speed to original G1 Z{sensors.probes[0].diveHeight} F360 ; move head back to dive height M291 P{"Trigger height set to : " ^ sensors.probes[0].triggerHeight ^ " OK to save to config-overide.g, cancel to use until next restart"} R"Finished" S3 M500 P31 ; optionally save result to config-overide.g
-
RE: Reprap G-Code syntax now part of RJ TextEd text editor
I have updated the syntax file for RJ TextEd to include more object model items.
I have also included a suggested colour format file.
You will need to update RJ TextEd to the latest version in order to take advantage of hints etc.Replace the existing files (reprap.syx, reprap.ini) in C:\Users"yourname"\AppData\Roaming\RJ TextEd\Syntax
Copy the file "Reprap Dark.xml" to C:\Users"yourname"\AppData\Roaming\RJ TextEd\Syntax color themes\To install.
1: Go to ENVIRONMENT > THEMES > CUSTOMISE
2: Select "Reprap G Code" from the drop down list of highlighters
3: Click the button, and select import colors from file
4: Select the "Reprap Dark.xml" file previously copied.
You can customize the colours to suit yourself.
Different G Code parameters such as X, Y, Z , E, F, G etc can be coloured to make individually.
Likewise, comments and other items can be individually coloured.
-
Forum categories for conditional Gcode & macros
Now that 3.1 is released, I think it would be beneficial to have a forum category dedicated to conditional gcode & macros.
This should probably be broken down into various kinematic types.
Furthermore it may be good to have some sort of āduet approvedā marker like the āsolvedā marker, once the macros have been peer reviewed and improved where necessary.
I usually try to make macros āportableā by not hard coding anything, but the very fact that certain parts of the object model are not visible if you donāt run that type of configuration, probably makes putting them in the categories for which they were designed beneficial and will reduce angst and support time.
(Yes, I know we should be checking for null objects and kinematic types as a matter of course in every macro)
Which leads to my final point, which is once we have some documentation on the object model, perhaps someone could do a small tutorial on best practice when writing macros.
My programming background is not in C or its variants so I admit Iām constantly searching for proper syntax etc.
To a non-programmer it is just gobbledygook.
If thereās going to be dozens of people learning to do it, they may as well learn to do it in a way that ensure portability and reduces the chance of unexpected issues.
Iāve always found it usually takes 10 lines of code to do the job, the another 50 lines of code to stop people trying to do it out of order or in a way you never imagined -
RE: Conditional G Code - RJ TextEd Syntax file.
For those using RJ Text Editor, I have posted an updated syntax file that includes the new object model items and G Codes contained in RRF3.5.0 b2
It can be downloaded here
https://www.rj-texted.se/Forum/viewtopic.php?p=18659#p18659It includes mouse over hints for G Code commands and auto-complete
The program comes with the RRF syntax file as standard but you may need to update it as new firmware versions come out. -
Heater fault checking routine to be run in daemon.g
This is a routine I run in daemon.g to check for heater faults.
It is mainly aimed at covering the time when the printer is idle as RRF already checks when a print is running.
I have excluded heaters that are currently being PID auto tuned
It does not take action if the heater temp is < 45 degrees but will shut down if temp is < zero as that would indicate a thermistor fault.
If the temperature is over 45 degrees it will only fault if the current temp is > 15 degrees from the set active temp AND the temperature is rising by > 0.5 degrees over 3 seconds.
This is to avoid activating when the temp is deliberately lowered.
NOTE: I have used a dummy tool to store variables which allow me to have this routine run only at intervals greater than 10 seconds whilst allowing the rest of daemon.g to run at normal intervals. Without this (and until we get variables) you will need to modify the code and use G4 to set the timing
For the timing I have used state.upTime. which will probably roll over at some point if the printer is left on long enough (I'm guessing it's a 16 bit signed integer?), so I have a check for that.
I have tested it in both idle and printing states and it seems to work as expected but have not confirmed the upTime rollover works as expected.; 0:/sys/daemon.g ; runs continually in background at approximately 1Hz if not delayed internally ;HEATER CHECKS ; this section of daemon.g checks for heater faults ; RRF doesn't currently check for faults when idle but by default will shutdown 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. I have used a dummy tool offset (Tool2) for this and to do elapsed time since last check ; 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. while iterations < #heat.heaters ; loop through all configured heaters if ((tools[2].offsets[1]+10) > 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 ^ " " ^ tools[2].offsets[1]+10 if tools[2].offsets[1] - 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 ;echo "checking heater " ^ iterations ^ " " ^ state.upTime ^ " " ^ tools[2].offsets[1]+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 echo "heater over max temp fault detected in daemon.g. - shutting down" M112; emergency shutdown M81 S1 ; turn off power when fans have turned off if (heat.heaters[iterations].current > 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" G10 P2 X{heat.heaters[iterations].current} ; set dummy tool X offset to current temp of heater G4 S3 ; wait 3 seconds if (heat.heaters[iterations].current > tools[2].offsets[0] + 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 >= 45) ; if heater is off and temp is greater than 45 there could be an issue ;echo "heater " ^ iterations ^ " is off but checking if temp is rising" G10 P2 X{heat.heaters[iterations].current} ; set dummy tool X offset to current temp of heater G4 S3 ; wait 3 seconds if (heat.heaters[iterations].current > tools[2].offsets[0] + 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 is off & temp is falling or stable on heater " ^ iterations ^ " - no action needed" else ;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 if iterations == #heat.heaters-1 ; all heaters have been checked G10 P2 Y{state.upTime} ; set the new time to check again ; END HEATER CHECKS ; run other checks ;G4 S10 ; pause daemon.g for 10 seconds before next run - required if not using variables
-
RE: How can I create a toggle macro?
@paulhew said in How can I create a toggle macro?:
@dc42 said in How can I create a toggle macro?:
state.gpout
Appreciate the input you have given, maybe I need to start at the beginning.
This is my config for my Lights;Lights M950 F10 C"out1" M106 P10 S0 H-1 C"Front Lights" M106 P10 S1
It looks correct, it works. Personally it would be better if it was an on/off and not PWM'd, Do not think I require mood lighting on my chamber lights
So after enabling Object Model Browser, I found F10 under Fans and it shows the correct info as in my config.
I change the lights on and off and it changes 'actualValue'Not being as clever as you guys but willing to learn, how do I query 'Fan.10' actualValue'?
I sort of understand the 'if' part
if 'actualValue' = 1
then set to 0
Elif 'actualValue' = 0
set to 1Personally, it would be handy if there were some basic 'Meta Guides' to help us understand how to write queries and some simple ones we could implement to advance our learning.
try here
https://duet3d.dozuki.com/Wiki/GCode_Meta_CommandsLike if the printer is not homed, then home it and how to turn on /off lights with a one button macro!
If you look through the meta commands topic section of the forum there are many examples which should help you understand.
https://forum.duet3d.com/category/34/gcode-meta-commandsMuch like you have done with the RRF configurator, it explains the function which has helped me learn a lot.
I did search for the "state.gpout[n].pwm" and variations in the dozuki and could not find any reference to it.
Again, Thanks in advance.
You have to use the object model to reference the proper name & syntax for the GPIO output, fan or whatever.
In our case, you're using a fan output, not a GPIO pin.
So you need to look in the fans section of the object browser.
Fan outputs are PWM capable, so that you can set a fan to any speed.
In your case, you can just set it to 0 or 1 using M106.
A GPIO output would be set by M42in terms of code you could have something like
if fans[10].actualValue = 1 M106 P10 S0 else M106 P10 S1
This example is only meant for an LED connected to a fan ouput that is only ever set full on, or full off.
-
RE: A couple of questions regarding global variables
As has been pointed out, you can declare the globals wherever you like, but of course you must ensure that you do so before you try to use them anywhere.
I always check if the global has already been created as I don't like seeing the errors if I run M98 P"0:/sys/config.g" for example.
It also ensures the global is reset in case I changed it in code somewhere.
In some cases I check for a null value, but in most cases that's probably not necessary.if !exists(global.InputStart) || global.InputStart=null global InputStart=0 else set global.InputStart=0 if !exists(global.InputEnd) || global.InputEnd=null global InputEnd=1 else set global.InputEnd=1
With regards to sending parameters using M98, it's pretty straight forward.
For example you might use it when there is a value you want to use from your slicer.
Here I pass an "S" and a "D" parameter taken from the slicerM98 P"0:/macros/print/doPrimeLine" S[extrusion_multiplier] D[nozzle_diameter] F[filament_diameter] ; does prime line with calculated extrusion amount
In my macro I use the values passed thus
This macro also uses local variables which are freed once the macro has run.
It's a fair bit of overkill to do a prime line, but it was mainly a test bed for various methods; 0:/macros/print/doPrimeLine if state.currentTool = -1 abort "No tool selected" var ThisHeater = tools[state.currentTool].heaters[0] ; create local variable if {heat.heaters[var.ThisHeater].state != "active"} abort "Heater " ^ var.ThisHeater ^ " on " ^ tools[state.currentTool].name ^ " not active" if {heat.heaters[var.ThisHeater].active < heat.coldExtrudeTemperature} abort "Heater " ^ var.ThisHeater ^ " on " ^ tools[state.currentTool].name ^ " set below min extrude temp" if !exists(param.S) abort "no ""S"" (extrusion factor) parameter sent to macro in M98" if !exists(param.D) abort "no ""D"" (nozzle diameter) parameter sent to macro in M98" if !exists(param.F) abort "no ""F"" (filament diameter) parameter sent to macro in M98" M116 ; wait for heaters to settle var height = 0.2 ; create a variable then set it depending on slicer commanded position prior to calling this macro if move.axes[2].machinePosition <= 0.4 set var.height = move.axes[2].machinePosition else set var.height = 0.3 var SF = 100 if param.S <=1 ; check if slicer sends percentage of 1 or 100 set var.SF = param.S ; extrusion multiplier as a percentage of 1 else set var.SF = param.S / 100 var FD = 1.75 ; set default filament diameter set var.FD = param.F ; but over write with slicer setting ; set start and end of move in Y direction - X position will be set manually var start = {move.axes[1].max -10 } ; extrude line start position var end = {move.axes[1].min +10} ; extrude line end position var l = var.start - var.end ; calculated line length var d = param.D ; nozzle diameter that is passed to macro as paramater var amount = ((var.d*var.height*var.l) + (pi*((var.height/2)*(var.height/2))*var.l)) / (pi*((var.FD/2)*(var.FD/2))) * var.SF ; calculate how many mm of filament to extrude - Owen's calculation echo "flow rate value " ^ var.SF ^ " with " ^ var.d ^ "mm nozzle, " ^ var.FD ^ "mm filament dia over " ^ var.l ^ "mm length = E" ^ var.amount ^ "mm" M83 ; set relative extrusion G1 X0 Y{var.start} Z{var.height} F1200 ; move to edge to wipe any oozed filament G1 X0 Y{var.end} F600 E{var.amount}; move and extrude G1 X{var.d} ; move by one nozle width G1 Y{var.start} F600 E{var.amount}; move and extrude G10 ; retract
Latest posts made by OwenD
-
RE: Emergency Push Button activates on both condition
@fcwilt said in Emergency Push Button activates on both condition:
I think (but my thinker may be losing it) that the T0 trigger is active during moves where the T2+ triggers are only active "between" moves.
Frederick
You could be right. I've never tested.
I only use a trigger for a filament sensor so it's neither here nor there
If it were me I'd wire the switch to the 24v supply -
RE: Emergency Push Button activates on both condition
Create your input with something like this
Change to suit how you want trigger to workM950 J0 C"exp.e5stop" M581 T2 P0 R0 S0
Create a trigger macro associated with the switch.
Note that by default if you attach your switch to trigger 0 it will do an estop.
I don't know if you can create a trigger0.g file to do the debouncing code.
Then use something like this;trigger2.g G4 P10 ; delay 10ms to debounce if sensors.gpIn[0].value = 0 echo "switch bounce detected - exit macro" M99 ; break out if sensor value is zero again (bouncing) ;we got to here so do an estop and restart M112 M999
-
RE: Feedrate reformatting post script
@justinkg
Just a guess as I have no experience with Yaskawa controllers.
However some CNC controllers accept a feed rate command on its own
So try changing
G1 F3600
to
F3600 -
RE: how do I calculate the E-parameter for Start G-Code
@axiom
I do a similar thing using this macro, which I call from the slicer (Prusa Slicer)
It's overkill for doing a trivial thing like a prime line that probably won't change, but I did it as the basis for doing dynamic generation of some test files I was working on.
The line you're interested in isvar amount = ((var.d*var.height*var.l) + (pi*pow(var.height/2,2)*var.l)) / (pi*pow(var.FD/2,2)) * var.SF
I can't guarantee if the way I calculate the extrusion amount is 100% correct as compared to a slicer, but it works well enough for a purge line and means I can change the length of the line easily.
You must pass the following parameters.
S = extrusion factor
D = nozzle diameter
F = Filament diameter
O = Origin X and Y points as an array
L = Line lengthe.g. in Prusa Slicer / Super Slicer I use the following after homing etc.
G1 X0 Y{"{move.axes[1].max}"} Z0.6 F1500 ; Move to back corner while heating M568 P{current_extruder} R{"{heat.coldExtrudeTemperature+5}"} S{first_layer_temperature[current_extruder]} A2 ; (set standby and active temperatures for active tool. Standby is 5 degrees above cold extrude temp ) M118 P3 S" Waiting for temps..." G4 S1 ; Wait 1 Second M116 ; Wait for all temps to stabilise G1 X0 Y{"{move.axes[1].max -5}"} Z0.26 F1200 ; move to edge to wipe any oozed filament M98 P"0:/macros/print/doPrimeLine.g" S{extrusion_multiplier[current_extruder]} D{nozzle_diameter[current_extruder]} F{filament_diameter[current_extruder]} O{"{1,0}"} L150; does prime line with calculated extrusion amount G10 ; Retract G1 Z0.1 ; lower head G1 X{move.axes[0].machinePosition + 50} F1200 ; wipe G1 Z10 ; raise head G92 E0 ; reset extruder
note that in order to pass an array as a parameter from Prusa Slicer you have to enclose the array in double quotes O{"{0,10}"}
; doPrimeLine.g ; example of calling from Prusa Slicer ;M98 P"0:/macros/print/doPrimeLine.g" S{extrusion_multiplier[current_extruder]} D{nozzle_diameter[current_extruder]} F{filament_diameter[current_extruder]} O{"{0,10}"} L150; if state.currentTool = -1 abort "No tool selected" var ThisHeater = tools[state.currentTool].heaters[0] if {heat.heaters[var.ThisHeater].state != "active"} abort "Heater " ^ var.ThisHeater ^ " on " ^ tools[state.currentTool].name ^ " not active" if {heat.heaters[var.ThisHeater].active < heat.coldExtrudeTemperature} abort "Heater " ^ var.ThisHeater ^ " on " ^ tools[state.currentTool].name ^ " set below min extrude temp" if !exists(param.S) abort "no ""S"" (extrusion factor) parameter sent to macro in M98" if !exists(param.D) abort "no ""D"" (nozzle diameter) parameter sent to macro in M98" if !exists(param.F) abort "no ""F"" (filament diameter) parameter sent to macro in M98" if !exists(param.O) echo "no ""O"" (Origin) parameter sent to macro in M98. Defaults will be used" if !exists(param.L) echo "no ""L"" (Length) parameter sent to macro in M98. Defaults will be used" echo "wait for heaters" M116 ; wait for heaters to settle echo "heaters done" G4 P500 echo "set height" var height = 0.2 ; create a variable then set it depending on slicer commanded position prior to calling this macro if move.axes[2].machinePosition <= 0.4 set var.height = move.axes[2].machinePosition else set var.height = 0.3 echo "move to Z" ^ var.height M400 echo "check extrusion percentage" var SF = 100 if param.S <=1 ; check if slicer sends percentage of 1 or 100 set var.SF = param.S ; extrusion multiplier as a percentage of 1 else set var.SF = param.S / 100 echo "check filament dianeter" var FD = 1.75 ; set filament diameter set var.FD = param.F echo "calculate distance and extrusion amount" var startPos = {0,move.axes[1].min + 10} ; create a default start point if exists(param.O) set var.startPos = param.O var start = var.startPos[1] var end = {move.axes[1].max - 10} ; extrude line end default position var l = var.end - var.start ; default line length if exists(param.L) set var.l = param.L set var.end = var.start + var.l ; do a sanity check to ensure we're within bounds if var.end > move.axes[1].max set var.end = move.axes[1].max set var.l = var.end - var.start var d = param.D*1.00 ; nozzle diameter that is passed to macro as paramater var amount = ((var.d*var.height*var.l) + (pi*pow(var.height/2,2)*var.l)) / (pi*pow(var.FD/2,2)) * var.SF ; calculate how many mm of filament to extrude - Owen's calculation echo "flow rate value " ^ var.SF ^ " with " ^ var.d ^ "mm nozzle, " ^ var.FD ^ "mm filament dia over " ^ var.l ^ "mm length = E" ^ var.amount ^ "mm" M83 ; set relative extrusion G92 E0 echo "moving to X" ^ var.startPos[0] ^ " Y" ^ var.startPos[1] ^ " Z" ^ var.height G1 X{var.startPos[0]} Y{var.startPos[1]} Z{var.height} F1200 ; move to edge to wipe any oozed filament M400 G92 E0 echo "Move and extrude to Y"^var.end ^ " E" ^ var.amount G1 X{var.startPos[0]} Y{var.end} E{var.amount} F600; move and extrude M400 G92 E0 echo "move over one nozzle width" G1 X{var.d} ; move by one nozle width M400 G92 E0 echo "Move and extrude - other direction" G1 Y{var.start} F600 E{var.amount}; move and extrude M400 G92 E0 echo "retract" G10 ; retract M400 G92 E0 echo "exit PrimLine" G4 P500
-
RE: What's the correct way to determine if there is a job active?
@gnydick
That would be expected whilst there is a tool change in progress.
If you need to check if there's an active job within your tool change files then maybeif job.file.fileName!=null echo "Print job loaded" ; do whatever here
-
RE: WIFI SPI timeout error
@danzaywer
I get the same thing from time to time and I'm running pretty much identical setup.
I've tried different versions of the wifi server but it still appears sporadically.
My latest attempt was to turn off telnet and FTP. I read a note aboutsome more memorybeing allocated due to issues if all were running, so it may still be related.
I haven't done enough printing since then to see if it helped.
Sometimes it can go weeks without happening, but when it does, I can't access DWC and the PanelDue is spamming the errors so fast you can't do anything.
I had to turn off the power and recover on my last print when it was running out of filament.EDIT:
Actually I think it was a timeout value that was increased , not memory allocation -
RE: SAMMYC21 ERCF
@VoodooBane
I think you need to ask @Th0mpy
I'm just an onlooker -
RE: Can this be done...
@fcwilt
I assume you can't use M703 because you're doing something inside a load/unload file?You can access the currently loaded filament using
move.extruders[state.currentTool].filament
So your M98 could look something like this.
var myFilament = move.extruders[state.currentTool].filament M98 P{"0:\filaments\" ^ var.myFilament ^ "\config.g"}
You would of course have to do checks and react if there is no loaded filament.
-
RE: Possible to change sensor value precision in BtnCmd?
@usinjin
In the OM Value Epression section putfloor(##VALUE##+0.5)
This will round to the nearest whole number
-
RE: Disabling Thermostatic Fan on Start-Up
@Dizzwold
I suppose if it is critical that the fan not run during startup you could power the fan by running one wire through a normally open relay.
Then if you configure the relay and close it at the end of your config.g