前言
本文由OpenAtom OpenHarmony(以下简称“OpenHarmony”)开源开发者成长计划活动的参与者李建涛提供,详细阐述了由搭载OpenHarmony系统的拓维Niobe开发套件开发而来的智能阳台项目的全过程,包括项目流程、硬件准备、软件分析,以及问题分析等,能够为开发者后续开发类似项目时提供一些参考。
一、项目设计与分析
1.1 项目描述
基于OpenHarmony的智能阳台具体功能如下:
- 能够实时监测室外环境是否下雨;
- 能够对接华为IoT物联网平台,从平台上接入设备实时查看到当前状态(窗户开关情况、室外是否下雨);
- 当传感器采集到的数据超过预先设定的阈值时,本地启动关窗马达,并上报关窗信息;
- 本设备能够成功搭载OpenHarmony开发板的环境监测设备,并实现环境监测功能。
1.2 系统架构图
基于OpenHarmony的智能阳台系统架构图如下:
根据系统架构图,可以看出基于OpenHarmony的智能阳台主要是由三部分组成: - 数据采集:由雨滴传感器采集室外的环境情况;
- 信号传送:开发板接收到传感器的数据进行判断,并且发送判断后的信号给电机驱动模块;开发板通过MQTT协议将数据上传到华为云平台;华为云平台也可以通过下发命令给开发板并将该命令的信号发送给电机驱动模块;
执行部件:电机控制模块根据单片机的信号控制电机执行相应的动作(开窗或关窗的动作)。
1.3 系统流程图
基于OpenHarmony的智能阳台系统流程图如下:
1.4 系统原理图
基于OpenHarmony的智能阳台系统原理图如下:
二、硬件准备
2.1 基于OpenHarmony的智能阳台硬件准备情况如下:
(1)预装windows系统的PC机
(2)拓维信息Niobe Wifi IoT开发板套件
(3)雨滴传感器模块一套
(4)电机及驱动电机模块一套(步进电机、直流电机、舵机等都可以)
(5)USB Type-C线(用于连接Windows工作台与Niobe Wifi IoT 开发板)
2.2 硬件一:OpenHarmony开发板
拓维Niobe开发板是一块专门基于OpenHarmony 3.0 LTS版本设计的开发板,板载高度集成了2.4GHz WLAN SoC芯片Hi3861V100。
Hi3861V100 WiFi基带支持正交频分复用(OFDM)技术,并向下兼容直接序列扩频(DSSS)和补码键控(CCK)技术,支持IEEE 802.11 b/g/n协议的各种数据速率。Hi3861V100芯片集成高性能32bit微处理器、硬件安全引擎以及丰富的外设接口,外设接口包括SPI、UART、I2C、PWM、GPIO和多路ADC。
Hi3861V100芯片适应于智能家电等物联网智能终端领域。
拓维信息-OpenHarmony开发板(Talkweb Niobe)的相关资料可以在拓维信息的Gitee仓库中查看。
2.3 硬件二:雨滴传感器模块
本项目选用雨滴传感器,目的是监测天气状况并转成AO电压输出。
(1)材质:雨滴传感器采用FR-04双面材料,并用镀镍处理表面,具有抗氧化,导电性等性能。
(2)输出形式:模拟量AO电压输出。
(3)AO模拟输出,连接单片机的AD口检测滴在上面的雨量大小(雨量越大输出电压越小)。
2.4 硬件三:电机模块
2.4.1 本项目选用直流电机目的是模拟窗户开关的情景(可根据自己的需要选择步进电机或者舵机也是可以的)。
电机正转一定角度表示开窗,反转一定角度表示关窗。
注:直流电机的工作电压为5V左右。
2.4.2 本项目选用了直流电机,故要另外选用L298N直流电机驱动模块,目的是驱动直流电机的运作。
(1)本模块使用L298N作为主驱动芯片,具有驱动能力强,发热量低,抗干扰能力强的特点。
(2)L298N直流电机驱动模块,支持双轴控制,其电路原理就是两个H桥电路。
(3)该模块可以直接驱动两路3-30V直流电机,并提供5V输出接口,可以方便地控制直流电机速度和方向
(4)该模块和控制端口的接口:控制直流电机时IN1、IN2和ENA为一组,IN1和IN2是逻辑信号,控制电机的正反转;OUT1和OUT2它们控制电机A,接在A+和A-。三、软件分析
3.1 开发环境的搭建
万事开头难,要完成基于OpenHarmony智能阳台的项目开发,首先第一件事就是开发环境的搭建。搭建好开发环境是学习OpenHarmony开发板以及后续项目开发的基础,其中包括安装虚拟机,配置Docker编译环境,下载开发板源码等步骤,每一步都非常重要,且需要确保零错误。对于一个有经验的开发者来说,从开发环境的搭建到编译成功可能会花一两天时间,而对于像我这样刚接触OpenHarmony开发板的小白来说花费的时间会更多,且非常困难。对此我经过几天的查阅资料和观看一些导师的课程,一步一步地进行开发环境的搭建以及烧录过程。对此也编写了一篇《基于OpenHarmony开发板的环境搭建及烧录过程(拓维Niobe开发板)》的文章,具体文章已发布于Gitee上。
链接如下https://gitee.com/lijiantao20...
3.2 关键代码分析
本项目的代码可以在Gitee仓库里下载https://gitee.com/openharmony...代码目录如下:
3.2.1 电机配置部分
电机配置分为电机的初始化和设置电机的开关状态两个部分,相应代码位置都在motor.c文件里。
(1) 电机的初始化
使用开发板上的GPIO7、GPIO8管脚控制电机正反转,使用PWM输出电压控制电机转动速度。
代码如下:
GPIO7和GPIO8的配置一样。但GPIO7使用PWM0,而GPIO8使用PWM1。
IoTGpioInit(IoT_GPIO_IO_GPIO_7);//GPIO初始化
IoTIoSetFunc(IoT_GPIO_IO_GPIO_7,IoT_IO_FUNC_GPIO_7_PWM0_OUT);//GPIO使能
IoTGpioSetDir(IoT_GPIO_IO_GPIO_7, IoT_GPIO_DIR_OUT);//设置GPIO方向---IoT_GPIO_DIR_OUT---输出
IoTGpioSetOutputVal(IoT_GPIO_IO_GPIO_7, IoT_GPIO_VALUE0);//设置GPIO输出电平---低电平
IoTPwmInit(IoT_PWM_PORT_PWM0);//初始化PWM设备
(2)设置电机的开关状态
启动PWM信号输出:使用PWM给定输出频率和相应的占空比指定给端口。
代码如下:
开窗情景为:MotorStatusSet(ON); 电机正转。
关窗情景为:MotorStatusSet(OFF); 电机反转。
void MotorStatusSet(Motor_Status_ENUM status)
{
if (status == ON)//正转
{
IoTPwmStart(IoT_PWM_PORT_PWM1, 30, 15000);
usleep(400000);
IoTPwmStop(IoT_PWM_PORT_PWM1);
}
if (status == OFF)//反转
{
IoTPwmStart(IoT_PWM_PORT_PWM0, 30, 15000);
usleep(400000);
IoTPwmStop(IoT_PWM_PORT_PWM0);
}
}
3.2.2 雨滴传感器配置部分
雨滴传感器配置分为雨滴传感器的初始化和使用ADC采集雨滴传感器数据两个部分,雨滴传感器的初始化代码位置在motor.c文件里,使用ADC采集雨滴传感器数据代码位置在balcony.c文件里。
(1)雨滴传感器初始化
使用开发板上的GPIO4管脚控制雨滴传感器(有雨输出低电平,雨量越大电压越低)
代码如下:
IoTGpioInit(IoT_GPIO_IO_GPIO_4);//GPIO初始化
IoTIoSetFunc(IoT_GPIO_IO_GPIO_4,IoT_IO_FUNC_GPIO_4_GPIO);//GPIO使能
IoTGpioSetDir(IoT_GPIO_IO_GPIO_4,IoT_GPIO_DIR_IN);//设置GPIO方向---IoT_GPIO_DIR_IN---输入
(2)使用ADC采集雨滴传感器数据
代码如下:
//GPIO4的ADC转换通道号为ADC1
ret = IoTAdcRead(IoT_ADC_CHANNEL_1,&val,IoT_ADC_EQU_MODEL_8, IoT_ADC_CUR_BAIS_DEFAULT, 256);
//将电压数值转化为百位数,以便数据分析与观察
val = IoTAdcConvertToVoltage(val);
val = 3.4 - val;
voltage = (float)((float)val)/3.5 * 100;
3.2.3 连接华为IoT平台部分
连接华为IoT平台后,设备端可向华为IoT平台上传设备状态、数据等信息。同时华为IoT平台也可以下发命令给设备端,设备端收到命令后进行响应。
我们把设备端与华为IoT平台连接分为获取华为IoT平台IP地址、华为IoT平台的搭建、编写上传数据相关代码以及编写下发命令相关代码四个部分。
(1)获取华为IoT平台IP地址
设备端与云端通讯采用的相关协议为MQTT协议。
首先在华为IoT平台选择MQTT协议的接入地址,并复制接入地址在PC终端上ping一下该接入地址。得到一个地址为121.36.42.100的IP地址,该地址为华为IoT平台的IP地址。
在oc_mqtt.h文件里我们可以查看到相应代码配置。
(2)华为IoT平台的搭建
华为IoT平台的搭建首先创建产品并且注册对应的设备,华为IoT平台就会分配给设备一个设备ID,设备端可通过设备ID和相应的密钥来确保安全可信地连接到华为IoT平台。
注册对应的设备步骤如下:
① 所有设备 --> 注册设备
② 选择所属产品、填写标识符和设备名称,分配设备ID平台会自动分配可以不用修改
③ 点击确认后会有两条设备信息,一条为设备ID另外一条为设备密钥,点击保存并关闭会提示你下载一个txt文件,txt文件里面就包含这两条信息。
④ 进去设备对接信息网站填写设备ID、设备密钥:https://IoT-tool.obs-website....
生成相应信息:ClientID、Username、Password。(每设备生成的信息都是不一样的)
代码如下:
在balcony.c文件里可以查看到以下配置:
注册设备后,我们可以在华为IoT平台产品中的模型定义里创建一个产品,并添加服务、属性、命令等内容。
服务信息:(服务ID、服务类型)
属性信息:(属性名称、数据类型)
命令信息:(命令名称、参数名称、数据类型、长度、枚举)
注:代码中的服务ID、属性名称、命令名称等与华为IoT平台一一对应。
引用开源代码oc_mqtt.c和oc_mqtt_profile_package.c函数编写代码。
Wi-Fi连接配置:引用开源代码wifi_connect.c函数编写代码,连接Wi-Fi需要用到本地的Wi-Fi账号密码,在balcony.c文件里修改Wi-Fi信息。
(3)上传数据的配置
代码如下:
static void deal_report_msg(report_t *report)
{
//定义Service级别数据,该处对应云平台配置的Balcony服务下的数据
oc_mqtt_profile_service_t service;
//定义属性级别数据,该处对应云平台配置的属性voltage信息
oc_mqtt_profile_kv_t voltage;
//定义属性级别数据,该处对应云平台配置的属性Window_flag信息
oc_mqtt_profile_kv_t Window_flag;
//定义属性级别数据,该处对应云平台配置的属性Rain_flag信息
oc_mqtt_profile_kv_t Rain_flag;
//定义属性级别数据,该处对应云平台配置的属性motor信息
oc_mqtt_profile_kv_t motor;
service.event_time = NULL;
//对应云平台配置的服务ID
service.service_id = "Balcony";
//在Balcony服务下添加属性信息
service.service_property = &voltage;
//该产品上报数据中仅存在Balcony一种服务,所以next指针为空
service.nxt = NULL;
//对应云平台配置的属性名称
voltage.key = "voltage";
//voltage的取值由设备实际状态voltage决定
voltage.value = &report->voltage;
//对应云平台配置的数据类型
voltage.type = EN_OC_MQTT_PROFILE_VALUE_FLOAT;
//继续添加Balcony服务下的另一属性
voltage.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 = &Rain_flag;
Rain_flag.key = "Rain_flag";
Rain_flag.value = g_app_cb.Rain_flag ? "ON" : "OFF";
Rain_flag.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
Rain_flag.nxt = &motor;
motor.key = "Motor_Status";
//Motor_Status的ON,OFF取值由设备实际
motor.value = g_app_cb.motor ? "ON" : "OFF";
motor.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
//Balcony服务下没有其它属性了,next置为null。
motor.nxt = NULL;
//打包数据
oc_mqtt_profile_propertyreport(USERNAME, &service);
return;
}
(4)下发命令控制电机的配置
代码如下:
if(0==strcmp(cJSON_GetStringValue(obj_cmdname), "Balcony_Control_Motor"))
{
obj_para = cJSON_GetObjectItem(obj_paras, "Motor");
if (NULL == obj_para)
{
goto EXIT_OBJPARA;
}
//操作电动马达
if (0 == strcmp(cJSON_GetStringValue(obj_para), "ON"))
{
g_app_cb.motor = 1;
MotorStatusSet(ON);//开窗
g_app_cb.Window_flag = 1;
Window_flag = 1;
}
else
{
g_app_cb.motor = 0;
MotorStatusSet(OFF);//关窗
g_app_cb.Window_flag = 0;
Window_flag = 0;
}
}
四、问题总结及解决过程
4.1 问题一:硬件连接
在硬件连接的过程,电机驱动模块的GND没有和开发板的GND相连,导致电机不转,输出端电压为0V。
查阅了资料发现L298N供电的12V如果是用另外电源供电的话,那么需要将单片机的GND和驱动模块的GND连接起来,这样单片机上过来的逻辑信号才有个参考点,板载12V稳压芯片的输入引脚和电机供电驱动接线端子导通的。
4.2 问题二:烧录问题
在烧录的时候,如果外接的传感器(雨滴传感器)的VCC接口接在开发板的5V上可能会导致烧录的时候复位不成功。
所以我们在烧录的时候需要将传感器接在开发板的5V及GND先断开,等待烧录成功后就可连接起来。
4.3 问题三:连接华为云IoT平台
在连接华为IoT平台的过程中,我们需要注意的问题是代码中的服务ID、属性名称、命令名称等信息与华为IoT平台一一对应,否则会导致数据上传不成功或者命令下发不成功。
五、项目作品演示
- 能在华为IoT平台上下发命令控制电机的转动。
- 可在雨滴传感器上滴上水珠,达到预定的阈值时,电机转动模拟关窗。
- 能够在华为IoT平台上查看相关传感器测得的数值以及窗户(是否开窗)、环境(是否下雨)状态的情况。
Wi-Fi连接成功串口显示:
华为IoT平台在线调试--可看到数据接收和命令发送的情况:
华为IoT平台查看到最新的上报数据:
以下分别对四个情景进行分析与说明:
情景一:无雨天气并且使用华为IoT平台下发命令开窗
当华为IoT平台下发命令Balcony_Control_Motor --> ON。窗户马达则会转动,将窗户打开并且将数据信息上传回华为IoT平台。
华为IoT平台数据信息同步更新:
硬件图如下:
情景二:无雨天气并且使用华为IoT平台下发命令关窗
当华为IoT平台下发命令Balcony_Control_Motor --> OFF。窗户马达则会转动将窗户关闭并且将数据信息上传回华为IoT平台。
华为IoT平台数据信息同步更新:
硬件图如下:
情景三:窗户开着,检测到下雨天气,则会关窗并且上报数据
当窗户开着的情况,天气从晴朗天气变成下雨天气,当雨滴检测板检测到雨滴,并且超过设定的阈值的时候,窗户马达将转动将窗户关闭并且将数据信息上传回华为IoT平台。
华为IoT平台数据信息同步更新:
硬件图如下:
情景四:下完雨后,雨滴检测板没有雨滴
当天气从下雨天气变成晴朗天气,雨滴检测板没有检测到雨滴(此处为了方便实验,使用了纸巾擦除雨滴检测板上的水),并且将数据信息上传回华为IoT平台。
华为IoT平台数据信息同步更新:
硬件图如下:
六、心得体会参加本次OpenHarmony开源开发者成长计划活动,让我收获良多,不仅了解到OpenHarmony的生态系统,也在开发项目的过程中深入接触到OpenHarmony的开发板。在开发项目的过程中曾经出现大大小小的问题,例如环境搭建、硬件连接、WiFi连接配网和连接华为云平台等,但有问题并不可怕,只要下定决心去解决就总会找到相应的方法。我在这个实践过程中积累了不少经验,这让我对OpenHarmony开发产生了更浓厚的兴趣,让我更想往下不断学习,学习一些更有深度和更有趣的OpenHarmony知识。