Strain Gauge/Load Cell based Endstops

Nice work @garethky
I planed to use 4 load cell to measure belt tension with your code.
But i have one question, in a setup with multiple ADC, does each HX711 need its own separate clock pin, or can they be connected to the same one?

1 Like

Each chip needs a dedicated clock pin. The clock pin also programs the chip. The number of pulses sets the input channel and sample rate for the next reading. So you don’t want the chip’s sate being messed with due to extra clock pulses. The C code allows interrupts while the timing pin is low (this allows the MCU to do something else, like perform a microstep), so in theory you could be reading from multiple chips at once and this would results in chaos with a single clock pin.

I found a bug with the current Multiplex ADC code that doesn’t yield the best timing fidelity. Currently the chip is sampled at the frequency the chip reports samples. It also uses a clock dead reckoning scheme to save bandwidth. This results in some clock drift and in this application time is equal to z distance, so timing is critical. I got around this by aggressively over sampling the pin and changing the C code to report the whole time (32 bits) from the MCU.

If your applications doesn’t require high timing fidelity then you should be fine with the code as-is.

1 Like

Thanks for the replay.
At this point i am just gonna use them for feedback, when i am adjusting the tension om my belts, so sample rate and timing is not a problem.

I am using a rp2040 as dedicated mcu for the adc inputs.
I think i have replaced klipper with your adc_enstop branch successfully , and flashed all t mcu’s, they are all showing Version: v0.9.1-1657-g1e034386.

But there is a klipper error ā€œInternal error during connect: invalid syntax (load_cell.py, line 270)ā€
when i put the [load_cell my_scale] part in to my config, no error on the rest.

[mcu rp2040-zero]
#serial: /dev/ttyACM0 
serial: /dev/serial/by-id/usb-Klipper_rp2040_E66138935F134528-if00

[hx711 y1_adc]
sclk_pin: rp2040-zero:gpio0
dout_pin: rp2040-zero:gpio1
gain: A-128
sample_rate: 10

[load_cell y1_belt]
sensor: hx711 y1_adc
is_probe: false
counts_per_gram: 1

I may have done a Python 3 specific syntax here:

    def get_samples(self):
        return [*self._samples]

Yes, that was my problem.
After updating klippy-env to python3, it is now working, thanks again.

In a future version, any possibility that you could add an option to store the tare value in the config?
In a belt tension setup, it would be nice to se the changes over time, but that is kinda hard if the tare value resets at shutdown.

1 Like

Has anyone considered using the ADC on the pi pico?
It is 12-bit, 500kSPS. It’s cheap and you’ll need some computation to process the signal anyway. I ordered some ad620/ad623 and a 10kg load cell to test the idea.
I think it is possible to use oversampling to get 10kSPS and a bit higher resolution.

12 bits is not enough resolution. That’s 4096 values. That’s fine if you want to measure temperature to 0.5 of a degree Celsius from 0 to 500.

But we want to measure 1/10th of a gram from -5kg to +5kg. That takes at least 17bits. And that’s if the matching of the load cell to the range of the sensor is perfect. In the real world you probably need to throw away half that, so 18bits minimum.

Realistically you could only get +2kg to -2kg in 1g increments. The noise would likely be on the order of 10 to 20g. And again that’s if your load cell is perfectly matched to the voltage range that the Pi expects to see.

(Alternately you could do ±200g in 0.1g increments to enable probing. But I’m not sure how you are going to have a 200g load cell that survives 5kg extrusion forces, or laying down a kg of filament if it’s in the bed. We are kind of stuck using larger load cells due to the physical system)

I just tuned the gain of the ad620(in-amp) to the adc range of the pico. You are absolutely right. I’m getting about +1.5kg to -1.5kg with noise about 10g - 20g, with oversampling.

I can keep look into signal prosessing/denoising. But as you said, it’s just a 12-bit adc, I shouldn’t expect too much from it.

On the topic of larger loadcell, I got a 45mm squre 10kg one. It’s pretty small and I hope to integrate it to the stealth burner. Is the extrution force really that large?

It’s not unusual to have multiple noisy bits. So in a 24bit adc maybe 4 bits are noise. If you can put the quantity you are trying to measure in the noise free bits it’s fine. So essentially you try to measure a unit smaller than your display units and throw that data out.

