• 方案介紹
    • 一、前言
    • 二、硬件選型介紹
    • 三、設(shè)計(jì)思路
    • 四、代碼實(shí)現(xiàn)
    • 五、總結(jié)
  • 附件下載
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

基于STM32的花卉溫室控溫系統(tǒng)設(shè)計(jì)

3小時(shí)前
153
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

更多詳細(xì)資料請(qǐng)聯(lián)系.docx

共1個(gè)文件

一、前言

隨著人們對(duì)花卉養(yǎng)殖的需求不斷增長(zhǎng),花卉溫室的建設(shè)和管理成為了一個(gè)重要的課題。在花卉溫室中,溫度是一個(gè)至關(guān)重要的環(huán)境參數(shù),對(duì)花卉的生長(zhǎng)和發(fā)展有著直接的影響。為了提供一個(gè)穩(wěn)定的生長(zhǎng)環(huán)境,控制溫室的溫度變得非常重要。

本項(xiàng)目設(shè)計(jì)一個(gè)基于STM32微控制器的花卉溫室控溫系統(tǒng)。該系統(tǒng)利用STM32F103C8T6作為主控芯片,通過(guò)與DS18B20溫度傳感器和0.96寸OLED顯示屏等硬件模塊的連接,實(shí)現(xiàn)對(duì)溫室內(nèi)溫度的監(jiān)測(cè)和控制。同時(shí),系統(tǒng)還配備了兩個(gè)獨(dú)立按鍵,用于設(shè)置溫度閥值。

溫度傳感器采用DS18B20,能夠準(zhǔn)確地監(jiān)測(cè)溫室內(nèi)的溫度。通過(guò)與STM32微控制器的通信,可以實(shí)時(shí)獲取溫度數(shù)據(jù)。顯示屏采用SPI協(xié)議的0.96寸OLED顯示屏,用于顯示當(dāng)前環(huán)境的溫度以及溫度閥值。用戶可以通過(guò)按鍵設(shè)置溫度閥值,以便系統(tǒng)能夠根據(jù)設(shè)定的閥值進(jìn)行溫度控制。

當(dāng)溫度低于設(shè)定的溫度閥值時(shí),系統(tǒng)將通過(guò)繼電器控制熱風(fēng)機(jī)進(jìn)行加熱,吹出熱風(fēng)來(lái)控制室溫。通過(guò)實(shí)時(shí)監(jiān)測(cè)溫度并根據(jù)設(shè)定的閥值進(jìn)行控制,系統(tǒng)能夠保持溫室內(nèi)的溫度在一個(gè)適宜的范圍,為花卉提供一個(gè)穩(wěn)定的生長(zhǎng)環(huán)境。

項(xiàng)目的設(shè)計(jì)用于提高花卉溫室的自動(dòng)化程度,減輕人工管理的負(fù)擔(dān),同時(shí)提供一個(gè)穩(wěn)定的溫度控制方案,以促進(jìn)花卉的生長(zhǎng)和發(fā)展。通過(guò)使用STM32微控制器和相關(guān)硬件模塊,該系統(tǒng)能夠?qū)崿F(xiàn)溫度的實(shí)時(shí)監(jiān)測(cè)和自動(dòng)控制,為花卉溫室管理者提供了一種方便、高效的解決方案。

加上遠(yuǎn)程控制之后的最終系統(tǒng)模型圖:

image-20230802154537086

二、硬件選型介紹

以下是基于STM32的花卉溫室控溫系統(tǒng)的硬件選型:

【1】主控芯片:STM32F103C8T6

  • STM32F103系列具有良好的性能和豐富的外設(shè),適合嵌入式應(yīng)用。
  • STM32F103C8T6是一款32位ARM Cortex-M3內(nèi)核的微控制器,具有64KB的Flash存儲(chǔ)器和20KB的RAM。

【2】溫度傳感器:DS18B20

【3】顯示屏:0.96寸OLED顯示屏

  • 選擇支持SPI協(xié)議的0.96寸OLED顯示屏作為顯示設(shè)備,可以方便地顯示環(huán)境溫度和溫度閥值。
  • OLED顯示屏具有低功耗、高對(duì)比度、視角廣等優(yōu)點(diǎn),適合嵌入式應(yīng)用。

