找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 1475|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

基于STM32單片機(jī)的PM2.5環(huán)境監(jiān)測系統(tǒng)設(shè)計(jì)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
一.項(xiàng)目背景
最近為了完成交付的任務(wù),遂重制了一下小項(xiàng)目用STM32做一個小型的環(huán)境監(jiān)測系統(tǒng)。
        項(xiàng)目整體示意框圖如下:


二.器件選擇
  • 單片機(jī)(STM32F103)
  • 數(shù)字溫濕度模塊(DHT11)
  • 液晶顯示模塊(0.8寸OLED)
  • 粉塵傳感器模塊(GP2Y10)
  • 報警模塊(蜂鳴器)
  • 按鍵控制模塊(獨(dú)立按鍵)
        由于筆者覺得時鐘模塊沒什么必要性,就沒再加DS1302上去了。
三.PCB繪制
PCB推薦使用嘉立創(chuàng)專業(yè)版繪制,對于初學(xué)者來說簡單易上手,而且這種DIY的小玩意繪制的PCB大小控制在10*10以內(nèi)還可以免費(fèi)打樣。
        嘉立創(chuàng)很方便的一點(diǎn)是可以使用它內(nèi)部自帶的在線庫,省去了自己畫封裝畫元件的步驟,非常簡單,但是注意要辨別這里的元件封裝的正確性,因?yàn)橛行┰庋b是用戶貢獻(xiàn)的,所以有些地方不一定正確,各位讀者如果是小白的話一定要注意辨別是否符合自己的需求�。。�


四.核心代碼
以下只對部分核心代碼做展示。


