Design of flower greenhouse temperature control system based on STM32

I. Introduction

As people's demand for flower cultivation continues to grow, the construction and management of flower greenhouses has become an important topic. In flower greenhouses, temperature is a crucial environmental parameter that has a direct impact on the growth and development of flowers. In order to provide a stable growing environment, it becomes very important to control the temperature of the greenhouse.

This project designs a flower greenhouse temperature control system based on STM32 microcontroller. The system uses STM32F103C8T6 as the main control chip to monitor and control the temperature in the greenhouse through connection with hardware modules such as DS18B20 temperature sensor and 0.96-inch OLED display. At the same time, the system is also equipped with two independent buttons for setting the temperature threshold.

The temperature sensor uses DS18B20, which can accurately monitor the temperature in the greenhouse. Temperature data can be obtained in real time through communication with the STM32 microcontroller. The display uses a 0.96-inch OLED display with SPI protocol, which is used to display the temperature of the current environment and the temperature threshold. Users can set the temperature threshold through buttons so that the system can control the temperature according to the set threshold.

When the temperature is lower than the set temperature threshold, the system will control the hot air fan through the relay to heat and blow out hot air to control the room temperature. By monitoring the temperature in real time and controlling it according to the set threshold, the system can maintain the temperature in the greenhouse within a suitable range and provide a stable growth environment for flowers.

The project is designed to increase the automation of flower greenhouses and reduce the burden of manual management, while providing a stable temperature control solution to promote the growth and development of flowers. By using STM32 microcontrollers and related hardware modules, the system can achieve real-time monitoring and automatic control of temperature, providing a convenient and efficient solution for flower greenhouse managers.

image-20230802154655957

The final system model diagram after adding remote control:

image-20230802154537086

2. Introduction to hardware selection

The following is the hardware selection of the flower greenhouse temperature control system based on STM32:

【1】Main control chip: STM32F103C8T6

  • The STM32F103 series has good performance and rich peripherals, making it suitable for embedded applications.
  • STM32F103C8T6 is a 32-bit ARM Cortex-M3 core microcontroller with 64KB Flash memory and 20KB RAM.

【2】Temperature sensor: DS18B20

  • DS18B20 is a digital temperature sensor that uses a single bus interface for communication.
  • It has the characteristics of high precision, waterproof and dustproof, and is very suitable for measuring the temperature in the greenhouse.
  • Connect to the GPIO port of STM32 through pins and use OneWire protocol for data communication.

【3】Display: 0.96-inch OLED display

  • Choose a 0.96-inch OLED display that supports SPI protocol as the display device, which can easily display the ambient temperature and temperature threshold.
  • OLED displays have the advantages of low power consumption, high contrast, and wide viewing angles, making them suitable for embedded applications.

【4】Buttons: two independent buttons

  • Select two independent buttons for setting the temperature threshold, which can be increased or decreased by pressing the button.

【5】Relay: used to control hot air fan heating

  • According to the temperature threshold and real-time temperature data, the switch of the relay is controlled through the GPIO port of STM32 to control the heating of the hot air fan.
  • The selection of the relay should be determined based on the rated current and voltage of the hot air blower to ensure normal operation.

3. Design ideas

Software logic design ideas:

【1】Initialize STM32 peripherals, including GPIO, SPI, USART, etc.

【2】Set the initial value of the temperature threshold and adjust the threshold through the buttons.

【3】Loop to read the data of DS18B20 temperature sensor and compare the read temperature value with the threshold value.

【4】If the current temperature is lower than the threshold, the control relay is closed and the hot air fan starts heating; otherwise, the relay is opened to stop heating.

【5】Display the temperature value and threshold value on the OLED screen and output them to the user through the USART serial port.

【6】Continuously execute the above steps in a cycle to realize the automatic temperature control function of the greenhouse.

pseudocode:

// 定义变量
float temperature;  // 当前温度值
float threshold;    // 温度阀值

