去年帮朋友改造他的小型蔬菜大棚时,我深刻体会到传统农业监测的痛点——每天要记录十几次温湿度数据,遇到极端天气还得半夜跑去大棚手动调节设备。于是我们用Arduino设计了一套成本不到300元的智能监控系统,现在连老爷子都能在手机上随时查看棚内环境。这个系统核心在于实时监测空气温湿度、土壤墒情和光照强度,当数值超出设定范围时自动触发通风、灌溉和补光设备,所有数据通过4G模块上传到云端,用微信小程序就能查看历史曲线。
相比市面上的成品农业物联网设备,这个方案有三个独特优势:一是硬件成本降低60%以上(商用设备动辄上千元);二是完全开源可定制,能根据作物类型调整控制策略;三是采用了模块化设计,传感器和执行器都可以即插即用。下面我就从硬件选型到代码调试,把整个实现过程拆解给你看。
主控板选择Arduino Uno R3而不是更便宜的Nano,主要考虑三点:一是大棚环境电磁干扰强,带金属屏蔽壳的Uno更稳定;二是需要驱动多个继电器模块,Uno的电源输出更充足;三是后期扩展传感器时I/O口余量更大。传感器方面特别推荐以下组合:
重要提示:所有传感器一定要选工业级(-40℃~85℃工作温度),我们第一批用的民用级DHT11在高温高湿环境下两周就失效了。
供电方案采用12V/5A开关电源接LM2596降压模块给Arduino供电,同时用5V继电器模块直接控制220V设备。电路设计时特别注意:
接线示意图如下(简化版):
cpp复制[12V电源] → [LM2596降压至5V] → [Arduino Vin]
│
└─[继电器模块VCC]
[DHT22] → D2
[土壤传感器] → A0
[BH1750] → SDA/SCL
[EC20模块] → SoftwareSerial(8,9)
读取DHT22时最常见的坑是库函数调用间隔不足2秒会导致读取失败。我们的解决方案是用状态机实现非阻塞读取:
arduino复制unsigned long lastDHTRead = 0;
float temp, humi;
void readDHT22() {
if(millis() - lastDHTRead > 2000) {
int ret = dht.read22(DHT_PIN);
if(ret == DHTLIB_OK) {
temp = dht.temperature;
humi = dht.humidity;
lastDHTRead = millis();
}
}
}
土壤湿度传感器要注意ADC值的非线性补偿。通过实测不同含水量下的读数,我们总结出经验公式:
arduino复制int soilMoisture = analogRead(SOIL_PIN);
// 针对我们使用的传感器校准公式
float moisturePercent = 102.3 - 0.1*soilMoisture + 0.0002*pow(soilMoisture,2);
为了降低流量消耗(农村4G按量计费),我们设计了紧凑型数据包格式:
code复制[HEAD][TEMP][HUMI][SOIL][LIGHT][CRC]
1B 2B 2B 2B 2B 1B
其中温度值放大10倍传输(23.5℃→235),光照强度除以10传输(12500lux→1250)。实测每小时上传一次数据时,月流量消耗不到5MB。EC20模块的AT指令交互要特别注意超时处理:
arduino复制bool sendToCloud(String data) {
Serial.println("AT+QISEND=0," + String(data.length()));
if(!waitResponse(">", 2000)) return false;
Serial.print(data);
return waitResponse("SEND OK", 5000);
}
不同于简单的阈值控制,我们实现了基于作物生长阶段的动态策略。以番茄种植为例:
arduino复制void checkConditions() {
// 白天模式(6:00-18:00)
if(hour >= 6 && hour < 18) {
if(temp > 28) controlFan(ON);
if(light < 10000 && hour < 10) controlLamp(ON);
}
// 夜间模式
else {
if(humi > 80) controlFan(ON);
if(soilMoisture < 40) controlWater(ON);
}
}
大棚设备频繁启停会缩短寿命,我们加入了最小运行时间限制:
arduino复制unsigned long fanStartTime = 0;
void controlFan(bool state) {
if(state == ON) {
if(millis() - fanStartTime > 300000) { // 至少间隔5分钟
digitalWrite(FAN_PIN, HIGH);
fanStartTime = millis();
}
} else {
digitalWrite(FAN_PIN, LOW);
}
}
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| DHT22读数异常 | 电源不稳或线缆过长 | 缩短线长至1米内,并联104电容 |
| 土壤值始终为0 | 探头氧化 | 用细砂纸打磨电极 |
| 4G频繁掉线 | SIM卡接触不良 | 用橡皮擦清理触点,加贴海绵垫 |
| 继电器无响应 | 未接续流二极管 | 在继电器线圈并接1N4007 |
当前系统已经稳定运行8个月,接下来计划加入:
整套代码和电路图已上传GitHub(搜索"SmartGreenHouse-Arduino"),包含详细的中文注释和接线说明。实际部署时建议先用杜邦线搭建原型,测试稳定后再焊接永久电路。遇到问题欢迎在Issues区讨论,一般24小时内会回复。