Task.c

  1. #include "Task.h"

  2. uint8_t Prime_Mode = 0;
  3. uint8_t Start_Mode = 0;
  4. uint8_t Threshold_Mode = 0;//溫度調(diào)節(jié)模式
  5. bool isCollecting = false;

  6. int Humidity = 0,Temperature = 0;
  7. float Dust_Concentration = 0;
  8. uint8_t TemperatureMax = 30;
  9. uint8_t TemperatureMin = 10;

  10. uint8_t DataRead_Count = 0;//數(shù)據(jù)采集計(jì)次
  11. uint8_t Blink_Count = 0;//閃爍
  12. uint16_t Timer_2000ms = 0;//數(shù)據(jù)采集間隔
  13. uint16_t Timer_Blink = 0;//

  14. void Task_Test(void)
  15. {
  16.         //LCD_Test();
  17.         //Key_Test();
  18. }

  19. void Device_Init(void)
  20. {
  21.         LCD_Init();
  22.         Buzzer_Init();
  23.         DHT11_Init();
  24.         GP2Y10_Init();
  25.         Key_Init();
  26. }

  27. void Task_Key(void)
  28. {
  29.         uint8_t Key_Number = Key_Scan();
  30.         
  31.         if(Prime_Mode == 2)
  32.         {
  33.                 if(Key_Number == 1)
  34.                 {
  35.                         LCD_Clear();
  36.                         Start_Mode = 1;
  37.                         Prime_Mode = 0;
  38.                         isCollecting = false;
  39.                 }
  40.         }
  41.         else
  42.         {
  43.                 if(Key_Number == 1)
  44.                 {
  45.                         LCD_Clear();
  46.                         Start_Mode ^= 1;
  47.                         Prime_Mode = 0;
  48.                         isCollecting = false;
  49.                 }
  50.         }

  51.         if(Prime_Mode == 2)
  52.         {
  53.                 if(Key_Number == 2)
  54.                 {
  55.                         LCD_Clear();
  56.                         Threshold_Mode ^= 1;
  57.                 }
  58.                
  59.         }
  60.         else
  61.         {
  62.                 if(Key_Number == 2)
  63.                 {
  64.                         LCD_Clear();
  65.                         Prime_Mode = 1;
  66.                         isCollecting = false;
  67.                 }
  68.         }
  69.                

  70.         //設(shè)置報警閾值
  71.         if(Key_Number == 3)
  72.         {
  73.                 LCD_Clear();
  74.                 Prime_Mode = 2;
  75.                 isCollecting = false;
  76.                
  77.                 if(Threshold_Mode == 0)//高溫閾值++
  78.                 {
  79.                         ++TemperatureMax;
  80.                 }
  81.                 if(Threshold_Mode == 1)//低溫閾值++
  82.                 {
  83.                         ++TemperatureMin;
  84.                 }
  85.         }
  86.         if(Key_Number == 4)
  87.         {
  88.                 LCD_Clear();
  89.                 Prime_Mode = 2;
  90.                 isCollecting = false;
  91.                
  92.                 if(Threshold_Mode == 0)//高溫閾值++
  93.                 {
  94.                         --TemperatureMax;
  95.                 }
  96.                 if(Threshold_Mode == 1)//低溫閾值++
  97.                 {
  98.                         --TemperatureMin;
  99.                 }
  100.         }
  101. }

  102. void filter_and_smooth(float *data, int size, float *smoothed_data) {
  103.     // 濾除0
  104.     int count = 0;
  105.     for (int i = 0; i < size; i++) {
  106.         if (data[i] != 0) {
  107.             smoothed_data[count++] = data[i];
  108.         }
  109.     }

  110.     // 平滑曲線
  111.     for (int i = 0; i < count - 2; i++) {
  112.         smoothed_data[i] = (smoothed_data[i] + smoothed_data[i + 1] + smoothed_data[i + 2]) / 3.0;
  113.     }
  114. }


  115. void Task_DataCollect(void)
  116. {
  117.         //DHT11_Read(&Humidity,&Temperature);
  118.         if ( DHT11_Read(&Humidity,&Temperature) !=0 )
  119.         {
  120.                 DHT11_Init();
  121.         }
  122.         Dust_Concentration = Get_PM25_Average_Data();//采集粉塵濃度數(shù)據(jù)
  123. //        printf("Humidity:%d\n",Humidity);
  124. //        printf("Temperature:%d\n",Temperature);
  125. //        printf("PM2.5:%f\n",Dust_Concentration);
  126.         printf("%f\n",Dust_Concentration/10);
  127. }

  128. void Task_Alarm(void)
  129. {
  130.         if(Temperature > TemperatureMax || Temperature < TemperatureMin)
  131.         {
  132.                 Buzzer_Control(ON);
  133.                 mdelay(20);
  134.                 Buzzer_Control(OFF);
  135.                 mdelay(20);
  136.         }        
  137. }


  138. void Task_OLED(void)
  139. {
  140.         switch(Prime_Mode)
  141.         {
  142.                 case 0:
  143.                 {
  144.                         //控制啟動關(guān)機(jī)
  145.                         if(Start_Mode == 1)//開機(jī)
  146.                         {
  147.                                 LCD_PrintString(0,0,"Welcome to:");
  148.                                 LCD_PrintString(5,2,"System");
  149.                         }
  150.                         else//關(guān)機(jī)
  151.                                 LCD_Clear();
  152.                         break;
  153.                 }
  154.                 case 1://溫濕度,PM2.5濃度
  155.                 {
  156.                         if(Start_Mode == 1)
  157.                         {
  158.                                 if(!isCollecting)
  159.                                 {
  160.                                         LCD_PrintString(2,3,"Collecting...");
  161.                                         mdelay(3000);
  162.                                         LCD_Clear();
  163.                                         isCollecting = true;
  164.                                 }
  165.                                 LCD_PrintString(0,0,"Data=>");
  166.                                 LCD_PrintString(0,2,"Humidity:");
  167.                                 LCD_PrintSignedVal(9, 2, Humidity);
  168.                                 LCD_PrintString(0,4,"Temperature:");
  169.                                 LCD_PrintSignedVal(12, 4, Temperature);
  170.                                 LCD_PrintString(0,6,"PM2.5:");
  171.                                 LCD_PrintSignedVal(6, 6, (int)Dust_Concentration);
  172.                         }
  173.                         break;
  174.                 }
  175.                 case 2://設(shè)置報警閾值
  176.                 {
  177.                         if(Start_Mode == 1)
  178.                         {
  179.                                 LCD_PrintString(0,2,"High:");
  180.                                 
  181.                                 LCD_PrintString(0,4,"Low:");
  182.                                 
  183.                                 if(Threshold_Mode == 0)
  184.                                 {
  185.                                         if(Blink_Count == 0)
  186.                                                 LCD_PrintSignedVal(6, 2, TemperatureMax);
  187.                                         else
  188.                                                 LCD_PrintString(6,2,"     ");
  189.                                         LCD_PrintSignedVal(6, 4, TemperatureMin);
  190.                                 }
  191.                                 if(Threshold_Mode == 1)
  192.                                 {
  193.                                         LCD_PrintSignedVal(6, 2, TemperatureMax);
  194.                                         if(Blink_Count == 0)
  195.                                                 LCD_PrintSignedVal(6, 4, TemperatureMin);
  196.                                         else
  197.                                                 LCD_PrintString(6,4,"     ");
  198.                                 }
  199.                         }
  200.                         break;
  201.                 }
  202. //                case 3://出行建議
  203. //                {
  204. //                        if(Start_Mode == 1)
  205. //                        {
  206. //                                if(Humidity > HUM_MAX)
  207. //                                        LCD_PrintString(0,0,"The humidity is too high!!!");
  208. //                                else if(Humidity < HUM_MIN)
  209. //                                        LCD_PrintString(0,0,"The humidity is too low!!!");
  210. //                        }
  211. //                        break;
  212. //                }               
  213.         }
  214. }

  215. void Task_Prime(void)
  216. {
  217.         Task_Key();
  218.         if(DataRead_Count == 1)
  219.         {
  220.                 Task_DataCollect();
  221.                 DataRead_Count = 0;
  222.         }
  223.         Task_Alarm();
  224.         Task_OLED();
  225. }

  226. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  227. {
  228.         if(htim->Instance == TIM2)
  229.         {
  230.                 ++Timer_2000ms;
  231.                 ++Timer_Blink;
  232.                 if(Timer_2000ms >= 2000)
  233.                 {
  234.                         DataRead_Count++;
  235.                         Timer_2000ms = 0;
  236.                 }
  237.                 if(Timer_Blink >= 650)
  238.                 {
  239.                         Blink_Count ^= 1;
  240.                         Timer_Blink = 0;
  241.                 }
  242.         }
  243. }
復(fù)制代碼


五.最終效果

六.總結(jié)
通過本項(xiàng)目的實(shí)踐,不僅實(shí)現(xiàn)了基礎(chǔ)功能監(jiān)測,還為未來更復(fù)雜的項(xiàng)目打下了堅(jiān)實(shí)的基礎(chǔ)。希望讀者通過該項(xiàng)目,也能夠掌握模塊化開發(fā)的思路,逐步進(jìn)階!

原理圖pcb: 無
仿真: 無
項(xiàng)目源碼如下: PM2.5_Monitor_NoRTOS.7z (5.92 MB, 下載次數(shù): 0)

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:302495 發(fā)表于 2024-12-20 12:59 | 只看該作者
厲害啊大佬,學(xué)習(xí)了
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表