Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login
    1. Home
    2. DonStauffer
    3. Best
    • Profile
    • Following 0
    • Followers 0
    • Topics 57
    • Posts 405
    • Best 29
    • Controversial 0
    • Groups 0

    Best posts made by DonStauffer

    • My Pressure Advance Calibration

      I wrote some GCode to calibrate pressure advance. I wasn't satisfied with how uncertain I was in reading the other ones I found. They usually try various PA values as a sort of gradient, which sounds fine until you have other artifacts confusing the issue. It also requires some effort to convert the measured height into a k value in many cases.

      But what most lacked entirely is a "normal" reference adjacent to each test value. I produced this reference by first laying down some lines at a very slow, steady speed, then putting the test lines right next to it. The picture doesn't quite show how much easier this is to read; I think I succeeded in what I was trying to do. Once removed from the bed, you can try various lighting, including back lighting.

      Features:

      Only 2 layers, so it doesn't take long.
      Raft, so it's not sensitive to initial nozzle height.
      Controlled by variables set at the beginning of the code.
      PA test values separated by configurable space, so you can read just by counting bands.
      Configurable number of lines in each band.
      Configurable for machines with multiple tools.
      Configurable speeds, temperatures, retraction, layer height & width, bed position, and of course, k values for PA.
      

      242192803_288063902757988_2824346948475361497_n.jpg

      Pictured is eSun Fire Engine Red PETG on an E3DV6 (my secondary hot end) at 243°, k values from 0.05 (bottom) to 0.25 (top), increasing 0.01 each band. The bottom of each band is 4 lines at 1,200mm/min. The top of each band is 4 lines of 35mm on each side at 1,200mm/min sandwiching 70mm at 6,000mm/min in the center.
      In my experience you can use something like this to find the general value, then do another print with fewer bands and more lines per band to confirm the best k value. My best band on this is the 8th from the bottom, so I'm using k=0.12.

      undefinedThis code uses RFF 3.x meta-commands, so it's for Duet hardware. Further, RFF 3.3 and earlier have a bug which doesn't end the lifetime of local variables when a job ends or gets canceled, so you have to do an M999, an emergency stop, or cycle the power between attempts. This will be fixed in RFF 3.4, which has been in beta for several weeks, so it should be out soon.

      Please consider this "copylefted".

      ;	set variables
      
      var StartX = 50
      var StartY = 50
      var LinesPerTest = 4
      var LinesBetweenTests = 4
      
      var TempBed = 74
      var TempTool = 243
      
      var ToolNum = 1
      var Width = 0.48
      var Height = 0.25
      var Retract = 1
      var Prime = 7.9	;	Before Raft
      
      var PALow = 0.05
      var PAHigh = 0.25
      var PAIncrement = 0.01
      
      var SpeedRaft = 2000
      var SpeedSlow = 1200
      var SpeedFast = 6000
      var SpeedTravelXY = 9000
      var SpeedTravelZ = 1200
      var SpeedRetract = 4500
      
      ;	Calculated and Utility Variables
      
      var TestCount = 1 + floor((var.PAHigh - var.PALow) / var.PAIncrement + 0.5)
      var FilFactor = var.Width * var.Height / (pi * 1.75 * 1.75 / 4)
      var PA = var.PALow - var.PAIncrement
      var Dist = 0
      
      ;	PREPARE
      
      ;M42 P1 S1	;	Lights Bright
      
      T{var.ToolNum}
      M82	;	Extruder Absolute Mode
      
      ;	Heat Bed and set Hot Ends to Standby
      
      M400
      M117 "Heat"
      
      M140 S{var.TempBed}				;	set Bed Temp
      
      M568 P{var.ToolNum} S{var.TempTool} A2	;	set Tool Temp
      M116 H{var.ToolNum + 1} S1			;	Wait for temp
      
      G4 S12					;	Delay to Allow for Overshoot
      M116 H{var.ToolNum + 1} S1		;	Wait for Recovery
      
      M116 H0 S1					;	Wait for Bed
      
      M400
      M117 "Home"
      
      G28
      
      ;	BEGIN RAFT
      
      M400
      M117 "Raft"
      
      ;	Go to StartX + Width, StartY
      
      G90	;	Absolute
      
      G92 E0
      G0 E{-var.Retract} F{var.SpeedRetract}
      
      G1 X{var.StartX + var.Width} Y{var.StartY} F{var.SpeedTravelXY}
      G1 Z{var.Height} F{var.SpeedTravelZ}
      
      G91	;	Relative
      
      ;	Prime
      
      G0 E{var.Prime} F{var.SpeedRetract}
      G92 E0
      
      var RaftLineCount = floor((floor(139 / var.Width) - 1) / 3) + 1
      set var.Dist = (2 * var.TestCount * var.LinesPerTest + var.LinesBetweenTests * (var.TestCount - 1)) * var.Width
      
      while iterations < var.RaftLineCount
      	
      	;	Draw Raft Line
      	
      	G0 Y{var.Dist} E{abs(var.Dist) * var.FilFactor} F{var.SpeedRaft}
      	G92 E0
      	
      	;	Break here if last time
      
      	if iterations + 1 >= var.RaftLineCount
      		break
      
      	;	Move Over
      
      	G0 X{3 * var.Width} E{3 * var.Width * var.FilFactor} F{var.SpeedRaft}
      	G92 E0
      
      	set var.Dist = -var.Dist
      
      G0 E{-var.Retract} F{var.SpeedRetract}	;	Retract
      
      ;	BEGIN TEST PATTERN
      
      M400
      M117 "Test Pattern"
      
      ;	Go to StartX, StartY
      
      G90	;	Absolute
      
      G1 Z{2 * var.Height} F{var.SpeedTravelZ}
      G1 X{var.StartX} Y{var.StartY} F{var.SpeedTravelXY}
      
      G91	;	Relative
      
      while iterations < var.TestCount
      
      	;	set PA
      
      	set var.PA = var.PA + var.PAIncrement
      	M572 D{var.ToolNum} S{var.PA}
      	echo "PA=",{var.PA}
      	
      	;	Draw Reference Lines
      
      	while iterations < var.LinesPerTest
      
      		G0 E0 F{var.SpeedRetract}		;	Unretract
      		G0 X140 F{var.SpeedSlow} E{140 * var.FilFactor}
      
      		G92 E0
      		G0 E{-var.Retract} F{var.SpeedRetract}	;	Retract
      
      		G1 Y{var.Width} F{var.SpeedTravelXY}
      		G1 X-140 F{var.SpeedTravelXY}
      
      	;	Draw Test Lines
      
      	while iterations < var.LinesPerTest
      	
      		G0 E0 F{var.SpeedRetract}		;	Unretract
      
      		G0 X35 F{var.SpeedSlow} E{35 * var.FilFactor}
      		G0 X70 F{var.SpeedFast} E{105 * var.FilFactor}
      		G0 X35 F{var.SpeedSlow} E{140 * var.FilFactor}
      
      		G92 E0
      		G0 E{-var.Retract} F{var.SpeedRetract}	;	Retract
      
      		G1 Y{var.Width} F{var.SpeedTravelXY}
      		G1 X-140 F{var.SpeedTravelXY}
      
      	;	Move to start of next comparison
      
      	G1 Y{var.LinesBetweenTests * var.Width} F{var.SpeedTravelXY}
      
      ;	Finish up
      
      M400
      M117 "Done"
      
      G1 Z10 F{var.SpeedTravelZ}
      
      G90					;	Absolute
      
      G1 X10 Y280 F{var.SpeedTravelXY}
      
      G0 E0	 F{var.SpeedRetract}		;	Unretract
      
      
      posted in Tuning and tweaking
      DonStaufferundefined
      DonStauffer
    • Thank You For Variables!

      Variables are an especially powerful feature that opens up huge new possibilities. I'm really enjoying having them. It's like when the Wizard Of Oz suddenly changed from black and white to color.

      Arrays are the icing on the cake. Combined with the object model so many things are possible!

      The implementation has been excellent too. Once I got used to the syntax it works fine.

      Thank you! Well done!

      posted in Gcode meta commands
      DonStaufferundefined
      DonStauffer
    • NeoPixel driver results

      I've had good results so far with the NeoDriver.

      In order to get around the inability to use M150 to control NeoPixels during printer moves, I got the $7.50 Adafruit NeoDriver card, which receives instructions for the NeoPixels via I2C, and takes care of the critical timing issue for controlling the NeoPixels.

      I have it working now, using M260 to send I2C transactions. It seems to work fine, although I haven't yet had time to test it during printer moves. I think G29 will be my first attempt.

      Once I got the correct transactions, it works as easily as M150 did, though quite differently. As expected, it's slower, but perfectly adequate for progress bars and the like. I'd say an update takes about 100ms. So my chasers go kind of at a moderate speed, not like greased lightning. That's fine for my purposes.

      I'll update this when I have tested during moves. Hopefully the daemon will still operate during moves. That's my main concern.

      Initialization script (run once - maybe from config.g):

      ;   Initializes NeoDriver and turns off LEDs
      
      var FUNC_REGISTER_PIN = 0x01
      var FUNC_REGISTER_SPEED = 0x02
      var FUNC_REGISTER_BUF_LENGTH = 0x03
      ;var FUNC_REGISTER_BUF = 0x04
      ;var FUNC_REGISTER_SHOW = 0x05
      
      var BASE_ADDR_NEO_PIX = 0x0E
      
      ;   Parameters
      
      var I2CAddress = 0x60
      var NeoPixelPinNum = 0x0F
      var LEDCount = 28
      
      if exists(param.A)
          set var.I2CAddress = param.A
      
      if exists(param.N)
          set var.NeoPixelPinNum = param.N
      
      if exists(param.L)
          set var.LEDCount = param.L
      
      ;   Set NeoDriver pin #, speed = 800,000, Buffer size
      
      var BufferSize = 3 * var.LEDCount
      
      M260 A{var.I2CAddress} B{var.BASE_ADDR_NEO_PIX,var.FUNC_REGISTER_PIN,var.NeoPixelPinNum}
      M260 A{var.I2CAddress} B{var.BASE_ADDR_NEO_PIX,var.FUNC_REGISTER_SPEED,1}
      M260 A{var.I2CAddress} B{var.BASE_ADDR_NEO_PIX,var.FUNC_REGISTER_BUF_LENGTH,var.BufferSize,0}
      
      ;   Turn all LEDs off
      
      M98 P"/macros/Lights/NeoPixel/SetNeoPix"
      M98 P"/macros/Lights/NeoPixel/ShowNeoPix"
      
      posted in General Discussion
      DonStaufferundefined
      DonStauffer
    • M150 with NeoPixels

      This statement, coupled with some wrong information out on the internet which uses the word "scroll" incorrectly, creates a confusing situation. It took me about a day to sort it out:

      "The specified RGB values will be sent to the number of LEDs in the LED strip as specified by the S parameter, pushing the existing colours along the strip. To set all the LEDs the same colour, make the S parameter equal to or a little longer than the number of LEDs in the strip."

      Strictly speaking, it is not correct that anything "pushes existing colors along the strip". That doesn't happen, ever.

      What happens is: After an M150 F0 command, the M150 commands append to one another, in order, not changing what's displayed, until another M150 F0 is reached. Then the whole string of appended new LED values (including the ones in the new M150 F0) get displayed, starting at the beginning of the strip. Only as many LEDs as those statements specified get changed, leaving any LEDs further along the strip with their prior values.

      There is no "scrolling" or "pushing existing colors along". The new values simply "overwrite" existing ones, from the beginning of the strip, and only as far as they "need" to, and it doesn't happen visibly until the M150 F0.

      A chaser, first lighting LEDs in a line, then darkening them in the same direction, would look like this (tested on 10 LED NeoPixel stick):

      M150 P0 S10 F0 E0	;	Turn entire strip off
      
      while iterations < 10
      	M150 R255 U0 B0 P32 S{iterations+1} F0 E0
      	G4 P20
      
      while iterations < 9
      	M150 R0 U0 B0 P0 S{iterations + 1} F1 E0
      	M150 R255 U0 B0 P32 S{9 - iterations} F0 E0
      	G4 P20
      
      M150 R0 U0 B0 P0 S10 F0 E0	;	Turn entire strip off
      
      

      433262322_7201834966538170_4235366852098968886_n.mp4

      posted in Documentation
      DonStaufferundefined
      DonStauffer
    • RE: Center Dot Character in macros

      @phaedrux The macro creates a few hundred short macros which support a system I developed to control printer settings on a feature level (solid fill, infill, supports, etc.) rather than just a layer level. So, you can set your outer perimeter to use a different fan setting than solid fill, for example.

      posted in Duet Web Control
      DonStaufferundefined
      DonStauffer
    • RE: Z-axis / tramming issues with 3.6.0-alpha2+3

      @Exerqtor One of my Z steppers now adjusts in the wrong direction for G32. It's not that it has reversed direction in general, because other things work. But I can't level the bed. Every time it finds that point to be off, it moves it in the other direction and then the next time around it's off by twice as much. Kind of a problem.

      Update: I've been trying to mess with it to get it level again and now my head has also hit the bed. This is a Railcore with 3 Z steppers, and #7 seem to be randomly reversing directions or not moving with the others. It's gotten to the point where I can't even do a home.

      I can't really revert to 3.5 because the memory issues will keep me from working, and I can't use this version because I can't manage the bed because probing doesn't work right. So I'm completely down right now until a new version comes out.

      Update 2: Now I'm getting Warning: Driver 7 warning: phase B may be disconnected

      posted in Beta Firmware
      DonStaufferundefined
      DonStauffer
    • RE: File exists check

      @phaedrux I found a very awkward workaround: M471 is the only code I know of which returns a result that tells you something about the existence of a file. Unfortunately, it does that when potentially deleting the file in question. I didn't want that, so I had to set up a system of dummy "semaphor" files created in parallel with the file I was interested in, which fortunately my macros created, so it could keep the semaphors consistent with the actual file status.

      But all that turned what would have been about a half page of code with a file exists capability into about 2 pages.

      posted in Firmware wishlist
      DonStaufferundefined
      DonStauffer
    • RE: Global Variable Question

      @dc42 My testing in error. exists() works fine.

      posted in Gcode meta commands
      DonStaufferundefined
      DonStauffer
    • RE: Vertical banding on COREXY machine

      @fcwilt I don't really have a theory. But I'm running out of moving parts to replace. So I'm frustrated and uncertain.

      posted in Tuning and tweaking
      DonStaufferundefined
      DonStauffer
    • RE: Center Dot Character in macros

      @dc42 Perfect, thanks! This worked:

      Private Const CENTER_DOT_CHAR As String = "·"

      Public Sub Test()
      Dim sFilename As String
      sFilename = "C:\Users\Don\3D Printing\Software\Slicing\FeatureSettings\TestDot"
      Dim fsT As Object
      Set fsT = CreateObject("ADODB.Stream")
      fsT.Type = 2 'Specify stream type - we want To save text/string data.
      fsT.Charset = "utf-8" 'Specify charset For the source text data.
      fsT.Open 'Open the stream And write binary data To the object
      fsT.WriteText ";special characters: " & String(10, CENTER_DOT_CHAR)
      fsT.SaveToFile sFilename, 2 'Save binary data To disk

      End Sub

      posted in Duet Web Control
      DonStaufferundefined
      DonStauffer
    • RE: Global Variable Question

      @dc42

      Macro "Caller":
      var X = 3
      M98 P"/macros/Test/Callee"

      Macro "Callee":
      echo "X="^{var.X}

      Result of running Caller:
      Error: in file macro line 1 column 17: meta command: unknown variable 'X'

      (This is fine with me. As expected.)

      posted in Gcode meta commands
      DonStaufferundefined
      DonStauffer
    • RE: Vertical lines vs. geared extruders

      @oliof My belts are most definitely not overtensioned. When I loosened them to do the Air Print tensioning, they didn't bounce at all so I stopped and just left them there. I used to have them at about 50Hz, but now they're much looser.

      posted in Tuning and tweaking
      DonStaufferundefined
      DonStauffer
    • RE: Center Dot Character in macros

      @phaedrux Macro:

      https://drive.google.com/file/d/1xkiiMbsnKcUBRHepfGuDxpLkeH_PS8OA/view?usp=sharing

      posted in Duet Web Control
      DonStaufferundefined
      DonStauffer
    • RE: Global Variable Question

      @gloomyandy C++ has something like Pascal has, in that you can create local constructs within a function, and the function becomes the enclosing scope and so is accessible. It's been too long and I don't remember the details.

      posted in Gcode meta commands
      DonStaufferundefined
      DonStauffer
    • RE: Dual Extruder Steps/mm

      @fcwilt I see. It wasn't clear to me what an "axis" was in terms of exrtruders. That's good! I can set them individually. I'm happy.

      posted in Tuning and tweaking
      DonStaufferundefined
      DonStauffer
    • RE: Center Dot Character in macros

      @phaedrux This took me forever because it's been through several complete rewrites.

      The concept is tested, but the latest rewrite is not yet, although I did go through the macro it generates and checked that it's doing what I wanted. So in theory, this should work. I'll post more information when I have updates.

      There is a Word document with it. The first 4 pages of it are reasonably good. The rest is garbage that includes false starts at documentation and old stuff that has changed. But the first 4 pages should give you an idea what this does and how it works.

      The guts is in the Excel spreadsheet in the form of a VBA macro that writes one HUGE GCode macro for you to upload to your printer and run. That macro creates all the other GCode macros which are needed.

      https://drive.google.com/file/d/1Jh4fO95Y5pp5moa_8uJQQ0AG0cifJVMD/view?usp=sharing

      posted in Duet Web Control
      DonStaufferundefined
      DonStauffer
    • RE: Variable "already exists"

      @fcwilt I've just been doing an M999 between jobs for now.

      posted in Gcode meta commands
      DonStaufferundefined
      DonStauffer
    • RE: Music skipping beats after firmware update (3.4.0beta6)

      @dc42 Unfortunately, adding a daemon.g file with a loop didn't fix it for me. I have a music macro called from my S3D ending script. If I run the macro while no job is running it works fine. But almost always, at the end of a print, the third note doesn't sound. Not a big deal, but I don't know why it does this.

      posted in Tuning and tweaking
      DonStaufferundefined
      DonStauffer
    • Colorized Macro Printing

      I discovered something I thought I'd mention in case it's useful for someone.

      I had been downloading a macro, then opening it in MS word, and going through and using styles to color code syntax manually. Not a huge big deal for most macros, and it made it more readable. But if you try to print in the web control, you only get the visible code. If the macro is longer than will fit, you'll get multiple pages of the same portion of the code!

      Then it occurred to me to go into the macro in the Web Control editor, do Ctrl-A to highlight the whole macro, Ctrl-C, then paste it into a new Word document, in the hopes of carrying the HTML formatting through the clipboard. Well, it worked, and the added advantage is it will be the same color coding as used in the web control. I haven't tried it in dark mode, and I suspect it wouldn't be so good. But it sure is easier than manually formatting.

      I hope this is helpful.

      posted in Duet Web Control
      DonStaufferundefined
      DonStauffer
    • Macro Parameter Letters

      This is a style question, but the answer may involve a feature I'm unaware of.

      If I want to call a macro with a pair of coordinates, I can do something like:

      M98 P"MacroFile" X{var.XCoord} Y{var.YCoord}

      Then in the macro, I just access them using param.X and param.Y.

      If I have ranges of coordinates, as in defining a bed area, I'm not aware of any way except choosing arbitrary letters:

      M98 P"MacroFile" X{var.XMin} A{var.XMax} Y{var.YMin} B{var.YMax}

      I could concatenate min and max as strings with a colon between them, but I know of no way to separate them again inside the macro.

      What's the best way to handle this?

      posted in Gcode meta commands
      DonStaufferundefined
      DonStauffer