For a while I’ve wanted to connect some scales to my home network to track weight day by day automatically. Its great having scales, but unless you can remember or write down the previous readings, its pretty useless if you’re looking to track performance. So I set about figuring out a way of getting an accurate reading from a set of cheap bathroom scales with an Arduino.
I bought 3 different kinds of scales, but they all had one thing in common – strain gauges. It seems as though the simplest and cheapest way of getting the weight of an object, is to use strain gauges which, for bathroom scales, 4 seem to be the magic number. All of the scales I found had 4 feet on the bottom which connected to an LCD display. Each of these feet is a little strain gauge which is a very simple measuring device. The one I ended up using was sourced from here.
The gauge is a piece of metal that is allowed to bend slightly, and in doing so, causes the resistance to change. If you have resistance change, you can measure it and voila – you’ve got a method of measuring weight. Obviously there is more to it than this, but for our purposes, this explanation covers it.
The 4 gauges are connected together in something called a Wheatstone bridge; it turns the resistance into a voltage which is much easier for a microcontroller to read. With 4 strain gauges, you not only spread the load more evenly over the plate on top, but you also gain temperature compensation. I’m not sure exactly how all that works, but smart people online said that you do.
This all sounds great and we can just plug the Wheatstone bridge straight into an analog to digital input on the Arduino and diet away. Well, strain gauges only change resistance by a tiny amount, so the Wheatstone bridge voltage is equally minuscule. As the Arduino only has a 10 bit ADC, it has a minimum resolution of 4.9 mV with a 5 V reference. You can set the reference to be an internal 1.1 V, but you would still only have steps of 0.1 mV; the bridge’s output is less than 0.01 mV for my scale.
The Arduino has a 10 bit ADC, but there are much better and more accurate ADC chips available. I chose this one – a MCP3424 chip – from JeeLabs which had a nice breakout (designed for his JeeNodes), 4 channels and 18 bit accuracy. Even more useful was a programmable gain of upto 8 meaning an incoming signal is first multiplied by 8 before being measured. For tiny signals that we’re measuring, that’s perfect.
Thankfully, the PCB I was working with had silkscreen labels showing which wires are which. There should be 4 important ones, S+, S-, E+ and E-. These stand for Signal and Excite, with signal being the output, and excite being the input voltage. The other connections are just the strain gauges being connected together through the PCB.
I noticed that there were several unpopulated sections on the PCB, and there are labelled SDA and SCL test points. I figured that this same PCB is also used in higher end models which have memory capability containing an I2C EEPROM. It might be possible to get readings via these pads, but I don’t own an oscilloscope to investigate with.
Measuring the excite pins, I got a voltage of 3v, which was the same as the input voltage delivered from the two AAA’s. The output voltage from the excite pins was around 0.01 mV with no load. This is perfect, as I wanted to use a 3.3 V microcontroller so I could use an XRF radio module.
I first prototyped the circuit and connected it up to an Arduino Mega connecting the S+ pin to 1+ on the MCP3424, the S- pin to 1- and then connected the grounds. The bridge would still be powered by the scales circuitry so its important to have a common ground. Even with the gain set to 8x, the highest reading with my full weight of 75 kg was only ~ 1000 which works out to be about 10 per kg. I’m not 100% sure what units I’m reading the result in, but that doesn’t matter, as I’m only interested in its relationship to a known weight.
Once my circuit was proved working, I extended the wires out of the battery compartment and now I could measure my weight as usual with the scale’s display still working as before, but also viewing the readings through the serial monitor.
I couldn’t figure out how the scales determined whether they should turn on, so I’m just going to use the LCD backlight wires (the backlight turns on when the scales are stepped on) and link it to an interrupt to wake a sleeping Arduino.
The ADC is a little over spec’d for what I need, so I’ll design a PCB that uses a MCP3422 which has the same specifications as the MCP3424, but only 2 channels. I’ll continue my project once the PCB has arrived.