// 初始化硬件和外设
void initialize() {
    
    
    initialize_GPIO();     // 初始化GPIO
    initialize_SPI();      // 初始化SPI
    initialize_USART();    // 初始化USART
    initialize_DS18B20();  // 初始化DS18B20
    initialize_OLED();     // 初始化OLED显示屏
    initialize_Button();   // 初始化按键
    initialize_Relay();    // 初始化继电器
}

// 读取温度值
float readTemperature() {
    
    
    // 通过DS18B20读取温度值
    // 返回温度值
}

// 读取阀值
float readThreshold() {
    
    
    // 读取按键的状态,并调节阀值
    // 返回阀值
}

// 控制加热器
void controlHeater(float currTemperature, float currThreshold) {
    
    
    if (currTemperature < currThreshold) {
    
    
        // 温度低于阀值,控制继电器闭合,热风机加热
    } else {
    
    
        // 温度高于或等于阀值,打开继电器,停止加热
    }
}

// 显示温度和阀值
void displayTemperature(float currTemperature, float currThreshold) {
    
    
    // 在OLED屏幕上显示温度值和阀值
    // 通过USART串口输出温度值和阀值
}

// 主函数
int main() {
    
    
    initialize();  // 初始化
    
    while (1) {
    
    
        temperature = readTemperature();          // 读取温度值
        threshold = readThreshold();              // 读取阀值
        controlHeater(temperature, threshold);     // 控制加热器
        displayTemperature(temperature, threshold);// 显示温度和阀值
    }

    return 0;
}

The above are the basic software logic design ideas and pseudo code.

4. Code implementation

4.1 Read the temperature display

The following is the implementation code for using STM32F103C8T6 to read DS18B20 temperature sensor data and display the temperature on the OLED display:

#include "stm32f10x.h"
#include "delay.h"
#include "onewire.h"
#include "ds18b20.h"
#include "ssd1306.h"

int main(void)
{
    
    
    // 初始化延迟函数
    delay_init();
    
    // 初始化OLED显示屏
    SSD1306_Init();
    
    // 初始化DS18B20温度传感器
    DS18B20_Init();
    
    float temperature = 0.0;
    char tempStr[10];
    
    while (1)
    {
    
    
        // 读取DS18B20温度传感器数据
        temperature = DS18B20_GetTemp();
        
        // 将温度转换为字符串
        sprintf(tempStr, "%.2f C", temperature);
        
        // 清空OLED显示屏
        SSD1306_Clear();
        
        // 在OLED显示屏上显示温度
        SSD1306_GotoXY(0, 0);
        SSD1306_Puts("Temperature:", &Font_7x10, SSD1306_COLOR_WHITE);
        SSD1306_GotoXY(0, 20);
        SSD1306_Puts(tempStr, &Font_11x18, SSD1306_COLOR_WHITE);
        
        // 刷新OLED显示屏
        SSD1306_UpdateScreen();
        
        // 延时一段时间
        delay_ms(1000);
    }
}

In the code, packaged library files are used, including library files for delay function (delay.h), OneWire bus (onewire.h), DS18B20 temperature sensor (ds18b20.h) and SSD1306 OLED display (ssd1306.h).

In the main function, initialize the delay function and OLED display, and initialize the DS18B20 temperature sensor. Then enter an infinite loop, read the temperature data of the DS18B20 temperature sensor in the loop, and display the temperature on the OLED display. The temperature data is converted into a string through the sprintf function and displayed on the OLED display using the SSD1306 library function. Delay for a period of time through the delay function to achieve regular updates of the temperature.

4.2 DS18B20 code

Header file code:

#ifndef DS18B20_H
#define DS18B20_H

#include "stm32f10x.h"

// DS18B20引脚定义
#define DS18B20_GPIO_PORT   GPIOA
#define DS18B20_GPIO_PIN    GPIO_Pin_0

// DS18B20函数声明
void DS18B20_Init(void);
void DS18B20_WriteByte(uint8_t data);
uint8_t DS18B20_ReadByte(void);
float DS18B20_GetTemp(void);

