“Precision” Scale#
How could we improve the accuracy of the scale? Besides the obvious - a better ADC - there are a few other steps we should take.
The most important is to change the ADC to use the bridge voltage as reference, rather than the built-in precision reference or supply voltage.
The voltage at the output of the bridge is
where \(S\) is a scale factor that is proportional to the weight and \(V_{\textrm{s}}V_{\textrm{s}}\) is the voltage across the bridge.
The output code from an ADC is
Let’s assume that \(V_\textrm{s}\) is the voltage of the battery powering the scale and \(V_\textrm{ref}V_\textrm{ref}\) is a constant precision reference voltage. As the battery voltage decreases over time, the ratio \(V_\textrm{s}/V_\textrm{ref}\) decreases, resulting in a gain error and consequent incorrect measured weight.
This and a host of other errors are avoided if \(V_\textrm{s}=V_\textrm{ref}\).
Integrated circuits for reading bridge outputs such as the HX711 include all the necessary circuits, including the amplifier and ADC.
Let’s modify our scale to use an HX711 breakout board. Connect the \(V_\mathrm{DD}\) and \(V_\mathrm{CC}\) pins to VUSB
of the ESP32 and GND
to ground. Note that although the breakout board states a minimum supply of just 2.7V and hence operation from a single cell rechargable Lithium battery, doing so requires changing the feedback resistors, \(R_1\) and/or \(R_2\). Tie DAT
and CLK
to two used pins of the ESP32. The code below assumes 12 and 27, respectively.
Also wire the load cell to the pins provided on the breakout board. My load cell does not have a shield, hence I left that pin unconnected. However I “twisted” the green and white wires from the load cell in an attempt to minimize electromagnic interference. Making these wires as short as possible also helps with noise.
HX711 MicroPython Driver#
The HX711 requires a driver. Several versions for MicroPython are available, I chose this one.
%%bash
url=https://raw.githubusercontent.com/robert-hh/hx711/master/hx711_gpio.py
dst=$IOT_PROJECTS/balance/code/lib/hx711.py
curl -o $dst $url
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2345 100 2345 0 0 12342 0 --:--:-- --:--:-- --:--:-- 12342
Updated Scale class#
Now update the Scale
class to use the HX711 rather than the ADC in the ESP32. I call the new class ScaleHX711
to easily switch between the two versions.
Simply change
from scale import Scale
in main.py
to
from scale_hx711 import ScaleHX711 as Scale
to use the new class, the code for which is below.
%%writefile $IOT_PROJECTS/balance/code/lib/scale_hx711.py
from hx711 import HX711
from machine import Pin
class ScaleHX711:
def __init__(self, data_pin=12, clock_pin=27, scale=500/1059800):
self._scale = scale
pin_OUT = Pin(data_pin, Pin.IN, pull=Pin.PULL_DOWN)
pin_SCK = Pin(clock_pin, Pin.OUT)
self._hx711 = hx = HX711(pin_SCK, pin_OUT)
hx.tare(20)
hx.set_time_constant(0.25)
@property
def hx711(self):
return self._hx711
def measure(self, N=10):
hx = self._hx711
v = 0
for _ in range(N):
v += hx.get_value()
v /= N
return v * self._scale
def tare(self, button):
self.hx711.tare(20)
scale = ScaleHX711()
while True:
print("read {:15.1f} grams".format(scale.measure()))
Writing /home/iot/iot49.org/docs/projects/balance/code/lib/scale_hx711.py
%connect balance -q
%rsync
Directories match
Reset the microcontroller. Use either the display or the code below to test the new setup. The resolution of my scale is now better than 0.1 gram (the first digit after the comma does not flicker). Not bad!
from scale_hx711 import ScaleHX711 as Scale
scale = Scale()
while True:
print("read {:15.1f} grams".format(scale.measure()))
Show code cell output
read 0.0 grams
read 0.0 grams
read 0.0 grams
read 0.0 grams
read 0.0 grams
read 0.0 grams
read 113.1 grams
read 194.8 grams
read 199.9 grams
read 200.1 grams
read 200.2 grams
read 200.2 grams
read 200.1 grams
read 200.1 grams
read 200.1 grams
read 200.1 grams
read 200.1 grams
read 272.4 grams
read 666.0 grams
read 705.4 grams
read 701.0 grams
read 700.8 grams
read 700.8 grams
read 700.8 grams
read 700.8 grams
read 700.7 grams
read 701.7 grams
read 560.6 grams
read 503.7 grams
read 500.5 grams
read 500.3 grams
read 500.3 grams
read 500.3 grams
Interrupted