<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于STM32設計的太陽能熱水器

DS小龍哥-嵌入式技術 ? 來源:DS小龍哥-嵌入式技術 ? 作者:DS小龍哥-嵌入式技 ? 2023-06-26 09:29 ? 次閱讀

一、概述

本項目使用 STM32F103C8T6 微控制器作為核心處理器,結合多個傳感器和執行器,實現了太陽能熱水器的自動控制。通過對光照、溫度、水位等各種參數的監測和分析,對水泵、電磁閥等設備進行自動控制,從而實現太陽能熱水器的高效、安全、可靠運行。

img

二、硬件設計

(1)模塊組成

太陽能熱水器模塊主要由以下幾個部分組成:

  • 光敏傳感器模塊:用于檢測陽光強度,反映太陽輻射強度和方向。
  • 溫度傳感器模塊:用于檢測太陽能集熱器表面和水箱內的溫度,并根據溫度變化調整水泵、電磁閥等設備的運行狀態。
  • 液位傳感器模塊:用于檢測水箱內的液位,并根據液位高低控制水泵和電磁閥的啟停。
  • 水泵模塊:通過控制水泵的啟停,實現水循環流動和充水功能。
  • 電磁閥模塊:通過控制電磁閥的開關,實現熱水器的放水和接水功能。

(2)硬件連接

其中,光敏傳感器模塊、溫度傳感器模塊和液位傳感器模塊通過 ADC 接口與 STM32F103C8T6 微控制器進行連接;水泵模塊和電磁閥模塊則通過 GPIO 口控制。

連接方式如下:

  • 光敏傳感器模塊:將光敏傳感器輸出口與 ADC1 通道10 連接,并用一個電位器調整 ADC 的參考電壓,使其范圍在 0-3.3V 之間。
  • 溫度傳感器模塊:將 DS18B20 溫度傳感器數據線與 GPIOA 的 PA8 引腳連接,并將 VCC 和 GND 分別接到 3.3V 和 GND。
  • 液位傳感器模塊:將液位傳感器輸出口與 ADC1 通道11 連接,并用一個電位器調整 ADC 的參考電壓。
  • 水泵模塊:將水泵正極接到 GPIOB 的 PB1 引腳,將負極接到電源的負極。
  • 電磁閥模塊:將電磁閥正極接到 GPIOB 的 PB0 引腳,將負極接到電源的負極。

三、軟件設計

3.1 任務分配

整個項目采用 FreeRTOS 系統進行開發,實現數數的監測和控制,開發以下幾個任務:

  • 光敏傳感器任務:定時讀取光敏傳感器輸出口的電壓值,并進行數據處理,得到當前的光照強度。
  • 溫度傳感器任務:定時向 DS18B20 溫度傳感器發送溫度采樣請求,接收并解析響應數據,得到當前的太陽能集熱器表面溫度和水箱內溫度。
  • 液位傳感器任務:定時讀取液位傳感器輸出口的電壓值,并進行數據處理,得到當前的水箱水位高度。
  • 控制任務:根據光照強度、溫度和水位高度等參數,決定是否需要啟動水泵或電磁閥等設備。

偽代碼如下:

void Light_Sensor_Task(void)
 {
     while (1)
     {
         voltage = ADC_Get_Voltage(); // 獲取光敏傳感器輸出電壓
         light_intensity = voltage * 100 / 3.3f; // 根據電壓計算光照強度
         vTaskDelay(1000); // 延時 1s
     }
 }
 ?
 void Temperature_Sensor_Task(void)
 {
     while (1)
     {
         DS18B20_Start_Conversion(); // 向溫度傳感器發送采樣請求
         temperature1 = DS18B20_Read_Temperature(); // 讀取太陽能集熱器表面溫度
         temperature2 = DS18B20_Read_Temperature(); // 讀取水箱內溫度
         vTaskDelay(1000); // 延時 1s
     }
 }
 ?
 void Water_Level_Sensor_Task(void)
 {
     while (1)
     {
         voltage = ADC_Get_Voltage(); // 獲取液位傳感器輸出電壓
         water_level = voltage * 100 / 3.3f; // 根據電壓計算水位高度
         vTaskDelay(1000); // 延時 1s
     }
 }
 ?
 void Control_Task(void)
 {
     while (1)
     {
         if (light_intensity > THRESHOLD && temperature1 > THRESHOLD && water_level > THRESHOLD) // 如果各種參數均符合要求,則啟動水泵和電磁閥
         {
             GPIO_SetBits(GPIOB, GPIO_Pin_1); // 啟動水泵
             GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 關閉電磁閥
         }
         else // 否則關閉水泵,打開電磁閥,放水
         {
             GPIO_ResetBits(GPIOB, GPIO_Pin_1); // 關閉水泵
             GPIO_SetBits(GPIOB, GPIO_Pin_0); // 啟動電磁閥
         }
         vTaskDelay(1000); // 延時 1s
     }
 }

