Hello;first of all thank you very much for all the effort on the load cell module.
We are now rigging the third home made 3d printer with under the bed loadcells.the first one was a Kobra 2 Neo, the second one is a homemade based on a SKR 1.4 Turbo) and they simply are perfect.The third one is based on a Manta M8P V2 and we have a lot of issues.The voltage regulator is simply made of noise,(DIAGNOSTIC simply give us no more than 20 unique values with a 40-50% of error) we have bypassed using a second MCU (an arduino nano) and it reads all the load cells without any issues (precision of 0,006%).Sample range / sensor capacity: 0.00489%
Sample range: [8.24% to 8.25%]
Good samples: 984, Saturated samples: 0, Unique values: 435
Measured samples per second: 98.4, configured: 80.0
Samples Collected: 984
Sensor reported no errors
Collecting load cell data for 10 seconds…
LOAD_CELL_diagnostic LOAD_CELL=load_cell_probeBut when it starts to probe for homing it simply does not read the tapping and gives just the RAW_RANGE error (it reach the maximum limit we have supposed, because it depends on the safety_limit)Also in the TEST_TAP mode it gives the same error.
What can be done to make more tests or solve the problem?Thank you in advance.Marco
This gives you a live plot of the force data and captures of individual probes.
You should try [LOAD_CELL_TEST_TAP](https://github.com/Klipper3d/klipper/blob/master/docs/G-Codes.md#load_cell_test_tap) before homing or probing to validate that the sensor does see taps.
If you cant see taps, turn off any drift_filter_cutoff_frequency that you cave configured. Setting this too high can cause the tap not to be detected.
LOAD_CELL_TEST_TAP doesn’t use the tap analysis, it just tests the triggering code on the MCU. So if LOAD_CELL_TEST_TAP doesn’t work and you try to home or probe, the machine will crash.
Try “tap and hold” to see if you can trigger LOAD_CELL_TEST_TAP
Also just try pushing on the build plate and make sure the graph responds to your hand.
every thing reads fine from the observableHq, reads and diagnostic is good.
I think there is an issue on the Tap/probing when connected through a second mcu.
On the Manta m8p we cannot use the main unit because there is too much voltage noise. the board is not so good to read a load cell.
If you can press on the build plate (or even put a spool of filament on it) and see the force go up to your target trigger force then you should be OK. If you cant do that then it wont work.
This does work with secondary MCUs. Maybe check what firmware version you have flashed on the separate MCU and make sure it all matches? (although I would expect it to fail if the command wasn’t on the MCU.)
The Sovol SV06 Ace uses a strain gauge and the Main board has 24V in. I think Sovol used canbus for everything on the toolhead - which I think the M8p has built in.
Hi folks, I wanted to share with you that I have implemented a proper Klipper support for Fly Alps board from Mellow and ADS131M02 sensor in it. Please give it a try if you want, but of course be aware of possible bugs and such. I have tested the code with that board and their load cell, and it seems to be working. How to get it working:
I recommend flashing Katapult to simplify subsequent reflashing of the MCU. I use the following configuration:
On my particular setup, I got the following results for probe accuracy:
probe accuracy results: maximum 0.261250, minimum 0.217656, range 0.043594, average 0.239375, median 0.240547, standard deviation 0.013149
Kind of, not great, but that’s just my current test setup, in my opinion, with not very rigid toolhead mount.
@garethky I also intended to ask you, the current load_cell code runs in a constant read mode. For sensors with low sampling rate that’s probably OK, but with typical ads131m02 sampling rates that creates unnecessary load on the MCU and host when the loadcell data is not really necessary. Was that design intentional? Would you mind if I rework the code and add commands like LOAD_CELL_TRACK_FORCE TRACKING=START and LOAD_CELL_TRACK_FORCE TRACKING=STOP that will enable and disable continuous reading of the loadcell data (if it is useful on some occasions in some macros)? I have prepared the code, in principle, just did not push it to the branch yet.
Excellent work. I was sure it was doable but lack the skills to implement it.
20 years ago I ran a digital data recorder and did data analysis on the collected data. So while I’m not a programmer I can, perhaps, help you reduce the “range” you seem disappointed with.
I spent some time with the ADS131M02 datasheet (with help from Gemini AI to summarize). Here are a few suggestions to squeeze more performance out of the ADS131M02 specifically for a single full-bridge load cell:
Global-Chop Mode: Enabling GC_EN in the CFG register is highly recommended. It averages two conversions to cancel internal offset and drift, improving S/N ratio by \approx \sqrt{2} and significantly reducing thermal drift during long prints.
Hardware Tare: Instead of software subtraction, you can write the resting bridge value to the OCAL (Offset Calibration) registers. This centers the 24-bit dynamic range around the actual signal, which is helpful if using high PGA gains. The “tare” routines in the downstream code should not mind the “help”
Internal MUX Short: For calibration, switching the MUX to “Internal Short” allows the MCU to measure the ADC’s own electronic noise floor independently of the load cell’s physical noise.
DC Block Filter: Setting DCBLOCK to Fh (the slowest coefficient) helps remove slow DC drift without “eating” the force ramp during a probe event. NOTE you should implement a 3 second delay on powerup to allow this to settle. Also during calibration the user needs to make measurements quickly as a constant input force will settle to 0. Good choice for probing but limits usefulness as a “scale” (IE filament force).
Analog Filtering Strategy: Hopefully the recommended aliasing filter is on the Fly board but I’d still recommend a 82nF C0G ( Part Number: C322C823J5G5TA or similar) Cap across the input. It induces a 0.2 ms delay but should not cause issues.
Thank you for sharing it. However, and please don’t take this the wrong way, but please understand that I can run LLM-aided summarization and analysis of a datasheet myself. So, I would appreciate if you used your expertise in the field to process the LLM output yourself and only share the findings that are really applicable to the specific situation for the benefit of the whole community. For example:
To say that it is highly recommended is a bit of an exaggeration, in my opinion. It appears that global-chop mode only cancels internal ADC offsets, which are generally not a problem in our case (at least, in my view), at the expense of various issues and limitations in the sampling process, settling times between conversions, and available modes. And slight improvement in the output noise can be achieved by increasing the oversampling (and reducing the sampling rate) instead with fewer downsides.
With those limitations, I’m not even sure why would you recommend enabling it? FWIW, the suggested coefficient (1/65536, for 0xF value) has a settling time (at SETTLED>99%) of ~75 seconds (at 4kSPS) according to the datasheet, so I’m not sure where 3 seconds settling time came from.
Well, the schematics for the FlyAlps board is available. Also, the insights from the real experience as to where 82nF capacitor recommendation came from would be helpful, as the datasheet suggests 10nF (as a part of RC filter) as an antialiasing protection, for example.
This summary was written by the AI but only AFTER I spent 2 hours refining the prompts and cross checking the responses against the data sheet and my 15 years hands on experience. THEN I edited the response to remove several less validated items.
True signal noise (external and internal) is by definition random (if it’s not random it is interference). Averaging 2 measurements reduces the noise by factor of \sqrt{2} (approximately 3 dB improvement in S/N ratio). That’s why TI included it.
This one is more grounded in data analysis than hardware. As currently implemented the load cell is never used as a seismic scale. Its sole function is as a collision detector. The closer to the center of the 24 bit window the signal remains the easier it is to detect a collision. Is there a future use for continuous measurement that is of sufficient use to negate the advantages?
This one is purely experience based. Interference is NOT random but periodic. A square wave that is a close multiple of the sample rate WILL bleed through a digital filter. The capacitor value was a SWAG guess to get about 3 dB of attenuation at 1000Hz (slightly higher if the 10nF is missing from the board). The recommended 10nF is to protect from aliasing at Nyquest of the Max output sample rate with a -3dB point of 8kHz. Filtering interference between 8 and 1 kHz MAY lower the noise floor for some users in some environments and has no adverse effects on collision detection. 1000Hz was chosen to balance noise rejection and signal delay.
The same effect is achieved by increasing OSR with no practical downsides (besides lower sampling rate, of course, which is the same as with global-chop mode), if I understand correctly?
This creates an inconvenience to the user that if they don’t run quickly around the printer and PC, they’ll calibrate the sensor scale incorrectly. Notably, the current software compensation as it is implemented lacks this problem.
FWIW, I personally plan to use the sensor at ~1kSPS or even more (not the same as a signal frequency, admittedly), for uses outside of homing. And more importantly, I think the current benefit of the alps board is that it comes as a ready-to-use package without the need of ‘fiddling’ with it, even if its design is suboptimal.
That said, with the given background behind them, others may find these insights useful.
Separately, I believe there are two reasons for the actual relatively low accuracy of the probing in my setup today. The first is that the hotend mount is actually pretty flimsy, and during probing the whole toolhead visibly wiggles upon the contact with the bed, so this negatively affects the accuracy of the probing. The second one is that it seems that there is ~120 Hz noise in the sensor, probably coming from either the Alps board powerchain or from USB (something to be wary of), amplified by a high gain of the ADS.
Just FYI, we have written a driver for this family of chips and it’s already merged into Kalico:
That version supports both the 02 and 04 version. It has config for global chop. It also supports simultaneous sampling, which isn’t in Klipper yet. You can sample multiple load cells for under-bed applications, sum them, but also get the individual reading back on the host.
I’ve been working on it with @mlmcu.
I’m currently working on submitting a version to Klipper. It should be posted this week. Turns out this is the sensor on the INDX board and Bondtech asked me to kindly submit it to Klipper. That version won’t get the simultaneous sampling support, but the commands will be the same.
The ALPS board is another problem. Klipper doesn’t support alternate pin functions. So I have a fix for that:
With that you can use the work from @nefelim4ag to define a high frequency clock pin to drive it.
Sorry I haven’t been super active in this thread lately. I’ve been busy testing, designing and shipping code.
Thanks @garethky! Alas, I was not aware of that version, the only one I knew of was from @53Aries, and unfortunately, this one did not work. And FWIW, I wouldn’t be able to use Kalico version for my development either. I briefly looked at your code, and it is very similar in many regards, naturally, so I while my code could be merged into mainline Klipper (with adding other features like 4-channel support, global chop, crc validation, either right away or later), I’m not too attached to it, so I am fine either way. But if you do have time, please take a look at it, I would appreciate it.
Fortunately, this is unnecessary. For ALPS board there is a simpler fix (since TIM2 is used for hardware timer anyway), which, in combination with this, then allows one to configure clock pin as
Here is my branch with the conversion steps from the Kalico codebase to klipper:
If you want to mash this up with your code and submit it, go right ahead.
I started with @53Aries code and had to make some changes to get the protocol working. They also deserve credit.
I no longer have access to a Python 2.7 env so I can no longer run klipper in a way that would let me fully validate that this works on 2.7.
Be aware that there are implementations where the chip is fed its clock by an external oscillator chip so a clock pin isn’t required. If you want to keep your clock pin implementation I would make it optional.
This is something we wanted to test out from early on in the load cell work because we saw it in reference designs for scales. Its in there, maybe it helps someone out with a noise problem.
I tested this and I cant say that there is a lot of difference vs dropping the sample rate. If you want 500SPS, you have to raise the sample rate to 3x that to enable global chop and get the same effective sample rate. e.g. At 2000SPS + Global Chop, you get effectively 666SPS. Since that’s higher than 500, its averaging across a total of fewer samples than the 500SPS mode is.
The phrase “which is helpful if using high PGA gains” is doing a lot of heavy lifting here. It doesn’t say in what way its helpful. The only help we need is noise. What we don’t need help with is off scale readings, which I think is what its saying. The signals are too weak to go off scale even with the max PGA gain.
It was very intentional. The intention is to run them continuously so we can use the data for other things during the print. e.g. we have folks interested in detecting spaghetti, filament runout, printing on air and nozzle collisions with the print. And of course there are people using it to just track filament weight.
What id say instead is: high sample rates aren’t very useful. The 500 and 1K Hz rates are plenty fast. Increasing the sample rate increases the noise. With the final form of the load cell code low noise matters much more than sensor speed. This was the intention from the start of the project.
The only thing we need a high sample rate for is stopping the probe from crashing. The 330sps on the HX717 is enough to do this well for 10mm/s homing moves. 500 is probably the ideal sample rate. I’m getting sub-micron PROBE_ACCURACY with that rate, a lead screw Z axis and Tap Analysis.
The klipper code, as it is now, is never going to beat a microswitch because the sensors just cant sample fast enough. The rest of the code really unlocks the door for accuracy and that was the plan from 4 years ago. Focusing on high sample rates is a dead end.
The issue is the signal position VS the position in the Digital “window” 000000 to FFFFFF for 24 bit data. If a an analog gain of 128x is applied with no offset the raw signal associated with the “tare” output of the load cell can fall close to (or outside) the range of the ADC.
By including an offset to the analog PGA the tare signal is centered in the sweet spot.
When I started Data Acquisition the company I worked for had 8 bit (and a limited number of 12 bit) ADC’s. Gain and offset are HUGE considerations in that environment. We would routinely set up gain and offset such that the time history would be railed 90% of the time to get high resolution of specific events.
Conversely shortly before I retired a vendor demoed a 32 bit DAC that had NO PGA at all. Range was 0 - 10V (differential) and scale and offset happened entirely post digitization.
Agreed that its theoretically possible. We haven’t seen this be an issue in practice with our hardware. Usually the tare value is within a couple of percent of 0 on the +/- 24 bit scale. And that makes sense, the strain gauges are assembled with no per-tension and they are installed with 0 tension applied.
Maybe this could show up more with beds where you have 1 kg of load from the build plate. We just haven’t had anyone report this issue in real life, even the folks trying under bed stuff.