Project Product Images:

Bilibili Video Link:
https://www.bilibili.com/video/BV1syFAe6Ee7/?share_source=copy_web&vd_source=097fdeaf6b6ecfed8a9ff7119c32faf2
(Material sharing can be found at the end of the article)
01
—
Project Overview
1. Function Details
STM32 Smart Greenhouse (Bluetooth Version)
The functions are as follows:
-
STM32F103C8T6 microcontroller as the main controller
-
Waterproof DS18B20 detects soil temperature. When the temperature exceeds the set maximum value, an audible and visual alarm is triggered, and the fan is turned on for cooling; when the temperature is below the set minimum value, an audible and visual alarm is triggered, and the heating element is turned on for heating.
-
The soil moisture module detects soil moisture. When the moisture is below the set minimum value, an audible and visual alarm is triggered, and the water pump is turned on to add water until the moisture exceeds the set maximum value;
-
The light-dependent resistor detects light intensity. When the light intensity is below the set minimum value, supplementary lighting is activated.
-
Threshold values can be set via buttons.
-
The OLED display shows measurement values.
-
The Bluetooth module sends measurement data to the mobile phone.
2. Bill of Materials
-
STM32F103C8T6 microcontroller
-
OLED screen
-
DS18B20 temperature sensor
-
Light sensor
-
Soil moisture sensor
-
BT04A Bluetooth module
-
Relay
-
Active buzzer
-
Heating element
-
Water pump
-
Fan module
-
LED lighting module
02
—
Schematic Design

03
—
PCB Hardware Design
PCB Diagram


