Minimalist Load Cell Meter - Page 1
Forum section: electronics / projects

author: azeeman
author_rank: Regular Contributor
timestamp: September 06, 2025, 06:16:45 pm
content: Here is a surprisingly precise and extremely simple load cell meter based on an Arduino Nano. The meter can be very fast at the expense of precision and take readings at a maximum speed of 244 readings per second or with more averaging, 1.22 Hz. The meter is intended for use as a reasonably precise and if required, reasonably fast force gauge. It also demonstrates how to use signal processing techniques for signal extraction.Two digital outputs fed by a PWM with complementary outputs act as an H bridge driver giving an AC load cell output signal. One side of the load cell signal is then AC coupled to non-inverting input and the other side is DC coupled to the inverting input. This biases the AC amplifier output almost exactly in the middle of the ADC input range when the ADC is programmed to use the 5 V supply as a voltage reference. The load cell Thevenin output resistance is used as part of the inverting input feedback with another resistor.The ADC is triggered synchronously at a frequency 32 times higher than the drive frequency. Because the op-amp output is biased to the center of the ADC range, the ADC can be used as a bipolar AC detector. Also, because the ADC is perfectly synchronous with the drive waveform, a very powerful signal processing technique, synchronous detection, can be used.Synchronous detection is commonly used in lock in amplifiers and is capable of detecting signals below the noise level.When two sinusoidal frequencies are multiplied together, two frequencies result, the sum of the two frequencies and the difference of the two frequencies. If the both frequencies are exactly the same, then the difference frequency is zero or DC and the sum frequency is twice the input frequency. The DC value is a measurement of how close the two input frequencies match and the sum frequency is proportional to the mismatch. Use a low pass filter to extract the DC and exclude the sum frequency and it's now possible to easily measure how well the two signals match.One problem is that the phases of the two input frequencies have to match, the DC value will go from negative to zero to positive as the phase difference changes. To get around this problem, the input signal is multiplied by two signals at the same frequency, but with a 90 degree phase difference. This gives two vectors at 90 degrees and Pythagoras' theorem is used to calculate the hypotenuse which is directly proportional to the match between the signals.Low pass filtering is done just by averaging multiple samples. The more samples that are averaged, the narrower the filter bandwidth. The filter bandwidth is proportional to square root of the number of samples. If the number of samples is increased by 10 times, the bandwidth is reduced by the square root of 10 or 3.16. Because noise is proportional to bandwidth, the noise level also decreases as the square root of the number of samples.Rather than calculating an average, multiple ADC readings are summed together and then multiplied by sine and cosine and the hypotenuse calculated. Because the ADC output is only ten bits with a maximum value of +/-511, up to 2^31/511 = 4.2 million ADC readings can be summed together as integers in one 32 bit signed word. Because averaging divides all readings and the average reading will in turn be multiplied by a scaling factor, the division can be skipped and the scaling factor adjusted accordingly. This will save a lot of CPU cycles.In this application, the microcontroller calculates an unscaled reading value which it sends to the Python host. Because the reading has to be scaled and offset for weight calibration, there's no point in the microcontroller doing more data processing than absolutely necessary. Also, the host computer will be many orders of magnitude faster.This signal processing technique has very wide application in measuring all kinds of low level signals. The microcontroller can drive a chopper followed by a fixed gain AC amplifier with the AC amplifier output biased to be at 1/2 the ADC input range. If possible, the bias voltage should be generated using a PWM operating at a 50% duty cycle at the highest possible frequency. There are two huge advantages to using a PWM and that is any noise on the power supply is shifted up in frequency because the PWM is sampling the power supply and the divide by two ratio is essentially perfect. The only noise that will translate down to low frequencies is noise with a frequency very close to the PWM fundamental frequency. The noise power at that frequency will tend to be very low. Also, the filter capacitance required for both PWM ripple and the frequency translated noise will be very small.The RS232 is set to 115k Baud.The Python script uses Tkinter as both the GUI and thread manager using a workcell paradigm as used in industrial automation. Objects like the serial port manager, device receiver, device manager, and so on are derived from Tkinter frames and are completely independent with all functions and variables private. Workcells communicate with each other over a virtual network and each workcell runs in its own thread and maintains its own state. Workcells are derived from a transceiver object, instantiated anonymously and will automatically connect themselves to the virtual network.Tkinter event handling is only used within a workcell, interaction with other workcells is only possible by message passing over the network. The messages themselves are text with an object payload.For presentation purposes, the GUI is constructed using the Tkinter parent-child type tree. For message and event handling between workcells, all communication is peer to peer. Events place on a first in first out queue and are executed atomically to prevent race conditions.I've spent decades working with industrial automation and have found that this is by far the easiest and least error prone way for interaction between autonomous machines and between machines and humans.Having to run to mommy every time the doorbell rings is just stupid. Autonomous adult humans and autonomous machines handle their own events and internal states, and maintain their privacy.

