Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login
    1. Home
    2. tfjield
    • Profile
    • Following 0
    • Followers 0
    • Topics 11
    • Posts 82
    • Best 15
    • Controversial 0
    • Groups 0

    tfjield

    @tfjield

    20
    Reputation
    6
    Profile views
    82
    Posts
    0
    Followers
    0
    Following
    Joined Last Online
    Website fjieldcnc.com Location California

    tfjield Unfollow Follow

    Best posts made by tfjield

    • RE: Mesh Bed Compensation Capabilities

      @3dreamer

      I ended up getting my problems all sorted out. But I had to do several things:

      • Increase the supports for my bed so that it was closer to level to start with. My bed is a bit over 600 mm x 600 mm and wasn't sufficiently supported, so there was a significant sag in the middle. Now I still have some sag, but my maximum variance across the surface is 0.387 mm.
      • Fix the twist in my gantry. There was a couple degree twist along my y-axis, and due to the location of my BL Touch relative to my nozzle, just a degree resulted in a very significant height error. One degree of twist was over 0.4 mm of height error.
      • I picked a common point on one corner for my z-axis datum, my probe z offset, my bed tilt probing points, and my bed mesh compensation.
      • Performed a high resolution map (21 x 21) at temperature.
      • Modified my macros so that for every print it will do the following:
        o Verify that the axes have been homed. If not, home them.
        o Verify that the bed has been adjusted for tilt. If not, adjust it, and home z again.
        o Turn on bed mesh compensation.

      I do not like the commonly accepted approach of using the center of the bed for my z datum. I work in a field where I'm very conscious of how things fail, and I don't want my datum at what is most likely the lowest point on my bed. If, for some reason, I don't turn on bed mesh compensation and I'm zeroed at that point, them I'm likely to run into my bed as I move away from the center and screw up my print head and PEI sheet. So I want my datum at one of the highest points.

      Also, I want the corners of my bed tilt and bed mesh to be identical to my datum point, and use the same exact point for measuring the probe's z offset. In this way, it's easy for me to verify that everything is working right. My bed mesh should show zero compensation at that corner, and because I've already corrected the tilt, all four corners of the bed mesh should show almost zero compensation.

      It's been a few weeks and several km of filament since I last took a bed mesh map, and my prints are rock-solid every time, now.

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Event notifications not dismissing on multiple clients

      @chrishamm
      Even though the messages aren't dismissed with M292, once the message either times out or close is pressed somewhere, why is the event message shown again, ever? Especially if it has a timeout, it must not be that important to keep coming back.

      How do we get rid of it and keeping it from showing up over and over?

      posted in Duet Web Control
      tfjieldundefined
      tfjield
    • Scale Layer Chart by Shown Data, Only

      Currently, the layer chart scales the Y axis by all the layer times:

      27f04b1f-5a58-4690-91d0-ed264073cd05-image.png

      But when showing only the last 30 layers, the Y axis stays the same:

      52f37d32-b61b-4852-b587-5da1aee06257-image.png

      When subsequent layers are much faster than the layers before, the graph loses it's value, since all the points are clustered near the bottom.

      My request is to adjust the Y axis based on the shown data, only.

      posted in Duet Web Control wishlist
      tfjieldundefined
      tfjield
    • RE: Intermittent WiFi Connection at Startup

      @oliof @Phaedrux
      I may have found something. On a hunch, I decided to replace the SD card with a faster one, thinking that there might be some kind of race condition occurring during startup.

      The card that came with it is a SanDisk Edge 8 GB class 4. Here's a stock image of the card:
      43983426-2011-4549-a057-036e0fd23447-image.png

      I replaced it with a SanDisk Ultra.

      With the original card it would boot and connect to WiFi no more than half the time. After replacing the card, it's connected 5 out of 5 reboots. I'll continue testing, but it seems much better!

      EDIT: This is on the same AP; I've only changed the card.

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Error in Docs for M591

      @comediantf2
      This is what I put in filament-error.g so that it would work with both 3.3 and 3.4+:

      M25				; first, pause the print as pre-RRF 3.3 did
       
      if {param.D == 0}		; now call the right pre-RRF 3.4 subroutines.
      	M98 P"filament-error0.g"
      elif {param.D == 1}
      	M98 P"filament-error1.g"
      
      posted in Filament Monitor
      tfjieldundefined
      tfjield
    • RE: G-Code Meta commands: Option unset (all) globals

      @fcwilt 🤣

      posted in Firmware wishlist
      tfjieldundefined
      tfjield
    • RE: Extruders Not Obeying G1 Feed Rate

      @phaedrux Nope, just set to 100%. My long print is almost done, and I'm going to try to duplicate the problem and gather more info.

      posted in General Discussion
      tfjieldundefined
      tfjield
    • Cura gcode Save to Disk with Thumbnails

      @resam
      Per the conversation in the other thread, I was looking for a an option in Cura to save a gcode file to disk with QOI thumbnails. I took your thumbnail code from github and incorporated it into this post-processing script:

      import os
      import base64
      import traceback
      from io import StringIO
      
      from PyQt6 import QtCore
      from PyQt6.QtCore import QCoreApplication, QBuffer
      from PyQt6.QtGui import QImage
      
      from UM.Application import Application
      from UM.Logger import Logger
      from UM.Math.Matrix import Matrix
      
      from cura.Snapshot import Snapshot
      from cura.PreviewPass import PreviewPass
      
      from ..Script import Script
      from qoi import QOIEncoder
      
      
      class CreateQOIThumbnail(Script):
          def __init__(self):
              super().__init__()
              
          def render_scene(self):
              scene = Application.getInstance().getController().getScene()
              active_camera = scene.getActiveCamera()
              render_width, render_height = active_camera.getWindowSize()
              render_width = int(render_width)
              render_height = int(render_height)
              Logger.log("d", f"Found active camera with {render_width=} {render_height=}")
      
              QCoreApplication.processEvents()
      
              preview_pass = PreviewPass(render_width, render_height)
              fovy = 30
              satisfied = False
              zooms = 0
              while not satisfied and zooms < 5:
                  preview_pass.render()
                  pixel_output = preview_pass.getOutput().convertToFormat(QImage.Format.Format_ARGB32)
                  # pixel_output.save(os.path.expanduser(f"~/Downloads/foo-a-zoom-{zooms}.png"), "PNG")
      
                  min_x, max_x, min_y, max_y = Snapshot.getImageBoundaries(pixel_output)
                  size = max((max_x - min_x) / render_width, (max_y - min_y) / render_height)
                  if size > 0.5 or satisfied:
                      satisfied = True
                  else:
                      # make it big and allow for some empty space around
                      zooms += 1
                      fovy *= 0.75
                      projection_matrix = Matrix()
                      projection_matrix.setPerspective(fovy, render_width / render_height, 1, 500)
                      active_camera.setProjectionMatrix(projection_matrix)
      
                  Logger.log("d", f"Rendered thumbnail: {zooms=}, {size=}, {min_x=}, {max_x=}, {min_y=}, {max_y=}, {fovy=}")
      
              # crop to content
              pixel_output = pixel_output.copy(min_x, min_y, max_x - min_x, max_y - min_y)
              Logger.log("d", f"Cropped thumbnail to {min_x}, {min_y}, {max_x - min_x}, {max_y - min_y}.")
              # pixel_output.save(os.path.expanduser("~/Downloads/foo-b-cropped.png"), "PNG")
      
              Logger.log("d", "Successfully rendered scene.")
              return pixel_output
      
      
          def render_thumbnail(self, pixel_output, width, height):
              # scale to desired width and height
              pixel_output = pixel_output.scaled(
                  width, height,
                  aspectRatioMode=QtCore.Qt.AspectRatioMode.KeepAspectRatio,
                  transformMode=QtCore.Qt.TransformationMode.SmoothTransformation
              )
              Logger.log("d", f"Scaled thumbnail to {width=}, {height=}.")
              # pixel_output.save(os.path.expanduser("~/Downloads/foo-c-scaled.png"), "PNG")
      
              # center image within desired width and height if one dimension is too small
              if pixel_output.width() < width:
                  d = int((width - pixel_output.width()) / 2. + 0.5)
                  pixel_output = pixel_output.copy(-d, 0, width, pixel_output.height())
                  Logger.log("d", f"Centered thumbnail horizontally {d=}.")
              if pixel_output.height() < height:
                  d = int((height - pixel_output.height()) / 2. + 0.5)
                  pixel_output = pixel_output.copy(0, -d, pixel_output.width(), height)
                  Logger.log("d", f"Centered thumbnail vertically {d=}.")
              # pixel_output.save(os.path.expanduser("~/Downloads/foo-d-aspect-fixed.png"), "PNG")
      
              Logger.log("d", f"Successfully rendered {width}x{height} thumbnail.")
              return pixel_output
      
          def encode_as_qoi(self, thumbnail):
              # https://qoiformat.org/qoi-specification.pdf
              pixels = [thumbnail.pixel(x, y) for y in range(thumbnail.height()) for x in range(thumbnail.width())]
              pixels = [(unsigned_p ^ (1 << 31)) - (1 << 31) for unsigned_p in pixels]
              encoder = QOIEncoder()
              r = encoder.encode(
                  width=thumbnail.width(),
                  height=thumbnail.height(),
                  pixels=pixels,
                  alpha=thumbnail.hasAlphaChannel(),
                  linear_colorspace=False
              )
              if not r:
                  raise ValueError("image size unsupported")
              Logger.log("d", f"Successfully encoded {thumbnail.width()}x{thumbnail.height()} thumbnail in QOI format.")
      
              size = encoder.get_encoded_size()
              return encoder.get_encoded()[:size]
      
          def encode_as_png(self, thumbnail):
              buffer = QBuffer()
              buffer.open(QBuffer.ReadWrite)
              thumbnail.save(buffer, "PNG")
              buffer.close()
              return buffer.data()
      
          def generate_thumbnail(self):
              thumbnail_stream = StringIO()
              Logger.log("d", "Rendering thumbnail image...")
              try:
                  scene = self.render_scene()
      
                  # PanelDue: 480×272 (4.3" displays) or 800×480 pixels (5" and 7" displays)
                  # ref https://forum.duet3d.com/post/270550 and https://forum.duet3d.com/post/270553
                  thumbnail_sizes = [
                      (48, 48),
                      (128, 128),
                      (160, 160),
                      (256, 256),
                  ]
                  for width, height in thumbnail_sizes:
                      thumbnail = self.render_thumbnail(scene, width, height)
                      qoi_data = self.encode_as_qoi(thumbnail)
                      b64_data = base64.b64encode(qoi_data).decode('ascii')
                      b64_encoded_size = len(b64_data)
      
                      thumbnail_stream.write(f"; thumbnail_QOI begin {width}x{height} {b64_encoded_size}\n")
                      max_row_length = 78
                      for i in range(0, b64_encoded_size, max_row_length):
                          s = b64_data[i:i+max_row_length]
                          thumbnail_stream.write(f"; {s}\n")
                      thumbnail_stream.write(f"; thumbnail_QOI end\n")
      
                  Logger.log("d", "Successfully encoded thumbnails as base64 into gcode comments.")
      
                  return thumbnail_stream
              except Exception as e:
                  Logger.log("e", "failed to create snapshot: " + str(e))
                  Logger.log("e", traceback.format_stack())
                  # continue without the QOI snapshot
                  return StringIO()
                  
          def getSettingDataString(self):
              return """{
                  "name": "Create QOI Thumbnail",
                  "key": "CreateQOIThumbnail",
                  "metadata": {},
                  "version": 2,
                  "settings":
                  {
                      "enabled":
                      {
                          "label": "Enabled",
                          "description": "Enable to generate thumbnails.",
                          "type": "bool",
                          "default_value": true
                      }
                  }
              }"""
              
          def execute(self, data):
              if not self.getSettingValueByKey("enabled"):
                  return data;
          
              snapshot = self.generate_thumbnail()
              if snapshot:
      
                  for layer in data:
                      layer_index = data.index(layer)
                      lines = data[layer_index].split("\n")
                      for line in lines:
                          if line.startswith(";Generated with Cura"):
                              Logger.log("d", "Found appropriate place in gcode file.")
                              line_index = lines.index(line)
                              insert_index = line_index + 1
                              lines[insert_index:insert_index] = snapshot.getvalue()[:-1].split("\n")
                              break
      
                      final_lines = "\n".join(lines)
                      data[layer_index] = final_lines
      
              return data
      

      This is just your code, slightly edited to work as a script, and it works well for me. I should have done this up on github, but I've never created a repository there and it would take me more time to figure it out than I wanted to spend today! lol. Besides, I'm just a hack, so if you wanted to take this (or do it better) please do!

      Thanks for doing the heavy lifting!

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Extruders Not Obeying G1 Feed Rate

      @fcwilt @Phaedrux
      Just an update, I've found that the issue isn't just when there's a filament error. If I just home the machine, turn on the hot end, and then try to retract to change the filament, I often have the same issue: the extruder races to try to extract. Hitting retract again and it usually runs at the normal rate.

      When this print is done, I'll see if this happens from a cold start so it can be duplicated.

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Mesh Outside of Limits

      @fcwilt Maybe! lol. What I mean is that with G30, I can probe wherever I want. The axes limits are not obeyed. Meaning if I set a location for the probe that will move the printhead beyond the limits, it will just do it. (This behavior is warned about in the documentation.) With G29, if such a move would require the printhead to move out of limits, it gives an error. (And trying to avoid the error by using M564 S0 doesn't work. ) And like I said, it surprises me that exceeding the limits is explicitly allowed by G30, but not by G29.

      posted in General Discussion
      tfjieldundefined
      tfjield

    Latest posts made by tfjield

    • RE: Cura gcode Save to Disk with Thumbnails

      @resam Sorry for the late reply! I am no longer using RRF, so I can't test your update. Thank you for keeping me in mind, though!

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Intermittent WiFi Connection at Startup

      @Exerqtor LOL, yeah, I know... 😞 I really like RRF! This was my first time using it, and not only is it great, but the support here is top notch. Kudos to @Phaedrux and @dc42 and everyone else that contributes.

      I ended up changing because I have a rather large printer (600 x 600 x 600 mm) that I'm using to print large prototypes of something before we invest in injection molding, and I need to crank them out as fast as possible. I upgraded my hotends to Takotos (they're great!) and went to Klipper, both for the speed. At this point, I think I'm limited by the residual stress in the plastic that causes warping if I try to print any faster.

      Good luck with your problem! I'm with you, it didn't seem like hardware to me because it never dropped the connection once it got it. It was only during startup. And if I remember right, I could get it to connect again by turning the module off and on via software, but my memory here is hazy at this point... Clearing out those other SSID's made sense to me that it could have been the problem, but I really didn't run it long enough afterwards to confirm. I rarely restart my machine, so the annoyance wasn't a daily thing and it took quite a while to get any useful stats.

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Intermittent WiFi Connection at Startup

      @Exerqtor Hey! I ended up switching to Klipper soon after my last post on this issue, so I don't use the WiFi on the Duet anymore.

      But before I switched, one of the last things I did was check the WiFi networks that had been associated with my card using M587, and I found that there were a couple that were not on my network, not added by me; perhaps they were there from testing of the board or something, or maybe just corrupt memory? Anyway, I removed them all using M588 (I had to use M588 S"*" because one of the network names had weird, unprintable characters in it).
      Then I re-associated with my network and confirmed that was the only one listed via M587.

      I can't say that solved the problem, but for the last several reboots before I upgraded it was connecting OK. Do you happen to have any spurious networks listed when you issue M587?

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Mesh Bed Compensation Capabilities

      @3dreamer

      I ended up getting my problems all sorted out. But I had to do several things:

      • Increase the supports for my bed so that it was closer to level to start with. My bed is a bit over 600 mm x 600 mm and wasn't sufficiently supported, so there was a significant sag in the middle. Now I still have some sag, but my maximum variance across the surface is 0.387 mm.
      • Fix the twist in my gantry. There was a couple degree twist along my y-axis, and due to the location of my BL Touch relative to my nozzle, just a degree resulted in a very significant height error. One degree of twist was over 0.4 mm of height error.
      • I picked a common point on one corner for my z-axis datum, my probe z offset, my bed tilt probing points, and my bed mesh compensation.
      • Performed a high resolution map (21 x 21) at temperature.
      • Modified my macros so that for every print it will do the following:
        o Verify that the axes have been homed. If not, home them.
        o Verify that the bed has been adjusted for tilt. If not, adjust it, and home z again.
        o Turn on bed mesh compensation.

      I do not like the commonly accepted approach of using the center of the bed for my z datum. I work in a field where I'm very conscious of how things fail, and I don't want my datum at what is most likely the lowest point on my bed. If, for some reason, I don't turn on bed mesh compensation and I'm zeroed at that point, them I'm likely to run into my bed as I move away from the center and screw up my print head and PEI sheet. So I want my datum at one of the highest points.

      Also, I want the corners of my bed tilt and bed mesh to be identical to my datum point, and use the same exact point for measuring the probe's z offset. In this way, it's easy for me to verify that everything is working right. My bed mesh should show zero compensation at that corner, and because I've already corrected the tilt, all four corners of the bed mesh should show almost zero compensation.

      It's been a few weeks and several km of filament since I last took a bed mesh map, and my prints are rock-solid every time, now.

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: New Input Shaping plugin v3.4.1-b1

      @oliof As I had posted in another thread, I measured my frequencies and applied a shaper and measured again and it looked good. (I haven't posted my results, yet.) But when I printed a test part, the ringing was noticeably worse.

      What would this be an indication of? Damping factor too high?

      posted in Plugins for DWC and DSF
      tfjieldundefined
      tfjield
    • RE: Intermittent WiFi Connection at Startup

      @phaedrux Here are some better pictures. I tried to image near the pads on the bottom.

      d0513ec0-a96d-4d60-ba40-692b4a4e6a61-image.png
      7c30bcab-50f7-45b0-a687-0dec6e741e8b-image.png
      43854fcc-afd2-461a-9987-0d9c2fcc1aa8-image.png
      5824e79f-dc7c-45c4-a3f0-ffd53c6c8e74-image.png

      That's about the best I can do.

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Intermittent WiFi Connection at Startup

      @phaedrux Sure, I can get better photos. Anything in particular I should try to capture? Are you looking for a cold solder joint? Perhaps it would be better if I viewed it from a 45° angle...

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Intermittent WiFi Connection at Startup

      @phaedrux
      These aren't great... Is there something specific you're looking for? If so, I can try to highlight it better. And these were with a cell phone camera... If these aren't good enough, I can pull out the USB microscope.

      3e9385d7-c377-4099-97c2-7cc2206bc1ff-image.png
      3a1fa8ce-e5b0-48bb-9b83-9f24cf0dc074-image.png

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Intermittent WiFi Connection at Startup

      Well, it turns out that this was not the fix. As time went on, the number of times it would fail vs. the number of times that it would succeed has increased a lot. We're back to 50/50 or greater failure rate.

      To this day, once the WiFi is connected I have never lost connection.

      I suppose this could be a hardware problem, but it sure seems more like some kind of race condition. Is there anything I can do to help determine the root cause for the failure?

      posted in General Discussion
      tfjieldundefined
      tfjield
    • RE: Using Input Shaping. Any suggestions or advice??

      @chickenwoman said in Using Input Shaping. Any suggestions or advice??:

      @tfjield this is off topic but what wire did you use on your Modix and what length? I have a Big 60 and have tried several different types of wire and cant get it to work.

      The first time I tried I used an old, unshielded network cable and it wouldn't recognize the accelerometer. Then I went with a USB cable.

      I followed this guide:
      https://forum.duet3d.com/topic/22878/software-package-3-3beta3-released/68?_=1624809172098

      I purchased this USB cable from Amazon:
      https://smile.amazon.com/dp/B014RWATK2

      I left the cable at about 5 feet / 1.5 meters. There are two shields inside wrapped around two different pairs, and a shield around the whole thing. I attached all three shields together, and connected it to one of the ground points on the Duet boards. (I have the DueX5, so I used one of the grounds on one of the 5 endstop connectors.)

      I use a PT100 daughterboard, and the daughterboard moves CS3 and CS4 from pins 7 and 9 to pins 3 and 1, respectively. So my CS connects to pin 1 and INT connects to pin 3.

      EDIT: Here are some pics of my connection. I didn't have a dual inline plug that took crimp connections for the Duet side so I made one with the connectors that I had.

      ee0ab1d7-ee9e-43a5-97dd-b0af4d850763-image.png
      633244bf-8312-4683-bf66-d2669ced8806-image.png
      7d83f86b-879a-4fdc-9c37-005c4229cd63-image.png

      posted in General Discussion
      tfjieldundefined
      tfjield