04
—
Program Design
#include "sys.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "delay.h"
#include "gpio.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "ds18b20.h"
#include "adc.h"
int main(void){
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // Configure interrupt priority group
Delay_Init(); // Delay initialization
Gpio_Init(); // IO initialization
Key_Init(); // Key initialization
Oled_Init(); // OLED initialization
Oled_Clear_All(); // Clear screen
Usart1_Init(9600); // Serial port 1 initialization
DS18B20_Init(); // DS18B20 initialization
Adc_Init(); // ADC initialization
Delay_ms(1000);
Delay_ms(1000);
while(1) {
key_num = Chiclet_Keyboard_Scan(0); // Key scan
if(key_num != 0) { // If a key is pressed
switch(key_num) {
case 1: // Key 1, switch to settings interface
flag_display++;
if(flag_display >= 6)
flag_display = 0;
Oled_Clear_All(); // Clear screen
break;
case 2: // Key 2
switch(flag_display) {
case 1: // Interface 1: Temperature maximum value +1
if(temp_max < 99)
temp_max++;
break;
case 2: // Interface 2: Temperature minimum value +1
if(temp_min < temp_max-1)
temp_min++;
break;
case 3: // Interface 3: Humidity maximum value +1
if(soil_max < 99)
soil_max++;
break;
case 4: // Interface 4: Humidity minimum value +1
if(soil_min < soil_max-1)
soil_min++;
break;
case 5: // Interface 5: Light minimum value
if(light_min < 99)
light_min++;
break;
default:
break;
}
break;
case 3: // Key 3
switch(flag_display) {
case 1: // Interface 1: Temperature maximum value -1
if(temp_max > temp_min+1)
temp_max--;
break;
case 2: // Interface 2: Temperature minimum value -1
if(temp_min > 0)
temp_min--;
break;
case 3: // Interface 3: Humidity maximum value -1
if(soil_max > soil_min+1)
soil_max--;
break;
case 4: // Interface 4: Humidity minimum value -1
if(soil_min > 0)
soil_min--;
break;
case 5: // Interface 5: Light minimum value -1
if(light_min > 0)
light_min--;
break;
default:
break;
}
break;
default:
break;
}
}
if(flag_display == 0) { // Measurement interface
if(time_num % 5 == 0) { // Get data
temp_value = DS18B20_Get_Temp();
light_value = 99-30*(Get_Adc_Average(0,3)*3.3/4096.0);
soil_value = 99-30*(Get_Adc_Average(1,3)*3.3/4096.0);
}
if(time_num % 30 == 0) { // Send data
UsartPrintf(USART1,"Temperature: %d.%dC\r\n",temp_value/10,temp_value%10);
UsartPrintf(USART1,"Humidity: %d%%\r\n",soil_value);
UsartPrintf(USART1,"Light: %dLux\r\n",light_value);
}
}
switch(flag_display) { // Display different interfaces based on the display mode flag
case 0: // Interface 0: Display temperature, humidity, and light values
Oled_ShowCHinese(1,1,"Soil Environment Monitoring");
Oled_ShowCHinese(2,0,"Temperature:");
sprintf(display_buf,"%d.%dC ",temp_value/10,temp_value%10);
Oled_ShowString(2,6,display_buf);
Oled_ShowCHinese(3,0,"Humidity:");
sprintf(display_buf,"%d%% ",soil_value);
Oled_ShowString(3,6,display_buf);
Oled_ShowCHinese(4,0,"Light:");
sprintf(display_buf,"%dLux ",light_value);
Oled_ShowString(4,6,display_buf);
break;
case 1: // Interface 1: Set maximum temperature
Oled_ShowCHinese(1,0,"Set Maximum Temperature");
if(time_num % 5 == 0) {
sprintf(display_buf,"%d ",temp_max);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0) {
Oled_ShowString(2, 7, " ");
}
break;
case 2: // Interface 2: Set minimum temperature
Oled_ShowCHinese(1,0,"Set Minimum Temperature");
if(time_num % 5 == 0) {
sprintf(display_buf,"%d ",temp_min);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0) {
Oled_ShowString(2, 7, " ");
}
break;
case 3: // Interface 3: Set maximum humidity
Oled_ShowCHinese(1,0,"Set Maximum Humidity");
if(time_num % 5 == 0) {
sprintf(display_buf,"%d ",soil_max);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0) {
Oled_ShowString(2, 7, " ");
}
break;
case 4: // Interface 4: Set minimum humidity
Oled_ShowCHinese(1,0,"Set Minimum Humidity");
if(time_num % 5 == 0) {
sprintf(display_buf,"%d ",soil_min);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0) {
Oled_ShowString(2, 7, " ");
}
break;
case 5: // Interface 5: Set minimum light
Oled_ShowCHinese(1,0,"Set Minimum Light");
if(time_num % 5 == 0) {
sprintf(display_buf,"%d ",light_min);
Oled_ShowString(2, 7, display_buf);
}
if(time_num % 10 == 0) {
Oled_ShowString(2, 7, " ");
}
break;
default:
break;
}
if(flag_display == 0) { // Measurement interface
if(temp_value < temp_min*10) { // Temperature below minimum, turn on heating and alarm
flag_temp_min = 1;
flag_temp_max = 0;
FS = 0;
JR = 1;
} else if(temp_value > temp_max*10) { // Temperature above maximum, turn on fan and alarm
flag_temp_min = 0;
flag_temp_max = 1;
FS = 1;
JR = 0;
} else { // Temperature between both, turn off fan, heating, and alarm
flag_temp_min = 0;
flag_temp_max = 0;
FS = 0;
JR = 0;
}
if(soil_value < soil_min) { // Humidity below minimum, turn on water pump and alarm
flag_soil_min = 1;
JS = 1;
} else if(soil_value > soil_max) { // Humidity above maximum, turn off water pump and alarm
flag_soil_min = 0;
JS = 0;
} else { // Humidity between both, turn off alarm
flag_soil_min = 0;
}
if(light_value < light_min) // Light below minimum, turn on supplementary lighting
BG = 1;
else // Light above minimum, turn off supplementary lighting
BG = 0;
if(flag_temp_min == 1 || flag_temp_max == 1 || flag_soil_min == 1) {
if(time_num % 3 == 0) { // Turn on alarm
LED = ~LED;
BEEP = ~BEEP;
}
} else { // Turn off alarm
LED = 1;
BEEP = 0;
}
} else { // Settings interface
LED = 1;
BEEP = 0;
FS = 0;
JS = 0;
JR = 0;
BG = 0;
}
time_num++; // Increment timer variable
Delay_ms(10);
if(time_num %10 == 0)
LED_SYS = ~LED_SYS;
if(time_num >= 5000) {
time_num = 0;
}
}
05
—
Experimental Results


Material Sharing (Baidu Cloud)
https://pan.baidu.com/s/13ZlmGxD4WajGlw1-is9YmQ?pwd=ksn4 Extraction Code: ksn4
(Or scan the QR code below to obtain)
For physical purchases, scan the QR code below