- Overview
- Key Features
- System Architecture
- Hardware Pinout
- Control Logic
- Wireless Bluetooth Protocol
- Companion Mobile App
- Installation & Dependencies
- Repository Structure
- Current Status & Roadmap
- Academic & Engineering Credits
- Acknowledgments
- Contributing
- License
SystemUnite4 is an embedded master controller engineered to automate microbial incubation and bioprocess regulation. It combines dual-zone digital temperature monitoring, independently-driven heating elements, dual-channel aeration control, Bluetooth telemetry, and a local LCD interface into a single closed-loop bioreactor/incubator controller.
The system is built around an Arduino Mega 2560, communicates with an Android control app over a Bluetooth serial link (HCβ05), and displays live process data on a 16Γ2 I2C LCD β so the reactor can be monitored and operated even without the phone connected.
- Dual-Zone Thermal Monitoring β two DS18B20 digital sensors on a shared OneWire bus (Pin 9) give independent upper-zone (
T1) and lower-zone (T2) temperature readings. - Independent Heater Control β the upper and lower heating elements are switched separately, each compared against its own zone's reading.
- Dual Aeration Channels β two independently-addressable air-pump relays (
AIR1/AIR2) for oxygenation or mixing during fermentation cycles. - Bluetooth Telemetry (UART) β a serial command protocol over
Serial1accepts remoteSTART/STOP/TEMP/TIME/AIRcommands and streams live temperature data back to the app. - Local HMI (I2C LCD) β a 16Γ2 display (
0x27) shows both temperatures, the setpoint, and the countdown timer without needing the phone. - Status LEDs β dedicated indicators for run state, stop state, aeration, and each heater zone give an at-a-glance hardware status even from across the room.
- Companion Android App β a KivyMD-based Bluetooth control app (
APP) with live gauges, parameter entry, and start/stop controls.
flowchart LR
subgraph UI["User Interface"]
APP["Android App\n(Bluetooth Terminal)"]
end
subgraph COMM["Wireless Link"]
HC05["HC-05 Bluetooth Module\n(Serial1, 9600 baud)"]
end
subgraph MCU["Arduino Mega 2560 β Main Controller"]
PARSE["Command Parser"]
CTRL["Control Logic\n(Heater / Aeration / Timer)"]
LCD["LCD Interface (I2C 0x27)"]
end
subgraph SENSE["Sensing"]
DS1["DS18B20 #1 (T1, Upper)"]
DS2["DS18B20 #2 (T2, Lower)"]
end
subgraph ACT["Actuation"]
H1["Upper Heater Relay\n(Pin 44)"]
H2["Bottom Heater Relay\n(Pin 45)"]
A1["Air Pump #1 Relay\n(Pin 42)"]
A2["Air Pump #2 Relay\n(Pin 43)"]
end
APP <-->|Bluetooth SPP| HC05
HC05 <-->|UART| PARSE
PARSE --> CTRL
DS1 --> CTRL
DS2 --> CTRL
CTRL --> H1
CTRL --> H2
CTRL --> A1
CTRL --> A2
CTRL --> LCD
CTRL -->|T1 / T2 stream| PARSE
style MCU fill:#203a43,stroke:#4ec9f5,color:#fff
style SENSE fill:#2c5364,stroke:#81c784,color:#fff
style ACT fill:#2c5364,stroke:#ffb74d,color:#fff
For a deeper, command-level walkthrough of the decision logic, see ARCHITECTURE.md.
| Component / Subsystem | Pin Name | Arduino Pin | Description |
|---|---|---|---|
| DS18B20 Sensors | ONE_WIRE_BUS |
Pin 9 | Shared digital temperature data bus (2 sensors) |
| Blue Status LED | startLed |
Pin 24 | Operational state indicator |
| Red Status LED | stopeLed |
Pin 25 | Emergency / standby indicator |
| Air Status LED | airGeneratorLed |
Pin 26 | Aeration active indicator |
| Heater 1 Indicator | heaterLed1 |
Pin 27 | Upper heater status LED |
| Heater 2 Indicator | heaterLed2 |
Pin 28 | Bottom heater status LED |
| Aeration Relay 1 | airGenerator1 |
Pin 42 | Primary air injection relay |
| Aeration Relay 2 | airGenerator2 |
Pin 43 | Secondary air injection relay |
| Upper Heater Relay | upperHeater |
Pin 44 | Upper heating element actuator |
| Bottom Heater Relay | bottomHeater |
Pin 45 | Lower heating element actuator |
| I2C LCD Module | SDA / SCL |
Dedicated I2C | System status & display (0x27) |
| Bluetooth Module | Serial1 (RX1/TX1) |
Hardware UART | Remote telemetry interface, 9600 baud |
Full electrical specs β sensor accuracy, pull-up values, relay isolation, power budget β are in HARDWARE.md.
Each zone runs an independent on/off threshold controller: a heater is driven while its own sensor reads below the shared desiredTemp setpoint, for as long as the countdown timer and START state remain active.
stateDiagram-v2
[*] --> Idle: Boot / STOP received
Idle --> Running: START received
Running --> Idle: STOP received\n(all outputs forced OFF)
Running --> Running: Read T1 / T2 every 1s
Running --> Idle: Countdown reaches 0\n(auto safety shutoff)
state Running {
[*] --> CheckZones
CheckZones --> UpperHeaterON: T1 < desiredTemp
CheckZones --> UpperHeaterOFF: T1 >= desiredTemp
CheckZones --> LowerHeaterON: T2 < desiredTemp
CheckZones --> LowerHeaterOFF: T2 >= desiredTemp
}
- Setpoint (
desiredTemp) and run duration (countdownTime) are both configurable at runtime over Bluetooth (TEMP:<val>,TIME:<sec>), with no reflash required. STOPand timer-expiry both perform a full safety shutoff β heaters, aeration, and their status LEDs are all forced off in the same code path.- The loop samples and updates once per second; command handling happens on every pass of
loop(), soSTART/STOPare responsive even mid-cycle.
| Command | Example | Action Taken |
|---|---|---|
START |
START |
Initiates the closed-loop process & timer |
STOP |
STOP |
Immediately cuts off all heaters and air pumps |
TEMP:<val> |
TEMP:37 |
Sets the desired thermal setpoint (37 Β°C) |
TIME:<sec> |
TIME:1800 |
Sets the process run timer (1800 s) |
AIR1:ON / AIR1:OFF |
AIR1:ON |
Toggles the primary aeration pump |
AIR2:ON / AIR2:OFF |
AIR2:ON |
Toggles the secondary aeration pump |
The controller streams T1:<value> and T2:<value> lines back over the same link once per second while the process is running, which the app parses to drive its live gauges.
The APP file is a KivyMD (Python) Android application that pairs with the HCβ05 module over classic Bluetooth SPP and provides:
- Live circular gauges for
T1andT2, color-coded by temperature band (Cold / Optimal / Warm / Hot) - Text fields to set the target temperature and run timer, transmitted as
TEMP:/TIME:commands - Toggle controls for both aeration channels
- Start / Stop buttons that mirror the firmware's
START/STOPcommands - A live hardware-status card showing connection state (
LIVE/SCAN/OFF)
It uses Android's native Bluetooth API via pyjnius, so it must be packaged with a tool such as Buildozer into an APK to run on-device β it will not run as a plain desktop Python script.
- Install the following libraries via the Arduino Library Manager:
OneWire(Paul Stoffregen)DallasTemperature(Miles Burton)LiquidCrystal_I2C(Frank de Brabander)
- Wire the hardware according to the pinout table above.
- Connect your Arduino Mega 2560, select the correct COM port, and upload
SystemUnite4.ino.
- Requires
kivy,kivymd, andpyjnius(Android-only Bluetooth bridge). - Package with Buildozer for Android; the native Bluetooth calls will not run on desktop Python.
- Pair your phone with the HCβ05/HCβ06 module beforehand β the app looks for a bonded device named
HC-05,HC-06, orSystemUnite.
| File | Role |
|---|---|
SystemUnite4.ino |
Main firmware β sensors, heater/aeration control, LCD, Bluetooth |
APP |
KivyMD Android companion app (Bluetooth control + live gauges) |
ARCHITECTURE.md |
Command-level logic flowchart and control-loop diagrams |
HARDWARE.md |
Full electrical specification, pinout, and wiring reference |
CONTRIBUTING.md |
Contribution guidelines |
LICENCE |
Project license |
docs/ |
Diagrams and images used in this README |
This is an active academic/lab project, not a finished production controller. Documented honestly for anyone building on it:
- Timing model: the main loop uses a blocking
delay(1000)for its once-per-second update, so Bluetooth commands are only read once per second rather than continuously. Amillis()-based non-blocking loop (as recommended inCONTRIBUTING.md) is a natural next step. - Threshold control, not hysteresis: heaters switch at a single
desiredTempboundary rather than a low/high hysteresis band, so relay chatter near the setpoint is possible β a hysteresis band would reduce relay wear. - No persistence:
desiredTempandcountdownTimereset to their defaults on every reboot; there is no EEPROM/NVS save of the last configuration. - Stirring/agitator relay reserved, not wired:
HARDWARE.mdand the architecture diagram reference an optional stirring motor channel that is not yet implemented inSystemUnite4.ino. - No watchdog or sensor-fault handling yet: unlike the hysteresis/safety layers in related ESP32-based incubator projects, this controller does not currently detect a disconnected DS18B20 or recover from a stuck relay automatically.
None of this blocks using the system as-is for supervised lab runs β it's simply the gap between the current firmware and a fully autonomous, unattended controller.
Project Leadership & Supervision
- Prof. Dr. Salah Badr β Principal Supervisor, Laboratory Host & Primary Sponsor
- Dr. Ragab Qasem β Main Co-Supervisor (Scientific & Engineering Lead)
- Dr. Omar β Co-Supervisor & Academic Mentor
- Mr. Mostafa Fathy β Lead Embedded Developer & Project Creator
Dr. Ragab Qasem is the main supervisor responsible for all scientific and engineering aspects of the project.
- Prof. Dr. Salah Badr β for direct supervision, funding the project, providing full access to his specialized research laboratory, and empowering the execution of this work.
- Dr. Ragab Qasem β for hands-on technical guidance, invaluable expertise, and dedication throughout every stage; his patience, problem-solving support, and scientific mentorship were foundational to this implementation.
- Dr. Omar β for the insightful advice and guidance that were the primary catalyst for initiating this project, and the continuous motivation that drove it to completion.
See CONTRIBUTING.md for how to report bugs, suggest new modules (e.g. pH or dissolved-oxygen sensors), and submit pull requests.
See the LICENCE file in this repository.