【4】按鍵:兩個(gè)獨(dú)立按鍵

  • 選擇兩個(gè)獨(dú)立按鍵用于設(shè)置溫度閥值,可以通過(guò)按下按鈕增加或減小溫度閥值。

【5】繼電器:用于控制熱風(fēng)機(jī)加熱

  • 根據(jù)溫度閥值和實(shí)時(shí)溫度數(shù)據(jù),通過(guò)STM32的GPIO口控制繼電器的開(kāi)關(guān),從而控制熱風(fēng)機(jī)的加熱。
  • 繼電器的選型要根據(jù)熱風(fēng)機(jī)的額定電流和電壓來(lái)確定,確保能夠正常工作。

三、設(shè)計(jì)思路

軟件邏輯設(shè)計(jì)思路:

【1】初始化STM32外設(shè),包括GPIO、SPI、USART等。

【2】設(shè)置溫度閥值的初始值,并通過(guò)按鍵調(diào)節(jié)閥值。

【3】循環(huán)讀取DS18B20溫度傳感器的數(shù)據(jù),并將讀取到的溫度值與閥值進(jìn)行比較。

【4】如果當(dāng)前溫度低于閥值,則控制繼電器閉合,熱風(fēng)機(jī)開(kāi)始加熱;否則,打開(kāi)繼電器,停止加熱。

【5】將溫度值和閥值顯示在OLED屏幕上,通過(guò)USART串口輸出給用戶。

【6】不斷循環(huán)執(zhí)行以上步驟,實(shí)現(xiàn)溫室的自動(dòng)控溫功能。

偽代碼:

// 定義變量
float temperature;  // 當(dāng)前溫度值
float threshold;    // 溫度閥值

// 初始化硬件和外設(shè)
void initialize() {
    initialize_GPIO();     // 初始化GPIO
    initialize_SPI();      // 初始化SPI
    initialize_USART();    // 初始化USART
    initialize_DS18B20();  // 初始化DS18B20
    initialize_OLED();     // 初始化OLED顯示屏
    initialize_Button();   // 初始化按鍵
    initialize_Relay();    // 初始化繼電器
}

// 讀取溫度值
float readTemperature() {
    // 通過(guò)DS18B20讀取溫度值
    // 返回溫度值
}

// 讀取閥值
float readThreshold() {
    // 讀取按鍵的狀態(tài),并調(diào)節(jié)閥值
    // 返回閥值
}

// 控制加熱器
void controlHeater(float currTemperature, float currThreshold) {
    if (currTemperature < currThreshold) {
        // 溫度低于閥值,控制繼電器閉合,熱風(fēng)機(jī)加熱
    } else {
        // 溫度高于或等于閥值,打開(kāi)繼電器,停止加熱
    }
}

// 顯示溫度和閥值
void displayTemperature(float currTemperature, float currThreshold) {
    // 在OLED屏幕上顯示溫度值和閥值
    // 通過(guò)USART串口輸出溫度值和閥值
}

// 主函數(shù)
int main() {
    initialize();  // 初始化
    
    while (1) {
        temperature = readTemperature();          // 讀取溫度值
        threshold = readThreshold();              // 讀取閥值
        controlHeater(temperature, threshold);     // 控制加熱器
        displayTemperature(temperature, threshold);// 顯示溫度和閥值
    }

    return 0;
}

以上是基本的軟件邏輯設(shè)計(jì)思路和偽代碼。

四、代碼實(shí)現(xiàn)

4.1 讀取溫度顯示

下面是使用STM32F103C8T6讀取DS18B20溫度傳感器數(shù)據(jù),并將溫度顯示到OLED顯示屏上的實(shí)現(xiàn)代碼:

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

int main(void)
{
    // 初始化延遲函數(shù)
    delay_init();
    
    // 初始化OLED顯示屏
    SSD1306_Init();
    
    // 初始化DS18B20溫度傳感器
    DS18B20_Init();
    
    float temperature = 0.0;
    char tempStr[10];
    
    while (1)
    {
        // 讀取DS18B20溫度傳感器數(shù)據(jù)
        temperature = DS18B20_GetTemp();
        
        // 將溫度轉(zhuǎn)換為字符串
        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();
        
        // 延時(shí)一段時(shí)間
        delay_ms(1000);
    }
}

