G2: Autonomous Greenhouse Environment Controller - shalan/CSCE4301-WiKi GitHub Wiki
Autonomous Greenhouse Environment Controller
| Name | GitHub |
|---|---|
| Arwa Abdelkarim | arwaabdelkarim |
| Kareem Elnaghy | kareemelnaghy |
| Rana Taher | rana5679 |
Github Repo: https://github.com/KareemElnaghy/Autonomous-Greenhouse-Environment-Controller.git
1. The Proposal
Abstract / Elevator Pitch:
Growing plants in a greenhouse means constantly juggling temperature, humidity, light, and watering. And getting any one of them wrong can damage or kill your plants. Most small greenhouses are managed manually, which means someone has to physically check on conditions regularly and intervene when something is off. This is tedious, error-prone, and simply not possible around the clock, requiring continuous monitoring which is difficult.
Our project is an embedded system that automates this entire process. It monitors soil moisture, air temperature, humidity, and light levels in real time, and automatically triggers the right response whether that's turning on a water pump, spinning up a ventilation fan, or switching on a grow light whenever conditions drift outside the configured safe range for the plant being grown.
The system is also designed to be genuinely useful beyond a single plant type. By letting the user configure thresholds for any plant's specific needs. Our system effectively turns any greenhouse into a tailored growing environment, adapting to what that plant actually needs rather than applying a one-size-fits-all approach. Adjusting these settings is done wirelessly from a phone over Bluetooth, and day-to-day monitoring happens entirely through the OLED screen.
Project Objectives & Scope:
Objectives:
- Sensors continuously monitor soil moisture, air temperature, humidity, and light levels, each triggering their corresponding actuator automatically when conditions fall outside the configured range
- All sensor reads are interrupt-driven, running under RTOS on the MCU with separate prioritised tasks per subsystem
- Safety interlock logic prevents conflicting actuator states and gates the water pump if the water level is low
- Live sensor readings and active alerts are shown on an OLED display, warnings displayed via LEDs and Buzzers
- Plant thresholds are configurable wirelessly from a phone over Bluetooth
Stretch Goals:
- Accommodation for multiple named plant profiles stored on the device and switchable
- Timestamped event logging to a form of memory for review to further develop and optimize configurations
- CO2 levels monitoring
2. System Architecture
2.1 High-Level Block Diagram:
Subsystem Breakdown:
Watering subsystem monitors soil moisture via an ADC interrupt-driven soil moisture sensor and a water level sensor. When soil moisture drops below the configured dry threshold and the reservoir is not empty, the subsystem activates the water pump relay for a fixed duration, then enforces a cooldown period before the next watering cycle can trigger. All readings are published to shared globals for the display layer to consume.
Light subsystem continuously reads light intensity from a TEMT6000 phototransistor via ADC. When light falls below the configured threshold, it drives a TIP122 transistor via TIM1 PWM to power an LED grow light strip, with brightness inversely proportional to current light level. When sufficient light is detected the strip is dimmed to zero.
Climate subsystem reads temperature and humidity from a DHT22 sensor over a GPIO pin, timed using TIM2 at 1µs resolution. Based on humidity readings it drives a ventilation fan via TIM1 PWM Channel 3 at three discrete speeds (off, 50%, and full) according to configurable humidity thresholds. And based on the temperature thresholds it activates and disables the peltier to cool the greenhouse.
Display and input layer runs in the defaultTask and owns the LCD exclusively. It renders one of four screens corresponding to each subsystem watering, light, climate, or settings and refreshing every 500ms from the shared sensor globals. Screen navigation is handled by both a physical keypad (scanned every 50ms) and a UART serial interface (used mainly for debugging), allowing the user to cycle between views and enter a settings menu where all thresholds can be adjusted at runtime without reflashing. Settings changes take effect immediately since all subsystem tasks read thresholds from shared volatile globals.
The subsystems interact exclusively through shared volatile globals and a FreeRTOS message queue where sensor tasks write readings and the display task reads them, with an LCD mutex preventing shared display access. No subsystem task touches the LCD directly.
3. Hardware Design
Component Selection:
| STM32 Nucleo-L432KC | Capacitive Soil Moisture Sensor | Water Level Sensor |
|---|---|---|
| TEMT6000 Light Sensor | DHT22 (Temp + Humidity) | 16x2 LCD with I2C Backpack |
| 4x4 Matrix Keypad (PmodKYPD) | Relay Board | TIP122 Transistor |
| Water Pump | 12V DC Fan | 12V LED Grow Light Strip |
| Resistors | GPIO Expander (PCF8574) | Peltier |
| Voltage Regulator | ||
Schematics & Wiring:
STM32 Nucleo-L432KC Pin Assignments
| Pin | Label | Connected To | Interface | Notes |
|---|---|---|---|---|
| PA0 | ADC_Light_Sensor | TEMT6000 SIG | ADC1_IN5 | 10kΩ pull-down resistor to GND |
| PA1 | ADC_Soil_Moisture | Capacitive moisture sensor SIG | ADC1_IN6 | Analog voltage 0–3.3V |
| PA2 | VCP_TX | ST-Link (USB serial) | USART2 TX | Debug UART output |
| PA3 | VCP_RX | ST-Link (USB serial) | USART2 RX | Debug UART input |
| PA4 | GPIO_Water | Relay board IN1 | GPIO Output | Active LOW — HIGH = relay OFF at boot |
| PA7 | ADC_Water_Level | Water level sensor SIG | ADC1_IN12 | Analog voltage 0–3.3V |
| PA8 | TIM1_CH1 | TIP122 Base (via 1kΩ) | TIM1 PWM CH1 | PWM for grow light brightness |
| PA10 | TIM1_CH3 (AF) | Fan PWM control | TIM1 PWM CH3 | PWM for ventilation fan speed |
| PB3 | LD3 | Onboard green LED | GPIO Output | Onboard indicator |
| PBx | GPIO_Pelt | Relay board IN2 | GPIO Output | Active LOW — controls peltier + cooling fan via relay CH2. |
| PBx | GPIO_DHT | DHT22 data pin | GPIO Bi-directional | 4.7kΩ pull-up to 3.3V. |
| PB6 | I2C1_SDA | LCD backpack SDA | I2C1 | Shared I2C bus |
| PB7 | I2C1_SCL | LCD backpack SCL | I2C1 | Shared I2C bus |
I2C Bus Devices
| Device | I2C Address | Connected To |
|---|---|---|
| LCD backpack (PCF8574) | 0x27 | I2C1 (PB6 SDA, PB7 SCL) |
| Keypad I2C expander (PCF8574) | 0x20 | I2C1 (PB6 SDA, PB7 SCL) |
Relay Board Connections
| Channel | Nucleo Control Pin | Load | Load Voltage |
|---|---|---|---|
| CH1 | PA4 | Submersible water pump | 5V |
| CH2 | PBx (GPIO_Pelt) | Peltier module + cooling fan (parallel) | 12V |
Timer Channels
| Timer | Channel | Pin | Function |
|---|---|---|---|
| TIM1 | CH1 | PA8 | Grow light PWM (brightness inversely proportional to lux) |
| TIM1 | CH3 | PA10 | Ventilation fan PWM (3-stage: OFF / 50% / 100%) |
| TIM2 | — | — | 1µs tick counter for DHT22 bit-bang timing |
Power Connections
| Rail | Source | Powers |
|---|---|---|
| 3.3V | Nucleo onboard regulator | STM32, all sensors, LCD, DHT22 |
| 5V | External 5V adapter | Relay board VCC, PmodKYPD, water pump load |
| 12V | External 12V adapter | LED grow strip, ventilation fan, peltier module + cooling fan |
| GND | Common ground | All components share a common ground |
Bill of Materials (BOM):
| Component | Part Number | Quantity | Cost (EGP) | Datasheet |
|---|---|---|---|---|
| Microcontroller | STM32L432KC (Nucleo-32) | 1 | 750 | Datasheet |
| Soil Moisture Sensor | FC-28 | 1 | 65 | Datasheet |
| Light Intensity Sensor | TEMT6000 | 1 | 316 | Datasheet |
| Temperature & Humidity Sensor | DHT 22 | 1 | 285 | Datasheet |
| Water Level Sensor | HW-038 | 1 | 40 | Datasheet |
| Peltier | - | 1 | 120 | - |
| Water Pump | - | 1 | 90 | - |
| Matrix Keypad | PmodKYPD | 1 | 100 | - |
| LCD Display | 16×2 (HD44780) | 1 | 70 | Datasheet |
| Total | 1836 EGP |
Power Budget:
All calculations use P = V × I.
3.3V Rail
| Component | Voltage | Typical Current | Power |
|---|---|---|---|
| STM32L432KC (core + peripherals) | 3.3V | 25mA | 82.5mW |
| Capacitive soil moisture sensor | 3.3V | 5mA | 16.5mW |
| Water level sensor | 3.3V | 5mA | 16.5mW |
| TEMT6000 light sensor | 3.3V | 1mA | 3.3mW |
| DHT22 | 3.3V | 1.5mA | 4.95mW |
| 16x2 LCD + I2C backpack | 3.3V | 25mA | 82.5mW |
| 3.3V Rail Total | 63.5mA | 209.5mW |
5V Rail
| Component | Voltage | Typical Current | Power |
|---|---|---|---|
| PmodKYPD keypad | 5V | 1mA | 5mW |
| Relay board coil — Channel 1 (pump) | 5V | 36mA | 180mW |
| Relay board coil — Channel 2 (fan + peltier) | 5V | 36mA | 180mW |
| Submersible water pump (via relay CH1) | 5V | 200mA | 1000mW |
| 5V Rail Total | 273mA | 1365mW |
12V Rail
| Component | Voltage | Typical Current | Power |
|---|---|---|---|
| LED grow light strip (1m, via TIP122) | 12V | 500mA | 6000mW |
| Ventilation fan (via relay CH2) | 12V | 200mA | 2400mW |
| Peltier module (via relay CH2, parallel with fans) | 12V | 400mA | 4800mW |
| Peltier cooling fan (attached to peltier heatsink) | 12V | 200mA | 2400mW |
| 12V Rail Total | 1300mA | 15600mW |
There is enough headroom between what the power supply delivers and what our components draw.
4. Software Implementation
4.1 Software Architecture:
The system's firmware runs on FreeRTOS (CMSIS-V2) on the STM32 Nucleo-L432KC. The system is fully interrupt-driven with no polling loops anywhere in the code and sensors are read either via hardware ADC interrupts or via timed GPIO bit-banging with interrupts disabled only during critical timing windows.
We organised the system into four FreeRTOS tasks, each owning a distinct subsystem:
| Task | Priority | Stack | Responsibility |
|---|---|---|---|
defaultTask |
Normal | 512 words | LCD rendering, keypad scanning, UART input handling, screen state machine |
StartWatering |
Low | 128 words | Soil moisture ADC, water level ADC, pump relay control, cooldown logic |
StartLightCtrl |
Low | 128 words | Light sensor ADC, grow light PWM duty cycle via TIM1 CH1 |
StartClimateCtrl |
Low | 128 words | DHT22 bit-bang read, fan PWM speed control via TIM1 CH3 |
Tasks communicate through shared volatile globals and a FreeRTOS message queue. The LCD is protected by a mutex so only one task can write to it at a time. The defaultTask owns the display entirely and all other tasks update globals which the display task reads on its 500ms refresh cycle. A FreeRTOS semaphore prevents concurrent pump activations, and a one-shot software timer enforces the post-watering cooldown period before the next pump cycle is allowed, to allow time for the soil to absorb the water.
4.2 Flowcharts & State Machines:
4.3 Key Algorithms:
The core control logic across all three subsystems uses a simple closed-loop control where an actuator has two states (on/off) determined by whether a sensor reading crosses a configured threshold. When soil moisture drops below the dry threshold the pump turns on; when light drops below the lux threshold the grow light turns on.
The ventilation fan uses three-state hysteresis controller to have three different modes based on two thresholds.
PWM is used to have different the led strip glow with different light intensities according to the light sensor readings.
4.4 Development Environment:
- STM32CubeMX was used for peripheral and pin configuration. Used to configure ADC, I2C, UART, TIM1, TIM2, GPIO, and FreeRTOS middleware with auto-generated HAL initialisation code.
- FreeRTOS was used to accommodate for our real time requirements and provided task scheduling, queues, mutexes, semaphores, and software timers.
- Keil MDK was used to build and compile our code and to debug.
- GitHub was used for version control and to host our wiki page.
5. Testing, Validation & Debugging
5.1 Unit Testing:
Watering subsystem
- The water pump functionality was tested to find out the duration of each pump.
- The soil moisture sensor was tested and a correct soil moisture threshold was derived.
- The water pump was tested with the soil moisture to make sure it only wrks when the moisture level is less than the threshold.
- Water level sensor was tested and a correct threshold of the tank water level was derived.
- The entire subsystem was tested to check that the pump only works when water level is high and the soil is dry.
Light subsystem
- The light intensity sensor was tested to figure out the light threshold.
- The lights were tested by changing the duty cycle of the pwm signal and checking the light intensity.
- The whole subsystem was tested to make sure that the light intensity changes based on the amount of light detected by the light intensity sensor.
Climate subsystem
- Fan was tested by changing the duty cycle of the pwm signal.
- The DHT22 sensor was tested to check the temperature and humidity readings.
- Fan was tested to check it works as the humidity passes a certain threshold.
- Peltier was tested to see if it cools when temperature is too high and stops when it is not.
- The whole entire subsystem was then tested.
Display and input layer
- LCD screen was tested to see if it displays the current readings for soil moisture, temperature, humidity, light intensity, and water level.
- The keypad was tested with the screen to see if the changes reflect on the screen.
5.2 Integration Testing:
Ran the entire systema and played with environmental conditions in order to see whether the expected actuator would trigger i.e. increased humidity to see if ventilation fan would activate, varied light source in the room to see how the LED strips would change, etc.
5.3 Challenges & Solutions:
- MCU pin interferance
- Problem: Pin PA6 on the Nucleo board caused the LCD screen to malfunction as it was interfering with the I2C pin
- Solution: Leaving the pin unused
- Measurement inaccuracies
- Problem: The temperature/humidity sensor we had at first was inaccurate
- Solution: we used the DHT22 sensor which is more accurate.
- LED lights
- Problem: The pins attached to the LED lights we used were too short
- Solution: we had to attach longer pins to it to be able to connect it properly to the wires.
- Keypad
- Problem: the keypad needed 8 GPIO pins and we did not have enough pins for it
- Solution: We used a GPIO Expander for the keypad
- Water level sensor
- Problem: Did not know how to attach it to the water it tank, so that only the sensor is submerged in water and not the wires attached to it
- Solution: Made it float in the water by attaching styrofoam to it
- Power Supply
- Problem: We have only one power supply, but different components need different input voltages. water pump needs 5V, Nucleo needs 5v, peltier needs 12V, Fan needs 12V, and Lights need 12V.
- Solution: We kept the DC supply at 12V and used a voltage regulator to get 5V.
6. Results & Demonstration
6.1 Final Prototype:
6.2 Video Demonstration:
Here is a link with several short video demos for each of our subsystems: Video Demos
6.3 Presentation Slides
Proposal Presentation Slides Progress Presentation Slides Final Presentation Slides
7. Project Management
7.1 Division of Labor:
- Kareem worked on climate subsystem and light subsystem (Sensor)
- Rana worked on water subsystem and light subsystem (LED Strip)
- Arwa worked on LCD Display, Keypad and Testing
7.2 Timeline:
| Date | Milestone | Deliverable / Task | Status |
|---|---|---|---|
| Mon, Mar 30, 2026 | Project kick-off | Project handout issued. Team brainstorming begins. | Done |
| Tue, Apr 14, 2026 | Milestone 1: Team formation | Team formed, roles assigned across hardware, control logic, and UI/comms. | Done |
| Wed, Apr 15, 2026 | Milestone 2: Proposal presentation | In-class presentation covering problem statement, block diagram, sensor/actuator choices, and FreeRTOS task structure. | Done |
| Mon, Apr 20, 2026 | Checkpoint A: Wiki/page setup | Wiki page live with approved proposal, block diagram, component list, and functional requirements. | Done |
| Tue, Apr 22, 2026 | Hardware sourcing | SHT31, BH1750, moisture sensor, float switch, SSD1306 OLED, ESP32, and Nucleo all in hand. | Done |
| Thu, Apr 24, 2026 | Dev environment setup | STM32CubeIDE with RTOS configured on Nucleo. ESP32 Bluetooth serial confirmed working with phone. | Done |
| Wed, Apr 29, 2026 | Milestone 3: Progress presentation & demo | Live demo of at least one complete interrupt-driven sensor loop i.e. sensor firing, RTOS task responding, actuator switching correctly. | Done |
| Fri, May 2, 2026 | All sensor interrupts working | All sensors wired to Nucleo. ISRs confirmed firing and posting to RTOS queues correctly. | Done |
| Mon, May 4, 2026 | Actuator control + interlock | Pump, fan, and grow light switching correctly per thresholds. Interlock FSM preventing conflicting states. | Done |
| Wed, May 6, 2026 | Checkpoint B: Integration update | Wiki updated showing which subsystem loops are integrated, any wiring or timing issues found, and plan for final week. | Done |
| Fri, May 8, 2026 | OLED + Bluetooth config | OLED displaying live readings and alerts. Thresholds adjustable from phone over Bluetooth. | Done |
| Mon, May 11, 2026 | Full system integration | All three subsystem loops running together under RTOS. System stable over an extended run with no task starvation or interlock violations. | Done |
| Wed, May 13, 2026 | Milestone 4: Final demo & presentation | Final in-class presentation and live demo of the complete system. Final code and completed wiki page submitted. | — |
8. Appendices & References
8.1 Source Code Repository:
Github Repo: https://github.com/KareemElnaghy/Autonomous-Greenhouse-Environment-Controller.git