#endif

Source file code:

#include "ds18b20.h"
#include "delay.h"

// 初始化DS18B20温度传感器
void DS18B20_Init(void)
{
    
    
    GPIO_InitTypeDef GPIO_InitStructure;
    
    // 使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置GPIOA引脚为推挽输出
    GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
    
    // 将引脚拉低一段时间
    GPIO_ResetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
    delay_us(500);
    
    // 将引脚拉高一段时间
    GPIO_SetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
    delay_us(80);
    
    // 等待DS18B20的响应
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
    delay_us(80);
}

// 向DS18B20写入一个字节的数据
void DS18B20_WriteByte(uint8_t data)
{
    
    
    uint8_t i;
    
    // 将引脚设置为推挽输出
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
    
    // 写入数据
    for (i = 0; i < 8; i++)
    {
    
    
        GPIO_ResetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
        delay_us(2);
        if (data & 0x01)
        {
    
    
            GPIO_SetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
        }
        delay_us(60);
        GPIO_SetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
        delay_us(2);
        data >>= 1;
    }
}

// 从DS18B20读取一个字节的数据
uint8_t DS18B20_ReadByte(void)
{
    
    
    uint8_t i, data = 0;
    
    // 将引脚设置为推挽输出
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
    
    // 读取数据
    for (i = 0; i < 8; i++)
    {
    
    
        GPIO_ResetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
        delay_us(2);
        GPIO_SetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
        delay_us(2);
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
        delay_us(2);
        data >>= 1;
        if (GPIO_ReadInputDataBit(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN))
        {
    
    
            data |= 0x80;
        }
        delay_us(60);
    }
    
    return data;
}

// 获取DS18B20温度数据
float DS18B20_GetTemp(void)
{
    
    
    uint8_t tempLSB, tempMSB;
    int16_t tempData;
    float temperature;
    
    // 发送温度转换命令
    DS18B20_WriteByte(0xCC);     // 跳过ROM操作
    DS18B20_WriteByte(0x44);     // 发送温度转换命令
    
    // 等待温度转换完成
    while (!GPIO_ReadInputDataBit(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN));
    
    // 发送读取温度命令
    DS18B20_WriteByte(0xCC);     // 跳过ROM操作
    DS18B20_WriteByte(0xBE);     // 发送读取温度命令
    
    // 读取温度数据
    tempLSB = DS18B20_ReadByte();
    tempMSB = DS18B20_ReadByte();
    
    // 计算温度值
    tempData = (tempMSB << 8) | tempLSB;
    if (tempData & 0x8000)      // 温度为负数
    {
    
    
        tempData = ~tempData + 1;
        temperature = -((float)tempData / 16.0);
    }
    else                        // 温度为正数
    {
    
    
        temperature = (float)tempData / 16.0;
    }
    
    return temperature;
}

4.3 OLED display code

head File:

#ifndef SSD1306_H
#define SSD1306_H

#include "stm32f10x.h"
#include "fonts.h"

// SSD1306显示屏参数定义
#define SSD1306_I2C_ADDR      0x78    // I2C地址
#define SSD1306_WIDTH         128     // 显示屏宽度
#define SSD1306_HEIGHT        64      // 显示屏高度

// SSD1306函数声明
void SSD1306_Init(void);
void SSD1306_Clear(void);
void SSD1306_UpdateScreen(void);
void SSD1306_GotoXY(uint16_t x, uint16_t y);
void SSD1306_Puts(const char* str, FontDef_t* font, uint8_t color);

#endif

Source File:

#include "ssd1306.h"
#include "i2c.h"

static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8];

