|
【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、顯示板
4、環(huán)境監(jiān)測(cè)板
5、紅綠燈板
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;
|
|