代碼中,使用了封裝好庫(kù)文件,包括延遲函數(shù)(delay.h)、OneWire總線(onewire.h)、DS18B20溫度傳感器(ds18b20.h)和SSD1306 OLED顯示屏(ssd1306.h)的庫(kù)文件。

在主函數(shù)中,初始化延遲函數(shù)和OLED顯示屏,初始化DS18B20溫度傳感器。然后進(jìn)入無(wú)限循環(huán),在循環(huán)中讀取DS18B20溫度傳感器的溫度數(shù)據(jù),將溫度顯示到OLED顯示屏上。溫度數(shù)據(jù)通過(guò)sprintf函數(shù)轉(zhuǎn)換為字符串,使用SSD1306庫(kù)函數(shù)在OLED顯示屏上進(jìn)行顯示。通過(guò)延時(shí)函數(shù)延時(shí)一段時(shí)間,實(shí)現(xiàn)溫度的定時(shí)更新。

4.2 DS18B20的代碼

頭文件代碼:

#ifndef DS18B20_H
#define DS18B20_H

#include "stm32f10x.h"

// DS18B20引腳定義
#define DS18B20_GPIO_PORT   GPIOA
#define DS18B20_GPIO_PIN    GPIO_Pin_0

// DS18B20函數(shù)聲明
void DS18B20_Init(void);
void DS18B20_WriteByte(uint8_t data);
uint8_t DS18B20_ReadByte(void);
float DS18B20_GetTemp(void);

#endif

源文件代碼:

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

// 初始化DS18B20溫度傳感器
void DS18B20_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    // 使能GPIOA時(shí)鐘
    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);
    
    // 將引腳拉低一段時(shí)間
    GPIO_ResetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
    delay_us(500);
    
    // 將引腳拉高一段時(shí)間
    GPIO_SetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
    delay_us(80);
    
    // 等待DS18B20的響應(yīng)
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
    delay_us(80);
}

// 向DS18B20寫(xiě)入一個(gè)字節(jié)的數(shù)據(jù)
void DS18B20_WriteByte(uint8_t data)
{
    uint8_t i;
    
    // 將引腳設(shè)置為推挽輸出
    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);
    
    // 寫(xiě)入數(shù)據(jù)
    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讀取一個(gè)字節(jié)的數(shù)據(jù)
uint8_t DS18B20_ReadByte(void)
{
    uint8_t i, data = 0;
    
    // 將引腳設(shè)置為推挽輸出
    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);
    
    // 讀取數(shù)據(jù)
    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溫度數(shù)據(jù)
float DS18B20_GetTemp(void)
{
    uint8_t tempLSB, tempMSB;
    int16_t tempData;
    float temperature;
    
    // 發(fā)送溫度轉(zhuǎn)換命令
    DS18B20_WriteByte(0xCC);     // 跳過(guò)ROM操作
    DS18B20_WriteByte(0x44);     // 發(fā)送溫度轉(zhuǎn)換命令
    
    // 等待溫度轉(zhuǎn)換完成
    while (!GPIO_ReadInputDataBit(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN));
    
    // 發(fā)送讀取溫度命令
    DS18B20_WriteByte(0xCC);     // 跳過(guò)ROM操作
    DS18B20_WriteByte(0xBE);     // 發(fā)送讀取溫度命令
    
    // 讀取溫度數(shù)據(jù)
    tempLSB = DS18B20_ReadByte();
    tempMSB = DS18B20_ReadByte();
    
    // 計(jì)算溫度值
    tempData = (tempMSB << 8) | tempLSB;
    if (tempData & 0x8000)      // 溫度為負(fù)數(shù)
    {
        tempData = ~tempData + 1;
        temperature = -((float)tempData / 16.0);
    }
    else                        // 溫度為正數(shù)
    {
        temperature = (float)tempData / 16.0;
    }
    
    return temperature;
}

4.3 OLED顯示屏代碼

頭文件:

#ifndef SSD1306_H
#define SSD1306_H

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

// SSD1306顯示屏參數(shù)定義
#define SSD1306_I2C_ADDR      0x78    // I2C地址
#define SSD1306_WIDTH         128     // 顯示屏寬度
#define SSD1306_HEIGHT        64      // 顯示屏高度

