Introduction: EndOftheLine: Arduino Washing Machine/Dryer Monitor

About: Never stops thinking.

Many of us facing the challenge of having the dryer/washer in different part of our building. Sometimes you just too busy with fragging online and forget about it while your wet cloths rotting in the washing machine for half a day so I come up with a quick and easy solution for notifications. Although it would be possible to do this task other ways (build in a parasitic circuit into the dryer/washer to check led or other states of the chip or use a gyro sensor to track the resonations coming from the machines) this mod is non-intrusive and can be applied to monitor any other appliance in long distances. This Instructable is basically a remote current monitor. It got the code name EndOftheLine since a boring name such as "current meter" CM_ is already used in my Coffee Machine project.
As always, a warning about playing with the mains (110/230V) can be deadly so only people with proper electronics background should do this build, if you are a beginner you should only build low voltage circuits and consider this writing as educational material.

Step 1: Hardware Design

This one is going to be one of my simplest Instructable hardware wise. You would not even need a breadboard, the parts can be connected through simple jumper wires. As much as I hate hot-gluing for this project it was the perfect choice.
Parts used:

-Arduino PRO Micro

-ACS 712 current sensor: 20A

-Relay module (do NOT use the pictured 10A module if your load drains over 10A!)

-HLK-PM01-5V mini power supply (Low power consumption, environmental protection, no-load loss <0.1W). Although it might not looks like it but this is a mini isolated power supply (not Transformerless Power Supply TPS what you should avoid at all costs in all your Arduino/ESP projects)

-HC12 transreceiver

-HC12 USB dongle for the other end

-Any 230V power strip


There are some misguided folks out there who think that the current (in case of single-phase AC power source) in the neutral wire (BLUE) is lower than the current in the hot wire (BROWN). This is simply not true. The current in single-phase AC networks on 2 loads in series (one is our current meter) is exactly the same. The ONLY advantage of putting the ACS current sensor in the neutral line is that if you touch that while the load is OFF (by a switch or relay) you won't be zapped since there is 0 current flowing through there, on the other hand if you would touch the brown wire even in OFF state (if the switch and relay is after the current meter) then the mains voltage would go through your body down to the ground. So from safety perspective one can say that it is safer to put the ACS current sensor to the neutral wire, but in a concealed environment it does not matter and you should not be touching any wires anyway while the device is ON.