author: ahsrabrifat
author_rank: Regular Contributor
timestamp: September 07, 2025, 09:53:27 am
content: How much will it cost to implement this project?

author: azeeman
author_rank: Regular Contributor
timestamp: September 07, 2025, 10:12:44 am
content: The cost of parts is minimal, $1 for the op-amp, another $1 for the capacitors and resistor. The Nano is about $10. The circuit is simple enough to build on a prototype board. It can be USB powered and connect to a computer.

author: gamalot
author_rank: Super Contributor
timestamp: September 07, 2025, 10:28:04 am
content: Very interesting, but if you ignore the technical specifications (because I don't see them in your description), the HX710 from 20 years ago looks simpler and cheaper.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: September 07, 2025, 10:50:40 am
content: It's good to see something that requires more thought then the HX711. The posted schematic does not list which opamp is used, but in the KiCad project in the zip file it's an MPC6002. Is that also the opamp you used?I once did some experiments with the ADC of the ATMEGA328 (or the ATMEGA8, it was a long time ago). Averaging multiple samples did not work very well, because (nearly) all samples were the same. Then I added a few lsb of noise to introduce some variation, and with that I could get around 13 bits of resolution out of it. I measured the resolution by adding a RC with a big RC constant, and then plotted the measured and averaged ADC values with the theoretical RC curve. So no fancy or expensive lab equipment needed.You could do real curve fitting, but I only did some relatively simple tests, and saw the "steps" from the first experiments disappear. You can get a good estimation of real resolution this way. I think I did see small repeating "bumps" between consecutive 10 bit samples, and this implied some inherent non-linearity with the oversampling.(Back then) Atmel also had an application note describing resolution enhancement of the ADC by adding noise and averaging:AVR121: Enhancing ADC resolution by oversamplingThis also reminds me of Milli Ohm meter as published in CircuitCellar #314. It also uses outputs of the uC to generate an AC, and synchronous detection.I like projects like this which use intelligently written software to reduce the influence of hardware limitations. Projects like this are good "intermediate" projects for people who want to dive deeper after getting bored by "arduino".How much usable resolution can you get out of this configuration? Yesterday I've been struggling again with STM32Cube and an STM32G031F6P6 "Coreboard" from WeAct, and this (quite cheap) uC (with <EUR 2 development board) has an 12 bit ADC, and the datasheet claims upto 16 bit resolution with oversampling.

author: azeeman
author_rank: Regular Contributor
timestamp: September 07, 2025, 01:09:31 pm
content: It takes very little effort and very few parts to build and test the circuit. The results may surprise you considering how simple the circuit is. The component cost is less than an HX711 which still requires a microcontroller to run it. My circuit is also much faster than the HX711, although not as precise and also not as noisy. The HX711 has maybe 10 bits of resolution and only with lots of software averaging of the readings.I have a USB connected HX711 and it works well, but it's only good as a weigh scale and the chip can't be used as a low voltage detector. The principles used in my circuit apply to a very broad range of applications and demonstrate a very simple way to implement a lock in amplifier.https://www.zhinst.com/americas/en/resources/principles-of-lock-in-detectionThis is one of the most powerful ways of detecting signals deep in noise. Also, the use of AC amplification and AC detection eliminates op-amp input offset when trying to detect very low level signals. It's very easy to implement various types of chopper circuits for different types of signals and then use AC amplification and synchronous detection for measurement. For example, an LED can be flashed on and off at a precise frequency and the light passed through a variable density medium and then amplified and detected. This could be used for something like measuring water turbidity.I've attached the HX711 circuit that I use for comparison purposes. This program runs in the background on my desktop and pops up whenever I step on the scale. It works very well as a weigh scale, but when I investigated the HX711 to see how useful it would be in other applications, it's not that good. The common mode range is very narrow, the input resistance is only 100k and the interface is not very friendly and requires a small amount of hardware to make it SPI compatible. It's also far too slow to use in force sensing applications where speed is more important than precision.Finally, my circuit uses leaded parts and can easily be prototyped without dealing with SMD parts and gives a starting point for more sophisticated projects.

author: azeeman
author_rank: Regular Contributor
timestamp: September 07, 2025, 02:13:47 pm
content: The op-amp is an MCP6002 as this is the most economical leaded op-amp that I could find. ADC resolution is determined mainly by noise. Noise is given as the square root of bandwidth so if the bandwidth is reduced by to 1/10th the noise is reduced to 1/3.17.Resolution is ultimately determined by loop gain and comparator hysteresis. For example if the ADC comparator has 100 uV of hysteresis, it cannot distinguish voltage changes below that. Noise helps because it is an AC signal riding on top of the DC signal. With sufficient peak to peak noise, it effectively samples the DC voltage by driving the comparator input over the hysteresis band. If the DC voltage is slightly high, over many samples, the comparator output will be high more times than it will be low. If the noise level is below the hysteresis band height, it will have no effect.I'm working on single bit DC null detection where the feedback to the null detector is done by attenuating the output of a DAC and feeding that back to the null detector. This topology has some very interesting features.Because the null detection is single bit and the feedback is digital, the effect of noise acts very differently than with AC detection as used with a traditional chopper. The only noise fed back to the null detector is the noise from the DAC which can be very low because the DAC attenuator will have a moderate sized resistor like 10k going to a 10 Ohm or smaller which greatly reduces thermal noise.Also, the detector itself is immune to peak noise less than the differential voltage at the input of the op-amp. If the differential voltage is 1 mV and the peak noise is 500 uV, it can't get high enough to change the detector output state. When the differential voltage becomes less than the peak noise, the op-amp output can then change state. It's also easy to add gain by just putting a comparator with low hysteresis after the op-amp. If the op-amp peak to peak output is 2 mV and a comparator with 1 mV hysteresis is added to give a 5 V output, the effective added gain is 5,000.The problem is converting a single bit detector output to a DAC reading. This has been solved in sigma-delta converters where a integrator is used to generate the feedback signal. If the detector output is high, the integrator starts to ramp up, if the detector output is low, the integrator output ramps down. The integrator then acts as a low pass filter and extracts a very noisy DC signal.The problem is that the integrator time constant is fixed. Ideally, with a DC null detector, the integrator time constant should be very low when the differential voltage is high and noise has no effect on the detector output and the time constant should be very low when the differential voltage is below the peak noise so that it acts as a very low bandwidth filter.I've found a way to do this. Take multiple samples from the null detector output and then calculate the measurement uncertainty. If the uncertainty is low, it's very likely that the feedback voltage is very far from the input voltage and it can be changed in huge steps. This acts like an integrator with a very small time constant because the voltage rate of change is very high. When the uncertainty starts to increase, reduce the feedback voltage steps to very small amounts. This now acts like an integrator with a large time constant. Because the integration is being done digitally, the time constant can be years if desired giving nanohertz bandwidths.The uncertainty is easy to measure by just counting the number of highs in a fixed number of samples such as 32. The probability of can then be measured by looking at how many 32 bit patterns have a single one, two ones, three ones, etc. A lookup table is then used to determine the feedback step size based on that probability. I've attached a spreadsheet showing how this works.I just got a Python model of the algorithm working which looks like it can kill two birds with one stone. It switches the inputs of the null detector and nulls the input for each switch configuration and then averages the results. Because of the noise threshold mentioned above, the null will slow down right at the peak noise level so in one switch orientation the feedback will be just above the null point because of peak noise and input offset. In the other switch orientation, the feedback will be just below the null point because of peak noise and input offset. Average the two readings and both input offset and noise disappear.Of course, this is just a model, and the real world may be a lot different. I have built a simple digital feedback null detector and the noise threshold is extremely obvious. To get down to nanovolt levels, I had to use a neat trick, the 1.xR:R ladder. This is covered in another forum and is still very much a research project.https://www.eevblog.com/forum/metrology/digital-null-meter-design/I've attached a preliminary schematic of the intended hardware on which the Python model is based.Based on my research so far, DC null detection is far better than AC null detection. Also, using software based AC detection is much superior to using a chopper for AC detection because it doesn't generate all kinds of garbage which is then fed back to the detector input. It makes a lot more sense to send back a pristine digitally derived DC signal.There's also one more neat trick which can be used with low level DAC feedback, simple self calibration. The DAC error is usually around one or two bits, but the following attenuator will introduce significant gain error especially if a high resolution DAC is used. A 16 bit PWM can be used to generate a precise low level signal just below the full scale attenuated DAC output. The DAC can then measure this and calculate a scale calibration value to correct the attenuator error. The PWM filter will have a huge time constant, but because its output never changes this just causes a long "warmup" time before the self calibration can be done.