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.
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
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.
distance = wait_for_distance() # Read the current water depthif distance isNone:
send(cloud, variables, distance, error_code=SENSOR_ERROR, force=True)
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:
# Distance from the sensor to the water level # based on the coffee-machine's water tank
MIN_DISTANCE = 2 # cm
MAX_DISTANCE = 8 # cm# Distance is out of expected range: do not start pouring
if distance > MAX_DISTANCE * 2:
log_error('Distance is out of range: %.2f' % distance)
We turn the pump off if it was active when an error occurred.
if is_pump_on() and prev_distance < STOP_PUMP_DISTANCE + DISTANCE_DELTA:
log_error('[!] Emergency stop of the pump. No signal from a distance sensor')
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.
PUMP_STOP_TIMEOUT = 5# secs
emergency_stop_time = Nonedefset_emergency_stop_time(now, is_pouring):global emergency_stop_time
emergency_stop_time = now + PUMP_STOP_TIMEOUT if \
is_pouring elseNonedefcheck_water_source_empty(now):return emergency_stop_time and now > emergency_stop_time
# --------- main loop -----------if GPIO.event_detected(GPIO_PUMP):
is_pouring = is_pump_on()
# ... global pump_disabled
log_error('[!] Emergency stop of the pump. \
Water source is empty')
pump_disabled = True
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.