電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 822|回復: 0
收起左側(cè)

【HarmonyOS HiSpark Wi-Fi IoT小視頻參賽】家庭多功能智能設(shè)備

[復制鏈接]

2607

主題

2607

帖子

7472

積分

高級會員

Rank: 5Rank: 5

積分
7472
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2021-1-26 09:56:34 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
【HarmonyOS HiSpark Wi-Fi IoT小視頻參賽】家庭多功能智能設(shè)備,   

Hispark Wi-Fi IOT套件試用的最后一篇連載,將介紹我做的一個demo。使用的套件板子包括擴展底板、主控板子、顯示板、環(huán)境監(jiān)測板、紅綠燈板、炫彩燈板。


一、主要功能





  • 火災報警,在檢測到顆粒煙霧或者有毒氣體時,發(fā)聲報警并把報警狀態(tài)發(fā)送到手機端;  
  • 防盜報警,在布防狀態(tài)下,檢測到人時,發(fā)聲報警并把報警狀態(tài)發(fā)送到手機端;  
  • 擁有手動、自動模式設(shè)置,布防、撤防狀態(tài)設(shè)置功能。在手動模式下,可以人為進行設(shè)置布撤防狀態(tài);在手動模式下,會自動根據(jù)設(shè)定的布撤防時間進行布撤防。在布防下,才進行防盜檢測;  
  • 具備聯(lián)網(wǎng)功能,設(shè)備能夠獲取網(wǎng)絡時間和最近3天的氣候情況,并在顯示屏上進行顯示;  
  • 可以與手機進行數(shù)據(jù)傳輸,把溫濕度情況、防火報警狀態(tài)、防盜報警狀態(tài)、手自動模式、布撤防狀態(tài)發(fā)送手機APP端,可以接收手機APP下發(fā)的手自動模式、布撤防狀態(tài)切換的命令;  
  • 具備燈開關(guān)控制功能,可以根據(jù)環(huán)境亮度,調(diào)節(jié)燈亮度;  
  • 可以設(shè)置自動模式下布撤防的時間;  
  • 可以通過按鍵或者手機APP端設(shè)置手自動模式、布撤防狀態(tài);  
  • 啟動后會自動獲取網(wǎng)絡時間或者網(wǎng)絡天氣數(shù)據(jù),也可以通過按鍵手動獲取網(wǎng)絡時間或者網(wǎng)絡天氣數(shù)據(jù);
      



二、硬件使用情況介紹



主要使用到下面硬件資源
1、主控板


2、擴展底板


3、顯示板

  • OLED顯示屏  
  • 兩個模擬按鍵
      



4、環(huán)境監(jiān)測板

  • 溫濕度傳感器  
  • 可燃性氣體傳感器  
  • 蜂鳴器
      



5、紅綠燈板

  • 一個按鍵  
  • 一個綠燈
      



6、炫彩燈板

  • 三色燈(紅綠藍混合)  
  • 人體紅外感應器  
  • 光敏電阻
      



三、主控IO資源分配



Hi3861的GPIO口不多,一共有15個IO口,但是IO口的復用功能較多。其中GPIO3、GPIO4用來作為調(diào)試串口,如果使用了串口功能,就不能使用GPIO3、4口作為其他功能。還需要注意的是,有些IO口是復用PWM通道和ADC通道功能。如果使用了該IO作為PWM功能,ADC通道功能就無法正常使用,應該是PWM會影響ADC正常使用。
  

下面是demo的IO分配表,GPIO3/GPIO4作為調(diào)試輸出口,沒有接其他器件。

  