// SSD1306函數(shù)聲明
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

源文件:

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

static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8];

void SSD1306_Init(void)
{
    // 初始化I2C總線
    I2C_Init();
    
    // 向SSD1306發(fā)送初始化命令
    uint8_t initCommands[] = {
        0xAE,           // 關(guān)閉顯示
        0xD5, 0x80,     // 設(shè)置時(shí)鐘分頻因子
        0xA8, 0x3F,     // 設(shè)置驅(qū)動(dòng)路數(shù)
        0xD3, 0x00,     // 設(shè)置顯示偏移
        0x40,           // 設(shè)置顯示開(kāi)始行
        0x8D, 0x14,     // 設(shè)置電荷泵
        0x20, 0x00,     // 設(shè)置內(nèi)存地址模式
        0xA1,           // 設(shè)置段重定義
        0xC8,           // 設(shè)置COM掃描方向
        0xDA, 0x12,     // 設(shè)置COM引腳配置
        0x81, 0xCF,     // 設(shè)置對(duì)比度控制
        0xD9, 0xF1,     // 設(shè)置預(yù)充電周期
        0xDB, 0x40,     // 設(shè)置VCOMH電壓倍率
        0xA4,           // 全局顯示開(kāi)啟
        0xA6,           // 設(shè)置顯示方式
        0xAF            // 開(kāi)啟顯示
    };
    
    for (uint8_t i = 0; i < sizeof(initCommands); i++)
    {
        I2C_WriteByte(SSD1306_I2C_ADDR, 0x00, initCommands[i]);
    }
    
    // 清空緩沖區(qū)
    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++;
    }
}

五、總結(jié)

本項(xiàng)目設(shè)計(jì)了基于STM32的花卉溫室控溫系統(tǒng),通過(guò)使用DS18B20溫度傳感器、OLED顯示屏和繼電器等硬件模塊,實(shí)現(xiàn)了對(duì)溫室內(nèi)溫度的監(jiān)測(cè)和控制。該系統(tǒng)能夠根據(jù)預(yù)設(shè)的溫度閥值,自動(dòng)控制熱風(fēng)機(jī)的加熱,以維持溫室內(nèi)的適宜溫度,從而保證花卉的生長(zhǎng)環(huán)境。

在軟件邏輯設(shè)計(jì)方面,采用了STM32的外設(shè)和中斷機(jī)制,結(jié)合合適的算法和狀態(tài)判斷,實(shí)現(xiàn)了溫度數(shù)據(jù)的獲取和比較,并根據(jù)結(jié)果控制繼電器的開(kāi)關(guān)。通過(guò)OLED顯示屏和USART串口,能夠及時(shí)地將溫度值和閥值反饋給用戶,方便用戶了解當(dāng)前環(huán)境并進(jìn)行調(diào)節(jié)。

本項(xiàng)目的設(shè)計(jì)和實(shí)現(xiàn)為溫室控溫系統(tǒng)提供了一個(gè)具體的解決方案,通過(guò)合理的硬件選型和軟件邏輯設(shè)計(jì),能夠滿足花卉種植對(duì)溫度控制的需求。在未來(lái)的發(fā)展中,系統(tǒng)將在農(nóng)業(yè)領(lǐng)域發(fā)揮重要作用,并為人們創(chuàng)造更舒適、高效的溫控環(huán)境。

  • 更多詳細(xì)資料請(qǐng)聯(lián)系.docx
    下載
意法半導(dǎo)體

意法半導(dǎo)體

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國(guó)Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱(chēng)改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷(xiāo)售收入在半導(dǎo)體工業(yè)五大高速增長(zhǎng)市場(chǎng)之間分布均衡(五大市場(chǎng)占2007年銷(xiāo)售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(chē)(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場(chǎng)居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專(zhuān)用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車(chē)用集成電路領(lǐng)域居世界前列.

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國(guó)Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱(chēng)改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷(xiāo)售收入在半導(dǎo)體工業(yè)五大高速增長(zhǎng)市場(chǎng)之間分布均衡(五大市場(chǎng)占2007年銷(xiāo)售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(chē)(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場(chǎng)居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專(zhuān)用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車(chē)用集成電路領(lǐng)域居世界前列.收起

查看更多

相關(guān)推薦