Displaying z level instructions on PanelDue
-
As noted in the thread Snapmaker J1 with a Duet 3... autocalibration possible? I am currently trying to use the witing time for my Duet and the Wifi module to arrive here and find my way to implement a guided calibration routine for my printer using conditional Gcode.
The bed has three adjustment screws = three probe points, and I measure z by contacting the bed with the nozzle which pulls a sensing wire to ground.
Basically I want to
- probe one screw (the reference point) several times,
- create a mean value of these measurements
- correct the z height based on this value
and then - go to the second screw,
- probe, display the value and a big arrow indicating the direction to turn on the PanelDue and repeat that and update the message continuously until the measured error is within the predefined limits.
Since AFAIK you cannot actually update an existing message that is shown on the PanelDue, I abuse the possibility to limit presentation time of the message and create a new message after each probing. This might flicker a bit and I need to tune loop timing for sync the messages to the measurement frequency and to let the poor PanelDue keep up with this, but I hope it will suffice.
The corresponding part of bed.g looks like this:
[for sake of easy readabilite, I removed the initialisation: - heat up bed and hotends - let the user clean the nozzles - remove the print plate - move the bed to measurement position] ; move to reference screw in centre back G1 X0 Y86 ; move M400 ; wait for the motion to finish var ZReference = 0 ; 1. measure and correct z value M201.1 Z50 ; define z speed for 1st calibration - a little faster while iterations <=6 G4 P200 ; wait 0,2s G30 S-1 ; measure z set var.ZReference = var.ZReference + move.calibration.initial.deviation M201.1 Z20 ; reduce z speed for subsequent iterations set var.ZReference = var.ZReference / 6 ; correct z value and z axis limit - endstop is at z_max set move.axes[2].max = move.axes[2].max - var.ZReference ; correct z axis limit G92 Z{-Referenzwert-sensors.probes[0].diveHeight} ; update z value M500 P31 ; save axis limits Move Bed to back to Z=5 G1 H2 Z5 F6000 ; move ; move hotend to probe point at front left G1 X-115 Y94 ; move M400 ; wait for the motion to finish ; measure error and let the user correct it M201.1 Z50 ; define z speed for first calibration - a little faster ; start loop while move.calibration.initial.deviation > 0.03 || move.calibration.initial.deviation < -0.03 G4 P200 ; wait 0.2s G30 S-1 ; measure Z M201.1 Z20 ; reduce z speed for subsequent iterations if move.calibration.initial.deviation > 0.03 M291 S0 T1 P"⇦" R"turn left adjustment screw" ; bigger arrow! ASCII art? elif move.calibration.initial.deviation < -0.03 M291 S0 T1 P"⇨" R"turn left adjustment screw" ; bigger arrow! ASCII art? [the same will be repeated then with the third probe point]
My question is about the arrow message. I want that arrow rather big to get it easily readable even if the message flickers. If I am not mistaken, I cannot format the message on the PanelDue, which means I cannot simply increase the size of the arrow (and yes, I still need to test if the PaneDue even is capable of presenting such a Unicode sign...). But is there some way to maybe use ASCII-Art? I would only need a line break for this to work, but I cannot seem to find that option...
(In case someone notices something in the above code snippet that obviously does not work: any feedback is highly appreciated, even if it has nothing to do with the primary question )
-
-
@NeoDue what's wrong with the automatic bed levelling routine built into RRF?
-
@jay_s_uk I guess you mean the Manual Bed Leveling Assistant? Automatic bed leveling ist only available for printers with multiple z axis steppers.
Well, the MBLA touches the points I define (just once) and simply reports what he found. There is no ongoing feedback for the user which means you need to run it, adjust, run it again, adjust... and so on.
In opposite to that, the Snapmaker calibration routine (Link points to a video showing it) I try to recreate touches the bed six times, averages the results, and then it guides the user on how to turn the knobs while continuing the measurement. This makes the task mich easier.
The reason why I want the best solution for this is however not just z leveling of the bed - the same logic (just for turning the adjustment screw for the hotend) is also used for z leveling both IDEX hotends towards each other, which needs to be done every time you swap the hotend module against another one. (Automatic XY calibration is done after that, but that one does not require any user interaction.)
-
Just an update: I might have come up with a solution that does not require line breaks, where I further split up the messages to display a kind of "terminal-like" graph. Some examples:
- |<<<<<<<<<<--...-->>>>>>>>>>> = more than 0.5mm too high
- <<<<<<<<<|<--...-->>>>>>>>>>> = 0.05...0,1 too high
- <<<<<<<<<<--.|.-->>>>>>>>>>> = perfectly centered (within ±0,01mm)
- <<<<<<<<<<--...-->|>>>>>>>>>> = 0.05...0,1 too low
and so on.
Since the PanelDue does not use a fixed-width font for messages: could someone tell me where to find the pixel widths of the font characters of the font that is used to display messages? The "glcd" font files located in the PanelDue Firmware repository contain hex values but I fear I do not know how to interpret those.
-
I think I found a way that works without knowing the font widths
[for sake of easy readability, I removed the initialisation: - heat up bed and hotends - let the user clean the nozzles - remove the print plate - move the bed to measurement position] ; move to reference screw in centre back G1 H2 X0 Y86 ; move M400 ; wait for the motion to finish var ZReference = 0 ; 1. measure and correct z value while iterations <=6 G4 P200 ; wait 0,2s G30 S-1 K0 ; measure z set var.ZReference = var.ZReference + sensors.probes[0].lastStopHeight G1 H2 Z5 F3000 ; move back up set var.ZReference = var.ZReference / 6 ; move hotend to probe point at front left G1 X-115 Y94 F3000 ; move M400 ; wait for the motion to finish ; measure error and let the user correct it ; start loop var Measurement1 = false var loopcount = 0 ; message timeout *must* be adapted to probing speed as good as possible. To avoid message buffer ; overflows, message (und thus measuring) interval should be significantly slower than 1s to let the ; Duet catch up if needed. while var.Measurement1 = false set var.loopcount = 0 G4 P200 ; wait 0.2s G30 S-1 K0 ; measure Z ; A "case" command, a kingdom for a "case" command... but we only have "if"... if sensors.probes[0].lastStopHeight > 0.5 M291 S1 T1.4 P"=>|<==========-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.5 && sensors.probes[0].lastStopHeight > 0.45 M291 S1 T1.4 P"=>|<=========-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.45 && sensors.probes[0].lastStopHeight > 0.4 M291 S1 T1.4 P"==>|<========-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.4 && sensors.probes[0].lastStopHeight > 0.35 M291 S1 T1.4 P"===>|<=======-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.35 && sensors.probes[0].lastStopHeight > 0.3 M291 S1 T1.4 P"====>|<======-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.3 && sensors.probes[0].lastStopHeight > 0.25 M291 S1 T1.4 P"=====>|<=====-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.25 && sensors.probes[0].lastStopHeight > 0.2 M291 S1 T1.4 P"======>|<====-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.2 && sensors.probes[0].lastStopHeight > 0.15 M291 S1 T1.4 P"=======>|<===-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.15 && sensors.probes[0].lastStopHeight > 0.1 M291 S1 T1.4 P"========>|<==-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.1 && sensors.probes[0].lastStopHeight > 0.05 M291 S1 T1.4 P"=========>|<=-..-==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight <= 0.05 && sensors.probes[0].lastStopHeight > 0.03 M291 S1 T1.4 P"==========>|<-..-==========" R"turn left bed screw" ; There is no non-blocking and time-out-able message the user can acknowledge ; Workaround: verify measurement several times, then display a blocking message elif sensors.probes[0].lastStopHeight <= 0.03 && sensors.probes[0].lastStopHeight >= -0.03 while sensors.probes[0].lastStopHeight <= 0.03 && sensors.probes[0].lastStopHeight >= -0.03 && var.loopcount <= 10 ; okay, but verify some times... if iterations > 0 ; not for the first loop G4 P200 ; wait 0.2s G30 S-1 K0 ; measure z G1 H2 Z5 F3000 ; move back up if sensors.probes[0].lastStopHeight <= 0.03 && sensors.probes[0].lastStopHeight > 0.01 ; just okay M291 S1 T1.4 P"==========->|<..-==========" R"turn left bed screw" set var.loopcount = var.loopcount + 1 elif sensors.probes[0].lastStopHeight <= 0.01 && sensors.probes[0].lastStopHeight >= -0.01 ; perfect M291 S1 T1.4 P"==========-.>|<.-==========" R"turn left bed screw" set var.loopcount = var.loopcount + 1 elif sensors.probes[0].lastStopHeight < -0.01 && sensors.probes[0].lastStopHeight >= -0.03 ; just okay M291 S1 T1.4 P"==========-..>|<-==========" R"turn left bed screw" set var.loopcount = var.loopcount + 1 if var.loopcount = 10 && sensors.probes[0].lastStopHeight <= 0.03 && sensors.probes[0].lastStopHeight >= -0.03 M300 S2000 P200 ; B G4 P200 ; e M300 S2500 P300 ; e G4 P300 ; p M291 S4 K{"OK","Repeat"} T1 P"Bed screw adjusted! End measurement?" R"Left bed screw adjusted" if input = 0 set var.Messung1 = true set var.loopcount = 99 if input = 1 set var.loopcount = 0 elif sensors.probes[0].lastStopHeight < -0.03 && sensors.probes[0].lastStopHeight >= -0.05 M291 S1 T1.4 P"==========-..->|<==========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.05 && sensors.probes[0].lastStopHeight >= -0.1 M291 S1 T1.4 P"==========-..-=>|<=========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.1 && sensors.probes[0].lastStopHeight >= -0.15 M291 S1 T1.4 P"==========-..-==>|<========" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.15 && sensors.probes[0].lastStopHeight >= -0.2 M291 S1 T1.4 P"==========-..-===>|<=======" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.2 && sensors.probes[0].lastStopHeight >= -0.25 M291 S1 T1.4 P"==========-..-====>|<======" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.25 && sensors.probes[0].lastStopHeight >= -0.3 M291 S1 T1.4 P"==========-..-=====>|<=====" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.3 && sensors.probes[0].lastStopHeight >= -0.35 M291 S1 T1.4 P"==========-..-======>|<====" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.35 && sensors.probes[0].lastStopHeight >= -0.4 M291 S1 T1.4 P"==========-..-=======>|<===" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.4 && sensors.probes[0].lastStopHeight >= -0.45 M291 S1 T1.4 P"==========-..-========>|<==" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.45 && sensors.probes[0].lastStopHeight >= -0.5 M291 S1 T1.4 P"==========-..-=========>|<=" R"turn left bed screw" elif sensors.probes[0].lastStopHeight < -0.5 M291 S1 T1.4 P"==========-..-==========>|<" R"turn left bed screw" [the same will be repeated then with the third probe point. Finally, save the updated z value and bring the printer back to a safe position]
Edit: fixed a generous amount of stupid typos, changed message type to S1 since the PanelDue does not seem to display S0 messages at all. Anything below "start loop" works now if I feed it with dummy data - for the rest I need the Duet built into the printer
2nd edit: updated to reflect how the script actually runs now, in case someone stumbles upon this and wants to use it. -
-
-
-
-
-