IoT for Beginners 实战:使用 CounterFit 虚拟硬件与 10 位 ADC 读取土壤湿度
【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners
导读
本文是 IoT for Beginners 课程「2-farm / 检测土壤湿度」单元的虚拟硬件实战指南。课程仓库同时为 Wio Terminal(Arduino)、Raspberry Pi 和虚拟设备三条硬件路线提供了完全对等的实验,本文聚焦于无需任何真实硬件的虚拟设备方案:在 CounterFit 中创建模拟的 Grove 电容式土壤湿度传感器,用 Python 编写程序通过模拟 ADC 持续读取湿度值,并完成传感器的校准换算。读完本文你将掌握:模拟传感器的物理原理、CounterFit 虚拟传感器环境的搭建与操作、counterfit_shims_grove.adc.ADC的完整用法,以及如何用烘干称重法把 0–1023 的原始读数换算成真实的重力含水率。
为什么需要检测土壤湿度
植物需要水才能生长,水主要经根系从土壤吸收,用于光合作用、蒸腾作用以及维持细胞结构(植物约 90% 由水构成,远高于人体的 60%)。土壤水分过少,植物无法吸收足够水分;水分过多,根系又无法获得维持功能所需的氧气,最终导致烂根。因此,对种植者而言,理想的土壤状态是"不干不湿、恰到好处"——IoT 设备通过实时测量土壤湿度,让农户仅在需要时才浇水。
测量土壤湿度主要有两类传感器(见 课程主文档):
- 电阻式(Resistive):两根探针插入土壤,向一根探针通电流、另一根接收,通过测量土壤电阻来间接反映湿度。水是良好导体,土壤含水量越高、电阻越低。这种传感器易受腐蚀。
- 电容式(Capacitive):测量土壤的电容(存储电荷的能力),再转换为电压输出。土壤越湿,输出电压越低。本课程使用的 Grove 电容式传感器即属此类,且耐腐蚀性更好。
两者都属于模拟传感器,输出的是电压信号,因此都需要模拟–数字转换器(ADC)才能被代码读取。
传感器如何与 IoT 设备通信
在动手编程前,先理解土壤湿度传感器返回的电压如何变成代码里的数字。传感器与 IoT 设备通信需要"硬件连接 + 通信协议"两层配合(详见 课程主文档):
- GPIO 引脚:通用输入输出引脚,可提供 3.3V/5V 电压、接地或可编程的输入/输出。按钮、LED 这类只关心高/低的数字器件可直接接 GPIO。
- 模拟引脚(Analog pins):以 Arduino 系列为代表,引脚内置 ADC,通常为 10 位分辨率,把电压映射为 0–1,023。例如 3.3V 板子上,传感器返回 3.3V 时读数为 1,023,返回 1.65V 时读数约为 511。土壤湿度传感器依赖电压,因此使用模拟引脚并给出 0–1,023 的读数。
- I²C:多控制器/多外设总线协议,数据以带设备地址的数据包传输,由 SDA(串行数据)、SCL(串行时钟)、VCC(电源)、GND(地)四条线构成。Raspberry Pi 的 Grove Base Hat 正是通过 I²C 把模拟信号转换为数字信号。
- UART:串行异步通信,Tx/Rx 交叉相连,以波特率(常见 9,600)逐位传输,需起始位与停止位。
- SPI:控制器/外设模型的短距离高速全双工协议,由 COPI、CIPO、SCLK、CS(每外设一根)构成。
- 无线:BLE、LoRaWAN、Zigbee 等,适合商用田间土壤湿度传感器这类需要远离主控设备的场景。
了解这些背景后,下面进入虚拟硬件实验。由于虚拟设备直接模拟了"模拟引脚 + ADC"的行为,你无需关心物理接线,只需关注与 ADC 打交道的编程逻辑。
虚拟硬件方案:用 CounterFit 模拟 Grove 电容式土壤湿度传感器
虚拟 IoT 设备使用CounterFit(CounterFit 是一个在浏览器中运行的传感器/执行器模拟服务)提供模拟的 Grove 电容式土壤湿度传感器。这样本实验与使用 Raspberry Pi + 物理 Grove 电容传感器的路径完全一致:
- 物理设备上,电容传感器通过检测土壤电容(随湿度变化而变化的属性)来测量湿度,土壤越湿、输出电压越低;
- 虚拟设备则用一个模拟的 10 位 ADC报告 1–1,023 范围内的数值。
本实验对应的完整源码存放在 code/virtual-device/soil-moisture-sensor/app.py;如果你使用 Raspberry Pi,可对照 pi-soil-moisture.md(代码见 code/pi/soil-moisture-sensor/app.py,其
ADC来自 Grove Python 库);若使用 Wio Terminal,可对照 wio-terminal-soil-moisture.md(用analogRead(A0)读取)。
第一步:创建 Python 项目与虚拟环境
在电脑上新建名为soil-moisture-sensor的文件夹,内含单个文件app.py,并创建 Python 虚拟环境、安装 CounterFit 相关 pip 包。项目创建与 CounterFit 环境的完整步骤可参考第一课(Getting Started)的虚拟设备章节:创建并配置 CounterFit Python 项目。
⚠️ 需要先运行 CounterFit Web 应用,并确保它与代码使用同一个端口。
第二步:在 CounterFit 中创建土壤湿度传感器
在浏览器打开 CounterFit 应用后:
- 在Sensors(传感器)面板的Create sensor(创建传感器)区域,展开Sensor type(传感器类型)下拉框,选择Soil Moisture(土壤湿度);
- 将Units(单位)保持为NoUnits(无单位);
- 确认Pin(引脚)为0;
- 点击Add按钮,即可在引脚 0 上创建Soil Moisture传感器。
传感器创建后会自动出现在传感器列表中:
编写土壤湿度传感器程序
在 VS Code 中打开soil-moisture-sensor项目,编辑app.py。
1. 连接 CounterFit
在文件顶部加入以下代码,把应用连接到本机运行在 5000 端口的 CounterFit 服务:
from counterfit_connection import CounterFitConnection CounterFitConnection.init('127.0.0.1', 5000)2. 导入依赖库
import time from counterfit_shims_grove.adc import ADCimport time:导入time模块,稍后用于读取间隔的睡眠控制;from counterfit_shims_grove.adc import ADC:导入ADC类,用于与虚拟的模拟–数字转换器交互,该转换器可连接到 CounterFit 中的传感器。注意虚拟环境使用的是counterfit_shims_grove兼容层,与 Raspberry Pi 上的grove.adc.ADC用法一致,这正是实验"保持与物理硬件一致"的关键。
3. 创建 ADC 实例
adc = ADC()4. 无限循环读取湿度
从引脚 0 读取 ADC 数值并打印到控制台,每次读取之间休眠 10 秒:
while True: soil_moisture = adc.read(0) print("Soil moisture:", soil_moisture) time.sleep(10)这段代码与仓库中的 app.py 完全一致:adc.read(0)即从 0 号引脚(也就是刚才在 CounterFit 中创建传感器的 Pin 0)读取当前湿度值。
运行程序并调整传感器值
运行 Python 应用:
(.venv) ➜ soil-moisture-sensor $ python app.py Soil moisture: 615 Soil moisture: 612 Soil moisture: 498 Soil moisture: 493 Soil moisture: 490 Soil Moisture: 388在 CounterFit 应用中改变传感器返回值,有两种方式:
- 固定值:在传感器的Value(数值)框中输入一个数字,点击Set按钮。该数字即为传感器每次返回的值;
- 随机值:勾选Random(随机)复选框,输入Min(最小)与Max(最大)值,点击Set。此后每次读取,传感器都会返回Min到Max之间的一个随机数。
通过调整上述设置,可以模拟"土壤湿度变化"的过程:从输出示例可见,随着设定的湿度值从 615 一路下降到 388,正好对应土壤越湿、输出电压越低的物理特性(对电容式传感器而言)。
传感器校准:把原始读数换算成真实土壤湿度
传感器读取到的是 0–1023 的原始电压读数,它本身并不是可直接使用的湿度单位。校准(Calibration)就是把测量值与真实物理量对应起来。有些传感器出厂已校准(如上一课的温度传感器,直接返回 °C),但土壤湿度传感器受土壤类型影响很大——土壤成分会改变其电气特性,因此同一读数在不同土壤中代表不同湿度。理想的校准方式是:用传感器读数与实验室科学测量结果建立映射关系(详见 课程主文档「Sensor calibration」一节 与 课后作业 assignment.md)。
重力含水率(Gravimetric soil moisture)的计算
土壤湿度可用重力法或体积法测量。课后作业要求用重力含水率校准:取土样、称湿重、烘干、再称干重,计算公式为:
土壤湿度 % = (W_wet - W_dry) / W_dry × 100其中W_wet为湿土重量,W_dry为干土重量。
示例:某土样湿重 212g,烘干后干重 197g:
- 212 − 197 = 15
- 15 / 197 ≈ 0.076
- 0.076 × 100 =7.6%
即该土壤的重力含水率为 7.6%。
校准操作步骤
- 用土壤湿度传感器读取当前土壤的原始值并记录;
- 取一份土壤样本,称湿重并记录;
- 烘干土壤——最理想的方式是在 110°C(230°F)的烤箱中烘数小时;也可放在阳光下或温暖干燥处,直到土壤完全干透、呈松散粉末状。实验室精度要求通常需要烘 48–72 小时,烘得越久样本越干、结果越准;
- 再次称重(若用烤箱烘干,务必先等土壤冷却)。
对至少 3 份不同湿度的土壤样本重复上述过程,然后将"传感器原始读数"与"重力含水率 %"绘制成散点图并拟合一条直线。之后任意一次传感器读数,都可以沿这条校准直线换算成真实的重力含水率。
💡 注意:对电容式传感器,电压(读数)随土壤湿度增加而下降,因此校准曲线是向下倾斜的;而电阻式传感器恰好相反,曲线向上倾斜。
校准评分标准
| 标准 | 优秀 | 合格 | 需改进 |
|---|---|---|---|
| 收集校准数据 | 至少采集 3 份校准样本 | 至少采集 2 份校准样本 | 仅采集 1 份校准样本 |
| 完成校准读数 | 成功绘制校准图并完成传感器读数到重力含水率的换算 | 成功绘制校准图 | 无法绘制校准图 |
总结与延伸
本实验通过虚拟硬件完整复刻了"电容式土壤湿度传感器 → 10 位 ADC → Python 程序"的数据链路:在 CounterFit 中创建传感器、用counterfit_shims_grove.adc.ADC读取引脚 0 的数值、以 10 秒间隔持续采样,并通过固定值/随机值两种模式模拟湿度变化。程序代码可以直接在三种硬件路线间平移(counterfit_shims_grove与 Raspberry Pi 的grove库接口相同,Wio Terminal 则使用analogRead)。最后,利用烘干称重法完成传感器校准,即可把原始读数转换为具有实际农业意义的土壤含水率,为下一课"自动化植物浇水系统"奠定数据基础。
如需继续深入,可阅读:课程主文档(含传感器通信协议详解)、课后校准作业、Raspberry Pi 硬件版本、Wio Terminal 硬件版本,以及 第一课的 CounterFit 项目搭建指引。
【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考