IO分配.jpg (27.1 KB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:11 上傳




四、軟件設(shè)計



我把整個工程軟件分為了七個任務,顯示任務、按鍵控制任務、環(huán)境監(jiān)測任務、燈控制任務、RTC任務、TCP數(shù)據(jù)發(fā)送任務、數(shù)據(jù)接收任務。


1、顯示任務

顯示任務主要是控制OLED的顯示。設(shè)置有六個顯示界面,時間顯示界面、現(xiàn)在天氣情況顯示界面、明天天氣情況顯示界面、后天天氣顯示界面、布撤防時間調(diào)整顯示界面、設(shè)置模式界面。顯示任務根據(jù)變量Now_Screen的值來選擇顯示什么界面。Now_Screen的值會在按鍵任務中進行改變。在獲取網(wǎng)絡時間或者網(wǎng)絡天氣數(shù)據(jù)時,會顯示獲取狀態(tài)提示內(nèi)容。  時間顯示界面如下

時間顯示.jpg (1.39 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:12 上傳 現(xiàn)在天氣情況顯示界面

今天.jpg (1.28 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:12 上傳 明天天氣情況顯示界面

明天.jpg (1.36 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:12 上傳 后天天氣情況顯示界面

后天天氣.jpg (1.38 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:11 上傳 布撤防時間調(diào)整顯示界面

時間設(shè)置.jpg (1.34 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:12 上傳 設(shè)置模式顯示界面

模式設(shè)置.jpg (1.38 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:12 上傳 獲取狀態(tài)提示顯示

時間成功提示.jpg (1.48 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:20 上傳



時間提示.jpg (1.31 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:20 上傳

天氣提示.jpg (1.41 MB, 下載次數(shù): 0)

下載附件  保存到相冊  

昨天 21:20 上傳

任務代碼如下

  • static void OledTask(void *arg)
      
  • {
      
  •     (void)arg;
      
  •     //Oled初始化
      
  •     GpioInit();
      
  •     OledInit();
      
  •     OledFillScreen(0x00);
      

  •   
  •     while (1)
      
  •     {
      
  •         //自動模式下,自動進行布撤防
      
  •         Zdbcf();
      
  •         //界面更新時,需要先刪除界面顯示的內(nèi)容
      
  •         if(Now_Screen != Last_Screen)
      
  •         {
      
  •             Last_Screen = Now_Screen;
      
  •             OledFillScreen(0);
      
  •             Get_Status = GET_NORMAL;
      
  •             Last_Get_Status = GET_NORMAL;
      
  •             i=0;
      
  •         }
      

  •   
  •         //獲取時間和天氣數(shù)據(jù)狀態(tài)提示,會隔一段時間進行清除
      
  •         if((Get_Status == GET_FAIL) ||(Get_Status == GET_SUC))
      
  •         {
      
  •             i++;
      
  •             if(i > 20)
      
  •             {
      
  •                 Get_Status = GET_NORMAL;
      
  •                 i=0;
      

  •   
  •                 switch(Now_Screen)
      
  •                 {
      
  •                 case TIMESCREEN:
      
  •                     OledClearString(16,7,“Sync time...“,1);     //清除提示
      
  •                     break;
      
  •                 case NOWSCREEN:
      

  •   
  •                 case TOSCREEN:
      

  •   
  •                 case ATOSCREEN:
      
  •                     printf(“clear oled i = %d\n“,i);
      
  •                     OledClearString(0,7,“Get Weather...“,1);    //清除提示
      
  •                     break;
      
  •                 case BCTIMESCREEN:
      
  •                     break;
      
  •                 default :
      
  •                     break;
      
  •                 }
      
  •             }
      
  •         }
      

  •   
  •         switch (Now_Screen)
      
  •         {
      

  •   
  •         case TIMESCREEN:
      
  •             TimeScreenDisp();       //顯示時間顯示界面
      
  •             Defenddisplay();
      
  •             break;
      

  •   
  •         case NOWSCREEN:
      
  •             WeatherDisp(NOWSCREEN); //顯示現(xiàn)在的天氣顯示界面
      
  •             break;
      

  •   
  •         case TOSCREEN:              //顯示明天天氣顯示界面
      
  •             WeatherDisp(TOSCREEN);
      
  •             break;
      

  •   
  •         case ATOSCREEN:             //顯示后天天氣顯示界面
      
  •             WeatherDisp(ATOSCREEN);
      
  •             break;
      
  •         case BCTIMESCREEN:
      
  •             OLED_ShowCHinese(32,0,14);//時
      
  •             OLED_ShowCHinese(48,0,15);//間
      
  •             OLED_ShowCHinese(64,0,18);//設(shè)
      
  •             OLED_ShowCHinese(80,0,19);//值
      
  •             sprintf((char *)TimeStr,“%02d:00-%02d:00“,starttime,stoptime);
      
  •             OledShowString(20,4,(char *)TimeStr,2); //顯示布撤防時間
      
  •             break;
      
  •         case BCADJUSTSCEEN:
      
  •             OLED_ShowCHinese(32,0,16);//模
      
  •             OLED_ShowCHinese(48,0,17);//式
      
  •             OLED_ShowCHinese(64,0,18);//設(shè)
      
  •             OLED_ShowCHinese(80,0,19);//值
      
  •             DefendDisplay();          //顯示手自動模式,布撤防狀態(tài)
      
  •             break;
      
  •         default:
      
  •             break;
      
  •         }
      
  •         usleep(100000);
      
  •     }
      
  • }

復制代碼


2、按鍵控制任務

本demo中使用了三個按鍵,顯示板上的兩個模擬按鍵、紅綠燈板的一個按鍵。顯示板右邊按鍵主要功能是切換界面,通過改變Now_Screen的值。Now_Screen可以取得值為

  • //顯示界面枚舉類型
      
  • typedef enum
      
  • {
      
  •     TIMESCREEN=0,       //時間顯示界面,開機后的界面
      
  •     NOWSCREEN,          //現(xiàn)在天氣情況的顯示界面
      
  •     TOSCREEN,           //明天天氣情況的顯示界面
      
  •     ATOSCREEN,          //后天天氣情況的顯示界面
      
  •     BCTIMESCREEN,       //布撤防時間調(diào)整的顯示界面
      
  •     BCADJUSTSCEEN,      //設(shè)置手自動模式、布撤防狀態(tài)的界面
      
  •     NOSCREEN,           //無界面
      
  • } SCREEN_STATUS;

復制代碼



顯示板左邊按鍵和紅綠燈板按鍵在不同的顯示界面,功能是不一樣的。

  • 在時間顯示界面時,顯示板左按鍵為獲取網(wǎng)絡時間功能按鍵,紅綠燈板按鍵為開關(guān)燈功能按鍵。
      
  • 在現(xiàn)在、明天、后天天氣情況的顯示界面,顯示板左按鍵為獲取網(wǎng)絡天氣數(shù)據(jù)功能按鍵,紅綠燈板按鍵無功能。
      
  • 在布撤防時間調(diào)整顯示界面,顯示板左按鍵為調(diào)整布防時間功能按鍵,紅綠燈板按鍵為調(diào)整撤防時間功能按鍵。
      
  • 在設(shè)置模式顯示界面,顯示板左按鍵為切換手自動模式功能按鍵,紅綠燈板按鍵為切換布撤防狀態(tài)的功能按鍵。
      


按鍵都只能單次觸發(fā),按下后必須松開才能再一次觸發(fā)功能。

任務代碼如下

  • //按鍵任務
      
  • static void KeyTask(void *arg)
      
  • {
      
  •     (void)arg;
      
  •     unsigned short data = 0;
      

  •   
  •     //按鍵IO初始化
      
  •     GpioInit();
      
  •     IoSetFunc(BUTTON_GPIO, BUTTON_GPIO_FUNC);
      
  •     GpioSetDir(BUTTON_GPIO, BUTTON_GPIO_DIR);
      
  •     IoSetPull(BUTTON_GPIO,WIFI_IOT_IO_PULL_UP);     //設(shè)置為上拉
      

  •   
  •     //按鍵按下標志,按下置1,松開置0
      
  •     static bool keyflag = false;
      
  •     static bool buttonflag =false;
      
  •     while(1)
      
  •     {
      
  •         //獲取模擬按鍵狀態(tài)
      
  •         AdcRead(analog_KEY_CHAN_NAME, &data, WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0);
      
  •         float voltage = ConvertToVoltage(data);
      

  •   
  •         //顯示板的左邊按鍵按下
      
  •         if((voltage>0.45 && voltage<0.65)&&(!keyflag))  //一直按下,不會重復操作,只有松開再按下,才能再次進入
      
  •         {
      
  •             keyflag = true;     
      
  •             //在不同的顯示界面上,按鍵按下的操作都不一樣
      
  •             switch (Now_Screen)
      
  •             {
      
  •             case TIMESCREEN:                        //在時間顯示界面時,獲取實時時間
      
  •                 if(connect_status == CONNECTED)
      
  •                     TcpDisconnect();                //需要先斷開之前的網(wǎng)絡連接
      
  •                 Get_Status = GET_PROPRESS;
      
  •                 if(getNtpTime())
      
  •                 {
      
  •                     Get_Status = GET_SUC;
      
  •                 }
      
  •                 else
      
  •                 {
      
  •                     Get_Status = GET_FAIL;
      
  •                 }
      
  •                 TcpConnect();                       //恢復之前的網(wǎng)絡連接
      
  •                 break;
      
  •             case NOWSCREEN:                         //在現(xiàn)在天氣顯示界面、明天天氣顯示界面、后天天氣顯示界面,都是獲取天氣數(shù)據(jù)
      
  •                 if(connect_status == CONNECTED)
      
  •                     TcpDisconnect();
      
  •                 Get_Status = GET_PROPRESS;
      
  •                 if(getWeather())
      
  •                     Get_Status = GET_SUC;
      
  •                 else
      
  •                 {
      
  •                     Get_Status = GET_FAIL;
      
  •                 }
      
  •                 TcpConnect();
      
  •                 break;
      
  •             case TOSCREEN:                          //在現(xiàn)在天氣顯示界面、明天天氣顯示界面、后天天氣顯示界面,都是獲取天氣數(shù)據(jù)
      
  •                 if(connect_status == CONNECTED)
      
  •                     TcpDisconnect();
      
  •                 Get_Status = GET_PROPRESS;
      
  •                 if(getWeather())
      
  •                     Get_Status = GET_SUC;
      
  •                 else
      
  •                 {
      
  •                     Get_Status = GET_FAIL;
      
  •                 }
      
  •                 TcpConnect();
      
  •                 break;
      
  •             case ATOSCREEN:                         //在現(xiàn)在天氣顯示界面、明天天氣顯示界面、后天天氣顯示界面,都是獲取天氣數(shù)據(jù)
      
  •                 if(connect_status == CONNECTED)
      
  •                     TcpDisconnect();
      
  •                 Get_Status = GET_PROPRESS;
      
  •                 if(getWeather())
      
  •                     Get_Status = GET_SUC;
      
  •                 else
      
  •                 {
      
  •                     Get_Status = GET_FAIL;
      
  •                 }
      
  •                 TcpConnect();
      
  •                 break;
      
  •             case BCTIMESCREEN:                      //在時間調(diào)整界面,調(diào)整布防時間
      
  •                 BfTimeAdjust();
      
  •                 break;
      
  •             case BCADJUSTSCEEN:                     //在模式設(shè)置界面,切換手自動模式
      
  •                 ZdAdjust();
      
  •                 break;
      
  •             default:
      
  •                 break;
      
  •             }
      

  •   
  •         }
      
  •         else if((voltage>0.9 && voltage<1)&&(!keyflag))    //顯示板右邊按鍵按下,切換界面
      
  •         {
      
  •             keyflag = true;
      
  •             Now_Screen ++;
      
  •             if(Now_Screen >= NOSCREEN)
      
  •             {
      
  •                 Now_Screen = TIMESCREEN;
      
  •             }
      
  •         }
      
  •         //按鍵松開
      
  •         if((!(voltage>0.45 && voltage<0.65)) && (!(voltage>0.9 && voltage<1)))
      
  •         {
      
  •             keyflag = false;
      
  •         }
      
  •         
      
  •         //紅黃綠燈板按鍵狀態(tài)
      
  •         WifiIotGpioValue buttonValue;
      
  •         GpioGetInputVal(BUTTON_GPIO,&buttonValue);
      
  •         //按鍵按下
      
  •         if((buttonValue == WIFI_IOT_GPIO_VALUE0)&&(!buttonflag))
      
  •         {
      
  •             switch (Now_Screen)
      
  •             {
      
  •             case TIMESCREEN:        //在時間顯示界面,打開或關(guān)閉LED燈
      
  •                 LedContrcl();
      
  •                 break;
      
  •             case NOWSCREEN:
      
  •             case TOSCREEN:
      
  •             case ATOSCREEN:
      
  •                 break;
      
  •             case BCTIMESCREEN:      //在時間設(shè)置界面,調(diào)整撤防時間
      
  •                 CfTimeAdjust();
      
  •                 break;
      
  •             case BCADJUSTSCEEN:     //在模式設(shè)置界面,切換布撤防狀態(tài)
      
  •                 BcAdjust();
      
  •                 break;
      
  •             default:
      
  •                 break;
      
  •             }
      
  •             buttonflag = true;
      
  •         }
      
  •         //按鍵松開
      
  •         if(!(buttonValue == WIFI_IOT_GPIO_VALUE0))
      
  •         {
      
  •             buttonflag = false;
      
  •         }
      
  •         usleep(100000);
      
  •     }
      
  • }

復制代碼


3、環(huán)境監(jiān)測任務

該任務主要功能是測量溫度、濕度,獲得可燃性氣體傳感器和人體紅外感應器ADC值,并根據(jù)獲得值進行火災和防盜檢查。獲得的可燃氣性氣體值低于一定數(shù)值時,可判斷有火災或者可燃性氣體泄漏,觸發(fā)火災報警,置位煙霧報警標志位,蜂鳴器發(fā)聲。只要檢測的數(shù)據(jù)高于設(shè)定的數(shù)據(jù),報警狀態(tài)則恢復為未報警狀態(tài)。獲得的人體紅外感應器ADC數(shù)值超過一定值,則視為觸發(fā)防盜報警。但是需要在布防狀態(tài)下,才能進行防盜檢測。防盜報警觸發(fā)后,蜂鳴器發(fā)聲報警,置位防盜報警標志位。一旦觸發(fā)防盜報警,只有通過切換到撤防狀態(tài),才能把防盜報警狀態(tài)恢復到未報警。

任務代碼如下
  

  • static void EnvironmentTask(void *arg)
      
  • {
      
  •     (void)arg;
      
  •     uint32_t retval = 0;
      
回復

使用道具 舉報

發(fā)表回復

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

本版積分規(guī)則


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表