随着城市的快速发展,城乡差距进一步缩小,居住区位置越来越集中,安全意识逐步提高。人们越来越关注他们所居住社区的安全性和可靠性,这对人们,家庭和居民区的安全提出了更高的要求。同时,随着经济的快速发展和城市流动人口的快速增长,城市社会保障也出现了新的问题。为了保证居住区的安全,我们必须有自己的安全系统。智能安全已成为当前的发展趋势,安全问题也是人们选择生存的关键因素之一。
本项目基于OpenHarmony设计了一款智能家居安防系统,通过对有害气体、烟雾、光照和雨量进行检测,当测量值值大于设定的阈值时,对当前情况进行相应的处理,并将当前情况上报到华为IoT平台。在华为IoT平台中可随时查看屋内的状态,并且能够下达指令控制设备运行。如今,生活安全是人们生活的基础。随着生活质量的不断提高,科技的不断发展和创新,智能化,安全化,简单化的家居用品逐渐进入千家万户,因此不难发现大量企业已经出现他们渴望加快智能家居安防产品的产业布局,抢先抢占市场,这恰好说明了智能家居安防产品的广阔前景。
本项目响应了联合国17项可持续发展目标:良好健康与福祉、可持续城市与市区和气候行动目标。
基于OpenHarmony的家居安防系统,由烟雾传感器、气体检测传感器、光照传感器和雨滴传感器组成;
① 能够实时监测室内烟雾情况,超过设定的阈值时本地启动警报,并上报烟雾浓度信息;
② 能够实时监测室内气体情况,检测到有毒气体时本地启动风扇进行抽风以及发出警报,并上报气体检测信息;
③ 能够实现监测室内光照情况,超过设定的阈值时本地启动窗帘马达,并上报光照值和窗帘状态信息;
④ 能够实时监测室外环境是否下雨,超过设定的阈值时本地启动关窗马达,并上报关窗信息;
⑤ 并且能够对接华为IoT平台,实时查看到当前状态(警报情况、窗帘开关情况、窗户开关情况、风扇开关情况等状态),本设备属于环境监测设备。
本项目的视频演示:https://www.bilibili.com/video/BV1LG411t7YB/?vd_source=a8f024e9fdfd1bd8aeba13c7adde54cf
使用拓维信息OpenHarmony开发板+烟雾传感器+气体检测传感器+光照传感器+雨滴传感器+电机+蜂鸣器+风扇来模拟家居安防系统。
根据系统架构图,可以看出基于OpenHarmony的家居安防系统是主要是由三部分组成:
1)预装windows系统的PC机
2)拓维信息 Niobe Wifi IoT开发板套件
3)蜂鸣器两个
4)继电器及风扇一套
5)烟雾传感器、气体检测传感器、光照传感器、雨滴传感器模块各一套
6)电机及驱动电机模块一套(步进电机、直流电机、舵机等都是可以)
7)USB Type-C线(Windows工作台通过USB与Niobe Wifi IoT 开发板连接)
其中具体硬件的详细信息如下:
拓维Niobe开发板是一块专门基于OpenHarmony 3.0LTS版本设计的开发板,板载高度集成了2.4GHz WLAN SoC芯片Hi3861V100。
Hi3861V100芯片集成高性能32bit微处理器、硬件安全引擎以及丰富的外设接口,外设接口包括SPI、UART、I2C、PWM、 GPIO和多路ADC。
Hi3861V100芯片适应于智能家电等物联网智能终端领域。
拓维信息-OpenHarmony开发板(Talkweb Niobe)的相关资料可查看官方文件:开发板相关资料
本项目选用雨滴传感器,目的是为了监测天气状况并转成AO电压输出。
(1)雨滴传感器采用FR-04双面材料,并用镀镍处理表面,具有抗氧化,导电性等性能。
(2)输出形式:模拟量AO电压输出。
(3)AO模拟输出,连接单片机的AD口检测滴在上面的雨量大小(雨量越大输出电压越小)。
本项目选用光照传感器,目的是为了监测环境光线状况并转成AO电压输出。
(1)GL7516光敏电阻对环境光线最敏感,用来检测周围环境的光线亮度。
(2)光敏电阻的阻值随着光照强度的变化而变化,光照强度增大,阻值减小,反之阻值增大。
(3)光照越低,电阻越小,AO端输出的电压越高;光照越高,电阻越大,AO端输出的电压越低。
(4)AO端可以和AD模块相连,通过AD转换,可以获得环境光强更精准的数值。
本项目选用MQ-2烟雾传感器,目的是为了监测室内环境烟雾浓度的情况。
(1)MQ-2气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。
(2)烟雾传感器所处环境中存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大。
本项目选用MQ-135气体传感器,目的是为了监测室内环境是否存在有害气体的情况。
(1)MQ135气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。
(2)MQ135气体传感器对氨气、硫化物、苯系蒸汽的灵敏度高,对烟雾和其它有害气体的监测也很理想。
(3)广泛适用于家庭用气体泄漏报警器、工业用可燃气体报警器以及便携式气体检测器。
本项目选用继电器控制风扇的开关,当气体传感器检测到有毒气体的时候将会打开排风扇进行通风。
1.继电器:
(1)继电器用偏小的信号,达到直接控制大电流负载的目的,即弱电控制强电。
(2)单片机的引脚输出来控制继电器的闭合与断开。简单来说,继电器就相当于一个开关。
(3)IN端给低电平,NC端断开,NO端闭合,负载端电路形成闭合回路,开始工作;
(4)IN端给高电平,NO端断开,电路断开,停止工作。
2.排风扇:
(1)继电器属于数字信号模块,我们通过继电器数字信号使继电器开合来控制风扇。
(2)风扇的电压注意不超过6V,不然会电压过高导致发热甚至可能烧坏风扇。
(1)本项目选用直流电机目的是为了模拟窗户开关的情景(可根据自己的需要选择步进电机或者舵机也是可以的)。
电机正转一定角度表示开窗,反转一定角度表示关窗。
注:直流电机的工作电压为5V左右。
(2)本项目选用了直流电机故要另外选用L298N直流电机驱动模块,目的是驱动直流电机的运作。
该模块和控制端口的接口:控制直流电机时IN1、IN2和ENA为一组,IN1和IN2是逻辑信号,控制电机的正反转;OUT1和OUT2它们控制电机A,接在A+和A-。
(3)本项目选用了拓维信息-OpenHarmony开发板套件的拓展板(Niobe WiFi IoT Motor V1.1)上的电机模拟窗帘开关的情景
1)下载并安装虚拟机VMware Workstation:
2)下载Ubuntu20.04镜像:Ubuntu20.04镜像
3)下载并安装MobaXterm工具:MobaXterm工具
4)下载并安装开发板USB驱动(CH341SER.EXE–CH340/CH341-USB转串口Windows驱动程序):USB驱动
5)下载并安装VS Code编译器:Visual Studio Code
6)下载HiBurn烧录工具:HiBurn烧录工具
开发基础环境由 windows 工作台和 Linux 编译服务器组成。
windows 工作台可以通过 samba 服务或 ssh 方式访问 Linux 编译服务器。其中 windows 工作台用来烧录和代码编辑
Linux 编译服务器用来编译OpenHarmony代码,为了简化步骤,Linux 编译服务器推荐安装Ubuntu20.04。
ifconfig
获取IP地址后并记录下来,每个人的IP地址都不一样。
虚拟机 --> 设置 --> 网络适配器 --> 网络路径
*注:如果查看IP地址的时候出现以下情况:
① 根据提示,输入以下命令,安装网络工具:
sudo apt install net-tools
② 如果还不行也可以安装一下VMware tools工具。
在/home/niobe/(niobe是我虚拟机的名字,根据个人虚拟机的情况来做调整)目录下新建一个文件夹命名为niobecode。
配置niobecode文件夹的读写权限。
sudo chmod 777 /home/niobe/niobecode
将新建的niobecode文件夹配置到/etc/samba/smb.conf中。
输入以下命令使用spt-get安装:
sudo apt-get install samba
查看sanba版本,以及是否安装成功:
samba
进入smb.conf文件配置:
sudo vi /etc/samba/smb.conf
在smb.conf文件最后加上以下语句:
[niobecode]
comment = samba home directory
path = /home/niobe/
public = yes
browseable = yes
public = yes
writeable = yes
read only = no
valid users = niobe
create mask = 0777
directory mask = 0777
#force user = nobody
#force group = nogroup
available = yes
添加上面语句后按下ESC后保存并退出:
:wq
设置samba的密码:
sudo smbpasswd -a niobe
重新启动samba:
sudo service smbd restart
在Windows环境下:
右键我的电脑 -> 映射网络驱动器 -> 输入IP地址(在Ubuntu安装的步骤中获取的IP地址),把共享文件夹映射到本地。
成功后我们就可以在我的电脑里面的网络位置可以看到niobecode文件夹。
输入相关信息登录。
login as:输入虚拟机用户名
Password:输入虚拟机密码
成功登录后如下:
可以在官网文档中查看独立Docker环境一节:Docker编译环境
添加docker的官方GPC密钥:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
添加仓库:
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
安装docker:
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
运行测试docker:
sudo docker run hello-world
运行成功结果:
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
获取docker镜像:
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5
这里注意一点就是:
如果安装完docker后,执行docker相关的命令,可能会出现以下报错:
原因分析:
可能就是docker 进程使用 Unix Socket 而不是 TCP 端口。
在默认情况下,Unix socket 属于 root 用户,需要 root 权限才能访问。
解决方法:
方法1:使用 sudo 获取管理员权限,运行 docker 命令时在前面加上 sudo。
方法2:docker 守护进程启动的时候,会默认赋予名字为 docker 的用户组读写 Unix socket 的权限,因此只要创建 docker 用户组,并将当前用户加入到 docker 用户组中,那么当前用户就有权限访问 Unix socket 了,进而也就可以执行 docker 相关命令了。
具体操作命名如下:
sudo groupadd docker # 添加docker用户组
sudo gpasswd -a $USER docker # 将登陆用户加入到docker用户组中
newgrp docker # 更新用户组
docker images # 测试docker命令在不加sudo时是否可以使用
到此步环境的搭建基本上已经完成了,下面就下载源码进行编写。
首先注册好Gitee账号。
进入共享文件夹niobecode:
cd /home/niobe/niobecode
安装 git:
sudo apt install git
安装 git-lfs:
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
sudo apt-get install git-lfs
git lfs install
repo下载
安装repo python3版本 向下兼容:
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo
赋予脚本可执行权限:
chmod a+x /usr/local/bin/repo
安装requests依赖,或在执行命令时依据提示自动安装:
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple requests
使用git https的方式下载开发板源码:
git clone https://gitee.com/talkweb_oh/niobe.git
在gitee仓库中下载本demo的代码,具体下载地址:
将对应的代码添加到开发板源码的相应位置:code
① 在源码文件下applications\app下新建一个工程文件夹Security_System
② 我们将demo_Security目录下的文件拷贝到Security_System文件夹目录下
③ 将smart_Security目录下的BUILD.gn文件拷贝applications\app目录下
如果源码文件applications\app目录下有BUILD.gn文件,我们可以在BUILD.gn的基础上添加一条:"Security_System:Security_System",
,指定Security_System
参与编译,将其他不需要编译的工程前加个#就可。
"Security_System:Security_System",
# "TW001_OS_helloworld:helloworld",
# "TW002_OS_thread:os_thread_example",
# "TW003_OS_timer:os_timer_example",
目录名 | 描述 |
---|---|
applications | Niobe WiFi IoT应用程序样例 |
base | 基础软件服务子系统集&硬件服务子系统集 |
build | 组件化编译、构建和配置脚本 |
domains | 增强软件服务子系统集 |
device | 设备适配层以及SDK |
foundation | 系统基础能力子系统集 |
kernel | 内核子系统 |
prebuilts | 编译器及工具链子系统 |
test | 测试子系统 xts套件 |
third_party | 开源第三方组件 |
utils | 常用的工具集 |
vendor | 厂商提供的软件 |
build.py | 编译脚本文件 |
进入niobecode文件夹(OpenHarmony代码的根目录下)执行命令进入Docker构建环境
cd /home/niobe/niobecode
进入docker环境来编译源码,Niobe使用的是小型系统的docker编译环境:docker-openharmony:0.0.5
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5
此时已经在Docker编译环境下:
编译hb文件
输入命令进入niobe文件下:
cd niobe
输入命令:
hb set
设置工作目录:
输入 .
输入源码所在目录,点(.)表示当前目录。
通过回车确定选择,选择talkweb niobe_wifi_iot开发板。
输入以下命令进行编译:
hb build -b release -f
回车等待编译过程,直到屏幕出现 build success 说明编译成功。
查看编译出的固件位置:
当编译完后,在Windows中可以直接查看到最终编译的固件,具体路径在:
Z:\niobe\out\niobe\niobe_wifi_iot\Hi3861_wifiiot_app_allinone.bin
*注意,路劲最前的Z:\是安装samba服务共享文件夹映射在Windows上的磁盘路径。
当然我们也可以直接使用VS Code的终端来访问虚拟机:
在菜单栏 --> 终端 --> 新建一个终端
输入虚拟机账号及密码
这里要注意的是:ssh 虚拟机用户名@ip地址
ssh [email protected]
往下编译的操作跟第五步编译代码的内容一致
安装CH340驱动。
使用TypeC数据线,将拓维OpenHarmony开发板与电脑连接起来。
连接电脑时需要注意将虚拟机捕获USB的功能关闭。(会导致Windows查看不到串口)
查看开发板的串口号
我的电脑–>右键–>管理–>设备管理器–>端口(COM和LPT)–>USB-SERIAL CH340(COMx)
在Windows下打开Hiburn工具:
点击菜单Setting,选择 Com settings设置。
在Com settings中设置波特率Baud为:921600,点击确定 。
点击Select file,在弹出的文件框中,out目录下(编译出的固件位置),并选中:Hi3861_wifiiot_app_allinone.bin 镜像文件
点击Auto burn复选框,然后点击Connect,此时Connect按钮变成Disconnect
按一下开发板上的复位按钮,开始烧录程序
1.能在华为IOT平台上下发命令控制窗户电机和窗帘电机的转动。
2.能够在华为IOT平台上查看相关传感器采集到的数值(光照值、烟雾值、气体值、雨滴值)及执行部件的状态情况(窗户开关、窗帘开关、排风扇开关、烟雾警报开关和气体警报开关等情况)。
3.在气体传感器附近通过打火机释放气体,当检测到有毒气体时,气体警报开启以及打开排风扇进行通风。
4.在烟雾传感器附近通过打火机释放气体,达到预定的阈值时,烟雾警报开启。
5.控制光照传感器周围的光照强度,当光照强度满足条件时,窗帘电机转动模拟开关窗帘的情况。
6.在雨滴传感器上滴上水珠,达到预定的阈值时,电机转动模拟关窗的情况。
华为IoT平台查看到最新的上报数据:
所有设备 -> 选择本项目的设备 -> 设备详情
可以看到本项目的设备状态为:在线
在最新上报数据可以看到相应传感器采集的数据及执行部件的状态(ON,OFF)
情况一:当室内检测到有毒气体的时候,气体警报将会启动,并且持续的进行鸣叫,抽风扇开启对室内的气体进行抽风。
情况二:当室内没有检测到有毒气体的时候,气体警报和抽风扇都不会开启。
情况一:当室内烟雾浓度大于50时,烟雾警报将会启动,并且持续的进行鸣叫。
情况二:当室内烟雾浓度小于50时,此时烟雾浓度构不成威胁,烟雾报警将不会启动。
华为IOT平台可以接收到光照传感器采集的数据,也可以通过下发命令控制窗帘的开关。
情况一:当光照传感器检测到当前光照强度大于80的时候,窗帘电机将会开启,将窗帘关闭进行遮光。
情况二:当光照传感器检测到当前光照强度小于30的时候,窗帘电机将会开启,将窗帘打开进行增加光照。
华为IOT平台可以接收到雨滴传感器采集的数据,也可以通过下发命令控制窗户的开关。
情况一:窗户正在开启,当雨滴传感器检测不到下雨的时候,窗户将正常开启。
情况二:窗户正在开启,当雨滴传感器检测到下雨的时候,窗户马达启动,窗户将会被关闭。
情况三:窗户正在关闭,当雨滴传感器检测不到下雨的时候,窗户仍关闭。
情况四:窗户正在关闭,当雨滴传感器检测到下雨的时候,窗户仍关闭。
(1)气体传感器初始化
使用开发板上的GPIO12管脚初始化配置气体传感器
void Gas_Init(void)
{
IoTGpioInit(IOT_GPIO_IO_GPIO_12);// GPIO初始化
IoTIoSetFunc(IOT_GPIO_IO_GPIO_12, IOT_IO_FUNC_GPIO_12_GPIO);// GPIO使能
IoTGpioSetDir(IOT_GPIO_IO_GPIO_12, IOT_GPIO_DIR_IN);// 设置GPIO方向---IOT_GPIO_DIR_IN---输入
}
(2)烟雾传感器初始化
使用开发板上的GPIO11管脚初始化配置烟雾传感器
void Smoke_Init(void)
{
IoTGpioInit(IOT_GPIO_IO_GPIO_11);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_11, IOT_IO_FUNC_GPIO_11_GPIO);
IoTGpioSetDir(IOT_GPIO_IO_GPIO_11, IOT_GPIO_DIR_IN);
}
(3)光照传感器初始化
使用开发板上的GPIO04管脚初始化配置光照传感器
void Light_Init(void)
{
IoTGpioInit(IOT_GPIO_IO_GPIO_4);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_4, IOT_IO_FUNC_GPIO_4_GPIO);
IoTGpioSetDir(IOT_GPIO_IO_GPIO_4, IOT_GPIO_DIR_IN);
}
(4)雨滴传感器初始化
使用开发板上的GPIO09管脚初始化配置雨滴传感器
void Rain_Init(void)
{
IoTGpioInit(IOT_GPIO_IO_GPIO_9);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_9, IOT_IO_FUNC_GPIO_9_GPIO);
IoTGpioSetDir(IOT_GPIO_IO_GPIO_9, IOT_GPIO_DIR_IN);
}
气体传感器使用GPIO12管脚,故ADC转换通道号为ADC0;
烟雾传感器使用GPIO11管脚,故ADC转换通道号为ADC5;
光照传感器使用GPIO04管脚,故ADC转换通道号为ADC1;
雨滴传感器使用GPIO09管脚,故ADC转换通道号为ADC4;
//以气体传感器为例
uint8 GetGas()
{
uint8 Gas_temp=0;//百分比的整数值
float Gas_vol=0.0;//ADC采样电压
unsigned short val;
unsigned int ret;
//获取ADC0采集值---气体传感器
ret = IoTAdcRead(IOT_ADC_CHANNEL_0, &val, IOT_ADC_EQU_MODEL_8, IOT_ADC_CUR_BAIS_DEFAULT, 256);
//将ADC0采集值转换成电压值
Gas_vol = IOTAdcConvertToVoltage(val);//以便数据分析与观察
printf("气体传感器电压值voltage:%f \r\n", Gas_vol);
Gas_temp = (float)((float)Gas_vol)*33;
if(Gas_temp<=30){Gas_temp=0;}
if(Gas_temp>=100){Gas_temp=100;}
return Gas_temp;
}
(1)蜂鸣器初始化
使用开发板上的GPIO05管脚配置烟雾警报使用的蜂鸣器
使用开发板上的GPIO10管脚配置气体警报使用的蜂鸣器
void BuzzerInit(void)
{
//烟雾传感器的蜂鸣器---GPIO05
IoTGpioInit(IOT_GPIO_IO_GPIO_5);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_5, IOT_IO_FUNC_GPIO_5_GPIO); // 设置GPIO_5的复用功能为普通GPIO
IoTGpioSetDir(IOT_GPIO_IO_GPIO_5, IOT_GPIO_DIR_OUT);// 设置GPIO_5为输出模式
//气体传感器的蜂鸣器---GPIO10
IoTGpioInit(IOT_GPIO_IO_GPIO_10);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_10, IOT_IO_FUNC_GPIO_10_GPIO); // 设置GPIO_10的复用功能为普通GPIO
IoTGpioSetDir(IOT_GPIO_IO_GPIO_10, IOT_GPIO_DIR_OUT);//设置GPIO_10为输出模式
}
(2)设置烟雾传感器触发烟雾警报蜂鸣器的开关状态
烟雾警报由SmokeBuzzer(ON);触发蜂鸣器,开启警报。
烟雾警报由SmokeBuzzer(OFF);触发蜂鸣器,关闭警报。
void SmokeBuzzer(Motor_Status_ENUM status)
{
if (status == ON)
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_5, IOT_GPIO_VALUE0); //设置GPIO_5输出--低电平--开启蜂鸣器
if (status == OFF)
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_5, IOT_GPIO_VALUE1); //设置GPIO_5输出--高电平--关闭蜂鸣器
}
(3)设置气体传感器触发气体警报蜂鸣器的开关状态
气体警报由GasBuzzer(ON);触发蜂鸣器,开启警报。
气体警报由GasBuzzer(OFF);触发蜂鸣器,关闭警报。
void GasBuzzer(Motor_Status_ENUM status)
{
if (status == ON)
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_10, IOT_GPIO_VALUE0); //设置GPIO_10输出--低电平--开启蜂鸣器
if (status == OFF)
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_10, IOT_GPIO_VALUE1); //设置GPIO_10输出--高电平--关闭蜂鸣器
}
(1)抽风扇初始化
使用开发板上的GPIO14管脚初始化配置继电器,通过继电器控制抽风扇的开关。
void FanInit(void)
{
IoTGpioInit(IOT_GPIO_IO_GPIO_14);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_14, IOT_IO_FUNC_GPIO_14_GPIO);
IoTGpioSetDir(IOT_GPIO_IO_GPIO_14, IOT_GPIO_DIR_OUT);
}
(2)设置继电器的连通或者断开触发抽风扇的开关
继电器连通由FanStatusSet(ON);触发,开启抽风扇。
继电器断开由FanStatusSet(OFF);触发,关闭抽风扇。
void FanStatusSet(Motor_Status_ENUM status)
{
if (status == ON)
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_14, IOT_GPIO_VALUE0); //设置GPIO_14输出--低电平--开启风扇
if (status == OFF)
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_14, IOT_GPIO_VALUE1); //设置GPIO_14输出--高电平--关闭风扇
}
(1)直流电机的初始化
使用开发板上的GPIO07、GPIO13管脚初始化配置电机正反转,使用PWM输出电压控制电机转动速度。
GPIO07和GPIO13的配置一样,但GPIO7使用PWM0,而GPIO8使用PWM4。
void MotorInit(void)
{
IoTGpioInit(IOT_GPIO_IO_GPIO_13);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_13, IOT_IO_FUNC_GPIO_13_PWM4_OUT);
IoTGpioSetDir(IOT_GPIO_IO_GPIO_13, IOT_GPIO_DIR_OUT);
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_13, IOT_GPIO_VALUE0);//低电平
IoTPwmInit(IOT_PWM_PORT_PWM4);
IoTGpioInit(IOT_GPIO_IO_GPIO_7);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_7, IOT_IO_FUNC_GPIO_7_PWM0_OUT);
IoTGpioSetDir(IOT_GPIO_IO_GPIO_7, IOT_GPIO_DIR_OUT);
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_7, IOT_GPIO_VALUE0);//低电平
IoTPwmInit(IOT_PWM_PORT_PWM0);
}
(2)设置直流电机的开关状态
开窗户情景由MotorStatusSet(ON); 电机正转。
关窗户情景由MotorStatusSet(OFF); 电机反转。
启动PWM信号输出:使用PWM给定输出频率和相应的占空比指定给端口。
void MotorStatusSet(Motor_Status_ENUM status)
{
if (status == ON)//正转
IoTPwmStart(IOT_PWM_PORT_PWM4, 30, 15000);//PWM4开始工作(GPIO13)---正转---开窗户
usleep(400000);//延时400ms
IoTPwmStop(IOT_PWM_PORT_PWM4);//停止PWM4
if (status == OFF)//反转
IoTPwmStart(IOT_PWM_PORT_PWM0, 30, 15000);//PWM0开始工作(GPIO7)---反转---关窗户
usleep(400000);//延时400ms
IoTPwmStop(IOT_PWM_PORT_PWM0);//停止PWM0
}
(1)电机初始化
使用开发板上的GPIO08管脚初始化配置电机
void CurtainInit(void)
{
IoTGpioInit(IOT_GPIO_IO_GPIO_8);
IoTIoSetFunc(IOT_GPIO_IO_GPIO_8, IOT_IO_FUNC_GPIO_8_GPIO);
IoTGpioSetDir(IOT_GPIO_IO_GPIO_8, IOT_GPIO_DIR_OUT);
}
(2)设置电机的开关状态
开窗帘情景由CurtainStatusSet(ON); 电机开启,打开窗帘。
关窗帘情景由CurtainStatusSet(OFF); 电机开启,关闭窗帘。
void CurtainStatusSet(Motor_Status_ENUM status)
{
if (status == ON)
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_8, 1); //设置GPIO_8输出高电平打开电机
usleep(2000000);
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_8, 0); //设置GPIO_8输出低电平关闭电机
if (status == OFF)
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_8, 1); //设置GPIO_8输出高电平打开电机
usleep(2000000);
IoTGpioSetOutputVal(IOT_GPIO_IO_GPIO_8, 0); //设置GPIO_8输出低电平关闭电机
}
连接华为IoT平台后,设备端可向华为IoT平台上传设备状态、数据等信息。同时华为IoT平台也可以下发命令给设备端,设备端收到命令后进行响应。
我们把设备端与华为IoT平台连接分为获取华为IoT平台IP地址、华为IoT平台的搭建、编写相关代码。
设备端与云端通讯采用的相关协议为MQTT协议。
首先在华为IoT平台选择MQTT协议的接入地址,并复制接入地址在本地电脑上ping一下接入地址。得到一个地址为121.36.42.100的地址,此地址为华为IoT平台的地址。
在华为云IoT平台上创建产品并且注册对应的设备,华为IoT平台就会分配给设备一个设备ID,设备端可通过设备ID和相应的密钥来确保安全可信的连接到华为IoT平台。
注册对应的设备步骤如下:
① 所有设备 --> 注册设备
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ktX21xCj-1665577486495)(C:/Users/12175/Desktop/Typora_image/image-20221010201343899.png)]
② 选择所属产品、填写标识符和设备名称,分配设备ID平台会自动分配可以不用修改
③ 点击确认后会有两条设备信息,一条为设备ID另外一条为设备密钥,点击保存并关闭会提示你下载一个txt文件,txt文件里面就包含这两条信息。
④ 进去设备对接信息网站填写设备ID、设备密钥:Huaweicloud IoTDA Mqtt ClientId Generator
⑤ 生成相应信息:Clienid、Username、Password。(每设备生成的信息都是不一样的)
注册设备后,我们可以在华为IOT平台产品中的模型定义里创建一个产品,并添加服务、属性、命令等内容。
服务信息:(服务ID、服务类型)
属性信息:(属性名称、数据类型)
命令信息:(命令名称、参数名称、数据类型、长度、枚举)
引用开源代码上的oc_mqtt.c和oc_mqtt_profile_package.c函数编写代码。
Wi-Fi连接配置:引用源码上的wifi_connect.c函数编写代码,连接Wi-Fi需要用到本地的Wi-Fi账号密码。
注:代码中的服务ID、属性名称、命令名称等与华为IoT平台一一对应
static void deal_report_msg(report_t *report)
{
oc_mqtt_profile_service_t service;//定义Service级别数据,该处对应云平台配置的Security服务下的数据
oc_mqtt_profile_kv_t light;//定义属性级别数据,该处对应云平台配置的属性light信息
oc_mqtt_profile_kv_t smoke;//定义属性级别数据,该处对应云平台配置的属性smoke信息
oc_mqtt_profile_kv_t gas;//定义属性级别数据,该处对应云平台配置的属性gas信息
oc_mqtt_profile_kv_t rain;//定义属性级别数据,该处对应云平台配置的属性rain信息
oc_mqtt_profile_kv_t Curtain_flag;//定义属性级别数据,该处对应云平台配置的属性Curtain_flag信息
oc_mqtt_profile_kv_t SmokeBuzzer_flag;//定义属性级别数据,该处对应云平台配置的属性SmokeBuzzer_flag信息
oc_mqtt_profile_kv_t Fan_flag;//定义属性级别数据,该处对应云平台配置的属性Fan_flag信息
oc_mqtt_profile_kv_t GasBuzzer_flag;//定义属性级别数据,该处对应云平台配置的属性GasBuzzer_flag信息
oc_mqtt_profile_kv_t Window_flag;//定义属性级别数据,该处对应云平台配置的属性Window_flag信息
service.event_time = NULL;
service.service_id = "Security";//对应云平台配置的服务ID
service.service_property = &light;//在Security服务下添加属性信息
service.nxt = NULL;//该产品上报数据中仅存在Security一种服务,所以next指针为空
light.key = "light";//对应云平台配置的属性名称
light.value = &report->light;//light的取值由设备实际状态light决定。
light.type = EN_OC_MQTT_PROFILE_VALUE_INT;//对应云平台配置的数据类型
light.nxt = &smoke;//继续添加Security服务下的另一属性。
smoke.key = "smoke";
smoke.value = &report->smoke;
smoke.type = EN_OC_MQTT_PROFILE_VALUE_INT;
smoke.nxt = &gas;
gas.key = "gas";
gas.value = &report->gas;
gas.type = EN_OC_MQTT_PROFILE_VALUE_INT;
gas.nxt = &rain;
rain.key = "rain";
rain.value = &report->rain;
rain.type = EN_OC_MQTT_PROFILE_VALUE_INT;
rain.nxt = &Curtain_flag;
Curtain_flag.key = "Curtain_flag";
Curtain_flag.value = g_app_cb.Curtain_flag ? "ON" : "OFF";//Curtain_flag的ON,OFF取值由设备实际
Curtain_flag.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
Curtain_flag.nxt = &SmokeBuzzer_flag;
SmokeBuzzer_flag.key = "SmokeBuzzer_flag";
SmokeBuzzer_flag.value = g_app_cb.SmokeBuzzer_flag ? "ON" : "OFF";
SmokeBuzzer_flag.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
SmokeBuzzer_flag.nxt = &Fan_flag;
Fan_flag.key = "Fan_flag";
Fan_flag.value = g_app_cb.Fan_flag ? "ON" : "OFF";
Fan_flag.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
Fan_flag.nxt = &GasBuzzer_flag;
GasBuzzer_flag.key = "GasBuzzer_flag";
GasBuzzer_flag.value = g_app_cb.GasBuzzer_flag ? "ON" : "OFF";
GasBuzzer_flag.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
GasBuzzer_flag.nxt = &Window_flag;
Window_flag.key = "Window_flag";
Window_flag.value = g_app_cb.Window_flag ? "ON" : "OFF";
Window_flag.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
Window_flag.nxt = NULL;//Security服务下没有其它属性了,next置为null。
oc_mqtt_profile_propertyreport(USERNAME, &service);//打包数据
return;
}
//命令控制---窗帘马达
if (0 == strcmp(cJSON_GetStringValue(obj_cmdname),"Security_Control_Curtain"))
{
obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
if (NULL == obj_paras)
{
goto EXIT_OBJPARAS;
}
obj_para = cJSON_GetObjectItem(obj_paras, "Curtain");
if (NULL == obj_para)
{
goto EXIT_OBJPARA;
}
//操作窗帘马达
if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
{
CurtainStatusSet(ON);//开窗帘
g_app_cb.Curtain_flag = 1;
Curtain_flag = 1;
}
else
{
CurtainStatusSet(OFF);//关窗帘
g_app_cb.Curtain_flag = 0;
Curtain_flag = 0;
}
cmdret = 0;
}
//命令控制---窗户马达
else if (0 == strcmp(cJSON_GetStringValue(obj_cmdname), "Security_Control_Window"))
{
obj_paras = cJSON_GetObjectItem(obj_root, "Paras");
if (NULL == obj_paras)
{
goto EXIT_OBJPARAS;
}
obj_para = cJSON_GetObjectItem(obj_paras, "Window");
if (NULL == obj_para)
{
goto EXIT_OBJPARA;
}
//操作窗户马达
if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
{
MotorStatusSet(ON);//开窗--电机正转
g_app_cb.Window_flag = 1;
Window_flag = 1;
}
else
{
MotorStatusSet(OFF);//关窗--电机反转
g_app_cb.Window_flag = 0;
Window_flag = 0;
}
经过层层解析,最终解出对应的命令,并设置到设备中。
在硬件连接的过程中,电机驱动模块的GND没有和开发板的GND相连,导致电机不转,输出端电压为0V。
查阅了资料发现L298N供电的12V如果是用另外电源供电的话,那么需要将单片机的GND和驱动模块的GND连接起来,这样单片机上过来的逻辑信号才有个参考点,板载12V稳压芯片的输入引脚和电机供电驱动接线端子导通的。
在烧录的过程中,如果外接了传感器(烟雾传感器、气体传感器、光照传感器、雨滴传感器)的VCC接口接在开发板的3V和5V上,可能会导致烧录的时候复位不成功。
所以我们在烧录的时候需要将传感器接在开发板的3V和5V及GND先断开,等待烧录成功后就可连接起来。
在连接华为IoT平台的过程中,我们需要注意的问题是代码中的服务ID、属性名称、命令名称等信息与华为IoT平台一一对应,否则会导致数据上传不成功或者命令下发不成功。