Smart Coffee Machine Pump Controlled by Raspberry Pi & HC-SR04 Ultrasonic Sensor

Alex Stakhanov
Nov 12, 2019 · 8 min read

In theory, every time you go to the coffee machine for your morning cup, there’s only a one-in-twenty chance you’ll have to fill the water tank. In practice, however, it seems that the machine somehow finds a way to always put this chore on you. The more you want coffee, the more likely you are to get the dreaded “fill the water tank” message. My colleagues feel the same way about this. Being the nerds that we are, we decided to implement the technology that would put an end to this.

Our Equipment

We have a SAECO Aulika Focus coffee machine. Up to this day, we used a hand pump to fill the machine’s water tank from a standard 5 Gallon (19L) water bottle.

Our Goals

  1. Use an electric pump driven by some kind of a controller or a microcomputer through a relay.
  2. Have a way to measure the water level in the coffee machine’s tank so our system knows when to refill it.
  3. Have means to control the system, preferably in real-time from a mobile device.
  4. Receive notifications (through Slack or a similar service) if anything goes wrong with the system.

1. Choosing the Equipment

The Pump

A quick web search will show several electric pump models designed for your water bottle of choice. Such pumps are usually controlled by an ON/OFF switch (for example, Hot Frost A12 or SMixx ХL-D2). Here’s the pump we chose for our project:

The Controller Device

We tried several devices but settled on a Raspberry Pi due to the following advantages:

  • It has a GPIO that allows us to connect a proximity sensor
  • It supports Python

We installed a fresh version of Raspbian Buster Lite and everything required to run Python 3.

How We Toggle the Pump

To control the power, we picked a medium power (12V/2A) solid state relay suited for alternating current.

The relay connects the pump to the outlet and is controlled by the Raspberry Pi’s digital pin.

How We Check the Water Level

It was important for us to not alter the coffee machine’s construction, so we decided to use the HC-SR04 Ultrasonic proximity sensor to measure the water level.

We 3d-printed a custom water tank cover with two holes for the sensor’s emitters.

We easily found a GitHub library for the sensor.

At this point all preparations were finished.

2. Designing and Running the System

System’s Logic

The system is designed with the following simple logic in mind:

  • The system constantly monitors the distance between the sensor and the water surface.
  • Whenever a change in distance goes over a threshold value, the system sends information about its state to the cloud.
  • If the distance goes over the maximum allowed value (the tank is empty), the system activates the pump and turns it off once the distance is less than the minimum allowed value.
  • Whenever the system’s state changes (for example, the pump activates), it informs the cloud.

In case of an error, a notification is sent to a Slack channel.

When the coffee machine is idle, the system pings the cloud service with diagnostic data once every minute. Additionally, it sends its state to the cloud every 5 minutes.

When the pump is active, the system sends data more frequently but no more than once every half a second.

Working with the Pump

We define the following constants as a base for pump operation logic.

IMPORTANT: If you are going to use Pin 4, do not forget to disable the 1-Wire raspi-config option to avoid conflicts.

At the program’s startup, we register a callback and set the initial state to OFF.

Here’s the code for the function that toggles the pump:

As defined in the startup code above, when the relay turns ON, the following callback is called:

In the callback, we save the pump’s current state to a variable.

In the application’s main loop, we can detect the moment when the pump toggles as shown below:

Measuring the Distance

It’s quite easy to measure the distance towards the water surface using an ultrasonic proximity sensor. In our repository, we shared a couple of python scripts that allow you to test a sensor.

In real applications, sensor readings can fluctuate because of the sensor’s bouncing effect and water oscillations. In some cases, readings can be completely missing.

We implemented a BounceFilter class that accumulates N recent values, discards peaks and calculates the average of remaining measurements.

The measurement process is implemented by the following asynchronous algorithm.

You can find the filter’s full implementation in the sources.

Handling Emergency Situations

What if the sensor burned out, or fell off, or points to a wrong area? We needed a way to report such cases so that we can take manual action.

If the sensor fails to provide distance readings, the system sends the changed status to the cloud and generates a corresponding notification.

The logic is illustrated by the code below.

We have an operational water level range that should be maintained when the sensor is in its place. We test if the current water level falls in this range:

We turn the pump off if it was active when an error occurred.

We also process the case when the bottle runs out of water. We check if the water level does not change when the pump runs. If so, the system waits for 5 seconds and then checks if the pump has turned off. If it has not, then the system implements emergency pump shutdown and sends an error notification.

Below is an example of a message log generated during an emergency stop.

Running the System 24/7

The code on the device is debugged and runs without problems. We launched it as a service, so it restarts if the Raspberry Pi is rebooted. For convenience, we created a Makefile that helps with deployment, running the service and viewing logs.

You can find this file and all the required scripts in our repository.

Cloud Monitoring

We used Cloud4RPi to implement a control panel. We first added widgets to indicate the systems essential parameters.

(By the way, the widget for the STATUS variable can use different color schemes based on its value.)

We added a chart widget to display dynamic data. In the image below you can see the moment the pump turned ON and OFF and respective water levels.

If you analyze a longer time span, you can see peaks — that’s when the pump was running.

Cloud4RPi also allows you to set different smoothing levels.

It works! The control panel in its entirety looks as shown below.

Currently, our automatic pump has been running for several weeks and all we needed to do is replace water bottles. The full code for our project is available in our GitHub repository.

Demo video



Cloud control panel for your IoT projects

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store