Also, the way the Delta Sigma ADC works is by averaging at the max sample rate. So if you sample faster you get more noise.

So we need some bits to spare for noise, some to spare for mismatch of the loadcell and gain, and some sample rate to spare to combat noise. The HX717 at 24 bits and 340 SPS is likely the least capable sensor you’d want to use. 24 bits at 2khz would be better, with selectable sample rate down to ~500SPS.

Thanks. I also found this article a few days ago: adc-resolution-by-dithering-oversampling
ā€œto get n extra bits of resolution, you need to read the ADC four to the power of n times.ā€

Delta-sigma ADCs are based on the principle of oversampling, and generally cannot sample faster than 1kSPS. There’s a table in ADS1220’s datasheet: ads1220.pdf, indicating it has an Effective Number of Bits (ENOB) of 16 at 1kSPS, 3.3V. In comparison, the rp2040’s SAR ADC provides 8.7 ENOB at 500kSPS, preserving the higher-frequency data.

It appears that we may require two sensors: one for high-speed but low-resolution data and another for low sample rates with higher resolution. The former would be suitable for probing, and the latter can be used for extrusion force.

After switching to an rp2040 board with an LDO regulator (Pi Pico uses a switching 3.3V supply), the noise level is lower. The performance I measured is 814 counts per kg and a noise level of 5 counts. So the noise level is about 6g. It can measure the weight of a pair of electrical tweezers. I think rp2040 adc + in-amp can be a good enough probe. But I need some investment in signal processing.

1 Like

+1 for using two sensors. You can have one setup fitting the requirements for extrusion force and one for the z-offset. Additionally, you can limit the z-offset of the loadcell on the lower side so the extrusion force won’t push the nozzle downwards.
In my opinion, it’s best when the nozzle is not moving downwards through extruder force - a compensation through software is a janky fix in my opinion which will be prone to error.

I have put a physical stop in my print head desgin to to limit the Z-offset of the loadcell so the extrusion force can only push the nozzle downwards until it hits the stop.

Quick update: I probably wont have a new code drop out for more than a month. I’m going to sacrifice my Voron2.4 and graft a Prusa Nextruder onto it. This seems like the shortest path to getting a working toolboard and print head on a machine I know works. Parts wont be here for at least another week and I’ll need time to CAD up an appropriate adapter and reverse-engineer the pin-puts on their breakout board to wire it all up.

In the next drop I want to get:

  • Fixed up C code for reading sensors that reports microsecond accurate time
  • The pullback move in homing
  • The collision detection algorithm we have settled on
  • Support for calling a plugin to do ā€œbad tapā€ detection. Any printer developer could come up with their own way of deciding if a tap is bad this way.
  • Support for calling a macro to wipe a toolhead when a ā€œbad tapā€ is detected
  • Support for using the load cell probe as the only z endstop

Life, the universe and everything are all getting in the way of this project. I will try my best to get something together to submit to klipper by Christmas.

2 Likes

Good morning,
I have been working on the load cell for referencing my z axis since Prusa communicated on this subject. I carried out a first test by installing load cells on the X axis carriage, without much success.

I have since done another test with load cells under the plate. the result seems to be of good quality.

Today I use an Arduino Uno to exchange with the HX711. So it was while looking for a solution to put the code in Klipper that I arrived on this page.

So this is the simplest way to integrate the code into my existing Klipper?

Thanks in advance.

PS: Sorry for my English I’m French!!!

Seems like this already works. At least on my setup.

1 Like

Oh sweet, I had not tried that yet!

Guys what is the feeling on how close the ads1263 needs to be positioned to the load cell. I am using four BF350-3AA strain gauges in a bridge set up.

Ideally I would like to have the ads1263 sitting on my electroincs panel at the back of my printer rather on the print head this means I would need to run the wires form the load cells to the ads1263 would need to be about 80mm long.

I had good success using LONG twisted pair wiring. A big cap on the 5V line also helps smooth things out. That’s my test setup. Looking at commercial load cells this is pretty common.

1 Like

Many thanks

CS1237 1.28k sps
The price of this chip is cheap, is the output rate of 1.28K sps enough? For probing