3.2 光敏傳感器任務

/* 光敏傳感器任務 */
 void Light_Sensor_Task(void *pvParameters)
 {
   uint16_t adc_value;
 ?
   while (1)
   {
     /* 讀取 ADC 值并計算光照強度 */
     if (HAL_ADC_Start(&hadc1) == HAL_OK)
     {
       if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
       {
         adc_value = HAL_ADC_GetValue(&hadc1);
         light_intensity = adc_value * 3300 / 4096.0;
       }
     }
 ?
     vTaskDelay(pdMS_TO_TICKS(1000)); // 延時 1s
   }
 }

在函數中,聲明一個變量 adc_value 用于存儲讀取到的 ADC 值。使用 if 條件語句檢查 ADC 是否成功啟動,并且使用 HAL_ADC_PollForConversion() 函數判斷當前轉換是否完成,如果轉換完成,就獲取 ADC 值,并且通過簡單的計算公式將 ADC 值轉換為光照強度值,最后將結果存儲在 light_intensity 變量中。

3.3 溫度傳感器任務

/* 溫度傳感器任務 */
 void Temperature_Sensor_Task(void *pvParameters)
 {
   float temperature;
 ?
   /* 初始化 DS18B20 */
   DS18B20_Init(&htim2, GPIOA, GPIO_PIN_10);
 ?
   while (1)
   {
     /* 讀取溫度值 */
     temperature = DS18B20_Read_Temperature();
 ?
     /* 將讀取到的溫度值存儲在全局變量中 */
     current_temperature = temperature;
 ?
     vTaskDelay(pdMS_TO_TICKS(1000)); // 延時 1s
   }
 }

在函數中,聲明一個變量 temperature 用于存儲讀取到的溫度值。然后,調用函數 DS18B20_Init() 初始化 DS18B20 溫度傳感器。使用 DS18B20_Read_Temperature() 函數讀取溫度值,并且將結果存儲在 temperature 變量中。最后,將讀取到的溫度值存儲在全局變量 current_temperature 中。

3.4 液位傳感器任務

/* 液位傳感器任務 */
 void Liquid_Level_Sensor_Task(void *pvParameters)
 {
   uint16_t adc_value;
   float voltage;
 ?
   /* 初始化液位傳感器 GPIO 口 */
   HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
   HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);
 ?
   while (1)
   {
     /* 讀取 ADC 值并計算電壓值 */
     if (HAL_ADC_Start(&hadc1) == HAL_OK)
     {
       if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
       {
         adc_value = HAL_ADC_GetValue(&hadc1);
         voltage = adc_value * 3.3 / 4096.0;
       }
     }
 ?
     /* 根據電壓值計算液位高度 */
     if (voltage < 0.5)
     {
       liquid_level = 0.0;
     }
     else if (voltage > 2.5)
     {
       liquid_level = 100.0;
     }
     else
     {
       liquid_level = (voltage - 0.5) * 100.0 / 2.0;
     }
 ?
     vTaskDelay(pdMS_TO_TICKS(1000)); // 延時 1s
   }
 }

在函數中,聲明變量 adc_valuevoltage,分別用于存儲讀取到的 ADC 值和計算得到的電壓值。使用 HAL_GPIO_WritePin() 函數初始化液位傳感器 GPIO 口,將啟用傳感器的引腳設置為高電平。使用 if 條件語句檢查 ADC 是否成功啟動,并且使用 HAL_ADC_PollForConversion() 函數判斷當前轉換是否完成,如果轉換完成,就獲取 ADC 值,并且通過簡單的計算公式將 ADC 值轉換為電壓值,并將結果存儲在 voltage 變量中。

