资料介绍
描述
概述
种植植物的宁静和清新是从城市生活的喧嚣中解脱出来的。然而,我们有时会因为生活中的烦恼而无法好好照顾这些美丽的植物。不过不用担心,智能室内花园是自动种植的完美解决方案。即使我们不在家,它也能照料我们的植物。
在这个项目中,我们将一个普通的室内花园改造为一个功能齐全且支持物联网的种植系统。
功能
您可以使室内花园在适度的预算内具有以下功能。
- 使用应用程序进行远程控制和数据监控。
- 监测温度和湿度、光照强度、土壤湿度和水位。
- 自动补光、加湿、加热、换气、浇水、水箱加水。
完成原型后,选择一个亚克力盒子来装饰你的花园。
逻辑
我们将功能划分为更小的构建块,如下图所示。
脚步
第 1 步:原型
程序一:修改主控板
使用涂鸦智能APP实现远程控制,我们使用涂鸦WB3S网络模块作为主控。涂鸦三明治 Wi-Fi SoC 主控板(WB3S)帮助您快速实现各种智能硬件原型。该板只有一个 ADC 端口,因此我们使用 4 通道模拟多路复用器RS2255来扩展更多模拟通道。
RS2255 提供对三个模拟通道的访问,分别表示为 A1、A2 和 A3。
- 模拟频道
电路图显示,要读取 A1、A2 和 A3 上的值,嵌入式系统必须首先读取 ADC 值。PWM0 和 PWM1 输出控制 RS2255,这与 ADC 如何连接到模拟通道有关。见下表:
程序 2:检测光强度
使用BH1750光传感器检测光强度。BH1750 是一款使用 I2C 进行通信的数字环境光传感器。BH1750FVI 是用于 I2C 总线接口的数字环境光传感器 IC。它可以精确测量高达 65535 lx 的光的 LUX 值。BH1750如下图:
- BH1750的电路图:
引脚配置:
程序 3:测量温度和湿度
使用SHT21湿度和温度传感器测量环境温度和湿度。SHT21经过全面校准,具有低功耗和出色的长期稳定性。它使用 I2C 协议进行通信。
注意:如果 SHT21 传感器不可用,您可以使用HTU21D传感器替代。
- SHT21的电路图:
- VCC:3.3V电源输入
- GND:电源地
- SCL:I2C 时钟引脚
- SDA:I2C 数据引脚
- SHT21的电路图:
- 引脚配置:
程序 4:测量土壤水分
使用土壤湿度传感器测量土壤的含水量。表面镀镍,感应面积大,可提高导电性,防止与土壤接触生锈的问题。该传感器提供模拟和数字输出。数字输出简单,而模拟输出更准确。您可以借助传感器板上的电位器(蓝色)调整传感器的灵敏度。传感器使用 LM393 比较器将土壤湿度水平与预设阈值进行比较。
- 土壤湿度传感器电路图:
- 引脚配置:VCC:3.3-5V 电源输入GND:电源地D0:数字输出A0:模拟输出
程序 5:测量水箱水位
使用水位传感器测量水箱中的水深。水位传感器具有高性能和低功耗的灵敏度。它可以很容易地将水量转换为模拟信号,输出值可以被微处理器识别,从而实现水位报警。
- 水位传感器电路图:
- 引脚配置:+:3-5V电源输入-:电源地S:模拟输出
程序 6:补光
使用室内花园上的 LED 植物灯补光。生长灯由2835颗LED灯珠组成。共有114颗珠子,分暖白、红、蓝、远红外四个波段,每个波段的比例为25:9:2:2。
为了实现蔬菜以及花卉和水果的两种生长模式,两个 PWM 输出控制光谱。一个控制蓝光,另一个控制暖白光、红光和远红外光。
- 蔬菜种植方式:
植物灯板提供暖白光、红光、蓝光和远红外光。频谱报告如下:
- 花果种植模式:
植物灯板提供暖白光、红光和远红外光。频谱报告如下:
- 引脚配置:12V:12V电源输入PON:PWM输入1 RON:PWM输入2 GND:电源地
注意蓝光只能在其他PWM信号输出时进行调节。如果您没有植物灯板,您可以使用两个 PWM 输出交替控制 LED 灯条。
程序 7:喷涂
使用 1 通道继电器模块来控制 5V 雾化器模块。造雾器芯片的工作频率为 108 kHz。第八针可用于监测水位,实现低水位切断,防止雾化盘缺水。
- 制雾器模块电路图:
- 引脚配置:红线:5V黑线:GND
程序 8:加热
使用1路继电器模块控制75W远红外线灯泡。红外线灯泡具有热效率高、遇水防爆、传热快、散热快等特点。重要的是,它可以在潮湿的环境中有效地工作。您可以根据需要使用冷却风扇。
(可选)冷却风扇:使用安装在室内花园中的冷却风扇(12V DC 0.18A)。风扇和红外线灯泡通过220V AC转12V DC电源变压器并联,由继电器模块控制。
程序 9:通风
使用1路继电器模块控制两个高速冷却风扇(12V 0.5A)。通风可以降低环境温度和湿度,从而为植物授粉。
程序 10:加注水箱
使用 1 通道继电器模块控制 12V 水泵。您可以根据需要选择供水或将水泵改为12V水电磁阀。
- 功率:24W
- 流量:5升/分钟
- 进水压力:0.48 MPa
程序 11:水
使用 1 通道继电器模块控制两个 12V DC 隔膜泵。水被泵送并施用于土壤。
程序 12:我们为什么要使用继电器模块?
继电器模块通常用于切换使用比大多数微控制器可以处理的电压更高的电压的设备。
您可以使用两个1路继电器模块和一个4路继电器模块来实现自动喷洒、加热、水箱加水、通风和浇水。
- 1通道继电器模块
- 4通道继电器模块
- 继电器引脚
程序 13:选择室内花园
选择一个简单的传统室内花园进行改造。
我们准备了一个传统的室内花园,配有种植灯板和大型土壤容器。
这个花园有以下功能:
程序 14:花园供电
花园需要四种电源,即220V AC、12V DC、5V DC和3.3V DC。为此,我们使用以下解决方案:
- 220V AC:来自 220V/50 Hz 电网的电源。
- 12V DC:将 S-120-12 开关电源连接到 220V AC 电网。
12V散热风扇与红外线灯泡相连。红外灯泡连接到 220V 交流电源。隔离开关电源模块 (12V 400 mA) 为冷却风扇产生 12V DC。
- 5V DC:为继电器模块和超声波雾化器供电。
模块规格:
- 输入电压:9V–36V DC
- 输出电压:5.2V/5A/25W
- 输入不同的电压会输出不同的功率:
- 9–24V DC,输出 5.2V/6A/30W。
- 24–32V DC,输出 5.2V/5A/25W。
- 32-36V DC,输出 5.2V/3.5A/18W。
3.3V DC:涂鸦三明治DC-DC电源板供电。此电源板配备双电源插孔,可接受 12V DC 或 5V DC 电源。
- 12V DC输入时,两颗SY8012B芯片工作,为板上其他元件提供12V、5V、3.3V DC供电
步骤 15:设计亚克力盒子
我们使用 Adobe AutoCAD 设计了一个亚克力盒子。注意事项:
- 锅大小
- 组件尺寸和布局
- 固定孔位
- 接线用螺丝孔
下图显示了组件布局供您参考。您可以修改和重新设计以满足您的需求。下载 2D 图纸。
- 正视图:
- 后视图:
第 2 步:组装
程序1:准备材料
准备以下组件和用品。
程序2:组装亚克力盒
根据图纸切割亚克力板。用粘合剂组装丙烯酸组件。
程序 3:接线
程序 4:安装组件
注意事项:
- 组件位置。
- 上排风口用于进风口,下排风口用于出风口。
- 电线使用和长度。
- 光传感器位置。
程序5:制作雾化器
- 找一个带盖的瓶子。
- 固定脱脂棉。
在盖子上钻一个直径合适的孔来固定脱脂棉。放一些沙子或小石头固定棉花的底部。
- 将水位感应线通过盖子孔插入瓶子。
- 修复雾化器。
1.如图所示将造雾器放在盖子上。
2. 重新拧上盖子,但不要太紧。否则无法产生雾气。如果没有瓶子,您可以用热胶固定雾化器。
程序 6:完成组装
将组件放入盒子中并整理电线。
第 3 步:创建
进行涂鸦 OS 开发,需要在涂鸦IoT 平台上创建一个室内花园产品,然后获取 SDK。该产品代表了智慧花园的所有物联网功能,包括产品授权和配置,构建了花园与涂鸦物联网平台的通信。本节介绍如何在涂鸦物联网平台上打造智能室内花园。有关详细信息,请参阅创建产品。
- 找到自定义函数并单击创建函数。设置自定义函数的属性。
- 要设置温度和湿度范围,请添加四个整数数据点 (DP),即Max Temp 、Min Temp 、Max Humidity和Min Humidity 。
- 要将水箱水位的数据传输到云端,请添加水箱水位的整数DP 。
- 要控制生长光色,请添加Light Color的枚举 DP 。
- 要在预定和自动补光之间切换,请添加Fill Light的布尔 DP 。
- 登录涂鸦物联网平台,点击创建。
- 选择小家电>植物种植者。
- 单击自定义解决方案>植物种植者。输入产品名称,协议类型选择WiFi+蓝牙,点击页面下方的创建产品。
- 在创建标准函数中,选择开关、泵、当前温度、当前湿度、倒计时、剩余时间和故障。
- (可选)要实现智能花园的非标准功能,需要自定义一些功能。
- 完成功能定义后,点击设备面板选择喜欢的应用控制面板。建议选择适合您的调试需要的调试面板。
您已完成在涂鸦 IoT 平台上创建产品。它已准备好进行嵌入式系统开发。
第 4 步:代码
嵌入式代码基于 BK7231 芯片组,使用涂鸦通用 Wi-Fi SDK 开发。您可以从涂鸦 GitHub 仓库拉取的 demo 例程中获取环境变量,也可以下载包含 SDK 环境变量的 demo 例程。我们通过方法 1 获取 SDK。
-
方法一: GitHub 仓库中的 BK7231T SDK
ty_iot_wf_bt_sdk_bk7231t
。 - 方法二: GitHub上的花园demo 。
程序 1:进入申请
克隆存储库以在您的计算机上创建本地副本。打开apps
存储演示代码的文件夹。在这个文件夹中,新建一个文件夹,命名bk7231t_plant_grow_mach_demo
为存放demo相关的源文件、头文件、编译文件。
如果您是第一次接触 BK7231 开发,我们建议您在和文件夹中分别找到tuya_device.c
和并将它们复制到这个新创建的文件夹中。tuya_device.h
src
include
bk7231t_bl0937_1_plug_demo
打开tuya_device.c
并找到该device_init
功能。
OPERATE_RET device_init(VOID)
{
OPERATE_RET op_ret = OPRT_OK;
TY_IOT_CBS_S wf_cbs = {
status_changed_cb,\
gw_ug_inform_cb,\
gw_reset_cb,\
dev_obj_dp_cb,\
dev_raw_dp_cb,\
dev_dp_query_cb,\
NULL,
};
op_ret = tuya_iot_wf_soc_dev_init_param(hw_get_wifi_mode(),WF_START_SMART_FIRST,\
&wf_cbs,NULL,PRODECT_KEY,DEV_SW_VERSION);
if(OPRT_OK != op_ret) {
PR_ERR("tuya_iot_wf_soc_dev_init_param error,err_num:%d",op_ret);
return op_ret;
}
op_ret = tuya_iot_reg_get_wf_nw_stat_cb(wf_nw_status_cb);
if(OPRT_OK != op_ret) {
PR_ERR("tuya_iot_reg_get_wf_nw_stat_cb is error,err_num:%d",op_ret);
return op_ret;
}
op_ret= app_dltj_init(APP_DLTJ_NORMAL);
if(OPRT_OK != op_ret) {
PR_ERR("dltj init err!");
return op_ret;
}
op_ret = app_switch_init(APP_SW_MODE_NORMAL);
if(op_ret != OPRT_OK) {
return op_ret;
}
return op_ret;
}
在 BK7231T 芯片组的开发环境中,device_init
函数是应用程序代码的入口。设备上电时,BK7231T适配层运行初始化代码,然后调用该函数初始化应用层。该函数处理以下内容:
-
调用
tuya_iot_wf_soc_dev_init_param()
SDK初始化配置工作模式和配对模式,注册回调函数,保存固件密钥和PID。
TY_IOT_CBS_S wf_cbs = {
status_changed_cb,\
gw_ug_inform_cb,\
gw_reset_cb,\
dev_obj_dp_cb,\
dev_raw_dp_cb,\
dev_dp_query_cb,\
NULL,
};
op_ret = tuya_iot_wf_soc_dev_init_param(hw_get_wifi_mode(),WF_START_SMART_FIRST,\
&wf_cbs,NULL,PRODECT_KEY,DEV_SW_VERSION);
if(OPRT_OK != op_ret) {
PR_ERR("tuya_iot_wf_soc_dev_init_param error,err_num:%d",op_ret);
return op_ret;
} op_ret = tuya_iot_reg_get_wf_nw_stat_cb(wf_nw_status_cb);
if(OPRT_OK != op_ret) {
PR_ERR("tuya_iot_reg_get_wf_nw_stat_cb is error,err_num:%d",op_ret);
return op_ret;
}
op_ret= app_dltj_init(APP_DLTJ_NORMAL);
if(OPRT_OK != op_ret) {
PR_ERR("dltj init err!");
return op_ret;
}
op_ret = app_switch_init(APP_SW_MODE_NORMAL);
if(op_ret != OPRT_OK) {
return op_ret;
}
-
调用
tuya_iot_reg_get_wf_nw_stat_cb()
注册设备网络状态回调。
op_ret = tuya_iot_reg_get_wf_nw_stat_cb(wf_nw_status_cb);
if(OPRT_OK != op_ret) {
PR_ERR("tuya_iot_reg_get_wf_nw_stat_cb is error,err_num:%d",op_ret);
return op_ret;
}
- 在应用层调用初始化函数。
op_ret= app_dltj_init(APP_DLTJ_NORMAL);
if(OPRT_OK != op_ret) {
PR_ERR("dltj init err!");
return op_ret;
}
op_ret = app_switch_init(APP_SW_MODE_NORMAL);
if(op_ret != OPRT_OK) {
return op_ret;
}
因为tuya_device.c
是借用了另一个demo,所以我们需要为这个demo实现一个应用初始化函数。创建app_plant.c
及其头文件并实现app_plant_init()
在device_init
.
程序 2:应用程序架构
应用程序代码分三层实现。
- 底层有传感器驱动代码和封装传感器初始化和数据采集接口。
- 第二层有部分控制逻辑代码,调用传感器驱动接口来实现各个组件的控制逻辑。该层封装了轮询数据处理的接口。
- 第一层创建应用任务调用第二层接口,处理DP数据传输,接受解析。
app_plant.c
实现第一层。
-
app_plant_init()
调用二层封装的设备初始化接口,创建应用任务。
OPERATE_RET app_plant_init(IN APP_PLANT_MODE mode)
{
OPERATE_RET op_ret = OPRT_OK;
if(APP_PLANT_NORMAL == mode) {
// Initialize I/O, sensors, PWM, and more
plant_device_init();
// Create data collection tasks for I2C sensors
xTaskCreate(sensor_data_get_iic_theard,"thread_data_get_iic",512,NULL,TRD_PRIO_3,NULL);
// Create data collection tasks for ADC sensors
xTaskCreate(sensor_data_get_adc_theard,"thread_data_get_adc",512,NULL,TRD_PRIO_4,NULL);
// Create data processing tasks
xTaskCreate(sensor_data_deal_theard,"thread_data_deal",512,NULL,TRD_PRIO_4,NULL);
// Create scheduled tasks for DP data reporting
xTaskCreate(sensor_data_report_theard,"thread_data_report",512,NULL,TRD_PRIO_4,NULL);
}else {
// Non-production test mode
}
return op_ret;
}
-
app_report_all_dp_status()
报告所有 DP 数据:
VOID app_report_all_dp_status(VOID)
{
OPERATE_RET op_ret = OPRT_OK;
INT_T dp_cnt = 0;
dp_cnt = 12;
TY_OBJ_DP_S *dp_arr = (TY_OBJ_DP_S *)Malloc(dp_cnt*SIZEOF(TY_OBJ_DP_S));
if(NULL == dp_arr) {
PR_ERR("malloc failed");
return;
}
memset(dp_arr, 0, dp_cnt*SIZEOF(TY_OBJ_DP_S));
dp_arr[0].dpid = DPID_SWITCH_P;
dp_arr[0].type = PROP_BOOL;
dp_arr[0].time_stamp = 0;
dp_arr[0].value.dp_value = plant_ctrl_data.Switch;
......
op_ret = dev_report_dp_json_async(NULL,dp_arr,dp_cnt);
Free(dp_arr);
if(OPRT_OK != op_ret) {
PR_ERR("dev_report_dp_json_async relay_config data error,err_num",op_ret);
}
PR_DEBUG("dp_query report_all_dp_data");
return;
}
- 任务功能。
在任务中,plant_get_iic_sensor_data()
、plant_get_adc_sensor_data()
、plant_ctrl_handle()
和plant_ctrl_all_off()
被循环调用。这些接口来自第二层并在plant_control.c
.
STATIC VOID sensor_data_get_iic_theard(PVOID_T pArg)
{
while(1) {
PR_DEBUG("plant_get_i2c_sensor_data");
vTaskDelay(TASKDELAY_SEC);
if(TRUE == plant_ctrl_data.Switch) {
plant_get_iic_sensor_data();
}
}
}
STATIC VOID sensor_data_get_adc_theard(PVOID_T pArg)
{
while(1) {
PR_DEBUG("plant_get_adc_sensor_data");
vTaskDelay(TASKDELAY_SEC*2);
if(TRUE == plant_ctrl_data.Switch) {
plant_get_adc_sensor_data();
}
}
}
STATIC VOID sensor_data_deal_theard(PVOID_T pArg)
{
while(1) {
vTaskDelay(TASKDELAY_SEC);
if(TRUE == plant_ctrl_data.Switch) {
plant_ctrl_handle();
}else {
plant_ctrl_all_off();
}
}
}
STATIC VOID sensor_data_report_theard(PVOID_T pArg)
{
while(1) {
vTaskDelay(TASKDELAY_SEC*5);
app_report_all_dp_status();
}
}
-
deal_dp_proc()
根据DP ID处理接收到的DP数据。
VOID deal_dp_proc(IN CONST TY_OBJ_DP_S *root)
{
UCHAR_T dpid;
dpid = root->dpid;
PR_DEBUG("dpid:%d",dpid);
switch (dpid) {
case DPID_SWITCH_P:
PR_DEBUG("set switch:%d",root->value.dp_bool);
plant_ctrl_data.Switch = root->value.dp_bool;
break;
case DPID_PUMP:
PR_DEBUG("set pump:%d",root->value.dp_bool);
plant_ctrl_data.Pump = root->value.dp_bool;
break;
......
default:
break;
}
return;
}
我们已经构建了应用程序架构。接下来,我们需要在第二层实现接口,这些接口放在plant_control.c
. 以下程序描述了温度和湿度、光照和土壤湿度方面的控制逻辑。
程序 3:温度和湿度
要控制温度和湿度,首先我们必须收集数据。SHT21 传感器收集温度和湿度数据。它使用 I2C 协议进行通信。我们根据SHT21 技术手册编写传感器驱动程序代码。驱动代码完成后,我们封装了传感器初始化、数据采集、数据转换的接口。
所有 SHT21 驱动程序和外部接口均以sht21.c
. 封装的外部接口从plant_control.c
.
1.tuya_sht21_init(sht21_init_t* param)
初始化传感器。request 参数是一个指向结构的指针,该结构包含有关 SDA 和 SCL I/O 引脚和分辨率的信息。
typedef struct
{
UCHAR_T SDA_PIN; ///< SDA pin
UCHAR_T SCL_PIN; ///< SCL pin
sht21_resolution_t RESOLUTION;
}sht21_init_t;
2.定义结构变量plant_control.c
并调用plant_device_init()
以初始化传感器。
#define IIC_SDA_PIN (6)
#define IIC_SCL_PIN (7)
STATIC sht21_init_t sht21_int_param = {IIC_SDA_PIN, IIC_SCL_PIN, SHT2x_RES_10_13BIT};
VOID plant_device_init(VOID)
{
// SHT21 IIC driver init
tuya_sht21_init(&sht21_int_param);
}
3.初始化后,传感器可以提供环境温度和湿度值。因为花园需要连续的环境参数,所以必须相应地调用获取传感数据的接口。在上述过程中,任务函数app_plant.c
之一plant_get_iic_sensor_data()
在plant_control.c
. 因此,我们需要调用传感器数据采集接口tuya_sht21_measure()
和计算接口tuya_sht21_cal_RH()
。这两个接口的参数都是枚举值,用来获取温度或湿度。
VOID plant_get_iic_sensor_data(VOID)
{
SHORT_T hum;
SHORT_T temp;
tuya_sht21_init(&sht21_int_param);
hum = tuya_sht21_measure(HUMIDITY);
device_data.humidity = tuya_sht21_cal_RH(hum);
if(device_data.humidity > 0){ // Remove invalid humidity values less than 0
plant_report_data.Humidity_current = (UCHAR_T)device_data.humidity;
PR_NOTICE("humidity = %d",plant_report_data.Humidity_current);
}
temp = tuya_sht21_measure(TEMP);
device_data.temperature = tuya_sht21_cal_temperature(temp);
plant_report_data.Temp_current = (UCHAR_T)device_data.temperature;
PR_NOTICE("tempre = %d",plant_report_data.Temp_current);
}
4.将环境温度和湿度与阈值进行比较。我们在涂鸦 IoT 平台上创建了最高最低温度和湿度的四个 DP ,因此我们可以通过应用设置阈值并通过云端发送到设备。处理DP数据中的deal_dp_proc()
函数。app_plant.c
VOID deal_dp_proc(IN CONST TY_OBJ_DP_S *root)
{
UCHAR_T dpid;
dpid = root->dpid;
PR_DEBUG("dpid:%d",dpid);
switch (dpid) {
......
case DPID_TEMP_MAX:
PR_DEBUG("set temp max:%d",root->value.dp_value);
plant_ctrl_data.Temp_max = root->value.dp_value;
break;
case DPID_HUMIDITY_MAX:
PR_DEBUG("set humidity max:%d",root->value.dp_value);
plant_ctrl_data.Humidity_max = root->value.dp_value;
break;
case DPID_TEMP_MIN:
PR_DEBUG("set temp min:%d",root->value.dp_value);
plant_ctrl_data.Temp_min = root->value.dp_value;
break;
case DPID_HUMIDITY_MIN:
PR_DEBUG("set humidity min:%d",root->value.dp_value);
plant_ctrl_data.Humidity_min = root->value.dp_value;
break;
......
default:
break;
}
return;
}
5.创建数据比较和I/O设备控制任务app_plant.c
。它在循环中调用plant_ctrl_handle()
函数。plant.control.c
所有控制逻辑都在 中指定plant_ctrl_handle()
。为了调节温度和湿度,我们使用了雾化器、红外线灯泡和冷却风扇,它们通过继电器模块打开/关闭。tuya_gpio_inout_set()
此 SDK 中封装的接口和tuya_gpio_write()
接口控制 I/O 输出。代码如下:
#define HUMIDIFIER_PORT (24)
#define HUMIDIFIER_LEVEL LOW
#define HEATING_ROD_PORT (20)
#define HEATING_ROD_LEVEL LOW
#define COOL_DOWN_FAN_PORT (21)
#define COOL_DOWN_FAN_LEVEL LOW
STATIC VOID __ctrl_gpio_init(CONST TY_GPIO_PORT_E port, CONST BOOL_T high)
{
// Set I/O pin to output mode
tuya_gpio_inout_set(port, FALSE);
// Set I/O level
tuya_gpio_write(port, high);
}
VOID plant_device_init(VOID)
{
// SHT21 IIC driver init
tuya_sht21_init(&sht21_int_param);
// gpio init
__ctrl_gpio_init(HUMIDIFIER_PORT, HUMIDIFIER_LEVEL);
__ctrl_gpio_init(COOL_DOWN_FAN_PORT, COOL_DOWN_FAN_LEVEL);
__ctrl_gpio_init(HEATING_ROD_PORT, HEATING_ROD_LEVEL);
}
STATIC VOID __passive_ctrl_module_temp_humidity(VOID)
{
if(device_data.humidity < plant_ctrl_data.Humidity_min) {
tuya_gpio_write(HUMIDIFIER_PORT, !HUMIDIFIER_LEVEL);
}else {
tuya_gpio_write(HUMIDIFIER_PORT, HUMIDIFIER_LEVEL);
}
if(device_data.temperature < plant_ctrl_data.Temp_min) {
tuya_gpio_write(HEATING_ROD_PORT, !HEATING_ROD_LEVEL);
}else {
tuya_gpio_write(HEATING_ROD_PORT, HEATING_ROD_LEVEL);
}
if((device_data.temperature > plant_ctrl_data.Temp_max)||(device_data.humidity > plant_ctrl_data.Humidity_max)) {
tuya_gpio_write(COOL_DOWN_FAN_PORT,!COOL_DOWN_FAN_LEVEL);
}else {
tuya_gpio_write(COOL_DOWN_FAN_PORT,COOL_DOWN_FAN_LEVEL);
}
}
VOID plant_ctrl_handle(VOID)
{
PR_DEBUG("enter ctrl handle");
__passive_ctrl_module_temp_humidity();
}
程序 4:灯光控制
BH1750 光传感器使用 I2C 协议进行通信。我们根据BH1750 数据表编写传感器驱动程序代码。驱动代码完成后,我们封装了传感器初始化和数据采集的接口。所有 BH1750 驱动程序和外部接口均以bh1750.c
. 封装的外部接口从plant_control.c
.
1.tuya_bh1750_init(sht21_init_t* param)
初始化传感器。request 参数是一个指向包含有关 SDA 和 SCL I/O 管脚信息的结构的指针。
typedef struct
{
UCHAR_T SDA_PIN; ///< SDA pin
UCHAR_T SCL_PIN; ///< SCL pin
}bh1750_init_t;
2.定义结构变量plant_control.c
并调用plant_device_init()
以初始化传感器。
#define IIC_SDA_PIN (6)
#define IIC_SCL_PIN (7)
STATIC bh1750_init_t bh1750_int_param = {IIC_SDA_PIN, IIC_SCL_PIN};
VOID plant_device_init(VOID)
{
......
// SHT21 IIC driver init
tuya_bh1750_init(&bh1750_int_param);
......
}
tuya_bh1750_get_bright_value()
3.初始化完成后,调用BH1750数据采集接口plant_get_iic_sensor_data()
获取光照强度值。为保证光传感器和温湿度传感器采集数据时通信稳定,plant_get_iic_sensor_data()
输入时只启用其中一个传感器。
VOID plant_get_iic_sensor_data(VOID)
{
SHORT_T hum;
SHORT_T temp;
switch (IIC_SELECT_FLAG)
{
case 0:
tuya_sht21_init(&sht21_int_param);
hum = tuya_sht21_measure(HUMIDITY);
device_data.humidity = tuya_sht21_cal_RH(hum);
if(device_data.humidity > 0){ // Remove invalid humidity values less than 0
plant_report_data.Humidity_current = (UCHAR_T)device_data.humidity;
PR_NOTICE("humidity = %d",plant_report_data.Humidity_current);
}
temp = tuya_sht21_measure(TEMP);
device_data.temperature = tuya_sht21_cal_temperature(temp);
plant_report_data.Temp_current = (UCHAR_T)device_data.temperature;
PR_NOTICE("tempre = %d",plant_report_data.Temp_current);
IIC_SELECT_FLAG = 1;
break;
case 1:
tuya_bh1750_init(&bh1750_int_param);
device_data.light_intensity_value = tuya_bh1750_get_bright_value();
PR_NOTICE("light_intensity_value = %d",device_data.light_intensity_value);
IIC_SELECT_FLAG = 0;
break;
default:
break;
}
}
4.因为我们没有创建一个DP来设置一个应用程序的光强度值,我们在代码中设置了一个值。调整光亮度,使光传感器采集的数据接近该值。我们还设置了一个误差范围,以避免在临界点出现光闪烁。
#define ACCURACY (2000) // Error range
#define light_value_set (12000) // Light intensity in lx unit
5.PWM输出控制灯光亮度。PWM 初始化和输出功能在plant_pwm.c
. 初始化PWM in plant_device_init()
,调用实现光控的接口plant_ctrl_handle()
。
USER_PWM_DUTY_T user_pwm_duty = {0,0};
VOID plant_device_init(VOID)
{
......
plant_pwm_init();
......
}
STATIC VOID __passive_ctrl_module_light(VOID)
{
if(IIC_SELECT_FLAG){ // If the I2C temperature and humidity sensor operates previously
return;
}
if((TRUE == plant_ctrl_data.Auto_switch)) { // Automatic light filling is switched on
USHORT_T current = device_data.light_intensity_value;
USHORT_T set = light_value_set;
if((current - set) > ACCURACY) { // Current light intensity is greater than the set value but not within the error range
if((current - set) >= 200) {
if(plant_ctrl_data.Bright_value >= 50)plant_ctrl_data.Bright_value -= 50;
}else if((current - set) > 150) {
if(plant_ctrl_data.Bright_value >= 20)plant_ctrl_data.Bright_value -= 20;
}else {
if(plant_ctrl_data.Bright_value >= 1)plant_ctrl_data.Bright_value--;
}
}else if((set - current) > ACCURACY) { // Current light intensity is less than the set value but not within the error range
if((set - current) >= 200) {
if(plant_ctrl_data.Bright_value <= 950)plant_ctrl_data.Bright_value += 50;
}else if((set - current) > 150) {
if(plant_ctrl_data.Bright_value <= 980)plant_ctrl_data.Bright_value += 20;
}else {
if(plant_ctrl_data.Bright_value <= 999)plant_ctrl_data.Bright_value++;
}
}
}
}
STATIC VOID __initiative_ctrl_module_light(VOID)
{
if(TRUE == plant_ctrl_data.Auto_switch) { // Automatic light filling is switched on
PR_NOTICE("Ligth open !!!!");
if(plant_ctrl_data.Light_color == red) { // Set light color to red
user_pwm_duty.duty_red = plant_ctrl_data.Bright_value;
user_pwm_duty.duty_blue = 0;
}else if(plant_ctrl_data.Light_color == blue) { // Set light color to blue
user_pwm_duty.duty_blue = plant_ctrl_data.Bright_value;
user_pwm_duty.duty_red = 0;
}else {
user_pwm_duty.duty_blue = plant_ctrl_data.Bright_value;
user_pwm_duty.duty_red = user_pwm_duty.duty_blue;
}
plant_pwm_set(&user_pwm_duty);
}else { // Automatic light filling is switched off. Users manually schedule light filling.
if(plant_ctrl_data.Light_color == red) {
user_pwm_duty.duty_red = 1000;
user_pwm_duty.duty_blue = 0;
}else if(plant_ctrl_data.Light_color == blue) {
user_pwm_duty.duty_blue = 1000;
user_pwm_duty.duty_red = 0;
}else {
user_pwm_duty.duty_red = 1000;
user_pwm_duty.duty_blue = 1000;
}
if((IsThisSysTimerRun(light_timer) == FALSE)&&(plant_ctrl_data.Countdown_set != cancel)) {
light_flag_min = (USHORT_T)plant_ctrl_data.Countdown_set * 60;
plant_pwm_set(&user_pwm_duty);
sys_start_timer(light_timer,1000*60,TIMER_CYCLE);
}else if(plant_ctrl_data.Countdown_set == cancel) {
user_pwm_duty.duty_blue = 0;
user_pwm_duty.duty_red = 0;
plant_pwm_set(&user_pwm_duty);
light_flag_min = 0;
sys_stop_timer(light_timer);
}else if(IsThisSysTimerRun(light_timer) == TRUE) {
plant_pwm_set(&user_pwm_duty);
}
// Save timer's remaining time in minute
plant_report_data.Countdown_left = light_flag_min;
}
}
VOID plant_ctrl_handle(VOID)
{
......
__passive_ctrl_module_light();
__initiative_ctrl_module_light();
}
程序 5:土壤水分
土壤湿度传感器根据土壤电阻的变化输出不同的模拟信号值。ADC 将来自传感器的模拟信号转换为数字信号,以监测水分的变化。
1.app_plant.c
中,ADC采集任务循环调用plant_get_adc_sensor_data()
。plant_control.c
所有ADC采集相关的代码都放在这个界面中:
VOID plant_get_adc_sensor_data(VOID)
{ // Control switch analog chip to select soil moisture channel
rs2255_channel_checkout(SOIL_MOISTURE_SENSOR_PORT);
tuya_hal_adc_init(&tuya_adc);
tuya_hal_adc_value_get(TEMP_ADC_DATA_LEN, &device_data.soil_humidity);
PR_NOTICE("soil_humidity = %d",device_data.soil_humidity);
tuya_hal_adc_finalize(&tuya_adc);
}
2.当土壤水分值低于阈值时,水泵开始运行并为植物供水。调用自动浇水接口plant_ctrl_handle()
。
-
和变量使水泵有一个休息间隔,以避免植物浇水过多
ADD_WATER_COUNT
。ADD_WATER_READY
STATIC VOID __passive_ctrl_module_soil_humidity(VOID)
{
if(device_data.soil_humidity > plant_ctrl_data.Soil_humidity_threshold) {
if(ADD_WATER_READY) {
tuya_gpio_write(WATER_VALVE_PORT, !WATER_VALVE_LEVEL);
ADD_WATER_COUNT++;
if(ADD_WATER_COUNT > 5) {
ADD_WATER_READY = 0;
}
} else{
tuya_gpio_write(WATER_VALVE_PORT, WATER_VALVE_LEVEL);
ADD_WATER_COUNT++;
if(ADD_WATER_COUNT >15) {
ADD_WATER_READY = 1;
ADD_WATER_COUNT = 0;
}
}
}else {
ADD_WATER_READY = 1;
ADD_WATER_COUNT = 0;
tuya_gpio_write(WATER_VALVE_PORT, WATER_VALVE_LEVEL);
}
}
VOID plant_ctrl_handle(VOID)
{
......
__passive_ctrl_module_soil_humidity();
......
}
程序 6:水箱
水泵用于从水箱抽水并向工厂供水。当水位下降时,需要另一个水泵为水箱供水。水位传感器根据电阻产生输出电压,通过测量我们可以确定水位。我们需要使用 ADC 读取这个模拟电压并将其转换为数字值。
1.rs2255_init()
用于初始化模拟开关芯片。RS2255 与 SDA 和 SCL 引脚共享相同的 I/O,因此初始化在 ADC 数据采集开始时运行,这与其他 I2C 传感器初始化相同。
VOID plant_get_adc_sensor_data(VOID)
{
rs2255_init();
switch (ADC_SELECT_FLAG)
{
case 0:
rs2255_channel_checkout(WATER_SENSOR_PORT);
tuya_hal_adc_init(&tuya_adc);
tuya_hal_adc_value_get(TEMP_ADC_DATA_LEN, &device_data.water_tank_value);
PR_NOTICE("water_tank_value = %d",device_data.water_tank_value);
ADC_SELECT_FLAG = 1;
break;
case 1:
rs2255_channel_checkout(SOIL_MOISTURE_SENSOR_PORT);
tuya_hal_adc_init(&tuya_adc);
tuya_hal_adc_value_get(TEMP_ADC_DATA_LEN, &device_data.soil_humidity);
PR_NOTICE("soil_humidity = %d",device_data.soil_humidity);
ADC_SELECT_FLAG = 0;
break;
default:
break;
}
tuya_hal_adc_finalize(&tuya_adc);
}
2.调用plant_ctrl_handle()
实现水箱水位控制。
#define WATER_PUMP_PORT (22)
#define WATER_PUMP_LEVEL LOW
STATIC VOID __initiative_ctrl_module_pump(VOID)
{
// Convert water level sensor value into remaining water level percentage for data transmission
if(device_data.water_tank_value < 1700) {
plant_report_data.Water_remain = 10;
}else if(device_data.water_tank_value < 2500) {
plant_report_data.Water_remain = 25;
}else if(device_data.water_tank_value < 2700) {
plant_report_data.Water_remain = 50;
}else if(device_data.water_tank_value < 2900) {
plant_report_data.Water_remain = 75;
}else if(device_data.water_tank_value >= 3000) {
plant_report_data.Water_remain = 100;
}
if(TRUE == plant_ctrl_data.Pump){ // If water pump is switched on
PR_NOTICE("water pump open !!!!");
tuya_gpio_write(WATER_PUMP_PORT,!WATER_PUMP_LEVEL);
}else {
tuya_gpio_write(WATER_PUMP_PORT,WATER_PUMP_LEVEL);
}
if(device_data.water_tank_value >= 3000) { // When the water level approaches the threshold, the water pump is switched off
PR_NOTICE("water tank is full !!!!");
tuya_gpio_write(WATER_PUMP_PORT,WATER_PUMP_LEVEL);
plant_ctrl_data.Pump = FALSE;
}
}
VOID plant_ctrl_handle(VOID)
{
......
__initiative_ctrl_module_pump();
......
}
现在,我们已经完成了编码部分。用APP上的调试面板测试DP数据传输后,我们就可以进行固件编译了。
程序 7:编译和烧录
在 Linux 终端中,运行build_app.sh
脚本来编译固件。生成的固件位于apps
> APP_PATH
>output
中。
- 命令格式:
build_app.sh /home/share/samba/ci/ty_iot_wf_bt_sdk_bk7231t$ sudo sh build_app.sh apps/bk7231t_plant_grow_mach_demo bk7231t_plant_grow_mach_demo 1.0.0
- 命令示例:
/home/share/samba/ci/ty_iot_wf_bt_sdk_bk7231t$ sudo sh build_app.sh apps/bk7231t_plant_grow_mach_demo bk7231t_plant_grow_mach_demo 1.0.0
- 下图显示成功返回。
将固件烧录到模块后,我们开始进行功能调试。有关刻录和授权的更多信息,请参阅刻录和授权 WB 系列模块。
第 5 步:调试
一旦模块被授权,我们将手机连接到 Wi-Fi 网络,打开蓝牙,按照说明对花园进行配对。然后,我们可以用应用程序控制花园。在本项目中,我们使用涂鸦智能 App 作为控制终端。有不同的应用程序选项。有关详细信息,请参阅应用程序开发。
调试过程如下:
程序 1:预定和自动补光
- 打开花园并设置倒计时。
2.设置灯光颜色,生长灯板相应改变颜色。
3.当倒计时设置为取消时,植物灯板将关闭。
4.开启自动补光后,灯光亮度会不断增加,直到达到预设值。
程序二:温湿度控制
1.可以在涂鸦智能APP上查看当前环境温度和湿度。
2.如果您设置的最小湿度大于当前湿度,雾化器将启动。当环境湿度超过最小值时,制雾器将停止。
3.如果您设置的最低温度高于当前温度,红外线灯泡将打开。当环境温度超过最小值时,红外灯泡将停止。
4.以同样的方式测试最高温度和湿度,并观察冷却风扇是否相应运行。这个风扇可以对空气进行除湿和冷却。
程序 3:加注水箱
1.可查看水箱水位剩余水百分比。
2.在涂鸦智能APP开启Pump ,开启水泵。
1:通风继电器模块
2:喷涂继电器模块
3:补水箱继电器模块
3.将水位传感器放入杯中,加水至铜线完全没入。您会发现水泵停止并且应用程序上的Pump恢复。
4.水箱水位变为100。
程序 4:自动浇水
- 当您打开花园时,用于浇水的水泵将持续运行。
- 4:浇水继电器模块
- 5:加热继电器模块
2.将土壤湿度传感器放入水中,模拟土壤湿度达到阈值的情况。你会发现水泵停止。
概括
恭喜!您已成功构建智能室内花园的原型。依托涂鸦物联网平台,您可以快速轻松地从零开始构建各种智能原型。
- 基于物联网技术的农业种植环境监控系统设计
- 支持物联网的16x2 LCD屏幕
- 使用Arduino构建基于物联网的天气监测系统
- 构建工业用物联网
- 支持物联网的智能风扇速度控制器PCB板
- 探究机械工程物联网系统远程解决方案 15次下载
- 构建基于 MCU 安全物联网系统
- 构建基于 MCU 安全物联网系统
- 什么是智能工厂-物联网系统 7次下载
- 基于ZigBee和物联网的智能草莓大棚控制系统 37次下载
- 基于蓝牙4.0构建医疗物联网系统 12次下载
- 物联网操作系统的技术路线有哪些之中国厂商的机遇有哪些
- 如何使用物联网操作系统Zephyr实现“连续集成”开源软件的详细说明
- 使用物联网进行家庭智慧种植系统的设计方案的详细资料说明 4次下载
- 物联网果园种植远程监控控制系统 4次下载
- 物联网智能宠物管理系统 825次阅读
- 基于阿里云物联网平台的智能灯光控制系统设计 4035次阅读
- 如何使用M5Stamp PICO和Qubitro构建物联网门锁监控系统 1680次阅读
- 基于电子标签和物联网实现工业企业物联网系统的设计 3698次阅读
- 如何构建一个完整的物联网解决方案 4743次阅读
- 为什么物联网存储基于对象 1424次阅读
- 物联网设备经常遇到怎样的网络问题 1225次阅读
- 突破物联网界限,您准备好了吗?(文末免费下载白皮书) 2027次阅读
- 物联网系统评价的模型如何去构建实现 1328次阅读
- 种植物联网系统架构图和功能介绍 6211次阅读
- 物联网十大经典开源操作系统 1w次阅读
- 采用物联网RFID技术构建的智能图书管理系统浅析 1683次阅读
- 物联网网关概述及系统设计 9432次阅读
- 物联网有哪些操作系统?物联网操作系统汇总 5.4w次阅读
- 利用物联网生态图研究物联网的方法 6045次阅读
下载排行
本周
- 1山景DSP芯片AP8248A2数据手册
- 1.06 MB | 532次下载 | 免费
- 2RK3399完整板原理图(支持平板,盒子VR)
- 3.28 MB | 339次下载 | 免费
- 3TC358743XBG评估板参考手册
- 1.36 MB | 330次下载 | 免费
- 4DFM软件使用教程
- 0.84 MB | 295次下载 | 免费
- 5元宇宙深度解析—未来的未来-风口还是泡沫
- 6.40 MB | 227次下载 | 免费
- 6迪文DGUS开发指南
- 31.67 MB | 194次下载 | 免费
- 7元宇宙底层硬件系列报告
- 13.42 MB | 182次下载 | 免费
- 8FP5207XR-G1中文应用手册
- 1.09 MB | 178次下载 | 免费
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 2555集成电路应用800例(新编版)
- 0.00 MB | 33566次下载 | 免费
- 3接口电路图大全
- 未知 | 30323次下载 | 免费
- 4开关电源设计实例指南
- 未知 | 21549次下载 | 免费
- 5电气工程师手册免费下载(新编第二版pdf电子书)
- 0.00 MB | 15349次下载 | 免费
- 6数字电路基础pdf(下载)
- 未知 | 13750次下载 | 免费
- 7电子制作实例集锦 下载
- 未知 | 8113次下载 | 免费
- 8《LED驱动电路设计》 温德尔著
- 0.00 MB | 6656次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935054次下载 | 免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB | 537798次下载 | 免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 | 420027次下载 | 免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 5Altium DXP2002下载入口
- 未知 | 233046次下载 | 免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 | 191187次下载 | 免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M | 183279次下载 | 免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 | 138040次下载 | 免费
评论
查看更多