|

【HarmonyOS HiSpark Wi-Fi IoT小视频参赛】家庭多功能智能设备,
Hispark Wi-Fi IOT套件试用的最后一篇连载,将介绍我做的一个demo。使用的套件板子包括扩展底板、主控板子、显示板、环境监测板、红绿灯板、炫彩灯板。
一、主要功能
- 火灾报警,在检测到颗粒烟雾或者有毒气体时,发声报警并把报警状态发送到手机端;
- 防盗报警,在布防状态下,检测到人时,发声报警并把报警状态发送到手机端;
- 拥有手动、自动模式设置,布防、撤防状态设置功能。在手动模式下,可以人为进行设置布撤防状态;在手动模式下,会自动根据设定的布撤防时间进行布撤防。在布防下,才进行防盗检测;
- 具备联网功能,设备能够获取网络时间和最近3天的气候情况,并在显示屏上进行显示;
- 可以与手机进行数据传输,把温湿度情况、防火报警状态、防盗报警状态、手自动模式、布撤防状态发送手机APP端,可以接收手机APP下发的手自动模式、布撤防状态切换的命令;
- 具备灯开关控制功能,可以根据环境亮度,调节灯亮度;
- 可以设置自动模式下布撤防的时间;
- 可以通过按键或者手机APP端设置手自动模式、布撤防状态;
- 启动后会自动获取网络时间或者网络天气数据,也可以通过按键手动获取网络时间或者网络天气数据;
二、硬件使用情况介绍
主要使用到下面硬件资源
1、主控板
2、扩展底板
3、显示板
4、环境监测板
5、红绿灯板
6、炫彩灯板
三、主控IO资源分配
Hi3861的GPIO口不多,一共有15个IO口,但是IO口的复用功能较多。其中GPIO3、GPIO4用来作为调试串口,如果使用了串口功能,就不能使用GPIO3、4口作为其他功能。还需要注意的是,有些IO口是复用PWM通道和ADC通道功能。如果使用了该IO作为PWM功能,ADC通道功能就无法正常使用,应该是PWM会影响ADC正常使用。
下面是demo的IO分配表,GPIO3/GPIO4作为调试输出口,没有接其他器件。
IO分配.jpg (27.1 KB, 下载次数: 0)
下载附件 保存到相册
昨天 21:11 上传
四、软件设计
我把整个工程软件分为了七个任务,显示任务、按键控制任务、环境监测任务、灯控制任务、RTC任务、TCP数据发送任务、数据接收任务。
1、显示任务
显示任务主要是控制OLED的显示。设置有六个显示界面,时间显示界面、现在天气情况显示界面、明天天气情况显示界面、后天天气显示界面、布撤防时间调整显示界面、设置模式界面。显示任务根据变量Now_Screen的值来选择显示什么界面。Now_Screen的值会在按键任务中进行改变。在获取网络时间或者网络天气数据时,会显示获取状态提示内容。 时间显示界面如下
时间显示.jpg (1.39 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:12 上传 现在天气情况显示界面
今天.jpg (1.28 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:12 上传 明天天气情况显示界面
明天.jpg (1.36 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:12 上传 后天天气情况显示界面
后天天气.jpg (1.38 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:11 上传 布撤防时间调整显示界面
时间设置.jpg (1.34 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:12 上传 设置模式显示界面
模式设置.jpg (1.38 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:12 上传 获取状态提示显示
时间成功提示.jpg (1.48 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:20 上传
时间提示.jpg (1.31 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:20 上传
天气提示.jpg (1.41 MB, 下载次数: 0)
下载附件 保存到相册
昨天 21:20 上传
任务代码如下
- static void OledTask(void *arg)
- {
- (void)arg;
- //Oled初始化
- GpioInit();
- OledInit();
- OledFillScreen(0x00);
- while (1)
- {
- //自动模式下,自动进行布撤防
- Zdbcf();
- //界面更新时,需要先删除界面显示的内容
- if(Now_Screen != Last_Screen)
- {
- Last_Screen = Now_Screen;
- OledFillScreen(0);
- Get_Status = GET_NORMAL;
- Last_Get_Status = GET_NORMAL;
- i=0;
- }
- //获取时间和天气数据状态提示,会隔一段时间进行清除
- 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); //显示现在的天气显示界面
- 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);//设
- 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);//设
- OLED_ShowCHinese(80,0,19);//值
- DefendDisplay(); //显示手自动模式,布撤防状态
- break;
- default:
- break;
- }
- usleep(100000);
- }
- }
复制代码
2、按键控制任务
本demo中使用了三个按键,显示板上的两个模拟按键、红绿灯板的一个按键。显示板右边按键主要功能是切换界面,通过改变Now_Screen的值。Now_Screen可以取得值为
- //显示界面枚举类型
- typedef enum
- {
- TIMESCREEN=0, //时间显示界面,开机后的界面
- NOWSCREEN, //现在天气情况的显示界面
- TOSCREEN, //明天天气情况的显示界面
- ATOSCREEN, //后天天气情况的显示界面
- BCTIMESCREEN, //布撤防时间调整的显示界面
- BCADJUSTSCEEN, //设置手自动模式、布撤防状态的界面
- NOSCREEN, //无界面
- } SCREEN_STATUS;
复制代码
显示板左边按键和红绿灯板按键在不同的显示界面,功能是不一样的。
- 在时间显示界面时,显示板左按键为获取网络时间功能按键,红绿灯板按键为开关灯功能按键。
- 在现在、明天、后天天气情况的显示界面,显示板左按键为获取网络天气数据功能按键,红绿灯板按键无功能。
- 在布撤防时间调整显示界面,显示板左按键为调整布防时间功能按键,红绿灯板按键为调整撤防时间功能按键。
- 在设置模式显示界面,显示板左按键为切换手自动模式功能按键,红绿灯板按键为切换布撤防状态的功能按键。
按键都只能单次触发,按下后必须松开才能再一次触发功能。
任务代码如下
- //按键任务
- 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); //设置为上拉
- //按键按下标志,按下置1,松开置0
- static bool keyflag = false;
- static bool buttonflag =false;
- while(1)
- {
- //获取模拟按键状态
- 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(); //需要先断开之前的网络连接
- Get_Status = GET_PROPRESS;
- if(getNtpTime())
- {
- Get_Status = GET_SUC;
- }
- else
- {
- Get_Status = GET_FAIL;
- }
- TcpConnect(); //恢复之前的网络连接
- break;
- case NOWSCREEN: //在现在天气显示界面、明天天气显示界面、后天天气显示界面,都是获取天气数据
- if(connect_status == CONNECTED)
- TcpDisconnect();
- Get_Status = GET_PROPRESS;
- if(getWeather())
- Get_Status = GET_SUC;
- else
- {
- Get_Status = GET_FAIL;
- }
- TcpConnect();
- break;
- case TOSCREEN: //在现在天气显示界面、明天天气显示界面、后天天气显示界面,都是获取天气数据
- if(connect_status == CONNECTED)
- TcpDisconnect();
- Get_Status = GET_PROPRESS;
- if(getWeather())
- Get_Status = GET_SUC;
- else
- {
- Get_Status = GET_FAIL;
- }
- TcpConnect();
- break;
- case ATOSCREEN: //在现在天气显示界面、明天天气显示界面、后天天气显示界面,都是获取天气数据
- if(connect_status == CONNECTED)
- TcpDisconnect();
- Get_Status = GET_PROPRESS;
- if(getWeather())
- Get_Status = GET_SUC;
- else
- {
- Get_Status = GET_FAIL;
- }
- TcpConnect();
- break;
- case BCTIMESCREEN: //在时间调整界面,调整布防时间
- BfTimeAdjust();
- break;
- case BCADJUSTSCEEN: //在模式设置界面,切换手自动模式
- 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;
- }
-
- //红黄绿灯板按键状态
- WifiIotGpioValue buttonValue;
- GpioGetInputVal(BUTTON_GPIO,&buttonValue);
- //按键按下
- if((buttonValue == WIFI_IOT_GPIO_VALUE0)&&(!buttonflag))
- {
- switch (Now_Screen)
- {
- case TIMESCREEN: //在时间显示界面,打开或关闭LED灯
- LedContrcl();
- break;
- case NOWSCREEN:
- case TOSCREEN:
- case ATOSCREEN:
- break;
- case BCTIMESCREEN: //在时间设置界面,调整撤防时间
- CfTimeAdjust();
- break;
- case BCADJUSTSCEEN: //在模式设置界面,切换布撤防状态
- BcAdjust();
- break;
- default:
- break;
- }
- buttonflag = true;
- }
- //按键松开
- if(!(buttonValue == WIFI_IOT_GPIO_VALUE0))
- {
- buttonflag = false;
- }
- usleep(100000);
- }
- }
复制代码
3、环境监测任务
该任务主要功能是测量温度、湿度,获得可燃性气体传感器和人体红外感应器ADC值,并根据获得值进行火灾和防盗检查。获得的可燃气性气体值低于一定数值时,可判断有火灾或者可燃性气体泄漏,触发火灾报警,置位烟雾报警标志位,蜂鸣器发声。只要检测的数据高于设定的数据,报警状态则恢复为未报警状态。获得的人体红外感应器ADC数值超过一定值,则视为触发防盗报警。但是需要在布防状态下,才能进行防盗检测。防盗报警触发后,蜂鸣器发声报警,置位防盗报警标志位。一旦触发防盗报警,只有通过切换到撤防状态,才能把防盗报警状态恢复到未报警。
任务代码如下
- static void EnvironmentTask(void *arg)
- {
- (void)arg;
- uint32_t retval = 0;
|
|