由于需要使用電壓值計算液位高度,使用 if 條件語句檢查電壓是否小于低液位警戒電壓 0.5V 或者大于高液位警戒電壓 2.5V,如果是則分別將液位高度設置為 0% 或 100%,否則使用簡單的線性關系計算液位高度。

3.5 控制任務

/* 控制任務 */
 void Control_Task(void *pvParameters)
 {
   float temperature_setpoint = 25.0; // 設定溫度值
   float liquid_level_setpoint = 50.0;  // 設定液位高度值
   float temperature_error, liquid_level_error;
   float temperature_integral, liquid_level_integral;
   float temperature_derivative, liquid_level_derivative;
   float temperature_output, liquid_level_output;
 ?
   float kp_temperature = 0.5, ki_temperature = 0.1, kd_temperature = 0.05; // 溫度 PID 參數
   float kp_liquid_level = 0.2, ki_liquid_level = 0.05, kd_liquid_level = 0.02; // 液位高度 PID 參數
 ?
   while (1)
   {
     /* 計算溫度 PID 控制器輸出 */
     temperature_error = temperature_setpoint - current_temperature;
     temperature_integral += temperature_error;
     temperature_derivative = temperature_error - last_temperature_error;
     temperature_output = kp_temperature * temperature_error + ki_temperature * temperature_integral + kd_temperature * temperature_derivative;
     last_temperature_error = temperature_error;
 ?
     /* 計算液位高度 PID 控制器輸出 */
     liquid_level_error = liquid_level_setpoint - liquid_level;
     liquid_level_integral += liquid_level_error;
     liquid_level_derivative = liquid_level_error - last_liquid_level_error;
     liquid_level_output = kp_liquid_level * liquid_level_error + ki_liquid_level * liquid_level_integral + kd_liquid_level * liquid_level_derivative;
     last_liquid_level_error = liquid_level_error;
 ?
     /* 通過 PWM 控制加熱器和水泵電機 */
     if (temperature_output > 0.0)
     {
       HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
       __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, (uint16_t)(temperature_output * 1000));
     }
     else
     {
       HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
       __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
     }
 ?
     if (liquid_level_output > 0.0)
     {
       HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
       __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, (uint16_t)(liquid_level_output * 1000));
     }
     else
     {
       HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
       __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0);
     }
 ?
     vTaskDelay(pdMS_TO_TICKS(10)); // 延時 10ms
   }
 }

在函數中:

(1)定義參數和變量,包括設定溫度值、設定液位高度值、溫度 PID 控制器的參數、液位高度 PID 控制器的參數等。使用 while 循環處理控制邏輯,循環開始時,計算溫度 PID 控制器輸出。

(2)計算當前誤差,并將誤差累積到積分項中。計算誤差變化率,并使用 PID 參數計算出輸出值,將結果存儲在 temperature_output 中,并將當前誤差存儲在 last_temperature_error 中以便于下一次計算,計算液位高度 PID 控制器輸出。

(3)根據控制器輸出值通過 PWM 控制加熱器和水泵電機的運行狀態。如果輸出值大于 0,則啟用電機或加熱器并設置對應的 PWM 占空比,否則關閉電機或加熱器并將 PWM 占空比設為 0。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 微控制器
    +關注

    關注

    48

    文章

    6868

    瀏覽量

    148297
  • 太陽能
    +關注

    關注

    37

    文章

    3256

    瀏覽量

    113321
  • STM32
    +關注

    關注

    2245

    文章

    10688

    瀏覽量

    349653
  • 熱水器
    +關注

    關注

    5

    文章

    205

    瀏覽量

    26538
  • STM32F103C8T6
    +關注

    關注

    104

    文章

    150

    瀏覽量

    81595
