Skip to content

Technical Notes

Jim Heaney edited this page Jan 16, 2023 · 2 revisions

Detailed Description

Click to Expand

I was sick of trying to guess how much filament I had left on my 3D printer, so I designed a scale that integrates directly with the spool holder!

This is the SpoolScale, an open-source 3D printer accessory that allows you to monitor how much filament you have on your 3D printer. I've had this idea kicking around in my head since I built my first printer almost 10 years ago. Since then a lot of printers have started integrating protections to detect if you run out of filament mid-print, but mid-print spool swaps are still a pain, increase the risk of a print failure, and can result in a print partially in the wrong color. With the SpoolScale, you know how much filament is on your printer before you even start the print! The SpoolScale is compatible with every 3D printer. It can read any arrangement of Wheatstone bridge loadcells to measure filament weight, allowing it to be integrated into nearly any spool holder design. In addition to the Artillery Sidewinder design pictured above, I am working on reference designs for Monoprice, Prusa, and Ender 3D printers. The SpoolScale can be operated independently of the printer's electronics but you unlock much more functionality when you connect the SpoolScale to the 3D printer's motherboard.

If integrated with the 3D printer's electronics, the SpoolScale has two additional modes of operation. The first of these is a GPIO toggle, where you can use an M42 or similar G-code command to turn on and off the SpoolScale's screen as desired mid-print. I use this to turn off the screen as the printer is moving/printing, since the extra pull on the filament from the extruder makes the SpoolScale readings inaccurate. The end G-code then runs another M42 to turn it back on when the print is done. This same functionality can be used to selectively dim or flash the screen of the SpoolScale. For more advanced motherboards, the SpoolScale can be interfaced with as an i2C slave. This allows for much more functionality and even the integration of logic into the setup. Some examples of this include automatically setting the empty spool weight based on what material the file was sliced with, or flashing a warning on the printer's screen if there is not sufficient filament to start a print.

The SpoolScale has some other handy features as well. The first of these is a 1 amp sink output that will automatically trigger when the filament remaining drops below some critical value. This could, for example, be tied to a buzzer, LED indicator, or Arduino (although the i2C interface is more versatile for that last one) to act as a warning that a machine is low on filament. There are also 2 terminals to connect an optional resistive element to control the brightness of the screen. This can be a standard resistor to set a fixed brightness, a potentiometer to dim the screen as desired, or a photoresistor to automatically brighten the screen to make it easier to read when there is light is shining on it, or turn the display fully off if you turn off the lights in the room.

The SpoolScale can be fully configured and calibrated using just a single known weight (by default an empty spool). Settings can be configured on this version using DIP switches on the back, however, I am also working on a 2nd revision that'll instead have an RJ11 port to connect an external keypadThis'd also allow for you to save presets, to quickly swap between spool styles.

Functional Breakdown

Click to Expand

The SpoolScale is composed of 3 main components; the scale, the screen, and the controller.

The scale, which actually handles measuring the amount of filament on the printer, is accomplished using basic Wheatstone load cells and an HX711 amplifier. Only the HX711 is integrated into the SpoolScale, allowing the load cell style and quantity to be determined on a per-application basis. For instance, reference designs for desktop 3D printers may only require 1 1kg load cell, whereas larger machines may require multiple 10kg load cells.

The screen is what displays the filament weight. It is comprised of a 4-digit, 7+1 segment display. This display is then driven by a TM1616, offloading most of the work of controlling the screen from the resource-strapped microcontroller. The TM1616 also handles brightness control with constant-current control of the display.

The controller at the heart of the SpoolScale is an 8-bit AtTiny microcontroller. This low-cost, low-power microcontroller ties together the scale, the display driver, and the miscellaneous inputs/outputs, such as the settings keypad and the warning lights. The AtTiny can be programmed using a simple USB-TTL converter and the MegaTinyCore for Arduino.

Design Concepts

Click to Expand

As mentioned above, one of the main goals of the SpoolScale was to be machine-agnostic. This meant designing the SpoolScale to somehow integrate in a standard way with any 3D printer. In addition, the system had to be designed to be compact and mostly self-contained, so that it could fit into any sized 3D printer.

From the get-go, this was intended to be an open-source project. Keeping this in mind, I took steps to use widely-known hobbyist components. These had the added benefit of being well-documented and with open-source library support. I also originally planned to try and make the system hand-assemblable, although limitations from the chip shortage made that difficult. I am hoping to make future iterations easy to solder by hand, if so desired.

Calibration and Filtering

One of the biggest challenges that faces a system like the SpoolScale is dealing with converting the erratic inputs from the load cells into smooth, reliable, repeatable weight data. Measuring the weight of an object, especially over extended periods and as it might be moving/being pulled on/etc. turns out to be quite the challenge.

Calibration

Click to Expand

The easiest of these challenges is calibration. To calibrate a load cell, all you need is a known weight. Place the known weight on the load cell, measure the output of the load cell, do some division, and you'll get a grams-per-millivolt conversion factor to apply to the load cell's output. Since the load cell has a linear (plus or minus around 0.05%) relationship between strain and voltage output, you can then use this conversion factor for any weight within the load cell's rated range. So to calibrate the SpoolScale you simply tell it the weight of an empty spool (which is needed to offset the weight anyway), put an empty spool on, and voila!

