AquaFlow is a smart, fully-automated touchless water dispenser built on the Raspberry Pi using C++. It utilizes intelligent hardware monitoring to safely dispense exact volumes of water using proximity detection.
For SOLID compliance, FillingController now depends on behavioral interfaces (IProximitySensor, IPump, IFlowMeter) instead of concrete drivers. We considered a template-based variant for zero-overhead static polymorphism, but chose runtime interfaces for clearer architecture and easier assessment traceability; at a 100 ms control interval, virtual dispatch overhead is negligible.
Below is the definitive hardware wiring guide to connect the sensors and pump to the Raspberry Pi. For a visual representation, please refer to our physical circuit diagram:

Note: Always ensure the Raspberry Pi is powered OFF when altering hardware connections.
This acts as the touchless cup detector. It communicates via the I2C protocol natively over 3.3V.
| Sensor Pin | Raspberry Pi Pin | Function |
|---|---|---|
| VCC | Pin 1 (3.3V) | Main Power |
| GND | Pin 6 (GND) | Ground |
| SDA | Pin 3 (GPIO 2) | I2C Data Line |
| SCL | Pin 5 (GPIO 3) | I2C Clock Line |
| VL | Pin 17 (3.3V) | Powers the IR LED for proximity |
Sends digital pulses to precisely measure volume.
| Sensor Wire Color | Raspberry Pi Pin | Function |
|---|---|---|
| Red | Pin 2 (5V) | Power |
| Black | Pin 9 (GND) | Ground |
| Yellow | Pin 11 (GPIO 17) | Pulse Signal Line |
Driven via a Darlington TIP122 with a flyback diode.
- Base: GPIO 18 (via 1k resistor)
- Collector: Pump Negative (-)
- Emitter: Ground (GND)
- Diode: Across Pump (+) and Collector.
The system follows a strict event-driven, non-blocking architecture using timerfd and libgpiod interrupts. For full class and sequence diagrams, see our detailed Architecture Documentation.
graph TD
A[Timer Worker] -->|timerfd 100ms| B[FillingController::tick]
C[Gesture Worker] -->|timerfd 50ms| B
D[Flow Worker] -->|GPIO Interrupt| E[Atomic Pulse Count]
B -->|Atomic Read| E
B -->|GPIO Write| F[Pump Controller]
B -->|Callback| G[LCD Display]
| Requirement | Value | Mechanism |
|---|---|---|
| Gesture Poll Interval | 50 ms | timerfd (blocking) |
| State Machine Tick | 100 ms | timerfd (blocking) |
| Flow Interrupt Latency | < 1 ms | libgpiod Edge Events |
| Emergency Stop | < 150 ms | Proximity CLEARED → Pump OFF |
Both team members contributed equally to the hardware integration and software development of the system.
| Team Member | Primary Responsibilities |
|---|---|
| Abdullah Alkabbawi | Hardware Integration, Software Development (Hardware Drivers & State Machine), 3D Printing & CAD Design. |
| Bonolo Masima | Hardware Integration, Software Development (Architecture & Testing Skeleton), Documentation (ADRs) & Project Setup. |
| Item | Cost |
|---|---|
| DollaTek APDS-9960 Gesture Sensor | £4.99 |
| YF-S401 Water Flow Sensor | £7.45 |
| JT80SL DC Submersible Pump | £5.20 |
| TIP122 Transistor + Diode + Resistor Kit | £2.50 |
| 16x2 I2C LCD Display | £6.10 |
| Breadboard & Jumper Wires | £3.50 |
| Silicone Tubing (1m) | £2.00 |
| TOTAL | £31.74 (Target: < £75) |
If you are starting from a completely blank Raspberry Pi OS (Bookworm or newer), follow these steps:
- Flash OS: Flash Raspberry Pi OS (64-bit recommended) onto a MicroSD card using Raspberry Pi Imager. Ensure SSH and Wi-Fi are configured.
- Boot & Connect: Insert the SD card, boot the Pi, and SSH into it.
- Enable I2C: Run
sudo raspi-config->Interfacing Options->I2C-> Enable. - Clone the Repo:
git clone https://github.com/mushyalpha/FlowFizzy.git && cd FlowFizzy
Run the following commands exactly as listed. This will safely install C++ compilers, CMake, the Qt6 GUI dependencies, and force-install the stable Version 1.6 of libgpiod (required for the hardware drivers) directly from the Debian archives:
sudo apt-get update
sudo apt-get install -y cmake g++ qt6-base-dev libqt6printsupport6-dev libqcustomplot-qt6-dev wget
# Install stable libgpiod v1 (V2 is incompatible with legacy hardware driver interfaces)
cd ~
wget http://deb.debian.org/debian/pool/main/libg/libgpiod/libgpiod2_1.6.3-1+b3_arm64.deb
wget http://deb.debian.org/debian/pool/main/libg/libgpiod/libgpiod-dev_1.6.3-1+b3_arm64.deb
sudo dpkg -i libgpiod2_1.6.3-1+b3_arm64.deb libgpiod-dev_1.6.3-1+b3_arm64.debmkdir build && cd build
cmake ..
make -j$(nproc)Important for marking: the assessed interface is
filling_machine_gui, because it provides the real-time plot and mouse interaction required by the course brief. If CMake reportsQt6 NOT foundorfilling_machine_guiis missing after the build, the GUI dependencies were not installed correctly and the marking-critical target has not been built.
You can automatically run all unit tests from the build directory:
# Run Google Test unit tests
make test
# OR manually run ctest to view verbose outputs:
ctest -V
# (Optional) Run hardware integration testing binaries:
sudo ./hardware_trio_testFor the marked demonstration, run the GUI target:
sudo ./filling_machine_guiIf you need the hardware-only console build for debugging over SSH, you can still run:
sudo ./filling_machineThis project is licensed under the MIT License - see the LICENSE file for details.
- Special thanks to the community at Arduino Libraries for providing helpful open-source code logic and inspiration for our hardware drivers and sensor integrations!
