Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login

    Displaying z level instructions on PanelDue

    Scheduled Pinned Locked Moved Solved
    PanelDue
    2
    5
    403
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • NeoDueundefined
      NeoDue
      last edited by NeoDue

      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

      1. probe one screw (the reference point) several times,
      2. create a mean value of these measurements
      3. correct the z height based on this value
        and then
      4. go to the second screw,
      5. 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 😉 )

      jay_s_ukundefined 1 Reply Last reply Reply Quote 0
      • NeoDueundefined NeoDue marked this topic as a question
      • jay_s_ukundefined
        jay_s_uk @NeoDue
        last edited by

        @NeoDue what's wrong with the automatic bed levelling routine built into RRF?

        Owns various duet boards and is the main wiki maintainer for the Teamgloomy LPC/STM32 port of RRF. Assume I'm running whatever the latest beta/stable build is

        1 Reply Last reply Reply Quote -1
        • NeoDueundefined
          NeoDue
          last edited by NeoDue

          @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.)

          NeoDueundefined 1 Reply Last reply Reply Quote 1
          • NeoDueundefined
            NeoDue @NeoDue
            last edited by

            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.

            NeoDueundefined 1 Reply Last reply Reply Quote 0
            • NeoDueundefined
              NeoDue @NeoDue
              last edited by NeoDue

              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.

              1 Reply Last reply Reply Quote 1
              • NeoDueundefined NeoDue has marked this topic as solved
              • NeoDueundefined NeoDue referenced this topic
              • NeoDueundefined NeoDue has marked this topic as unsolved
              • NeoDueundefined NeoDue has marked this topic as solved
              • NeoDueundefined NeoDue referenced this topic
              • NeoDueundefined NeoDue referenced this topic
              • First post
                Last post
              Unless otherwise noted, all forum content is licensed under CC-BY-SA