Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login
    1. Home
    2. garethky
    3. Best
    • Profile
    • Following 0
    • Followers 1
    • Topics 8
    • Posts 73
    • Best 22
    • Controversial 0
    • Groups 0

    Best posts made by garethky

    • RE: Feedback wanted: conditional GCode without indentation

      @wilriker +1

      The target audience for this language is not skilled programmers. Its designers & makers that are trying to solve some problem with their printer. There is going to be a LOT of copy/paste code that mixes indentation types (tabs, spaces, number of spaces). Begin/end constructs survive this kind of abuse better than Python style strict indentation. Having just 1-way-to-do-it makes its safer/easier for newbies copying code.

      The few of us that are writing most of the code can use whatever construct you come up with.

      posted in Future Direction
      garethkyundefined
      garethky
    • Syntax Highlighter for RepRap Gcode

      I've started work on an syntax highlighter grammar for RepRap GCode. These are the results (of some absolute garbage code) in Sublime Text 3:

      Screen Shot 2021-01-08 at 12.37.13 AM.png

      So far it knows about G, M & T commands, expressions, language keywords, comments etc. Open source of course: https://github.com/garethky/RepRapGCodeSyntaxHighlighter/tree/development
      (I'm pointing you to the development branch because its not ready for a mainline release yet)

      I didn't want to do this for just my editor, so I found a tool called Iro. Iro uses a generic grammar and then generates the highlighter files for a slew of popular text editors. Its not perfect, its not open source and I have already found some bugs, but it got me 95% the way there for 1 editor so far (and apparently Sublime is the editor with the weakest support). If you are an editor guru and want to help out I would like your support:

      • You can generate the grammar for your editor using the .rion file on github and test your editor and tell me if it works or not
      • You can contribute the Scope mappings for Pygments & Rogue
      • You want to fix something or make something better, please submit a patch on github
      posted in Gcode meta commands
      garethkyundefined
      garethky
    • rrf-mesh-level: Custom Mesh Bed Probing with Python

      For my E3D Tool Changer I want to have a magnetic bed with swapable build plates. A somewhat surprising roadblock has been using an inductive probe on this bed with G29. With a high enough mesh density its inevitable that the probe samples the magnets and returns a false result:

      Screen Shot 2021-01-24 at 12.23.55 PM.png

      With some GCode meta commands, execonmcode, an attached SBC and Python we can build an accurate heightmap from a set of probe points that miss all of the magnets:

      Screen Shot 2021-01-24 at 12.55.17 PM.png

      Source Code

      I've put everything into a project on github: rrf-mesh-level so you can do this too.

      Results

      Before I talk about how its done lets see how it prints. The best build plate that I have is the Prusa textured sheet so that's what I'm testing on:

      IMG_5953.jpeg

      The lowest square (some over extrusion is present):

      IMG_5956.jpeg

      An average square:

      IMG_5955.jpeg

      The highest square (some under extrusion is present):

      IMG_5954.jpeg

      I could nitpick but I think you see the technique works.

      How?

      The process goes like this:

      • Probe the bed and log the probed points to the SD card
      • Use execonmcode to invoke mesh-level.py with the log file and bed shape
      • mesh-level.py uses Python/SciPy to processes the probe data with some cool math and produce a heightmap.csv file
      • Profit! 💰

      Step 1 - Probing

      You will need to work out what X/Y points you want to probe your bed at. I used a CAD model of my bed to measure X/Y probing locations from machine 0,0. Then I used a Python script to generate the GCode for probing each point. This takes the sensor offset and sensor travel speed into account. My bed.g file contains all the probe points that were generated. This is the truncated version:

      ; delete any previous log file so previously probed points don't get sampled
      M30 "/sys/meshbedprobe.log"
      ; start INFO logging to the SD card
      M929 S2 P"/sys/meshbedprobe.log"
      
      ; probe bed points by moving to each X/Y coordinate and then calling the point probe script
      ; Probing row #1, Direction: ->
      G1 X{32.353 - sensors.probes[0].offsets[0]} Y{-11.0 - sensors.probes[0].offsets[1]} F{sensors.probes[0].travelSpeed * 60}
      M98 P"/sys/probe-point.g"
      
      ; ... many, many more points get probed
      
      ; stop logging
      M929 S0
      

      The probe-point.g macro is where the actual probing of individual points happens. It uses a loop and G30 S-1 to probe the location and M118 to write the results of each probing to the open log file. You don't have to copy this, any macro that writes the same Mesh Point: Xn Yn Zn format will work with the python script. The resulting log file looks like this:

      2021-01-24 12:26:58 Mesh Point: X32.355 Y-11.000 Z-0.254
      2021-01-24 12:26:59 Mesh Point: X32.355 Y-11.000 Z-0.254
      2021-01-24 12:26:59 Mesh Point: X67.030 Y-11.000 Z-0.313
      2021-01-24 12:27:00 Mesh Point: X67.030 Y-11.000 Z-0.314
      

      Step 2: Calling Python with execonmcode

      Using the excellent execonmcode utility we invoke the mesh-level.py script using a custom MCode M7029 from inside bed.g:

      ; call the custom MCode to create the heightmap.csv file, all params must be passed as strings
      M7029 X"0:300" Y"0:200"
      

      The parameters here are the same as X, Y from M557
      The script supports a lot more parameters besides these, the file names, point spacing etc. can be customized if desired.

      Building the heightmap.csv

      mesh-level.py uses something called Radial Basis Functions (RBF) to compute an interpolated surface from your probe point data. The surface is a high quality representation of the bed shape where the surface passes through all of your probe points (no smoothing is performed). The more points your probe, the better that representation is going to be.

      RBF has some characteristics that make it very useful in this application:

      • It can work with scattered X/Y input points, they don't need to be in anything like a regular pattern
      • It can extrapolate beyond the bounds (convex hull) of the probed points. This solves the problem of not being able to probe right at the edge of the bed and allows the final heightmap to cover the entire printable area
      • It can be up-sampled. The final heightmap point density can be higher than the sample density! This leaves the liner interpolation code in RRF with less guessing to do and better encodes curves in the bed surface. The script automatically tries to use up as much of the 441 points that RRF allows.
      posted in Gcode meta commands
      garethkyundefined
      garethky
    • RE: Slow/Unreliable SPI Communication when Logging with M929??

      I switched to a SanDisk Extreme 128GB card and that totally cleared up the issue. This is one that I use for recording 4K video.

      The card I had before was a Kingston 16GB card I got with the Pi.

      I'm happy that I figured out a way around this, but I'm surprised that the async/await programming constructs don't protect us from I/O flakiness!

      • The file is wrapped in a StreamWriter that should have a 4K buffer
      • The whole call chain is async/await. Log writing doesn't have to complete before the next GCode instruction executes (at least from what I can read without debugging it).

      I was going to suggest keeping a queue of logging data and writing it on a separate dedicated thread for I/O. But StreamWriter is basically that. (the only difference being that the log time can be captured without trying to lock the file)

      So yeah, not sure how the code should change. But if you are having problems, get a FAST SD card.

      posted in DSF Development
      garethkyundefined
      garethky
    • RE: Resonance, spreadCycle and stealthChop

      So the StepperOnline 17HS19-2004S1, I'll admit I was skeptical. It doesn't sound any quieter in Stealth Chop mode, if anything its noisier. But in Spread Cycle, its significantly quieter and smoother than the Moons. So quiet that I think I could live with them in Spread Cycle mode in general and leave them on the printer. That's a big deal if you are on the Duet 2 and don't have access to Stealth Chop.

      The other big difference is the low frequency rumble is greatly reduced.

      I don't know why any of this is so?

      The moons are 1.04 Ohm and 2.2mH
      The Stepper Online motor is 1.4Ohm and 3.0mH

      posted in Tuning and tweaking
      garethkyundefined
      garethky
    • Wait for passive thermistor temprature to stabilize

      Do you have a passively heated chamber? Maybe one of those thick Rail Core beds with the secondary thermistor on top? Wouldn't it be cool if you could wait for that temperature to stabilize before starting your print?

      I'm talking about something like this:
      Screen Shot 2021-01-29 at 10.25.26 AM.png
      Top Bed Temp takes ~6 minutes to stabilize after the bed reaches temperature. That's going to cause the bed to change shape as it heats through, possibly messing up the mesh bed leveling. Also the temperature or the print surface is supposed to be 90 degrees, but at the point when the bed heater reports that it has heated its barely 60.

      The trouble is generally we don't know what temperature we are waiting for. There is going to be some thermal loss and the temperature will change with the environment's temperature, airflow etc. Really we don't care about the exact value, we just want to know its not changing before printing. So instead of a fixed temp, we can look at the rate of change of the temperature (delta T) and wait for this to fall below some desired value.

      ; wait for the top bed sensor to stabilize
      G10 L2 P9 Y0 ; keep the loop counter here because it can't be used in sub-expressions
      while true
          ; Store the current temperature reading from the Top Bed thermistor:
          G10 L2 P9 X{sensors.analog[5].lastReading}
          
          ; Dwell for 500ms
          G4 P500
          
          ; if the temperature increase is less than 0.01 C over that time break the loop
          if {sensors.analog[5].lastReading - move.axes[0].workplaceOffsets[8]} < 0.01
              echo "Top of bed temperature stabilized at ", sensors.analog[5].lastReading, "C in ", move.axes[1].workplaceOffsets[8] / 2, " seconds"
              break
          
          ; if 5 minutes has passed abort with an error
          if {{move.axes[1].workplaceOffsets[8] / 2} > {5 * 60}}:
              abort "Bed temp stabilization failed after 5 minutes"
      
          ; increment the loop counter
          G10 L2 P9 Y{move.axes[1].workplaceOffsets[8] + 1}
      

      (source in my printer repo)

      When the temperature stabilizes it prints a message to the console:

      Top of bed temperature stabilized at 74.865C in 18.5 seconds
      

      The script will wait for up to 5 minutes before it gives up. You can extend the waiting time, the sensing interval and the threshold to suit your application. With variables it will become possible to do a better job by saving more temperature history, but this works OK for now.

      Even without variables I still need to store the loop counter and the last temperature reading. I'm using workplace offsets 9 as my temporary variable storage area. Be careful this doesn't conflict with with your printer's configuration.

      posted in Gcode meta commands
      garethkyundefined
      garethky
    • RE: Request for Filament Tweaks

      @chrishamm awesome! I will make both PRs. I don't think its very complicated at all, and from what I read in the C code there wont be any side effects. It doesn't cause a memory leak or anything like that.

      posted in Firmware wishlist
      garethkyundefined
      garethky
    • RE: Resonance, spreadCycle and stealthChop

      +1. I have the same issue with my E3D Toolchanger. I have changed over to 0.9 degree motors and that helped a lot but it did not entirely go away. I have the same vibration problem you are talking about and the community has noticed the same as well. Similar speeds as you demonstrated too.

      Going faster is smoother, switching to 0.9 degree motors is basically doubling the speed. I've also ended up with Stealth Mode being the quietest.

      posted in Tuning and tweaking
      garethkyundefined
      garethky
    • RE: load unload macro with endless loop and cancel condition

      I just did this and I deeply loath writing a macro for every filament. I'll have to go back and try G701 inside load/unload to save some extra lines that are not totally DRY. Here is what I did:

      each filament has a config that defines some variables

      ; set filament name, temperature and speed "variables"
      M563 P5 S"PLA"
      G10 P5 X215 Y300
      
      ; set retraction parameters
      M207 S0.4 F2100
      

      When I make a new filament, this is a bsically all I have to do now.

      Then load.g and unload.g just load up those variables and call a macro (this is where I need to try M703):

      M98 P"/filaments/PLA/config.g" ; the filament config isn't loaded until AFTER this macro runs, but we need the variables set now.
      M98 P"/macros/Filament/loadFilament.g"
      

      Then my load macro looks like this:

      ; loadFilament.g
      
      ; ask the user if they really want to light up the heater and load some filament
      M291 S3 P{"Click OK to heat to " ^ tools[5].offsets[0] ^ "C and load " ^ tools[5].name} R{"Load " ^ tools[5].name ^ "?"}
      
      ; Set current the configured temperature and wait for the extruder to reach temp
      M109 S{tools[5].offsets[0]}
      
      ; Pause and ask the user to position the filament for feeding
      M291 S2 P{"Load filament in the extruder and click OK to start loading " ^ tools[5].name} R{"Ready to Load " ^ tools[5].name} 
      
      M83 ; Extruder to relative mode
      
      ; rapidly feed filament from the gears to the bottom of the heat break
      G1 E58 F900 ; Feed 58mm of filament at 15mm/s
      G1 E30 F300 ; Feed 30mm of filament slowly
      
      ; purge and ask for more loop
      while true
          G1 E30 F300 ; Feed 30mm of filament slowly
          M400; Wait for moves to complete
      
          ; ask the user if they want to do that again?
          M291 S3 P{"Click OK to purge some more"} R{"Continue purging?"}
      

      So it asks put the temps and the filament name in all the messages. Plus it has a loop to purge more plastic and you can keep doing that as long as you want. (See the whole commit on github)

      When variables are implemented this will become so much less ugly.

      My next challenge is finding a way to check, at print start, if the filament/tool pairings in the print match the filaments configured on the tools in in the printer and abort if they don't 😔

      posted in Gcode meta commands
      garethkyundefined
      garethky
    • RE: Request for Filament Tweaks

      No one replied and I'm not keen on wasting my time building and testing a change that the maintainers will not accept because it conflicts with your future plans for the software.

      Going by whats written there: https://duet3d.dozuki.com/Wiki/Filaments#Section_Loading_filaments

      ". You can only load one filament at once. The current filament mechanism is intended to reflect your spools and the underlying mechanism will be likely enhanced to include some usage statistics as well."

      My PR would be to expressly remove this idea. If you want to track filament usage per-spool then you should add that as a separate feature for spool tracking. I don't think the two ideas are incompatible, If you add spool tracking as an extension to filaments you can make the individual spool the thing that can only be loaded into 1 extruder. But we don't have that yet, and even if we did, I don't see why I would copy my filament config for every spool of filament that I buy. Nor would I want the filament selection menu cluttered with dozens of spools of filament. Config for a filament type and tracking data for an individual spool are two different concepts.

      You can keep a file for spools in the filament directory with per-spool statistics. Making a new spool of PETG wouldn't require copying a filament, its just a new line in the stats file. After you select a filament you can then, optionally, select an individual spool if you want to do spool tracking. This de-clutters the main selection menu.

      Can I get a response so I can move forward on this @dc42 or @chrishamm?

      posted in Firmware wishlist
      garethkyundefined
      garethky
    • RE: Resonance, spreadCycle and stealthChop

      @matt3o I do mean Stealth Chop, I don't really have numbers. One of the frustrations here is not having the right measuring equipment to really put numbers to this problem. It would be good to know the frequency of the vibration and what speed it occurs at. Certainly a deeper investigation on my part is required to get to that. I need to design a test to isolate the speed and direction where this is worst, but that would be based on my subjective judgement without a way to do measurements.

      I think this deep dive is way better than anything I could do.

      Here are my own wild theories:

      • Its the grease in the linear rails: at the speeds where we run these printers an oil may be more appropriate. We may just be experiencing the speed where the grease causes the most stiction. I plan to disassemble and clean my bearings and replace the grease with PTFE oil. (mine are Hiwin so its unlikely to be a quality issue)
      • It is some unavoidable frame resonance. Damping the frame may help with this.
      • Its something in the way the steppers are driven. I don't even know where to begin here. The carriage is basically on the end of 2 springs (the belts) which allow it to vibrate. Steppers don't perform continuous velocity movements, every microstep has an acceleration and deceleration phase. At some step frequency these cause a constructive resonance in the carriage.
        • Maybe running the stepper pulses out of phase to try and eliminate the constructive interference. Maybe this is what M593 is attempting to do?
        • Maybe we can try a tuned mass damper on the carriage to soak up the vibrations?

      I'm pretty sure using true servo motors would eliminate this issue but I haven't found any Nema17 servos that I could try that out with.

      posted in Tuning and tweaking
      garethkyundefined
      garethky
    • RE: "Virtual Axis" break stall detection?

      @jay_s_uk Thank you for the suggestion!

      For my machine I think this will work, I have 4 tools and 4 axes, what are the odds? 😁

      Sorry if I'm being very pedantic beyond this point, I'm documenting how it works for the next person that wants to try it out:

      To make accessing the values easy I'm storing all of a tool's properties in a single axis, so X=Tool 0, Y=Tool 1, Z=Tool 2 and C=Tool 3. Lets say I want to record the nozzle diameter for each tool, that would looks like this:

      ; store tool nozzle diameters in coordinate system 5
      G10 L2 P5 X0.4 Y0.6 Z0.4 C0.8
      

      Then the object model makes retrieving the values by tool painless because the axes are in an array:

      echo "Current tool nozzle diameter is: ", {move.axes[state.currentTool].workplaceOffsets[4]}, "mm"
      

      You get from G10 L2 P2 to G10 L2 P9 to store stuff in, enough for 8 per-tool properties. G10 L2 P1 is G54 so that's already in use.

      For me its a drop in replacement for the axis hack and likely to be supported long term. If your machine has more tools than axes this wouldn't work out quite as well for you.

      posted in Gcode meta commands
      garethkyundefined
      garethky
    • Slow/Unreliable SPI Communication when Logging with M929??

      I've been running a rather long macro from the SBC and found that it cannot complete reliably. I get various symptoms and errors:

      • The printer pauses or hesitates between moves for approx. 0.25 to 2 second
        • Pauses are more frequent if the expression language is used, particularly loops
      • Warning that the Macro has not completed in 3000ms (the macro takes 3+ minutes to run, but I don't always get this error, so its no the total macro runtime its complaining about)
      • Warning: Controller has been reset - macro execution stops and I have to reset the machine

      What Hardware and Software?

      Duet 3 and Raspberry Pi 3B+ running 3.2 final

      What debugging steps have been taken?

      In order:

      • Re-worked my macro to remove all scripting and expressions so its plain GCode (eliminates parsing weirdness on the SBC as root cause)
      • Switch to Ethernet on the SBC, disabled WiFi
      • Switched SBC power to an external power adapter, removed the 5v -> SBC jumper
      • Checked that there is no SD card in the Duet
      • Tried the following config changes in DCS suggested here: https://github.com/Duet3D/DuetSoftwareFramework/issues/137
        • Raised the SPI frequency to 16Mhz
        • Dropped the poll interval to 5ms
        • Increased buffered macro codes to 32
      • Moving the Pi board and ribbon cable as far away from any other wiring as is practical in case its interference
      • Disable logging in the script by commenting out the M929 S3 P"/sys/bed-sample.log" line

      Results

      Increasing the SPI frequency and lowering the poll interval had a positive impact. This resulted in noticeably snappier macro execution. But the intermittent complete stalls remained and the Warning: Controller has been reset still happened.

      Turning off the logging command in the macro seems to have eliminated the stall problem. My wild guess in that DCS blocks to perform logging file I/O and this causes an SPI stall but I haven't looked at the DCS code to check. Since I need this on to capture the probing data for Python to process I cant accept turning this off as a solution (unless you know another way to get data out of the duet reliably).

      Possible Next Steps

      • Try a very fast SD card to see if the faster I/O speed helps
      • Try raising the logging level from Info to Error and then log all data as 'Error' on the theory that this would have less overhead somehow
      • Try a Pi4 on the theory that more CPU might help.

      M122

      I got one right before a reset 😁 SPI Shows some disconnects have occurred and there appears to be an underun logged on the Duet (if I'm reading that correctly).

      1/19/2021, 1:06:45 PM	Warning: Controller has been reset
      1/19/2021, 1:06:33 PM	M122
      === Diagnostics ===
      RepRapFirmware for Duet 3 MB6HC version 3.2 running on Duet 3 MB6HC v0.6 or 1.0 (SBC mode)
      Board ID: 08DJM-956L2-G43S4-6JTD4-3SS6K-TA7AH
      Used output buffers: 1 of 40 (16 max)
      === RTOS ===
      Static ram: 149788
      Dynamic ram: 65312 of which 76 recycled
      Never used RAM 143656, free system stack 122 words
      Tasks: Linux(ready,87) HEAT(blocked,296) CanReceiv(blocked,834) CanSender(blocked,344) CanClock(blocked,352) TMC(blocked,19) MAIN(running,1120) IDLE(ready,19)
      Owned mutexes: Telnet(MAIN)
      === Platform ===
      Last reset 00:26:13 ago, cause: software
      Last software reset at 2021-01-19 12:40, reason: User, none spinning, available RAM 143620, slot 0
      Software reset code 0x0012 HFSR 0x00000000 CFSR 0x00000000 ICSR 0x0044a000 BFAR 0x00000000 SP 0x00000000 Task Linu Freestk 0 n/a
      Error status: 0x00
      Aux0 errors 0,0,0
      Aux1 errors 0,0,0
      MCU temperature: min 44.5, current 46.4, max 46.7
      Supply voltage: min 24.2, current 24.3, max 24.3, under voltage events: 0, over voltage events: 0, power good: yes
      12V rail voltage: min 12.2, current 12.2, max 12.3, under voltage events: 0
      Driver 0: position 56774, standstill, reads 48573, writes 8 timeouts 0, SG min/max 0/1023
      Driver 1: position 48723, standstill, reads 48573, writes 8 timeouts 0, SG min/max 0/1023
      Driver 2: position 1600, standstill, reads 48573, writes 8 timeouts 0, SG min/max 0/1023
      Driver 3: position 24800, standstill, reads 48578, writes 2 timeouts 0, SG min/max not available
      Driver 4: position 0, standstill, reads 48581, writes 0 timeouts 0, SG min/max not available
      Driver 5: position 0, standstill, reads 48581, writes 0 timeouts 0, SG min/max not available
      Date/time: 2021-01-19 13:06:32
      Slowest loop: 2882.45ms; fastest: 0.04ms
      === Storage ===
      Free file entries: 10
      SD card 0 not detected, interface speed: 37.5MBytes/sec
      SD card longest read time 0.0ms, write time 0.0ms, max retries 0
      === Move ===
      DMs created 125, maxWait 446431ms, bed compensation in use: none, comp offset 0.000
      === MainDDARing ===
      Scheduled moves 1506, completed moves 1506, hiccups 0, stepErrors 0, LaErrors 0, Underruns [0, 0, 3], CDDA state -1
      === AuxDDARing ===
      Scheduled moves 0, completed moves 0, hiccups 0, stepErrors 0, LaErrors 0, Underruns [0, 0, 0], CDDA state -1
      === Heat ===
      Bed heaters = 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1, chamberHeaters = -1 -1 -1 -1
      === GCodes ===
      Segments left: 0
      Movement lock held by HTTP
      HTTP* is idle in state(s) 45 0, running macro
      Telnet* is doing "M122" in state(s) 0
      File is idle in state(s) 0
      USB is idle in state(s) 0
      Aux is idle in state(s) 0
      Trigger* is idle in state(s) 0
      Queue is idle in state(s) 0
      LCD is idle in state(s) 0
      SBC is idle in state(s) 0
      Daemon is idle in state(s) 0 0, running macro
      Aux2 is idle in state(s) 0
      Autopause is idle in state(s) 0
      Code queue is empty.
      === CAN ===
      Messages queued 6765, send timeouts 0, received 17182, lost 0, longest wait 1ms for reply type 6013, free buffers 48
      === SBC interface ===
      State: 4, failed transfers: 0
      Last transfer: 1ms ago
      RX/TX seq numbers: 8122/8122
      SPI underruns 0, overruns 0
      Number of disconnects: 2, IAP RAM available 0x2c884
      Buffer RX/TX: 1416/112-4088
      === Duet Control Server ===
      Duet Control Server v3.2.0
      HTTP:
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: M118 L1 S"Bed probe location: X:236.872 Y:8.128"
      Buffered code: G1 X236.872 Y20.128 F9000
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: M118 L1 S"Bed probe location: X:196.872 Y:8.128"
      Buffered code: G1 X196.872 Y20.128 F9000
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: M118 L1 S"Bed probe location: X:170.0 Y:8.128"
      Buffered code: G1 X170.0 Y20.128 F9000
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: M118 L1 S"Bed probe location: X:130.0 Y:8.128"
      Buffered code: G1 X130.0 Y20.128 F9000
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: M118 L1 S"Bed probe location: X:103.128 Y:8.128"
      Buffered code: G1 X103.128 Y20.128 F9000
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      Buffered code: G30 S-1
      Buffered code: G1 Z1 F252
      ==> 1420 bytes
      Executing macro 0:/macros/mesh-bed-leveling/mesh-bed-probe.g, started by M98 P"0:/macros/mesh-bed-leveling/mesh-bed-probe.g"
      > Next stack level
      Code buffer space: 2696
      Configured SPI speed: 16000000 Hz
      Full transfers per second: 78.97
      Maximum length of RX/TX data transfers: 3669/1548
      ok
      1/19/2021, 1:05:45 PM	Connected to duet3
      
      gtjoseph created this issue in Duet3D/DuetSoftwareFramework

      closed DCS 2.2.0: Can't keep up at 150mm/sec print speeds even with 16MHz SPI speed #137

      posted in DSF Development
      garethkyundefined
      garethky
    • RE: Resonance, spreadCycle and stealthChop

      @matt3o said in Resonance, spreadCycle and stealthChop:

      @garethky I mean proper stepper drivers... not the 1-chip-embedded drives like trinamic. Gecko drives come to mind ( https://www.geckodrive.com/gr214v-bulletproof-high-resolution-stepper-drive.html ), but there are dozens of them.

      I don't know, maybe? There are a lot of alternatives on the way to servos: better drivers, "better steppers", closed loop steppers etc. I could spend time and money trying all of those out or I could skip straight to the end game and get a conclusive answer.

      My vibration/noise happens at constant speeds in long moves. I don't think that focusing on the Acceleration/Jerk/Jounce will fix that. My bet is the motor's physical design has to change to enable smoother operation.

      posted in Tuning and tweaking
      garethkyundefined
      garethky
    • RE: "Virtual Axis" break stall detection?

      This is really turning out to be the right answer. One of the benefits of using the work offsets is that they are one of the few things that can be stored with M500!

      (I thought I could store things from the object model by exploiting M28/M29. But no expressions between those commands gets evaluated, so you can't store the result of an expression.)

      So I explained above how to store things by writing gcode to a file you run on startup. But what if you want to store something in the work offsets during operation of the printer? You have a tool number, say 2, and you need to write a gcode expression with an axis letter, G10 L2 P5 Z.... How do you get that Z?

      Well, you can write an if block to do that but that code is pretty long and you wouldn't want that cluttering up your all your macros. So I wrapped that up into macro itself so I can re-use it everywhere I need to store something. The trick is we don't have a way to pass variables into macros yet. So I just write the tool #, value to store and desired coordinate system index into coordinate system #9. Basically coordinate system #9 is now the stack for my program:

      ; copy_var.g
      ;
      ; this macro copies a variable from the temporary variable slot and stores it in the requested slot for the specified tool:
      ;
      ; How To use:
      ;
      ;     G10 L2 P9 X{state.currentTool} Y{value_to_store} Z{target_coordinate_system_index}
      ;     M98 P"/macros/scripts/copy_var.g"
      ;
      ; Inputs:
      ;
      ; move.axes[0].workplaceOffsets[8] - tool number to store the value for
      ; move.axes[1].workplaceOffsets[8] - the value to store
      ; move.axes[2].workplaceOffsets[8] - the coordinate system number to store it in
      
      if move.axes[0].workplaceOffsets[8] == 0
         G10 L2 P{floor(move.axes[2].workplaceOffsets[8])} X{move.axes[1].workplaceOffsets[8]}
      elif move.axes[0].workplaceOffsets[8] == 1
         G10 L2 P{floor(move.axes[2].workplaceOffsets[8])} Y{move.axes[1].workplaceOffsets[8]}
      elif move.axes[0].workplaceOffsets[8] == 2
         G10 L2 P{floor(move.axes[2].workplaceOffsets[8])} Z{move.axes[1].workplaceOffsets[8]}
      elif move.axes[0].workplaceOffsets[8] == 3
         G10 L2 P{floor(move.axes[2].workplaceOffsets[8])} C{move.axes[1].workplaceOffsets[8]}
      else
         abort   ; if you pass -1 you call at the wrong time!
      

      Now that is solved I can combine it with M500 and I give you per-tool baby stepping adjustment that persists between reboots:

      call this in tfreeN.g

      ; save_babystep.g
      
      ; writes the baby stepping value into the work offset 7 and then stores it with M500
      G10 L2 P9 X{state.currentTool} Y{move.axes[2].babystep} Z6
      M98 P"/macros/scripts/copy_var.g"
      M500
      

      and call this in tpostN.g

      ; restore_babystep.g
      
      ; restore the absolute babystepping value from its storage slot
      M290 R0 S{move.axes[state.currentTool].workplaceOffsets[5]}
      

      Then call M501 at startup before you write any config values as described in the post above.

      alt text

      😸 🍻

      posted in Gcode meta commands
      garethkyundefined
      garethky
    • RE: [DSF Extension] Exec On MCode (was: Shutdown SBC)

      @oozeBot said in [DSF Extension] Exec On MCode (was: Shutdown SBC):

      @wilriker Thanks. So the return is echo'ed in DWC, correct? Could the return value be evaluated within conditional gCode?

      I was thinking about this today. Currently there are no variables so there is nothing to write the result back to. (there is a result int from the last code but it can't contain other data types) I think we might have to wait for variables and then we could write the value back to a global.

      When that happens... it should be possible to set up an MCode that stores and retrieves values from a file on the SD card. So we could do what M500 does but with key/value semantics of M409:

      M7500 K"some.key" V"The value"
      M7500 K"some.other.key" V0.05
      

      and then get them back in a global with:

      M7500 K"some.key"
      echo {global.M7500_value}    ; or whatever you want to name it!
      

      and stored on disk as JSON:

      "some": {
          "key": "The Value"
          "other": {
              "key": 0.05
          }
      }
      
      posted in DSF Development
      garethkyundefined
      garethky
    • RE: Resonance, spreadCycle and stealthChop

      Yep, I was doing it wrong! @DC42 to the rescue:

      https://forum.duet3d.com/topic/16297/help-needed-with-duet-3-6hc-tmc5160-stealthchop-config/64?_=1612995436610

      So we need to kill the motor power with M18, then make a tiny move.

      So now I get real tuning values in my logs!! 😮

      # (log truncated to make it easy to read)
      Drive 0 pwmScaleSum 22, pwmScaleAuto 0, pwmOfsAuto 23, pwmGradAuto 22, pos 632
      Drive 1 pwmScaleSum 23, pwmScaleAuto 0, pwmOfsAuto 27, pwmGradAuto 19, pos 600
      

      And I can hear the difference! My 55mm/second resonance is gone. Its not gone at every step frequency but its an improvement. @matt3o do you have something like this in your homing script??

      posted in Tuning and tweaking
      garethkyundefined
      garethky
    • RE: Manual Grid Mesh Levelling

      If you are running a Duet 3 with the SBC, I have released an automated way to probe around the magnets and still get a valid heightmap:
      https://forum.duet3d.com/topic/21213/rrf-mesh-level-custom-mesh-bed-probing-with-python?_=1611770964248

      posted in Duet Hardware and wiring
      garethkyundefined
      garethky
    • RE: Wait for passive thermistor temprature to stabilize

      This is not intended to run an active heater. This is for passively heated scenarios where an actively controlled heater is running at a constant temperature. Its usually the bed heater. So overshoot shouldn't be a concern here because the active heat source is being controlled. Does that make sense?

      It takes a temperature delta between now and 500ms ago. It will break if the delta is negative or smaller than the threshold value.

      The 500ms gap between samples is a substitute for sample smoothing. There might be momentary fluctuations or noise but over 500ms that should be dominated by real temperature change. Its crude but its works for this specific scenario.

      posted in Gcode meta commands
      garethkyundefined
      garethky
    • RE: Resonance, spreadCycle and stealthChop

      @matt3o said in Resonance, spreadCycle and stealthChop:

      I read your interesting report and it's exactly my experience. In real life printing I can't use switching from stealth to spread, jolts and lost steps... it's a nightmare. At "high" speed stealth is not usable, not just for the noise but it loses steps. Unfortunately that happens already at around 130mm/s (with my motors).

      So honestly I don't know what else to do apart throwing more money into motors or trying a corexyuv.

      Long story short, I don't think this is an issue that can be solved with stealthchop

      Agreed. I'm happy that I got it to work but unhappy with being limited to 150mm/sec. I'd like to see 300 max when loaded with a tool and maybe 500 when no tool is loaded.

      I'm going to try the 1.8 degree 2 Amp steppers that the Voron community are recommending. But that is the last stepper I'm going to mess with. Seeing the StealthChop results we know its not the mechanical system that's at fault.

      posted in Tuning and tweaking
      garethkyundefined
      garethky