I added WiFi to my coffee machine, and I control it with my home automation server, this part is about how I attached the esp8266 module to it.
In part 1 I talked about the idea and how I was planning to do it.
In this part I will describe how I attached the esp8266 WiFi module to my coffee machine.
Hardware
Schematic
Buttons
As you can see, in this schematic there are only four buttons connected, instead of 7. This is because the esp8266 module requires GPIO0, GPIO2 and GPIO15 to be connected either to VCC or GND in order to work. This sucked as I already soldered everything when I realized that. I decided to keep the following four buttons:
- Power (top right)
- Small coffee (top left)
- Large coffee (middle left)
- Coffee Strength (middle right)
Power module
In the schematics, I put a regular AMS1117 component to convert the 5V from the coffee machine to 3.3V required by the esp8266, but in fact I use a small module that includes caps and a status LED. The module uses an AMS1117.
Soldering and installation
Board
Most of the components I will be using (from left to right) :
- Power module (5V > 3.3V)
- esp8266 chip (esp-12) and breakout board
- prototype board
- 9x 2n2222a transistors
- 9x 1k resistors
Missing components on the picture:
- 2x 10K resistors
- 11 lines ribbon cable
- ribbon cable connector
- reset button and it’s resistor
You’ll notice that there’s too many transistors on the picture, it should be 4 but there’s 9:
- I originally thought about using a transistor for detecting the LED state on the input pin of the esp8266 but realized a resistor was enough
- there are 7 transistors, one for each button, but I only used 4 at the end. The 7 are soldered though.
Wiring up buttons, power and LED lines