收藏 人收藏

    評論

    相關推薦

    太陽能熱水器自動上水電路

    太陽能熱水器自動上水電路
    發表于 02-15 14:24 ?7501次閱讀
    <b class='flag-5'>太陽能熱水器</b>自動上水電路

    太空熱水器介紹—摘自《新型熱水器的使用與維修》

    ,空氣熱水器的安裝,空氣熱水器的使用與維修;太陽能熱水器的工作原理與組成部件,太陽能熱水器
    發表于 09-18 10:52

    太陽能熱水器智能控制

    太陽能熱水器智能控制 太陽能熱水器以其諸多的優點受到人們的歡迎。本系統結合實際太陽能熱水器的具體應用,在介紹太陽能、傳感
    發表于 11-12 20:53

    這中太陽能熱水器方案有人做過嗎

    用中穎的芯片做太陽能熱水器有朋友做過嗎,效果怎么樣
    發表于 02-03 11:53

    自動太陽能熱水器溫控設計

      引言  目前,市場上銷售的太陽能熱水器大多沒有自動控制功能,使用起來不靈活方便,為此,為太陽能熱水器加裝自動控制功能,具有廣泛的市場?! ? 自動控制系統技術要求 ?。?) 設定溫度的范圍為25
    發表于 11-13 16:13

    如何用樹莓派控制太陽能熱水器?

    太陽能熱水器最近一直陰天溫度一直不夠洗澡只能用電加熱熱水器就是很耗電連著兩個月電費400多了另外給太陽能熱水器加裝了一根加熱棒但是要手動開手動關熱水器都在三樓跑上跑下也很麻煩昨天苦于無
    發表于 08-01 01:01

    怎么給太陽能熱水器增加光電互補防凍功能

    太陽能熱水器在陽光照射充足情況下,給人們的生活帶來極大方便,但在惡劣天氣,尤其北方溫度下降至-30C、-40℃時,會導致管道凍裂、結凍。因此,加裝自控溫電熱帶光電互補防凍很重要。
    發表于 04-26 06:04

    如何自制半自動的太陽能熱水器上水系統

    太陽能熱水器一般都配有自動上水系統。 它是電腦板的,浮球控制的等等。但是這許全自動上水系統歸結起來不論采用哪一種都容易壞。 人工上水就更加麻煩了。 自來水的水壓高還可以。 水壓低就不行了,幾個小時
    發表于 06-03 08:02

    太陽能熱水器系統主要由哪幾部分組成

    太陽能熱水器系統主要由哪幾部分組成?太陽能熱水器系統的控制原理是什么?太陽能熱水器系統有哪些功能特點?
    發表于 09-28 08:49

    太陽能熱水器電路圖

    太陽能熱水器電路圖 由于近年來常規能源的緊缺,開發和利用太陽能這樣的綠色能源有著重要的意
    發表于 01-12 13:37 ?326次下載
    <b class='flag-5'>太陽能熱水器</b>電路圖

    太陽能熱水器水位報警電路圖

    太陽能熱水器水位報警電路圖
    發表于 05-08 16:05 ?2099次閱讀
    <b class='flag-5'>太陽能熱水器</b>水位報警電路圖

    平板型太陽能熱水器的結構

    平板型太陽能熱水器主要是由平板集熱器、水箱、水管、支架及配件等部分組成。 (一)平板集熱器 平板集熱器是平板型太陽能熱水器的核心,包括吸熱器、蓋板、保溫層、外殼四大部分。 1、吸熱器:也叫集熱器或集熱芯子,其作用是吸收太陽的輻射
    發表于 01-13 15:21 ?105次下載

    太陽能熱水器自動溫控設計

    目前,市場上銷售的太陽能熱水器大多沒有自動控制功能,使用起來不靈活方便,為此,為太陽能熱水器加裝自動控制功能,具有廣泛的市場
    發表于 07-01 14:43 ?3471次閱讀
    <b class='flag-5'>太陽能熱水器</b>自動溫控設計

    太陽能熱水器安裝步驟及安裝圖

    太陽能熱水器作為一個清潔能源,可以減少非循環能源的使用,受到眾多家庭的青睞,已經被越來越多的家庭采購使用,那么購買了太陽能熱水器后如何安裝呢?下面我們就來看看太陽能熱水器安裝圖以及太陽能熱水器
    發表于 06-20 11:10 ?5.1w次閱讀
    <b class='flag-5'>太陽能熱水器</b>安裝步驟及安裝圖

    太陽能熱水器怎么清洗 2021年太陽能熱水器十大品牌排行榜

    太陽能熱水器太陽光能轉化為熱能,將水從低溫度加熱到高溫度,以滿足人們在生活、生產中的熱水使用。太陽能熱水器按結構形式分為真空管式太陽能熱水器
    的頭像 發表于 09-19 16:13 ?1871次閱讀
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>