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

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

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

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

[復(fù)制鏈接]

2607

主題

2607

帖子

7472

積分

高級(jí)會(huì)員

Rank: 5Rank: 5

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

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


一、主要功能





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



二、硬件使用情況介紹



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


2、擴(kuò)展底板


3、顯示板

  • OLED顯示屏  
  • 兩個(gè)模擬按鍵
      



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

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



5、紅綠燈板

  • 一個(gè)按鍵  
  • 一個(gè)綠燈
      



6、炫彩燈板

  • 三色燈(紅綠藍(lán)混合)  
  • 人體紅外感應(yīng)器  
  • 光敏電阻
      



三、主控IO資源分配



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

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

  

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

下載附件  保存到相冊(cè)  

昨天 21:11 上傳




四、軟件設(shè)計(jì)



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


1、顯示任務(wù)

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

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

下載附件  保存到相冊(cè)  

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

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

下載附件  保存到相冊(cè)  

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

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

下載附件  保存到相冊(cè)  

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

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

下載附件  保存到相冊(cè)  

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

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

下載附件  保存到相冊(cè)  

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

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

下載附件  保存到相冊(cè)  

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

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

下載附件  保存到相冊(cè)  

昨天 21:20 上傳



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

下載附件  保存到相冊(cè)  

昨天 21:20 上傳

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

下載附件  保存到相冊(cè)  

昨天 21:20 上傳

任務(wù)代碼如下

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

  •   
  •     while (1)
      
  •     {
      
  •         //自動(dòng)模式下,自動(dòng)進(jìn)行布撤防
      
  •         Zdbcf();
      
  •         //界面更新時(shí),需要先刪除界面顯示的內(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í)間和天氣數(shù)據(jù)狀態(tài)提示,會(huì)隔一段時(shí)間進(jìn)行清除
      
  •         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();       //顯示時(shí)間顯示界面
      
  •             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);//時(shí)
      
  •             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); //顯示布撤防時(shí)間
      
  •             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();          //顯示手自動(dòng)模式,布撤防狀態(tài)
      
  •             break;
      
  •         default:
      
  •             break;
      
  •         }
      
  •         usleep(100000);
      
  •     }
      
  • }

復(fù)制代碼


2、按鍵控制任務(wù)

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

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

復(fù)制代碼



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

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


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

任務(wù)代碼如下

  • //按鍵任務(wù)
      
  • 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è)置為上拉
      

  •   
  •     //按鍵按下標(biāo)志,按下置1,松開(kāi)置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))  //一直按下,不會(huì)重復(fù)操作,只有松開(kāi)再按下,才能再次進(jìn)入
      
  •         {
      
  •             keyflag = true;     
      
  •             //在不同的顯示界面上,按鍵按下的操作都不一樣
      
  •             switch (Now_Screen)
      
  •             {
      
  •             case TIMESCREEN:                        //在時(shí)間顯示界面時(shí),獲取實(shí)時(shí)時(shí)間
      
  •                 if(connect_status == CONNECTED)
      
  •                     TcpDisconnect();                //需要先斷開(kāi)之前的網(wǎng)絡(luò)連接
      
  •                 Get_Status = GET_PROPRESS;
      
  •                 if(getNtpTime())
      
  •                 {
      
  •                     Get_Status = GET_SUC;
      
  •                 }
      
  •                 else
      
  •                 {
      
  •                     Get_Status = GET_FAIL;
      
  •                 }
      
  •                 TcpConnect();                       //恢復(fù)之前的網(wǎng)絡(luò)連接
      
  •                 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:                      //在時(shí)間調(diào)整界面,調(diào)整布防時(shí)間
      
  •                 BfTimeAdjust();
      
  •                 break;
      
  •             case BCADJUSTSCEEN:                     //在模式設(shè)置界面,切換手自動(dòng)模式
      
  •                 ZdAdjust();
      
  •                 break;
      
  •             default:
      
  •                 break;
      
  •             }
      

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

復(fù)制代碼


3、環(huán)境監(jiān)測(cè)任務(wù)

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

任務(wù)代碼如下
  

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

發(fā)表回復(fù)

本版積分規(guī)則


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