On the front panel, I soldered thin wire on one pad of each button (GND is on the bottom pads) then some more wires to the LEDs and power (not visible on the picture), then I routed all these wires on the top left of the PCB. I finally glued the ribbon cable on the top left of the PCB and made the connections.
Now that everything is wired, it is time to start testing the connections and start coding!
Software
Testing connections and functionality
If you hold the top left button and the bottom right button and plug-in the coffee machine, you get into it’s debug menu – this is very useful as it allows me to not only test each button (see picture, if the button is pressed the N turns to Y) but also the LEDs (as the screen color changes when you press buttons)
Manual testing
I’m first testing the buttons without the esp8266 plugged in its socket, just by shorting the different pins to VCC, to check that the transistors circuit are working properly.
Preparing the esp8266 module
Next step is to flash the NodeMCU firmware on the esp8266, then connect a USB-Serial adapter to the module (the yellow and orange cables on the pictures, you see the serial adapter on the top picture).
Using ESPlorer, I can now start creating LUA scripts to control the esp8266.
First thing is to make sure all pins of the esp8266 are correctly configured as output/inputs and set the outputs to low.
For that I wrote the init.lua script as follows (the init.lua script is executed as soon as the esp8266 module starts):
1 2 3 4 5 6 7 8 9 10 11 12 |
gpio.mode(1, gpio.OUTPUT) -- middle right gpio.mode(2, gpio.OUTPUT) -- top left gpio.mode(6, gpio.OUTPUT) -- top right gpio.mode(7, gpio.OUTPUT) -- middle left gpio.write(1, gpio.LOW) gpio.write(2, gpio.LOW) gpio.write(6, gpio.LOW) gpio.write(7, gpio.LOW) gpio.mode(5, gpio.INPUT) -- LED red gpio.mode(0, gpio.INPUT) -- LED green |
This script simply defines the correct direction for each pin and sets all output to low.
Test buttons
Once the init script is in place, I start testing clicking on the buttons via the serial communication in ESPlorer:
1 2 |
gpio.write(2, gpio.HIGH) gpio.write(2, gpio.LOW) |
Test LEDs
A small script to determine the current color of the screen: function redON() return gpio.read(5) == 1 end function greenON() return gpio.read(0) == 1 end — return screen’s backlight based on the LEDs status. function color() if greenON() and redON() then return “yellow” elseif greenON() then return “green” elseif redON() then return “red” else return “off” end end print(“color: “..color()) it simply returns the current screen color every time it is executed. At this point, everything is in place, I am able to control each button separately from the esp8266 serial interface, and retrieve the machine status. Next step is to create a LUA script that contains a bunch of functions to control the machine and get it’s status back.
Make the machine actually smart
Being a C++ developper, I really like modularity, so let’s put all the functions to control the machine in a script called CoffeeMachine.lua – this module will be be called from another LUA file and we won’t have to think about GPIO or how long a button needs to be pushed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
local coffeeMachine = {} print("coffeeMachine V0.03") local pinTopLeftButton = 2 --small coffee local pinMiddleLeftButton = 7 --large coffee local pinTopRightButton = 6 -- power local pinMiddleRightButton = 1 --strength local pinRedLed = 5 local pinGreenLed = 0 -- returns true if the red LED is on function coffeeMachine.redON() return gpio.read(pinRedLed) == 1 end -- returns true if the green LED is on function coffeeMachine.greenON() return gpio.read(pinGreenLed) == 1 end -- returns a human readable string of the screen color function coffeeMachine.colorStr() if coffeeMachine.greenON() and coffeeMachine.redON() then return "yellow" elseif coffeeMachine.greenON() then return "green" elseif coffeeMachine.redON() then return "red" else return "off" end end -- returns a human readable string of the machine status function coffeeMachine.statusStr() if coffeeMachine.greenON() and coffeeMachine.redON() then return "warning" elseif coffeeMachine.greenON() then return "ready" elseif coffeeMachine.redON() then return "error" else return "off" end end -- returns true if the machine is on function coffeeMachine.isON() return coffeeMachine.colorStr() ~= "off" end -- turns the machine on -- if the machine is already on, do nothing function coffeeMachine.turnON() print("turning it ON") if not coffeeMachine.isON() then coffeeMachine.pushButton(pinTopRightButton) --turn machine ON coffeeMachine.tryStopRinse() end end -- turns the machine off -- if the machine is already off, do nothing function coffeeMachine.turnOFF() print("turning it OFF") if coffeeMachine.isON() then coffeeMachine.pushButton(pinTopRightButton) --turn machine OFF coffeeMachine.tryStopRinse() end end -- Try to interrupt the rinsing cycle function coffeeMachine.tryStopRinse() print("tryStopRinse") -- after one minute, stop clicking, there's something wrong... tmr.alarm(1, 40000, 0, function() tmr.stop(2) end) tmr.alarm(2, 1500, 1, function() -- every 0.5s, try pushing the button stop if the screen -- color is still yellow if coffeeMachine.colorStr() == "yellow" then coffeeMachine.pushButton(pinTopLeftButton) elseif coffeeMachine.colorStr() == "green" or coffeeMachine.colorStr() == "red" then tmr.stop(2) end end) end -- make a small coffee function coffeeMachine.makeASmallCoffee() print("makeASmallCoffee") coffeeMachine.pushButton(pinTopLeftButton) end -- make a large coffee function coffeeMachine.makeALargeCoffee() print("makeALargeCoffee") coffeeMachine.pushButton(pinMiddleLeftButton) end -- Brief (300ms) push on a button identified by it's pin function coffeeMachine.pushButton(pin) gpio.write(pin, gpio.HIGH) tmr.alarm(3, 300, 0, function() gpio.write(pin, gpio.LOW) end) end return coffeeMachine |
This module can now be accessed from another script, in a very easy to read manner:
1 2 3 4 5 6 7 8 9 |
coffeeMachine = require("coffeeMachine") coffeeMachine.turnON() if (coffeeMachine.statusStr() == "ready") coffeeMachine.makeASmallCoffee(); end coffeeMachine.turnOFF() |
That’s it for part 2, the next part will be about adding the WIFI connectivity and link the coffee machine to Domoticz. See you in part 3!
[…] How-to: Add WiFi to your coffee machine, part 2 […]
Great project! The thought of connecting a coffee machine to an esp8266 had crossed my mind too….. Instead of using a bean machine like you did I was thinking about an unused Nespresso machine.
My thoughts on the unusable IO:
GPIO 15, GPIO 0 and GPIO 2 need to be 011 during the boot process but I think you can use them as regular IO during runtime. Of course the easiest way would be to use them as outputs in your program.
Very interesting project!!!
I’m planing to control my low cost domestic ventilation in the same way as you did it with your coffee machine (2 switches and 3 leds).
What ist the reason for 011 of GPIO 15, GPIO 0 and GPIO 2?
Found!
https://github.com/nodemcu/nodemcu-devkit
Hello,
I am trying to make your coffee project work. I am at the point of adding the switches to domoticz so the LUA scripts can be executed.
That is where the problem comes into view:
The scripts (coffee small script, large coffee script and coffee machine power script) are triggered every two seconds without me touching any switch.
Also when I do use one of the switches, domoticz shows the “error sending switch command” window.
Do you perhaps have any idea about what is going wrong?
Even though my coffee is still analog, this is a very awesome project. thanks for posting it on your site.
Kind regards, Jeroen.
Hi,
Nice post about this nice coffee machine!
This coffee machine is really fun to hack. Look at https://github.com/OpHaCo/smart_coffee_machine . Same coffee machine has been hacked, it is now interfaced using MQTT protocol. Technically, there is some other features :
* interrupt on button presses are caught in order to capture user button presses and its duration.
* LCD signals over SPI are decoded in order to get a precise coffee machine status coupled with LCD backlight status. Now for example you can set remotely current coffee strength…
I’ve used nodemcu and did a shield.
Some example applications based on this hack are given, example provide :
* coffee machine metrics over grafana using influxdb framework and Openhab automation middleware (look at it, I’m sure you will like it).
* user interaction with coffee machine using camera, if user smiles, its face is detected and he gets a coffee. Moreover coffee machine talks (refer openhab rules).
These applications runs on a rasperry.
bye
Hi there,
Great project! good job on the spying of the SPI lines to get infos from the screen.
Your version is very interesting, I might adapt mine to use your improvements.
Cheers,
Benoit
If you are a Cpp programmer why you even bother to code in LUA? You can write C++ directly for esp modules using VS with plugin or Arduino IDE.