Have you ever forgotten your wet clothing inside the washer for a whole day? I have. Even for two days. They smell. You have to wash them again and you know you might end up forgetting about them again!

Actually that is happening to me since me moved to an old house in a town north of Barcelona. Instead of having the washer in the kitchen, like we used to, now we have it in the cellar, in a place I don't normally pass by to notice the laundry is done.

So I started thinking about monitoring the washer to get notifications when the laundry is done. And since I was at the same time playing with ITead's Sonoffs, which has an AC/DC transformer and a powerful controller with wifi, it looked like a nice project to put together.

EXTREME CAUTION: live mains are very dangerous. Don't work with them unless you know what you are doing and what the consequences might be.

Wiring the ADC pin

The Sonoff does not bring out the ADC pin on then ESP8266EX. Some Sonoff TH versions do bring out GPIO14 and latest Sonoff TH 10A/16A probably do the same through a jack interface. But that's not the case for TOUT aka ADC pin.

No problem, follow me:  grab the iron with a narrow tip, a short thin cable and a magnifier, because you are going to need it. If you are not really good at soldering (and I'm not) you can still do it, but you will have to check and double check for bridges between the ADC pin and its neighbours. The ADC pin is the 6th in the left side of the chip (with the dot on the top left corner).

First solder a 3 pin header on the unpopulated holes for the RF module. If you use the first 3 counting from the relay you will already have GND and 3V3 on the first two, so you just need to connect the ADC pin in the Espressif chip to the third header. Take your time, do not apply heat for more than a second and leave it cool before doing it again. Check with your continuity tester after and prepare a simple gig to test your hack: a 10k potentiometer with a 20k resistor to build a voltage divider will do.

Don't work with the board connected to mains! Again: Don't work with the board connected to mains! After testing for shorts and continuity hot glue everything to prevent the cable from comming loose and create a potentially fatal short between mains.

That was tricky! Bringing out the ADC GPIO in the ES8266EX to a 3 pin header using the unpopulated RF header of the Sonoff...

Sensor board

Now that I had the ADC pin I prepared a simple stripboard with a current sensor and a simple voltage bias circuit. The current sensor I use is a chep (and not very accurate) Talema ASM-010. It outputs a small voltage proportional to the current flowing through the hole. According to the charts in the datasheet the ratio is about 300A per 1V. That's a very poor value, and even thou I could pass the cable twice, reducing the ratio to 150A per V the YHDC SCT-013-030, a very common non invasive current, has a ratio of 30A per 1V, 5 times more accurate. But I just need to know whether there is current flowing or not.

The board has two resistors (nominal 10k and 56k) to build a voltage divider to bias the output voltage by 0.5V so the ADC will always read positive values, and a 10uF capacitor to soften signal.

The sensor board with one of the live cables doing two turns inside the coil. There are also two resistors to bias the voltage and a capacitor.
The Sonoff and the sensor board inside the enclosure.

Adapting the EmonLib

The EmonLib is the unofficial standard library to monitor current on an Arduino and alikes. But it doesn't support ESP8266 based boards yet. Current issues are:

  • It only supports 10 bit ADCs (ESP8266 ADC is 10bits too, but it only has one analog pin, so chances are you will use an external ADC chip in some projects, like de 16bits ADS1115)
  • Voltage reference calculation doesn't take into account non-atmel chips (the ESP8266 ADC is 1V referenced)
  • Analog reading is hardcoded in the library, again, what if you are using and external chip with I2C communication?

The usual approach is to include parts of the library code into your code and monitor analog pin 0. You could also use and external ADS1115 like Tisham Daar does.

This is not the first project I use current monitoring on a ESP8266, so I decided to wrap all the functionality I wanted in a proper library. And so EmonLiteESP was born. As the name says it's a lite version of the EmonLib, since it only supports current monitoring at the time (only apparent power). But truth is that naming it after the EmonLib could be misleading since it is not API compatible (and maybe I'm violating some trade mark, didn't check that).

The library main features are:

  • Customizable ADC bit count
  • Customizable ADC voltage reference
  • Read ADC values via callbacks

And its easy to use:

#include "EmonLiteESP.h"

EmonLiteESP power;

unsigned int adcBits = 10; // ADC bit resoltion (normally 10)
double referenceVoltage = 1.0; // 1.0V for a bare ESP8266 chip
double currentRatio = 30; // 30A 1V for a YHDC SCT-013-030
double mainsVoltage = 230.0 // EU standard
unsigned int samples = 1000; // 1000 samples each time we measure current

unsigned int currentCallback() {
   return analogRead(0);

void setup() {
   power.initCurrent(currentCallback, adcBits, referenceVoltage, currentRatio);

void loop() {
  double current = power.getCurrent(samples);
  Serial.print(F("Power now: "));
  Serial.print(int(current * mainsVoltage));

Now that…

Some time ago, at a previous job, our CTO was very concerned about unnecessary code. He had a list of anti-patterns to identify bad practices when developing a new feature. The YANGNI (You Are Not Gonna Need It, meaning just code what you are going to use now) was his favourite one. Another favourite was the YAQUE (spanish for “Now that…"). Now that we are touching this code, why don't we add this cool feature?

So breaking the YAQUE rule I added a DHT22 sensor because I could, and because we have moisture related problems in the cellar. The sensor is connected to the GPIO14 pin already available in the Sonoff board. I soldered a 10K SMD0805 resistor between the left-most 2 pins of the DHT22 (VCC and DATA) and drilled a hole in the case to place the sensor outside the box.

Another improvement was to add a case mounted momentary button on the enclosure, soldered to the onboard button, so I can manually switch the relay ON and OFF.

A wired Sonoff board with connections to the current sensor board, to the DHT22 temperature and humidity sensor and to the case mounted button.
The final project box

I have included all these features in my last ESPurna firmware version. Please check it out at espurna bitbucket repository.

Analyzing the data

So the goal of this project was to get a notification when my laundry is done. You don't really need an accurate power measurement for that, only monitoring if there is current flowing or not and keeping track on how long has the washer been “quiet”.

First step is to see how the washer power profile looks like. It will probably depend on the washing program you are using but for the one we normally use for day-by-day laundry it looks like this:


So you can see the washer has been working for 27 minutes (from 11:27 to 11:54) with several quiet windows of no more than 2 minutes each. Please note this measurements have been taken every minute averaging 6 readings every 10 seconds. For this program it might be enough to check whether the washer has been quiet for the last, say, five minutes after seeing activity and then emit the notification.

Node-RED driven notifications

Final step is to set a notification when the laundry is done. I've been using Node-RED for some time now and I like having everything in one place in a flexible and structured way: notifications, database persistence, cloud service connections (xively, blynk, thethings.io, thigspeak…), schedulers,…

Now that I have an MQTT topic with the washer power consumption is pretty easy to write a javascript function that monitors it and sends a notification when the washer has been idle for five minutes after some significant activity. To implement that I built a 5 positions ring that stores whether there has been activity or not for the last 5 minutes or last 5 messages. It sets a flag when at least 3 of those messages contain non-zero values (that's a significat activity). After that, when the buffer empties (5 minutes without activity) it sends the notification and clears the flag.

I'm sure the code will be much more clear than my explanation:

// Configuration
const WASHER_BUFFER = 5;

// Get current state
var washer_flag = flow.get('washer_flag') || 0;
var washer_sum = flow.get('washer_sum') || 0;
var washer_store = flow.get('washer_store') || Array(WASHER_BUFFER);
var washer_pointer = flow.get('washer_pointer') || 0;

// Update state
var current = parseInt(msg.payload) < 100 ? 0 : 1;
washer_sum = washer_sum - washer_store[washer_pointer] + current;
if (washer_sum < 0) washer_sum = 0;
washer_store[washer_pointer] = current;
washer_pointer = (washer_pointer + 1) % WASHER_BUFFER;
if (washer_sum > 2) washer_flag = 1;

    fill: (washer_sum === 0) ? "red" : "green",
    shape: "dot",
    text: "Washer machine state: " + (washer_sum === 0 ? "idle" : "working")

// Notifications
if ((washer_flag === 1) && (washer_sum === 0)) {
    washer_flag = 0;
    msg.topic = "Washer";
    msg.payload = "Your laundry is done!!";
    msg.trigger = {
        'topic': '/trigger/washer/done',
        'payload': 1
} else {
    msg = null;

// Store state
flow.set('washer_flag', washer_flag);
flow.set('washer_sum', washer_sum);
flow.set('washer_store', washer_store);
flow.set('washer_pointer', washer_pointer);

return msg;

The message is then passed to a subflow that sends it to Pushover service and also publishes it to the local MQTT broker.


And voilà: no more forgotten laundries… I hope.

"Your laundry is done" was first posted on 30 July 2016 by Xose Pérez on tinkerman.cat under Code, Hacking, Projects and tagged adc, ads1115, current sensor, dht22, emonlib, emonliteesp, esp8266, espurna, hack, humidity, itead, node-red, notifications, power, sonoff, talema, temperature.