For my circuit the mains 230V goes into the relay first (which is in always closed state, unless it's controlled) then I used a rigid wire which can easily handle even 20 Amps to connect the ACS together with it. This wire also helped to hold the components in place before hot-gluing.

My original idea was to build the whole circuit into the power strip but as my pictures shows they made these intentionally not disassemblable (dohh!) so I just cut the main power cable and put in a junction box.

One last note you should not use 10A relay if your load drains more than that. Make sure you read the datasheet of the devices or do tests with a current meter to see what is the peak current.

The tricky part of the project was the radio communication since my washer and dryer are in the basement. I have experimented with some solutions to see if they are viable:

1, ESP32/8266 wifi -> not a chance all wifi signal is completely blocked

2, 2G/3G/4G -> nope, dead

3, Lora -> works but it's an overkill for the project

4, 433Mhz cheap transmitter, it does work with boosted TX power, operating from 12V but would interfere with my weather station and other equipment using this band. Originally I did not plan a relay in this build, without that a simple transmitter would have been enough.

Therefore I ended up with the HC12 long range transceiver as perfect choice for this project. Although some folks out there claim kilometers from this I failed to achieve 200 meters in an urban area due to signal interference but nevertheless it was just perfect for this project. This transceiver supports a lot of different transfer modes going from 1200Bps -> 115200 Bps with the lowest is 1200 it works perfectly with my distance and obstacles in the way. I'm quite impressed with this little module that it is able to communicate through 3 floor levels and multiple doors in between the two units.

Step 2: HC12 Notes

This section is optional, you can skip it if you are not interested since this module will just work with the settings out of the box for short distances. If you still have problem with the communication in your environment go ahead and read.

I have found multiple tutorials and manuals mentioning that the HC12 can automatically adjust the radio transfer speed corresponding to the serial's bandwidth.

However this is unfortunately not true. You cannot just do a HC12.begin(1200) and expect the communication to go over the air with 5000 bps (which would be the best for our application).

It must be put into programming mode first by pulling down the SET pin to GND then sending an AT+B1200 command but once this has been done it is written to it's flash and you will never have to change it again.

But also don't forget that when you communicate with the device first you are using 9600bps, as soon as you set it to any other baud rate you will get gibberish and have to change your code accordingly.

The way to easily program it therefore from an Arduino side.

1, Have your program open the serial port with HC12.begin(9600);

2, You connect the programmer pin (SET) of the HC12 to GND

3, Your program sends a HC12.println("AT+B1200") out

4, The device is set to 1200bps Serial / 5000 bps Air at this point, you will never have to redo this procedure again (except if your transmitter breaks and you have to program a new one)

5, You must modify your program to open the serial every time with HC12.begin(1200);

It entertained my thoughts that theoretically HC12 nodes can reprogram each other remotely. For this you could implement a command like PROG_MODE and once the remote Arduino receives it, it pulls down it's HC12's programmer pin to the ground then sends an "AT+whatever bandwidth" command it closes it's serial and reopens it with the new bandwidth then the local node essentially does the same. To survive reboots after modifying the baud rate your program could put the HC12 in programming mode at start (by pulling the SET to GND) and do an AT+RX where the module returns with the currently set bandwidth and use that as a base value.

The default setting is FU3, 9,600bps (8-dibit data, no check, one stop bit), CH001 (433.4MHz). To get the farthest communication distance, the serial port baud rate can be set to be low.

I have also bought some HC12 USB dongles for testing, what is great about them that they not just work out of the box but they have a neat PROGRAMMER button for programming. One issue I have run into after playing around with these modules is that I have left them in unknown states (different channels, different baudrates) for a couple of months and after I pulled them from my drawer nothing worked anymore so if you change parameters it is the smartest to print a small label put it on your box or on the module or log your project so you avoid an hour of QQing.

The manufacturer claims that you can always reset your settings with putting the port to 9600Bps and sending AT+DEFAULT to the device, sadly this is not always true :(

With one of my dongles this worked, the other just did not respond in programmer mode to anything then I was forced to go through manually from 1200Bps on the other settings trying to send it commands nothing worked. I found the solution after searching online for a bit, you need to hold down the PROGRAMMER (reset) button for a long time period. The 30,30,30 practice similar to WRTG hard reset will definitely work although time does not need to be this long: push the buttong for 5 sec while the device plugged in, unplug the device keep the button down, replug it keep the button down then it resets to DEFAULT.

I had another physical HC12 module where I changed the settings and never could make it work again, using 2 Arduino Megas, a Leonardo and a Pro Micro so unless you MUST change parameters the best thing is to leave them on default. I have changed the CHANNEL from the default because later on I might do another HC12 project and would not like to interfere with this one.

Step 3: Arduino Code

The ACS 712 was made to measure DC current but measuring AC is also possible with it. I won't go into this as many other articles detail it:

If you are not interested how it's done you can just take my code and adjust the voltage (110/230V and the ACS type value for ACS 712 10A/20A/30A modules) and it will work.

To monitor 2 devices things get a bit more tricky. Fortunately as wasteful as this class B dryer is when it comes to energy usage (eating up over 1200W constantly) it comes in hand to differentiate from the washing machine which while it operates goes from bare standby 1W to 500W (I would note that there are modes like white wash on 90C where it even goes up to almost 2KW, but I never use these). The software is querying the amps, calculating the power many CPU (or shall we say MCU) cycles per second but there is a problem, as stated earlier the washing machine can go down to very low power usage mode even for half a minute playing pokemons in its dreams or whatnot. If we would pull this value once in 5 minutes there is a good chance it would be inaccurate so a technique called smoothing is implemented in the code which takes this value 100 times and averaging it. With each new value, the sum of all the numbers is generated and divided, producing an average value which then be used to smooth outlying data. Because this averaging takes place each time a new value is added to the array (rather then waiting for 100 new values, for instance) there is no lag time in calculating this running average.

Measured data:

1, Washing machine

128W usage -> can go down between motor spin cycles to -> 1W

0.5-1.5W standby

2, Dryer

over 1275W usage !

2W standby

The following states can be defined:

if powercons_for_5mins < 1.5W washing ready
if powercons_for_5mins < 5W drying ready
if powercons_for_5mins > 50W washer is running
if powercons_for_5mins > 500W dryer is running
if powercons_for_5mins > 1350W dryer+washer is running

Messages would have been enough to be sent once per 5 minutes however I preferred 1 sec delays when the load is on for further debugging. Also detected some strange anomalies this way.

Since the mains voltage never changes the formula will always be P = 230*I (measured amps).


Once both washing and drying is done the system will still sample the power consumption but does not send any more messages. The final notification is repeated 3 times for example:


Some notes about the code:

Since the relay was just an extra addition which will rarely (or never) be used I using the always closed state of the relay to extend it's life. The code sets the relay to 0 which means it will need to go HIGH to shut down the device (not to turn it on).

 digitalWrite(POWER_RELAY, LOW);

The code will calculate the power and evaluate that as criteria to send the specific events but all the sent data is just for debug, the only thing we make an action on the 3 states:

                    if (Match(eolstate, "EOL_LOAD_WF") != NULL)
                        system("/home/pi/ wf");
                    if (Match(eolstate, "EOL_LOAD_DF") != NULL)
                        system("/home/pi/ df");
                    if (Match(eolstate, "EOL_LOAD_WDF") != NULL)
                        system("/home/pi/ wdf");

Where the F stands for Finished. These states are depending on the previous states (washer/dryer was running or not). For example the washer is running, the dryer is off the code will go into the else if (PowerAVG<500 && PowerAVG>50) section and print EOL_LOAD_W but this is NOT what we care about but when the washing is finished. Then once the machine is done and the power consumption drops to 1W for a longer time period the code goes into else if (PowerAVG<10 && PowerAVG>1) but because of the previous state eol_state>=1 was 1 it will print the EOL_LOAD_WDF message and lock (sets the sate to 0). The next time when it goes into this code section the load will be on standby EOL_LOAD_S when the machines are physically turned off and the load goes under 1 Watt an EOL_LOAD_OFF will be generated ans eol state set to 0. After reaching the actual print section that will send the data out and lock, as long as the eol state goes higher than 1.

Usually when I spend a lot of time on designing the hardware and software separately and put the circuit together nothing works and I have to spend days on troubleshooting mistakes, not in this project. There were only four minor issues:

1, When there is no load the ACS712 gives out a floating readout, as 1 whole day test shows this goes between 0.09A -> 0.16A. This is similar to my wallplug power meter, which defaults to 0.10 A when there is no load. Solution: instead of working with fake power values and adjusting to this I put in a simple if check which check if the current consumption is under 0.20A it sets it to 0.

2, Smoothing code had issues for calculating the AVG power due to the number of samples could not be fit into an integer variable for example 1000W*100 element = 100000 so it has been changed to unsigned long which can store values 0 to 4,294,967,295, the division result should always be low so this is the only variable which needed to be changed.

3, The small coil antenna needed to be replaced with an external antenna, what I used was standard 2.4Ghz wifi antenna (remember any antenna is better than no antenna). My initial tests using the coil antenna worked however once the device was assembled I got major packet loss, maybe because of interference with the high voltage wires. In the upstairs receiver I also extended the coil with connecting a simple wire to the end of it.

4, Regardless my low current ignoring code when the load is attached and turned off sometimes there are current spikes such as:

2019-04-17 13:42:12 => [EOL] Data received at 2019-04-17 13:42:12 => EOL_LOAD_S,0,0.22,1

2019-04-17 13:42:13 => [EOL] Data received at 2019-04-17 13:42:13 => EOL_LOAD_OFF,0,0.00,0

I could not make up much sense of these (maybe some fluctuations on the power line from others turning on/off their devices?!). Ignoring 1W can't be done since that is determining the idle state but fortunately these fluctuations never go over 10 Watts to put the program into WDF state so they will be just logged.

What is better way to test this new circuit than with an 1400W hair dryer :P Using 100 samples in the smoothing code resulted me about 2 minutes to fully propagate the changes in power, which means it took 2 minutes from the state the load was turned ON to reach it's real value. Once the load was turned off it took about the same time to go down to 0. However I would note that this was accomplished by a hold time of 1000 (1sec) in where the device sends the data on HC12. If the device has nothing to do for 1 minute just sample and keep looping those loops would happen a lot faster and 100 elements would not be enough. That was the major reason why I left the sample submission rate on 1 second instead of sending it in every or every five minutes once.

On the receiver end a Raspberry PI runs the C base code and plays different .wav files with aplay when the washer or dryer finished.

There is no Closure and ToDo list this time since I consider this project well done :-)