Wifi body weight scale – ESP8266

Introduction

Today you can buy body weight scales with fancy functionality like WIFI and body fat analysis. I wanted a simple way to track my weight over time and began looking at WIFI scales. They are a bit pricey and the data collected is often sent to some proprietary database, meaning that you don’t have full control of your data. So why not give an old electronic scale new life, by making it WIFI enabled?

The idea

  1. Buy an old electronic body weight scale dirt cheap at a thrift shop.
  2. Incorporate an ESP8266 WIFI micro controller that will tap into the scale’s circuitry.
  3. Extract the weight by probing using the ESP8266.
  4. Send the data over WIFI as a GET request to a web server.

I found an old electronic weight scale of the brand EKS at a thrift shop for $2. So lets get to it!

The old electronic body weight scale bought at thrift shop for $2

Components used

Table 1: Components used
Component Quantity Link (Ebay affiliate link)
ESP8266 esp01 (or NodeMcu Lua dev board) 1 (or )
SUP85N04 mosfet 1
TTL UART Module 6Pin Serial Converter (if you use ESP8266 esp01) 1

Cracking it open

The scale is opened by removing a couple of springs holding the front panel to the back plate. They were easy to remove using a pair of pliers

The back of the scale

Removing the front panel reveals some circuitry and a couple of metal rods linked to a sensor that measures the weight.

The inside of the scale

I hooked up an external PSU and fed 9V to it. At first nothing happened, was it broken? Fortunately that was not the case! Notice the yellow pair of wires going down to one of the feet? This foot is used as a button that when pressed activates the scale. Below is a picture of how much the scale pulls when active.

Power consumptiom when scale is active (before adding the ESP8266)

Analyzing the signal

The next step is to find a pin or trace on the circuit where a signal, that correlates to the weight, can be read. A good place to start is to look at the two ICs on the circuit.

The smaller one, close to the input cables from the sensor, is a HA17324 quad opamp. From this we can conclude that the signal from the sensor needs amplification. Looking up the pinout for this IC and measuring the amplified analog value from the sensor would be one way to extract the data.

The second IC, next to the display, is of unknown type. I could not find any information about it online. However I’m guessing it’s responsible for calibration, driving the display and computing the weight in kilograms. I decided to focus on this IC in hopes of finding some good way to derive the weight measured. A good tool for this would be an oscilloscope.

The circuit board has two ICs, a opamp(smaller ic) and some unkown IC (larger)

After probing the pins of the IC I managed to conclude the following.

  1. Circuit is powered by 9V but the IC operates at 5V
  2. There are pins driving the display(as expected)
  3. One of the pins inputs/outputs a pulse width modulated square wave
  4. For the same signal, the time in ms that the signal is low seems to be linear to the weight placed on the scale
The signal when no weight is applied. Display showing 0kg
The signal when applying some weight. Display showing 29kg

The ESP8266 and reading the signal

The esp8266 will read the PWM signal, interpret the readings and send the information as a GET-request to a web server. The following things need to be solved.

  1. Find a way to power the ESP8266(3.3V) from the 9V supply powering the scale
  2. Read the pwm-signal using interrupts
  3. Find a way to calibrate the signal to a weight in Kilograms
  4. Construct a GET-request

Note!

I have gone over the ESP8266 MCU in a previous article. Check it out if you want to learn how to program it.

First step: how to connect and power the ESP8266

The images below demonstrate how to setup the ESP8266. In short the components include buttons and pullup resistors(used when programming the MCU), and a voltage regulator + stabilization caps + diode for regulating the 9V power down to 3.3V.

How to hook up and power the esp8266
The schematic

Note!

I use a ESP8266 esp01 module. However this set up will also work with an esp12, esp12e and nodeMcu dev board. Just make sure that you connect to the same pins. Also, if you have a dev board with esp8266 you can skip many of the components in the schematics above, since they are already on the dev board.

Second step: reading the signal

The signal is a 5V square wave where the duration of a cycle that is LOW correlates to the weight being measured. I decided to program the ESP to trigger on change of this signal and store the time between two interrupt events.

Since the signal is 5V I had to bring down the voltage to around 3.3V so that the ESP wouldn’t take damage. I tried two approaches: voltage divider using resistors, and a diode. However none of these worked. Either the ESP would not start, due to that the resistors pulled GPIO 0 to ground at boot (prevents correct boot). Or, with a diode to GPIO 0, which caused the IC on the circuit to flash “EL” on the display. I’m guessing that the ESP some how affected the signal it was measuring.

I finally ended up using a mosfet (SUP85N04). As you might know a mosfet can act as a switch where the gate pin acts as the control pin for the switch. I let the PWM signal from the IC switch the mosfet on and off. I attached the drain pin to GPIO0 and source pin straight to GND. This results in that GPIO0 will read 3.3V(pullup resistor) when the pwm-signal is LOW and 0V when the pwm-signal is HIGH. Also since mosfets are controlled using voltage rather than current, the inteference with the PWM-signal should be minimal.

Adding a mosfet for safely reading the PWM-signal
The signal from the mosfet to the ESP8266 is inverted and with peaks at 3.3V

And finally some code! I used the Arduino framework together with the Nabton Library. The complete code is available at Github

The main sketch has the setup function and loop function. The code will connect to the WIFI network that is specified in the configuration.h file. It will then attach the interrupt function “measurePulseWidth” to GPIO0 and make it trigger every time there is a change to the signal. When a pulse with a width between 20000 and 100000 μs is found it will print the result over the WIFI network to a computer logging the results (this is only for debugging purposes).

Conversion

We need to translate the duration of a peak in microseconds to a weight in kilograms. I assume that the weight scales linearly to the duration of the peak. This means that if we can find the coefficient k and constant m of the linear equation y=k*x+m, we will be able to convert the duration(x) to a weight(y).

To solve the equation two measurments need to be gathered. The best approach is to linearize near weights where the scale will often operate. Meaning weights in the interval of e.g. 50 to 100 kg. The first measurement is my own weight. The body weight scale displayed 84.5 kg, at the same time the ESP8266 registered a mean duration of roughly 65 000 μs. The second measurement is my girlfriend’s weight. Display showed 54 kg and the ESP reported 50 600 μs.

k is computed by the following formula:

k_eq

where (x1,y1) and (x2,y2) correspond to the measurements. When you have k compute m by solving the linear equation with your new k value for one of the measured points.

In the code this translate to a conversion function. See below.

Sending the data

Before we can send a weight to the server the ESP needs some logic for determining when a stable and valid weight has been measured. The square wave has a frequency of roughly 5 Hz, this means that we can sample rather rapidly. I chose to store all durations in an array of length 10. The interrupt rutine will add new values as soon as they arrive from the scale. Once every second, I will in the loop function try to compute a valid weight.

I consider a measurement to be valid if the variance is less than 0.1. Variance is the squared deviation from its mean, i.e a indication of how stable/reliable the mean(final weight) actually is. I also check that the mean is larger than 0 kg.

Translated to code it looks like this:

When a valid weight has been established constructing the GET request and sending it to a web server is rather simple, thanks to the nabton library:

Wrapping it up

The GET-request can be confgured to be sent wherever you like. I send it to my nabton server. The figure below shows my weight ranging over a couple of days. The spike in the beginning is related to some calibration of the linear coefficient k.

Plotting the data received from the EPS8266

For the complete project and code go to the Codeterrific repo. Button below!

WifiBodyWeightScale GitHub repository

Finally, the following video wraps up this article. In the video I briefly go through the project. I also explain the code in more detail and show you how to use platformio, a great alternative to the Arduino IDE. Check it out!

Video compilation of the build.