完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
完成全功能智慧植物生长系统以后,我们就可以为它赋能了,让它活起来。
创建产品
嵌入式开发 [size=1pc]嵌入式代码基于BK7231平台,使用涂鸦通用Wi-Fi SDK进行SOC开发,具体环境可以拉取涂鸦git库上的demo例程或者直接下载已经包含了SDK环境的demo例程。
[size=1pc]将库克隆至本地后,打开文件目录,找到apps文件夹,该文件夹用于存放应用层代码,也就是demo的代码。在这里创建一个文件夹,命名为 bk7231t_plant_grow_mach_demo,与demo有关的所有源文件、头文件以及编译产物都将放到该文件夹中。 [size=1pc]若为初次进行该平台的开发,为求快速上手,推荐将apps文件下的bk7231t_bl0973_1_plug_demo中的tuya_device.c、tuya_device.h文件都复制过来。 [size=1pc]打开tuya_device.c文件,找的device_init #4CAF50函数: 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;}[size=1pc]在BK7231t平台的SDK环境中,该函数为重要的应用代码入口,设备上电后平台适配层运行完一系列初始化代码后就会调用该函数来进行应用层的初始化操作。 [size=1pc]该函数做了三件事:
2.应用结构 [size=1pc]本demo应用代码主要分三层来实现:
3.温湿度控制 [size=1pc]要实现温湿度控制,首先要做的就是采集到温湿度。本demo方案采集温湿度的方式是使用SHT21温湿度传感器,该传感器是IIC协议通讯,因此首先需要根据该传感器的技术手册编写传感器驱动代码。在完成驱动代码后,再封装出传感器的初始化、数据采集、数据换算等接口。本demo有关SHT21传感器的驱动和外部接口都实现在sht21.c #4CAF50文件中,封装的外部接口都在plant_control.c #4CAF50中被调用:
#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); }[size=1pc]初始化完成后,就可以获取环境温湿度了。因为植物生长机需要不断的获取环境参数,所以代码上也需要不断的使用传感器数据获取接口。在上一节内容中有提到在app_plant.c #4CAF50文件中有创建过各个功能逻辑任务,其中有一个任务函数循环调用了plant_control.c #4CAF50的plant_get_iic_sensor_data(),所以这里需要在该接口中调用SHT21传感器的数据采集接口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){ // 剔除小于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); }[size=1pc]获取到环境温湿度值后,就可以和温湿度设定值做一个判断。在创建产品的时候新建了最大最小温度和最大最小湿度四个自定义功能点,所以可以在app上进行设置,并通过云端下发给设备。下发的DP点数据在app_plant.c #4CAF50的deal_dp_proc()函数中进行处理: 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;}[size=1pc]在app_plant.c #4CAF50中创建过一个任务用于数据判断和IO设备控制,该任务循环调用了plant.control.c #4CAF50中的plant_ctrl_handle()函数,所有有关具体的控制逻辑实现都放在plant_ctrl_handle()中。本demo方案用于控制温湿度的器件为一个加湿器、一个加热灯和一个风扇,通过继电器实现用IO口的高低电平控制这些器件的开和关。控制IO口电平需要用到SDK封装好的接口tuya_gpio_inout_set()和tuya_gpio_write()。温湿度控制相关代码如下: #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 LOWSTATIC VOID __ctrl_gpio_init(CONST TY_GPIO_PORT_E port, CONST BOOL_T high){ // 设置IO口为输出模式 tuya_gpio_inout_set(port, FALSE); // 设置IO口电平 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.光照控制 [size=1pc]本demo方案使用BH1750照度检测传感器,和温湿度传感器一样也是IIC协议的。根据该传感器的数据手册编写传感器驱动代码。在完成驱动代码后,封装出传感器的初始化、数据采集等接口。本demo有关BH1750传感器的驱动和外部接口都实现在bh1750.c #4CAF50文件中,封装的外部接口都在plant_control.c #4CAF50中被调用:
#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); ......}[size=1pc]初始化完成后,在plant_get_iic_sensor_data()函数里调用BH1750传感器的数据采集接口tuya_bh1750_get_bright_value()获取光照强度值。由于调试过程中发现光照传感器和温湿度传感器的采集中间不加延时的话会影响通讯,因此做了点改动让每次进入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){ // 剔除小于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; }}[size=1pc]光照控制方面的设定值没有创建对应的DP点,无法用app设置,只在代码内写死了一个数值,通过控制灯光亮度来使光照传感器采集值不断逼近该数值,并给定了一个误差范围值来防止在亮度临界点时发生的灯光不断闪烁的现象。 #define ACCURACY (2000) // 误差范围值#define light_value_set (12000) // 亮度设定值 unit:lux[size=1pc]本demo方案通过输出PWM波的方式来控制灯板的亮度,有关PWM的初始化和输出控制函数接口都实现在plant_pwm.c #4CAF50中,在plant_device_init()中初始化PWM,并在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){ // 若上一次启用的iic传感器为温湿度传感器 return; } if((TRUE == plant_ctrl_data.Auto_switch)) { // 自动补光开关为开 USHORT_T current = device_data.light_intensity_value; USHORT_T set = light_value_set; if((current - set) > ACCURACY) { // 当前光照强度大于设定值且不在误差范围内 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) { // 当前光照强度小于设定值且不在误差范围内 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) { // 自动补光开关为开 PR_NOTICE("Ligth open !!!!"); if(plant_ctrl_data.Light_color == 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) { // 灯光颜色设为蓝灯 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 { // 自动补光开关为关 用户手动定时控制 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); } // 保存定时剩余时间 单位分钟 plant_report_data.Countdown_left = light_flag_min; } }VOID plant_ctrl_handle(VOID){ ...... __passive_ctrl_module_light(); __initiative_ctrl_module_light();}5.土壤湿度控制 [size=1pc]本demo方案使用的土壤湿度检测传感器可以根据土壤的湿度情况输出模拟量,因此代码上就需要通过ADC采集模拟量转换为数字量的方式来监测土壤湿度。 在app_plant.c #4CAF50文件中创建的获取ADC采集任务中循环调用了plant_control.c #4CAF50的plant_get_adc_sensor_data(),所有有关adc采集的代码都放在该函数接口内: VOID plant_get_adc_sensor_data(VOID){ // 控制开关模拟芯片选择土壤湿度的通道 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);}[size=1pc]获取土壤湿度值后,根据湿度情况控制水泵是否打开来实现自动浇水。在plant_ctrl_handle()中调用实现控制浇水逻辑的接口:
[size=1pc]给土壤浇水的水泵是从水箱中抽水,当水箱中的水量过少时则需要另一个水泵给水箱加水。控制水箱自动加水就用到了水位传感器,该传感器也是通过输出模拟量的大小来反映测量区域水位的位置的,因此和土壤湿度传感器一样也使用ADC采集模拟量转换数字量:
#define WATER_PUMP_PORT (22)#define WATER_PUMP_LEVEL LOWSTATIC VOID __initiative_ctrl_module_pump(VOID){ // 根据水位传感器值转换剩余水量百分比,用于上报 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){ // 若水泵开关为开 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) { // 当水量接近测量上限时关闭水泵 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(); ......}[size=1pc]至此,本demo的大部分控制逻辑代码就基本完成了,在完善dp点上报和接收部分后即可开始后续的功能调试。想了解demo代码的其他细节请自行查看demo例程。 7.编译和烧录 [size=1pc]在linux终端输入指令运行SDK环境目录下的build_app.sh #4CAF50脚本来编译代码生成固件,指令格式为 sh build_app.sh APP_PATH #F44336 APP_NAME #F44336 APP_VERSION #F44336: 若出现下图所示提示,则表示编译成功,固件已经生成: 固件生成路径为:apps->APP_PATH #F44336->output 将固件烧录至模组即可开始功能调试阶段,有关烧录和授权方式请参照文档:WB系列模组烧录授权 赋能完成 程序烧录完以后,我们就完成了赋能部分,之后我们就可以对各个功能进行调试了。 |
|
|
|
只有小组成员才能发言,加入小组>>
733 浏览 0 评论
1132 浏览 1 评论
2512 浏览 5 评论
2846 浏览 9 评论
移植了freeRTOS到STMf103之后显示没有定义的原因?
2693 浏览 6 评论
684浏览 7评论
keil5中manage run-time environment怎么是灰色,不可以操作吗?
997浏览 3评论
198浏览 2评论
如果mmcblk1boot0启动失败可不可以从mmcblk1boot1启动呢
189浏览 2评论
用核心板GPIO直接控制网卡1的复位信号是否会导致液晶屏初始化失败?
231浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-4 03:14 , Processed in 1.435139 second(s), Total 79, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号