OpenHarmony鸿蒙硬件-Kaihong_Hi3861土壤湿度感应板、土壤检测探头获取土壤湿度 作者:马育民 • 2026-03-30 21:44 • 阅读:10002 # 应用场景 在物联网智能农业、盆栽监测等场景中,土壤湿度是核心监测指标之一。本文基于**OpenHarmony 1.0 轻量级系统**(Hi3861_WiFi_IoT开发板),搭配电阻式土壤湿度传感器,实现土壤湿度的精准采集、ADC模拟信号转数字信号、电压值到湿度百分比的换算,并输出标准化采集数据,为后续的智能浇水、湿度阈值报警等功能提供基础。 开发核心需求: 1. 基于OpenHarmony 1.0标准驱动,实现ADC采集功能,匹配Hi3861硬件特性; 2. 完成模拟电压到土壤湿度百分比的转换,解决传感器实际特性与理论公式的匹配问题; 3. 保证代码符合OpenHarmony开发规范,结构精简、可维护性强; 4. 输出纯英文打印日志,避免串口乱码,适配嵌入式开发调试场景。 # 二、硬件准备与原理说明 ### 2.1 硬件 [](https://www.malaoshi.top/upload/0/0/1GW32eRNu5PK.png) ### 2.2 传感器工作原理 本文使用的**电阻式土壤湿度传感器**为模拟输出型,核心原理是:土壤湿度不同,导电性不同,传感器电极间的电阻值会发生变化——**土壤湿度越高,电阻越小,输出的模拟电压越低;土壤湿度越低,电阻越大,输出的模拟电压越高**。 传感器输出 `0~3.3V`(5V供电时)的模拟电压,需通过开发板的ADC(模拟/数字转换器)将模拟信号转换为0~4095的数字信号,再通过公式换算为 `0~100%` 的湿度百分比,实现量化监测。 # 三、开发环境准备 1. **系统环境**:Ubuntu 18.04/20.04(推荐,OpenHarmony官方编译环境); 2. **开发工具**:VS Code(代码编写)、MobaXterm/Xshell(串口调试)、HarmonyOS DevEco Device Tool(可选); 3. **固件版本**:OpenHarmony 1.0(Hi3861专用版,已适配ADC、GPIO驱动); 4. **串口配置**:波特率115200、数据位8、停止位1、无校验、无流控。 # 四、核心代码实现 ### 4.1 代码设计思路 1. **分层设计**:按“硬件初始化、数据采集、数值换算”分层,函数职责单一,符合高内聚低耦合原则; 2. **规范适配**:严格遵循OpenHarmony 1.0开发规范,头文件、宏定义、函数命名、注释均符合嵌入式开发标准; 3. **异常处理**:对ADC读取结果做校验,对湿度值做范围限制,避免程序崩溃或输出异常数据; 4. **无冗余设计**:仅保留土壤湿度采集核心功能,移除无关的GPIO控制、水泵驱动等代码,降低资源占用。 ### 4.2 代码 创建目录,如: ``` \applications\sample\wifi-iot\app\code_v2.0\std_30_土壤湿度 ``` 创建 `main.c`文件 ``` #include #include #include // OpenHarmony系统初始化头文件 #include "ohos_init.h" // 操作系统任务创建头文件 #include "cmsis_os2.h" // ADC驱动头文件(核心:读取模拟信号) #include "hi_adc.h" // GPIO配置头文件(配置ADC引脚功能) #include "hi_io.h" // ===================== 硬件配置(匹配你的开发板) ===================== // 土壤湿度传感器ADC通道:GPIO9对应ADC4(硬件文档指定) #define SOIL_ADC_CHANNEL HI_ADC_CHANNEL_4 /** * @brief 初始化ADC采集引脚(GPIO9) * @note 仅配置ADC采集所需的GPIO,移除水泵/继电器相关配置 */ static void ADC_Pin_Init(void) { // 配置GPIO9为ADC功能(关闭默认的上下拉电阻,避免干扰采集) hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_GPIO); hi_io_set_pull(HI_IO_NAME_GPIO_9, HI_IO_PULL_NONE); } /** * @brief 读取并计算土壤湿度(核心函数) * @return 湿度百分比(0~100%) * @note 电压越低 → 湿度越高(0V=100%,3.3V=0%) */ static uint8_t Read_Soil_Humidity(void) { uint16_t adc_raw = 0; // 原始ADC值(0~4095) float voltage = 0.0f; // 转换后的电压值(0~3.3V) uint8_t humidity = 0; // 最终湿度百分比 // 读取ADC原始值:通道4、8次平均滤波、默认偏置电流 if (hi_adc_read(SOIL_ADC_CHANNEL, &adc_raw, HI_ADC_EQU_MODEL_8, HI_ADC_CUR_BAIS_DEFAULT, 0) == HI_ERR_SUCCESS) { // ADC值转换为实际电压(公式:电压 = ADC值 * 3.3V / 4095) voltage = hi_adc_convert_to_voltage(adc_raw); // 计算湿度:电压越高湿度越低,最终结果限制在0~100% humidity = 100 - (uint8_t)((voltage / 3.3f) * 100); humidity = (humidity > 100) ? 100 : humidity; // 打印结果(纯英文,避免乱码) printf("ADC raw: %d | Voltage: %.2fV | Soil humidity: %d%%\n", adc_raw, voltage, humidity); } else { // ADC读取失败时的提示 printf("Failed to read ADC data!\n"); humidity = 0; } return humidity; } /** * @brief 土壤湿度采集主任务 * @param arg: 任务入参(未使用) * @note 死循环持续采集,每秒刷新一次 */ void Soil_Humi_Collect_Task(void *arg) { (void)arg; // 忽略未使用参数,避免编译警告 // 初始化ADC引脚 ADC_Pin_Init(); // 任务启动提示(纯英文) printf("Soil humidity collection task started!\n"); // 持续采集湿度 while (1) { Read_Soil_Humidity(); // 读取并打印湿度 sleep(1); // 延时1秒,降低采集频率 } } /** * @brief 系统初始化入口 * @note 创建并启动湿度采集任务,系统开机自动运行 */ void Soil_Humi_Init(void) { // 任务属性配置:名称、栈大小、优先级 osThreadAttr_t task_attr = { .name = "SoilHumiTask", // 任务名称 .stack_size = 1024 * 2, // 简化栈大小(仅采集功能,2KB足够) .priority = osPriorityNormal, // 普通优先级 }; // 创建任务并启动 if (osThreadNew(Soil_Humi_Collect_Task, NULL, &task_attr) == NULL) { printf("Failed to create soil humidity task!\n"); } } // 注册系统启动入口,开机自动执行Soil_Humi_Init SYS_RUN(Soil_Humi_Init); ``` 同目录创建 `BUILD.gn` 文件: ``` # static_library中指定业务模块的编译结果.为静态库文件libmyapp.a,开发者根据实际情况完成填写。 #sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。 #include_dirs中指定source所需要依赖的.h文件路径。 static_library("app") { sources = [ "main.c" ] include_dirs = [ "//utils/native/lite/include", "//base/iot_hardware/interfaces/kits/wifiiot_lite", "//kernel/liteos_m/components/cmsis/2.0", ] } ``` ### 4.3 核心代码解析 #### 4.3.1 头文件引入 仅引入核心必要头文件,遵循“最小依赖”原则: - 标准库头文件(`stdio.h`/`stdint.h`/`unistd.h`):实现打印、固定宽度类型、延时功能; - OpenHarmony系统头文件(`ohos_init.h`/`cmsis_os2.h`):实现系统启动、任务创建; - 硬件驱动头文件(`hi_adc.h`/`hi_io.h`):实现ADC采集、GPIO引脚配置。 #### 4.3.2 宏定义配置 所有硬件配置、任务参数均通过宏定义实现,便于后期修改与移植: - `SOIL_ADC_CHANNEL`:指定ADC采集通道,与硬件接线匹配; - 任务栈大小与优先级:根据功能需求配置,避免资源过度分配或不足。 #### 4.3.3 ADC引脚初始化 `ADC_Pin_Init`函数仅完成ADC采集引脚的核心配置: 1. `hi_io_set_func`:将 **GPIO9** 配置为 **ADC** 功能,兼容OpenHarmony 1.0底层驱动; 2. `hi_io_set_pull`:关闭GPIO9上下拉电阻,防止外部电阻干扰ADC采集信号,保证数据准确性。 #### 4.3.4 土壤湿度采集与换算 `Read_Soil_Humidity`是核心业务函数,完成三大核心功能: 1. **ADC采集**:调用`hi_adc_read`读取原始值,使用8次平均滤波(`HI_ADC_EQU_MODEL_8`)提高采集稳定性; 2. **电压转换**:调用官方API`hi_adc_convert_to_voltage`将ADC原始值转换为实际电压,避免手动计算带来的误差; 3. **湿度换算**:根据传感器“电压越低湿度越高”的特性,通过理论公式 `humidity = 100 - (uint8_t)((voltage / 3.3f) * 100);` 将电压值换算为0~100%的湿度百分比,并对电压、湿度值做范围限制,避免异常数据。 同时对ADC读取结果做校验,采集失败时打印错误日志并返回默认值,保证程序健壮性。 #### 4.3.5 任务创建与系统启动 1. **采集任务**:`Soil_Humi_Collect_Task`为后台死循环任务,初始化引脚后每秒调用一次采集函数,实现持续监测; 2. **任务创建**:`Soil_Humi_Init`配置任务属性并创建任务,判断创建结果,避免任务创建失败导致程序无响应; 3. **系统注册**:通过`SYS_RUN`宏注册入口函数,OpenHarmony系统开机后自动执行,无需手动调用。 # 五、编译与烧录 ### 5.1 编译 详见: https://www.malaoshi.top/show_1GW1wTyUOMPk.html ### 5.3 固件烧录 详见: https://www.malaoshi.top/show_1GW1wWWflGbq.html # 六、运行结果与调试 [](https://www.malaoshi.top/upload/0/0/1GW32eamDKfs.png) - 传感器在**干燥空气中**:ADC值≈1800~4095,电压≈3.0~3.3V,湿度≈0%~10%; - 传感器**插入湿润土壤**:ADC值≈500~1500,电压≈0.5~2.5V,湿度≈20%~80%; - 传感器**完全浸入水中**:ADC值≈0~300,电压≈0~0.5V,湿度≈90%~100%。 **注意:**经过测试发现,探头前三分之一放到水里,湿度是:`25%`,探头全部放到水里,湿度是:`33%`,应该是硬件问题 # 七、常见问题与调试方案 ### 问题1:ADC值固定不变,湿度无变化 **原因**:GPIO引脚未配置为ADC功能;接线错误,AO引脚未接GPIO9;传感器供电异常。 **调试**:检查`ADC_Pin_Init`函数是否执行;重新核对接线,确保AO接GPIO9;用万用表测量传感器VCC电压,保证5V/3.3V供电正常。 ### 问题2:传感器放入水中,湿度仅20%~30%,无法达到90%+ **原因**:传感器供电为3.3V,量程压缩;传感器电极氧化/污染;传感器本身质量问题。 **调试**:将传感器VCC改为5V供电;用酒精棉擦拭电极表面,清除氧化层与污垢;更换全新的电阻式模拟输出传感器。 ### 问题3:串口打印乱码 **原因**:打印内容包含中文;串口波特率与开发板不匹配。 **调试**:保证打印内容为纯英文(本文代码已做处理);确认串口波特率为115200,与开发板配置一致。 ### 问题4:ADC采集失败,打印“Failed to read ADC data!” **原因**:ADC通道被其他功能占用;GPIO9引脚损坏;底层驱动未适配。 **调试**:检查工程中是否有其他代码使用ADC4通道;更换开发板其他ADC通道(如ADC5)测试;确认使用的是Hi3861专用的OpenHarmony 1.0固件。 原文出处:http://www.malaoshi.top/show_1GW32ee3Hbty.html