void SSD1306_Init(void)
{
    
    
    // 初始化I2C总线
    I2C_Init();
    
    // 向SSD1306发送初始化命令
    uint8_t initCommands[] = {
    
    
        0xAE,           // 关闭显示
        0xD5, 0x80,     // 设置时钟分频因子
        0xA8, 0x3F,     // 设置驱动路数
        0xD3, 0x00,     // 设置显示偏移
        0x40,           // 设置显示开始行
        0x8D, 0x14,     // 设置电荷泵
        0x20, 0x00,     // 设置内存地址模式
        0xA1,           // 设置段重定义
        0xC8,           // 设置COM扫描方向
        0xDA, 0x12,     // 设置COM引脚配置
        0x81, 0xCF,     // 设置对比度控制
        0xD9, 0xF1,     // 设置预充电周期
        0xDB, 0x40,     // 设置VCOMH电压倍率
        0xA4,           // 全局显示开启
        0xA6,           // 设置显示方式
        0xAF            // 开启显示
    };
    
    for (uint8_t i = 0; i < sizeof(initCommands); i++)
    {
    
    
        I2C_WriteByte(SSD1306_I2C_ADDR, 0x00, initCommands[i]);
    }
    
    // 清空缓冲区
    SSD1306_Clear();
    
    // 更新显示屏
    SSD1306_UpdateScreen();
}

void SSD1306_Clear(void)
{
    
    
    memset(SSD1306_Buffer, 0x00, sizeof(SSD1306_Buffer));
}

void SSD1306_UpdateScreen(void)
{
    
    
    for (uint8_t i = 0; i < 8; i++)
    {
    
    
        I2C_WriteBuffer(SSD1306_I2C_ADDR, 0x40, &SSD1306_Buffer[SSD1306_WIDTH * i], SSD1306_WIDTH);
    }
}

void SSD1306_GotoXY(uint16_t x, uint16_t y)
{
    
    
    if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT)
        return;
    
    SSD1306_Buffer[(x + (y / 8) * SSD1306_WIDTH)] |= (1 << (y % 8));
}

void SSD1306_Puts(const char* str, FontDef_t* font, uint8_t color)
{
    
    
    while (*str)
    {
    
    
        for (uint8_t i = 0; i < font->FontWidth; i++)
        {
    
    
            uint8_t temp = font->data[(*str - 32) * font->FontWidth + i];
            for (uint8_t j = 0; j < font->FontHeight; j++)
            {
    
    
                if (temp & (1 << j))
                {
    
    
                    SSD1306_GotoXY(font->FontWidth * i + j, font->FontHeight * i + j);
                    SSD1306_Buffer[(font->FontWidth * i + j + (font->FontHeight * i + j) / 8 * SSD1306_WIDTH)] |= (1 << ((font->FontHeight * i + j) % 8));
                }
                else
                {
    
    
                    SSD1306_GotoXY(font->FontWidth * i + j, font->FontHeight * i + j);
                    SSD1306_Buffer[(font->FontWidth * i + j + (font->FontHeight * i + j) / 8 * SSD1306_WIDTH)] &= ~(1 << ((font->FontHeight * i + j) % 8));
                }
            }
        }
        
        str++;
    }
}

5. Summary

This project designs a flower greenhouse temperature control system based on STM32. By using hardware modules such as DS18B20 temperature sensor, OLED display and relay, the temperature in the greenhouse is monitored and controlled. The system can automatically control the heating of the hot air fan according to the preset temperature threshold to maintain the appropriate temperature in the greenhouse to ensure the growth environment of flowers.

In terms of software logic design, STM32 peripherals and interrupt mechanisms are used, combined with appropriate algorithms and status judgments, to achieve the acquisition and comparison of temperature data, and control the switching of the relay based on the results. Through the OLED display and USART serial port, the temperature value and threshold can be fed back to the user in a timely manner, making it easier for the user to understand the current environment and make adjustments.

The design and implementation of this project provides a specific solution for the greenhouse temperature control system. Through reasonable hardware selection and software logic design, it can meet the temperature control needs of flower planting. In future development, the system will play an important role in the agricultural field and create a more comfortable and efficient temperature-controlled environment for people.

Guess you like

Origin blog.csdn.net/xiaolong1126626497/article/details/133266452