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: oibject model "status" dcos.
@Tinchus
Political correctness has spread even to RRF.
In the spirit of inclusiveness , you must now use "processing" in deference to those machines that do not identify as "printers" -
Setting up video streaming using raspberry pi
Recently I had to set up a Raspberry Pi is camera to use as a monitoring device for my printer.
I found that pretty much all the online information was outdated and had no end trouble getting it to work on the current version of Pi OS (BullseyeBookworm).
The entire camera and video handling system has changed over the years.
So I decided to document what worked for me.
In the end it was relatively easy (once you knew the correct steps0I must first point out I know bugger all about Linux.
All this work is taken from bits and pieces I found on various sites and cobbled together, so my apologies for not crediting the original author(s)NOTE: These instructions were done using a Raspberry Pi 4 running
BullseyeBookworm 64 bit and an official Pi camera
Also if you're running RRF in SBC mode, you don't need to do this as I believe it has a built in camera setup.The first step is to install the OS using the Pi Imager
https://www.raspberrypi.com/software/When prompted, choose your user name, password and Wifi details.
NOTE: The current version no longer uses the default user pi and password raspberrywhen you get to this point, click on "edit settings"
Enable SSH so that you can connect to the Pi via PUTTY rather than always needing a monitor and keyboard.
If you installed a Pi OS that has a desktop you can use the inbuilt command line terminal for all the steps listed below.Then click on YES to apply the settings.
Once the image has been loaded onto the SD card, insert the card in your Pi and start it up.
Start Putty (or some other terminal) and SSH into the Pi
If you used the default settings, you should be able to go to
raspberrypi.local
You should see something like this
You may get any updates/upgrade by using these commands
sudo apt update
sudo apt upgrade
sudo apt install
Change directory
cd /usr/local/bin/
Open a text edior
sudo nano streamVideo.py
Paste in the following code
#!/usr/bin/python3 # This is the same as mjpeg_server.py, but uses the h/w MJPEG encoder. import io import logging import socketserver from http import server from threading import Condition from picamera2 import Picamera2 from picamera2.encoders import MJPEGEncoder from picamera2.outputs import FileOutput PAGE = """\ <html> <head> <title>3D Printer Camera</title> </head> <body> <img src="stream.mjpg" width="800" height="600" /> </body> </html> """ class StreamingOutput(io.BufferedIOBase): def __init__(self): self.frame = None self.condition = Condition() def write(self, buf): with self.condition: self.frame = buf self.condition.notify_all() class StreamingHandler(server.BaseHTTPRequestHandler): def do_GET(self): if self.path == '/': self.send_response(301) self.send_header('Location', '/index.html') self.end_headers() elif self.path == '/index.html': content = PAGE.encode('utf-8') self.send_response(200) self.send_header('Content-Type', 'text/html') self.send_header('Content-Length', len(content)) self.end_headers() self.wfile.write(content) elif self.path == '/stream.mjpg': self.send_response(200) self.send_header('Age', 0) self.send_header('Cache-Control', 'no-cache, private') self.send_header('Pragma', 'no-cache') self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME') self.end_headers() try: while True: with output.condition: output.condition.wait() frame = output.frame self.wfile.write(b'--FRAME\r\n') self.send_header('Content-Type', 'image/jpeg') self.send_header('Content-Length', len(frame)) self.end_headers() self.wfile.write(frame) self.wfile.write(b'\r\n') except Exception as e: logging.warning( 'Removed streaming client %s: %s', self.client_address, str(e)) else: self.send_error(404) self.end_headers() class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer): allow_reuse_address = True daemon_threads = True picam2 = Picamera2() picam2.configure(picam2.create_video_configuration(main={"size": (640, 480)})) output = StreamingOutput() picam2.start_recording(MJPEGEncoder(), FileOutput(output)) try: address = ('', 8888) server = StreamingServer(address, StreamingHandler) server.serve_forever() finally: picam2.stop_recording()
Press CTRL + X to exit and choose Y to save file
change directory
cd /etc/systemd/system
Open the text editor to create a system service file
sudo nano streamVideo.service
Paste in the following code
[Unit] Description=A script for straming video to http After=syslog.target network.target [Service] WorkingDirectory=/usr/local/bin/ ExecStart=/usr/bin/python3 /usr/local/bin/streamVideo.py Restart=always RestartSec=120 [Install] WantedBy=multi-user.target
PRess CTRL + X
press Y and enter to saveEnter the following to reload the daemon
sudo systemctl daemon-reload
Enable the service
sudo systemctl enable streamVideo.service
You should see something like
Created symlink /etc/systemd/system/multi-user.target.wants/streamVideo.service ā /etc/systemd/system/streamVideo.service.
Restart the Pi
sudo shutdown -r now
After the Pi has rebooted, you should be able to access the stream by going to the following URL in your browser
http://raspberrypi.local:8888/index.html
In DWC you need to enter this URL on order to get the stream
http://raspberrypi.local:8888/stream.mjpg
Your video stream should now be visible in the Webcam tab
I hope this saves someone some frustration.
-
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: Setting up video streaming using raspberry pi
I found another application that works quite easily and has the benefit of being able to adjust all the settings from the web interface.
It's called picamera2-WebUI-Lite
There's a slight error on the instructions to install and it doesn't tell you how to set it up as a service, so I've listed thesteps.
To install.
SSH into your PI (or open a terminal if using a desktop)
Change directory
cd /usr/local/bin/
Clone the repositry
sudo git clone https://github.com/monkeymademe/picamera2-WebUI-Lite.git
Change directory
cd /usr/local/bin/picamera2-WebUI-Lite
Test that it's running
python3 app.py
Open your browser and go to
http://raspberrypi.local:8080/To see just the video feed go to
http://raspberrypi.local:8080/video_feedGo back to the terminal and hot CTRL + C to shut the app down
To set it up as a service
Change directorycd /etc/systemd/system
Open a text editor to create a system service file
sudo nano webui-lite.service
Paste in the following
[Unit] Description=Start script for WebUi-Lite as a service After=syslog.target network.target [Service] WorkingDirectory=/usr/local/bin/picamera2-WebUI-Lite/ ExecStart=/usr/bin/python3 /usr/local/bin//picamera2-WebUI-Lite/app.py Restart=always RestartSec=120 [Install] WantedBy=multi-user.target
Press CTRL + X to exit and Y to save
Reload the daemon
sudo systemctl daemon-reload
Enable the service
sudo systemctl enable webui-lite.service
NOTE that if you already have the other streamVideo service I listed above using Picamera you will have to disable it as you can't run both.
sudo systemctl disable streamVideo.service
Reboot the system to make sure the service starts
sudo shutdown -r now
Adjust your DWC settings as follows
This will allow you to easily get to the settings page by clicking on the webcam image in DWC
From there adjust your resolution and you can also zoom in a particular area using the scaler crop settings.Full view
Cropped view
-
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.
Latest posts made by OwenD
-
RE: How to report current/last position and move on event
It occurred to me that the macro wouldn't work if the axis minima was not zero, so I've adjusted it to cater for that.
After running it many times, it seems to show that in my case at least, the repeatability of the end stops is poor.
Or at least inconsistent enough that the error can amount to between 1 and 3 steps.
So I'm not sure it's going to work as desired. -
RE: How to report current/last position and move on event
I am determined to put an end to ruined prints due to layer shifts.
Therein lies the rub.
You can react to a stall, but you can't fix a hardware problem with a software solution.
I've usually found the root cause of layer shifts to be mechanical in nature (bearing failure etc) or print parameter issues like the time my slicer setting for overhang extrusion was set to 100 (thinking it was %) when it should have been in the range 0-1 š¤¬ -
RE: Forced Ending Script or Macro
@3DPotter said in Forced Ending Script or Macro:
Is there a way to force an ending script/macro/gocde file to run at the end of every print?
The gcode print file that just finished does not have any run commands/scripts in the gcode file. And the Duet board automatically runs file X once a print has been completed, no mater what the print is or what is in the gocde file.
As @jay_s_uk has said, stop.g is run at the end of every print job.
No such function exists for other gcode files such as macros. -
RE: How to report current/last position and move on event
@Triet said in How to report current/last position and move on event:
I am wondering if it is possible to check if the stall event is a false positive case. In this case, the distance to the homing position would be unchanged. So it boils down to measuring the travel it takes to home and compare it to the saved position. If it is different than the saved position, a layer shift has occurred.
Do you know a way to do homing starting at some position and report the traveled distance?
You can do that using G1 H3
The sequence (posted by @DC42 a ling time ago) would beG92 X0. ; Set current position to 0 G1 S3 X-300. ; Home to X minimum and set the axis limit M208 ; Report axis limits M208 S1 X0. ; Set axis limit back to 0 G92 X0. ; Set current position as 0
I thought about how to make that into a useful macro and came up with the following.
However I'm not really sure if it's of great benefit.
The driver won't report an error unless it thinks it's skipped a minimum of either 1 or 4 steps as I understand it.
A lot will depend on the repeatability of the end stop and whether the measured distance can be resolved to a meaningful number of steps difference.
It might help tuning for false positives.I've tested the macro, but haven't introduced stalls or used it as part of an event.
I'd be interested to hear the results if you care to test it as such.; dist2home.g ; ASSUMES HOMING TO MINIMA!! ; only accepts X and Y axes ; send axis by using A parameter ; e.g. ; M98 P"dist2home.g" A"Y" ; **********adjust as required********** var dist2move = -500 ; set greater than all axies length var thisAxis = "X" ; default to x axis,but can be changed if parameter sent var moveSpeed =600 ; speed during moves var homeOnError = true ; home axes is error found var return = true ; return to start position var logErrors = true var logFile = "0:/sys/driver_error_log.txt" ;***************************************** ; don't edit below here var stepX = {1 / move.axes[0].stepsPerMm} var stepY= {1 / move.axes[1].stepsPerMm} var currentXlimit = move.axes[0].min var currentYlimit = move.axes[1].min var currentX = move.axes[0].machinePosition var currentY = move.axes[1].machinePosition var currentZ = move.axes[2].machinePosition var xMove = var.dist2move ; will be reset as needed var yMove = var.dist2move ; will be reset as needed var searchPosX = move.axes[0].machinePosition var searchPosY = move.axes[1].machinePosition var hasErrorX = false; var hasErrorY = false; if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed echo "Machine not homed" M99 M400 ; wait for any moves to stop G91 ; set relative moves if exists(param.A) set var.thisAxis = param.A echo "selected axis is " ^ var.thisAxis echo "start position X" ^ var.currentX ^ " Y" ^ var.currentY if var.thisAxis = "X" set var.yMove = 0 G92 X0. ; Set current X position to 0 G1 H3 X{var.xMove} Y{var.yMove} F{var.moveSpeed}; Home to selected axis to minimum and set the axis limit M400 set var.searchPosX = move.axes[0].min - var.currentXlimit echo "pos " ^ abs(var.searchPosX) ^ " start " ^ var .currentX if (abs(var.searchPosX) = var.currentX) set var.hasErrorX = false echo "Move distance was equal - False positive" else set var.hasErrorX = true echo "Measured error on X is : " ^ var.currentX - abs(var.searchPosX) ^ " mm - Steps = " ^ abs(var.currentX - abs(var.searchPosX) ) / var.stepX M208 S1 X{var.currentXlimit} Y{var.currentYlimit} ; Set axis limit back to original M208 ; report axis setting G90 ; absolute moves G92 X{var.currentXlimit}.Y{var.currentY} Z{var.currentZ}; Set current position as original elif var.thisAxis = "Y" set var.xMove = 0 G92 Y0 ; Set current position to 0 G1 H3 X{var.xMove} Y{var.yMove} F{var.moveSpeed}; Home to selected axis to minimum and set the axis limit M400 set var.searchPosY = move.axes[1].min - var .currentYlimit if (abs(var.searchPosY) = var.currentY) set var.hasErrorY = false echo "Move distance was equal - False positive" else set var.hasErrorY = true echo "Measured error on Y is : " ^ var.currentY - abs(var.searchPosY) ^ " mm - Steps = " ^ abs(var.currentY - abs(var.searchPosY) ) / var.stepY M208 S1 X{var.currentXlimit} Y{var.currentYlimit} ; Set axis limit back to original M208 ; report axis settings G90 ; absolute moves G92 Y{var.currentYlimit}. X{var.currentX} Z{var.currentZ}; Set current position as original else echo "Undefine axis sent: " ^ param.A echo "Exiting macro with no action" G90 ; absolute moves M99 ; exit macro G90 ; absolute moves if var.homeOnError if var.hasErrorX G28 X if var.hasErrorY G28 Y if var.hasErrorX || var.hasErrorY if var.logErrors echo >{var.logFile} "Error amount X:" ^ var.currentX - abs(var.searchPosX) ^ " mm - Steps = " ^ abs(var.currentX - abs(var.searchPosX) ) / var.stepX echo >>{var.logFile} "Error amount Y:" ^ var.currentY - abs(var.searchPosY) ^ " mm - Steps = " ^ abs(var.currentY - abs(var.searchPosY) ) / var.stepY if var.return G1 X{var.currentX} Y{var.currentY} F{var.moveSpeed} ; move back to original position
-
RE: Feature Request - workpiece angle compensation CNC
@jay_s_uk said in Feature Request - workpiece angle compensation CNC:
@CanDo415 i've made another change but I don't think its going to fix the issue.
I don't know why "degrees" throws an error though as its a built in commanddegrees() is a function
You've used curly braces instead of parentheses
set var.y_x_tan_deg=degrees{var.y_x_tan_rads}
try
set var.y_x_tan_deg=degrees(var.y_x_tan_rads)
-
RE: How to report current/last position and move on event
From the documentation I linked above
How it works
Any time you pause a print from SD card, the state of the print is saved to a special file on the SD card, sys/resurrect.gThe example I showed above is after a pause.
When I initially went to get a sample, resurrect.g didn't exist, so I had to start a print and pause it to create one.
As I said, I don't know if it will put you on the exact line that caused the driver error, but it's fairly easy to use the object model to get the machine position at the time to compare.
You could either write it to file or use G60 to save it to a slot.My own driver_stall.g re-homes after a stall rather than pauses so I use G60 but also write to a log file.
That's ok for a random stall but if there's a problem it'll keep stalling and re-homing.
I guess creating a "max stalls" variable would make sense.;0:/sys/driver-stall.g var yMotorTemp = {sensors.analog[5].lastReading * 1.00} var xMotorTemp = {sensors.analog[4].lastReading * 1.00} var xDriver = 4 var yDriver = 1 if (param.D = var.xDriver) || (param.D = var.yDriver) set var.yMotorTemp = sensors.analog[5].lastReading; get the current motor temp set var.xMotorTemp = sensors.analog[4].lastReading; get the current motor temp echo "X motor temp =", var.xMotorTemp ^ "C" , " : Y motor temp =", var.yMotorTemp ^ "C" echo " A driver stall has occured on driver " ^ param.D echo "Layer shifting may have occured at X:",move.axes[0].machinePosition, "Y:", move.axes[1].machinePosition, "Z:", move.axes[2].machinePosition echo "Requested speed is " , move.currentMove.requestedSpeed, "mm/sec. Top speed is", move.currentMove.topSpeed, "mm/sec" if (var.xMotorTemp !=0) || (var.yMotorTemp !=0) echo "X motor temp =", var.xMotorTemp ^ "C" , " : Y motor temp =", var.yMotorTemp ^ "C" echo >>"0:/sys/print_log.txt" "A driver stall has occured on driver " ^ param.D echo >>"0:/sys/print_log.txt" "Layer shifting may have occured at X:",move.axes[0].machinePosition, "Y:", move.axes[1].machinePosition, "Z:", move.axes[2].machinePosition echo >>"0:/sys/print_log.txt" "Requested speed is " , move.currentMove.requestedSpeed, "mm/sec. Top speed is", move.currentMove.topSpeed, "mm/sec" if (var.xMotorTemp !=0) || (var.yMotorTemp !=0) echo >>"0:/sys/print_log.txt" "X motor temp =", var.xMotorTemp ^ "C" , " : Y motor temp =", var.yMotorTemp ^ "C" echo >>"0:/sys/print_log.txt" "**********************************" ; check if a driver stall is already being acted on. if global.InMacro=true echo "Driver stall macro already running - no further action taken" M99 ; exit macro M400 if job.file.fileName!= null ; check if we are printing set global.InMacro=true ; stop the mcro being run multiple times G60 S3 ; save position to slot 3 echo "File position is ", job.filePosition, "bytes" echo "Physical position is X:",move.axes[0].machinePosition, "Y:", move.axes[1].machinePosition, "Z:", move.axes[2].machinePosition G4 P5 ; if a tool is selected and the heater is up to temp we'll retract if heat.heaters[tools[max(state.currentTool,0)].heaters[0]].current > heat.coldRetractTemperature G10 G1 F1800 ; reduce speed before homing G28 X Y ; home X & Y M400 M116 set global.InMacro = false ; unset the flag so it will start looking for stalls on the return G1 F1200 ; reduce speed when travelling back to saved slot G1 R3 X0 Y0 Z5; travel to 5mm above stall position G1 F60 ; reduce speed G1 R3 X0 Y0 Z0 ; move to stall position ; if a tool is selected and the heater is up to temp, we'll un-retract if required. if (heat.heaters[tools[max(state.currentTool,0)].heaters[0]].current > heat.coldExtrudeTemperature) && (tools[max(state.currentTool,0)].isRetracted) G11
-
RE: How to report current/last position and move on event
@Triet
If you look for the M26 command in resurrect.g it gives you the offset in bytes that represents the file progress.
You can use Notepad ++ to find the line as shown below.
Not sure it will be the exact line where the driver error occurred, but it should be close.Go to SEARCH -> GOTO
-
Odd appearance in M291 window
This isn't causing me an issue, so just reporting it out of interest.
It only seems to have started since 3.5.1
Don't recall seeing it at any time previous.I have an M291 during my bed soaking period that pops up every few seconds as a notice of what's going on.
The relevant section of code iswhile ((heat.heaters[0].active - var.target) > (sensors.analog[8].lastReading)) && (global.BedHasSoaked = false) if heat.heaters[0].state != "active" echo "Bed heater no longer active. Soaking cancelled" M99 M291 R{"Soaking Bed (" ^ heat.heaters[0].active ^ "C) Please wait"} P{"Bed temp = " ^ heat.heaters[0].current ^ " : Edge temp = " ^ (sensors.analog[8].lastReading)} S0 T2 G4 S4
I've just noticed that for a fraction of a second, you can see an emergency stop button in the corner.
-
RE: Probe no retracting at end of macro
I'm not that familiar with a klicky probe, but I believe it uses a micro switch
In your macro you use
if sensors.probes[0].value[0]==0The documentation for the OM state
sensors.probes[].value[]
Current analog values of the probeSo your condition is going to return true any time the micro switch is not actually pressed if it's an N/O circuit and likewise return false if it's an N/C circuit
How is it defined in config.g?You can check in the object model browser which value you have during the process.
I would have thought you'd be checking if the probe was attached rather than whether it's "active" ?
EDIT
Your code seems to assume that as soon as the probe is picked up you get a value of 1000.
That may be possible, but as stated the value is meant to be an indicator of whether the switch is depressed by touching the bed.
If the probe is docked and not electrically present do you get a null value?
That may be a way to check if it's attached.Also it's much better to put your code in blocks rather than as attachments
Use the </> button -
RE: How to report current/last position and move on event
You will need to use the object model rather than a gcode command
https://github.com/Duet3D/RepRapFirmware/wiki/Object-Model-Documentation
Look at the move. and job. sections
Much of what you want is stored when a print is paused in resurrect.g, so you don't need to worry about it from a resume point of view