|
【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、顯示板
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;
|
|