Neopixels as progress bar
-
@achrn thank you nonetheless for you input
-
@semi55 I'm in the process right now. This was a 3 day project I started over 6 months ago, so beware.
The first issue is what board you have. Some of them have support natively for NeoPixels and similar displays, but some don't have robust enough hardware to handle it, so the CPU has to do the timing work. But given a choice of the CPU working on bling vs. moving and extruding, it makes sense the latter takes precedence. So those boards (Duet 2, I think) have sending NeoPixel using M150 deferred while moves take place. Good for your print. Bad for your bling. But if you have one with actual NeoPixel-type support, that can work. But you may need a CMOS logic buffer to pull the voltage up to the 5V the NeoPixels need. And unless you have only a half dozen LEDs, you'll need a sufficiently capable 5V power supply to light them. I'd consider that almost a definite need.
I have the Duet 2 WiFi, which means I'm not one of the lucky ones. So I got an AdaFruit NeoDriver I2C NeoPixel "Driver". It's a card that your Duet communicates with via I2C protocol (use the M260 GCode), and it handles the heavy processing to manage the NeoPixel signal timing. Amazingly, AdaFruit sells it direct for $7.50. I've found it a bit clunky in that it doesn't like things like too little time between setting the color values and executing the "Show" command, so I've had to put G4 commands in between. Also I think the data is ins something like RBG order instead of RGB, or something like that.
The I2C communication is slow, so I've taken to tracking the colors of the LEDs locally, to avoid sending the data redundantly. There also can be rounding issues with converting the data you're displaying into how many LEDs to display, but it can be worked out.
My conclusion is that the web interface uses filament usage to figure percentage done; so something like this:
100 * (job.rawExtrusion)/(∑job.file.filament[extruder]〗)
These values are available from the object model. You'd replace "extruder" with a number. I'd be happy to do what I can to help. Most of what I know about this was from extensive experimentation. -
@semi55 I've been working on bed leveling display this evening. Cyan on the upper right track probe points. Lower left is a complicated overlay of a target error maximum of 0.005 and an actual error of 0.041. Tens digit on top, ones on bottom. Green for target, blue for actual. Unfortunately my phone doesn't pick up the difference between green and blue-green very well, so the bottom 5 LEDs are actually one blue-green and 4 green. Not immediately clear but you get used to reading it and it provides lots of information.
-
@DonStauffer I will be using a Duet 6XD main board with NeoPixels natively supported, and they will get 5V from an external power supply.
It sounds like a lot to consider... . Hopefully this will go somewhat smoothly with my hardware when everything else is ready as this will only be a nice to have feature on the wishlist (I am building the printer at work, so depending on other projects, there will be limited time to experiment with this).@robotsneversleep I've taken a closer look at your code and have some questions I hope you could answer.
If I understand correctly, the daemon.g runs in the background. Do I have to set the state.status in the slicer Gcode or will it automatically run every now and then when I start a print because the firmware automatically sets the state.status?
How often will the macro be executed? Could that interrupt the print?Thanks in advance!
-
@robotsneversleep Regarding your problem with small prints and not showing the correct percentage:
Maybe using the actual layer number instead of the file progress would fix this. I can't test this right now but maybe something like this (swapping job.file.size with job.file.numLayers and job.filePosition with job.layer) :var strip_number = 0 var num_leds = 12 var brightness = 255 var chunk_size = job.file.numLayers / var.num_leds var led = 0 var chunk = var.chunk_size while var.led < var.num_leds var f = var.led < (var.num_leds - 1) ? 1 : 0 if job.layer >= var.chunk M150 E{var.strip_number} P{var.brightness} F{var.f} R U255 B0 W0 S1 else M150 E{var.strip_number} P{var.brightness} F{var.f} R0 U0 B0 W0 S1 set var.chunk = var.chunk + var.chunk_size set var.led = var.led + 1
-
@semi55 IIRC using job.file.numLayers doesn't work because the layer height is determined based on the first layer only, which is problematic if the first layer is different from the rest of your model, or you're using adaptive layer height.
To answer your other questions... daemon.g is typically checked for every 10s by the firmware for existence and if it exists, it's executed.
I decided an update of the LED's every 10s is not fast enough, so put a while loop in it which is executed every 1s. The dwell (G4 S1) is there to hand control back to the firmware. You do have to be careful not to let the macro take too long to execute or it will affect printing.state.status is updated automatically by the firmware.
-
@robotsneversleep thanks for clarification, that makes sense.
Sounds quite impressive that updating the LEDs every second does not interfere with the print (from a noobs perspective).What about the following object models for calculating the true print progress:
job.file.height
job.layers[].heightThat sounds like it should use the actual Z-coordinate when printing and compare it to the objects height.
-
@semi55 I had things working reasonably well with the M150 command on my Duet 2 WiFi. It just didn't work while the motors were running, so I got the NeoDriver and used M260. But you still might need a CMOS buffer to pull up the voltage.
My macros would not be too hard to retrofit for M150 commands. All the M260 commands are run through a small group of macros. The biggest difference is M150 (native support) starts at the beginning of the strip, where M260 (NeoDriver I2C), and hence my macros, can start at an arbitrary LED number. That could require resending data just to get to the starting LED number. You also might not need my system of deferred writes, since you're not using I2C, but it would still work.
This was the culmination of my work with M150:
https://forum.duet3d.com/topic/35190/m150-with-neopixels?_=1716145163555
-
@semi55 Using height might not be an intuitive way to generate a percentage, because sometimes higher layers take much less time. That's why I intend to use filament usage.
-
@DonStauffer that also makes sense.
Thanks for your input, I will keep that in mind when starting to implement this for my future machine.