DIY Connected Espresso Machine: Boiler (Part 3)
By: Danila Loginov
Tags: Nodemcu, Connected Home, IoT, DIY, Arduino

Until a certain temperature is not achieved, the “button” is pressed, so the thermistor contact closed and the input pin goes to the LOW state since it is commutated with the ground.

Temp is not high enough — the contact is closed, input pin goes to LOW.

Temp is high enough — the contact is opened, input pin goes to HIGH.

Having this in mind, let’s first double the relays to control the boiler and then make three connections to thermistors: first is shared ground, second is for the “isBoiling” input pin, and third — for the “isSteam” input pin.

With Arduino Uno, I used A0 and A1 pins:

Boiler controlled by Arduino

With NodeMCU it was D5 and D6 pins:

Boiler controlled by NodeMCU

Firmware

Boiler class extends the Relay class because it basically operates the relay, however, the behavior is extended: since we have information about the temperature we can command the boiler to achieve a certain temperature based on the thermoresistors state.

First, we define BoilerTemp ranges as an enum: Cold, Boiling, Steam — this clearly represents possible temperature ranges and eases operation.

Relay class inherited as private not to expose its methods (restrict from switching the relay directly) and three parameters are passed to the constructor: the relay pin, “isBoiling” pin, and “isSteam” pin.

getState() will shadow the Relay getState() method, while getTemp() and getTargetTemp() are the new getters to understand the current and target boiler temperature.

setTargetTemp(BoilerTemp) exposes control of the desired temperature. And the last, but not least work() method will encapsulate the algorithm to switch the relay based on temperature.

getTemp() implementation checks for the voltage from the input pins connected with thermistors and based on that returns the current temperature range.

work() compares the current temperature with the desired and switches the relay using the underlying Relay methods — to have proper reaction time, this method should be called as much as possible.

I believe there are many ways to implement even such simple functionality, however, having the behavior encapsulated in a class and proper interface, it can be easily done at any time during the firmware evolution!

Also with the enum describing temperature ranges, we can extend it with additional thresholds like AlmostBoiling, KindaSteam without rewriting the dependent pieces of code.

Test

Test sketch is a bit more complex than in the previous episode since we need to iterate over possible temperature ranges.

Attention! To have thermistors reacting to temperature we need to wire everything, including the pump as well because we can’t heat up an empty boiler!

First, we instantiate the pump and boiler passing actual pins. Then we create two flags to remember passed states and prevent looping. In the setup() phase we turn on the pump to catch up pressure in the boiler and then set the target temperature to Boiling.

In the working loop(), we switch the target temperature if it was raised and call the boiler.work() method every iteration so it can timely react to the thermistors changing state.

Test Boiler

Next Steps

In the next episode, we will focus on the toggle mechanism in order to return back its capability to control the espresso machine.

The project code is available here: https://github.com/loginov-rocks/Connected-Espresso-Machine — it’s not finished by the moment I write this article so I will work on this during the next episodes.

That’s all for today, see you next time!