The issue, though, is that load cells are temperamental and very sensitive. That grams-per-millivolt conversion only holds true in those specific conditions. The temperature, humidity, breeze, and even whether there is sunlight shining through the window or not can all cause shifts in a load cell's readings. In testing, ambient conditions caused no more than 10 grams of drift in readings. Considering I wanted the entire system to be closer to a 5-gram accuracy and ambient conditions were one of the lesser sources of error, this was a big deal. This effect, paired with other anomalies in load cells, is generally referred to as drift.

Drift can be fixed by regularly re-calibrating the system, but that is very involved and tedious. Instead, I am working on developing an automatic calibration routine. The routing will work roughly as follows:

  1. Measure the current weight of filament on the printer
  2. Wait some amount of time later
  3. Check if the amount of filament has changed by a small amount
    • If it has changed by a lot, a print must've started or something, so just restart the cycle.
  4. If the amount of filament changed by a small amount, this must've been caused by drift
  5. Run a basic version of the calibration re-calculating a grams-per-millivolt conversion using the old known weight of the filament as the reference

I'll probably implement a similar version of this that'll re-calibrate from power-down to power-up since that is a potentially long, indeterminate amount of time that the load cells were subjected to unknown ambient conditions.

The biggest downside to such an approach is that it can compound issues as time goes on, since it is basing its calibration on a weight value that it internally determined. If there was an error in calculating weight accurately in the first round of calibration, it'll continue to get further and further off with each pass of the automatic calibration. More testing will need to be carried out to see if this is a good option.

Tensioning Compensation

Click to Expand

The biggest source of error found in testing was the tension on the filament. When the extruder pulls on a spool of filament, that force is applied to the load cells, making it seem like there's more weight on the spool than there actually is. Conversely, when the printer retracts the filament, it lifts the rigid filament up off the spool slightly, making it read lighter than it actually is (although this has a significantly lower magnitude than the downward pulling force). In addition, during testing, we ran into severe issues with nearly-empty spools. As you get closer to the center of a spool of filament, the filament often will be curled from being wrapped around the core of the spool for so long. This leads to the filament acting almost like a spring, pulling down or pushing up on the load cells. In some situations, this skewed the SpoolScale's readings by up to 100 grams and usually did it in such a way as to make you think there's more filament left than there actually is. This is obviously an issue since a nearly-empty spool is when you'd want the most accurate measurements.

The biggest fix for this issue actually came from a hardware solution, completely independent of the SpoolScale or the load cells. Most 3D printers have their filament mounted above the extruder, so it is pulled down in. Routing the filament over a bar before going down to the extruder eliminated most of the pull on the spool, and what pull there still was on the load cells now was in the opposite direction, making the spool report as having less filament than it actually did, if anything.

Beyond that, there were still issues from tensioning. The first of these issues was to try and compensate for that remaining upward pull, to get a more accurate measurement of the remaining filament. This was extremely difficult to do in software though since every printer performed differently and applied different amounts of pull on the filament. The initial solution tested was to simply modify the printer's G-code to retract as much filament as possible when a print finished, releasing the tension on the spool. This would lead to issues of filament knotting or binding when printing from a nearly-full spool, though.

To fix this issue, I am working on implementing a third step to the manual calibration routine. In this third step, you load a full 1kg spool of filament into the 3D printer as you normally would. The SpoolScale can then read how much it is currently measuring, subtract that from the known 1000 grams, and get an offset factor to use to adjust for how much "pull" the extruder normally has.

As a factor of safety on top of all of this, in testing, I put a blanket -10 grams at the end of the code so that the SpoolScale would always be guaranteed to underreport the amount of filament. I may tune this or completely remove it if I can get the reading more consistent.

Filtering Jitter

Click to Expand

The last major source of "error" to account for is measurement jitter. Jitter isn't necessarily an actual error in the measurement, but rather an undesirable over-accurate measurement. While the extruder of a 3D printer consumes filament in a smooth, consistent manner, the spool is less consistent. The filament will be brought under tension until eventually this tension from the extruder overcomes the friction of the spool holder, and the spool will lurch forward, unwinding a good amount of filament. The spool will then come to a stop, now with slack in the filament for the extruder to consume. On the readout for the SpoolScale, this makes it seem like the printer uses no filament, then a bunch, then none again. The sudden slack in the line also can lift some filament up, making it look like the printer is consuming no filament, then consumes some, then un-consumes some of it.

Beyond that reverse spike, there are also jitter issues from the movement of the printer. As the printer moves around, it will slightly shake the spool. This movement can be picked up by the load cells and reported on the SpoolScale as if the spool is rapidly changing between a few different measurements, usually no more than 1-2 grams apart. This can even happen when the printer isn't moving, and just someone walking past the machine causes it to shake enough to change the reading.

While all of this is how the filament actually is used and doesn't impact the long-term accuracy of the SpoolScale however in the short-term, it can look like the SpoolScale is wildly inaccurate and bouncing all over the place. So, steps had to be taken to filter out this jitter.

The first, and easiest step to filtering, is to just take more samples and average them together, and then to wait longer between taking new measurements. In the first beta testing stages, 10 samples were taken and averaged every 100 milliseconds, which slowed down any jittering but did not eliminate it all.

The next step to filtering is to add some logic. Filament never gets added back to the spool, so it is a safe assumption to simply say "the new weight can never be more than the old weight", however, this does overlook the issue of what happens when you load a new spool. Therefore, a filtering step was added to the output that won't show any new weight that's more than what's currently shown, unless the readout first reaches 0. If it does hit 0, then assume a new spool is being loaded and let the number go in either direction for the next 10 seconds or so.

It is also important to note that this jitter control only impacts the reported output of the SpoolScale. Internally, it still works off of the true weight for things like calibration.

Clone this wiki locally