基于Arduino的短日照草莓环境监控系统:从传感器原理到农业自动化实践

Arduino环境监控传感器
于 2026-06-01 13:10:47 修改
·本内容遵循CC 4.0 BY-SA版权协议

1. 项目概述:为什么草莓需要“精准作息”?

如果你在阳台上种过草莓,或者参观过现代化的草莓种植园,可能会发现一个有趣的现象:有些草莓品种,比如我们常说的“短日照草莓”,它们开花结果不是看心情,而是看“天色”。这里的“天色”不是指阴晴雨雪,而是指每天光照时间的长短,专业上称为“光周期”。这类草莓需要经历一段每天光照时间少于某个临界值(通常在12-14小时以下)的时期,才能从营养生长顺利转向生殖生长,也就是开花。与此同时,温度也是一个极其关键的因子,过高或过低都会影响花芽分化、授粉坐果以及果实品质。

传统上,农民靠天吃饭,凭经验管理。但在设施农业,比如温室或大棚里,我们有了主动权。基于Arduino的短日照草莓生长环境监控系统,就是为了解决这个问题而生的。它的核心目标很简单:像一个不知疲倦的园丁,24小时不间断地监测温室内的温度和光照强度,并依据草莓生长的最佳需求,通过直观的灯光信号(LED)来告知管理者当前环境是否“达标”。

我之所以选择Arduino Uno作为核心,是因为它对爱好者、学生甚至初创农业项目来说,是性价比和易用性的完美平衡点。它开源、社区支持强大、编程门槛相对较低,能让我们把精力更多地集中在解决农业问题本身,而不是纠缠于复杂的底层硬件驱动。这个项目麻雀虽小,五脏俱全,涵盖了传感器选型、模拟信号采集、数据处理算法(线性拟合)、控制逻辑实现以及人机交互(串口监视器)等嵌入式系统开发的关键环节。无论你是电子爱好者想涉足农业应用,还是农业专业的学生希望将理论知识工程化,这个项目都是一个绝佳的起点。

接下来,我将带你从零开始,完整复现这套系统。我会详细解释每一个硬件选择背后的考量,推导每一个计算公式的来龙去脉,并分享在代码调试和系统集成中容易踩到的“坑”。我们的目标是,你读完这篇文章,不仅能照猫画虎做出来,更能理解其所以然,并能举一反三地应用到其他作物或环境参数的监控中去。

2. 系统核心设计与硬件选型解析

在动手焊接第一根线之前,我们必须把系统的设计思路理清楚。一个好的设计是成功的一半,它能避免我们在后期陷入“为什么灯不亮?”“为什么读数不准?”的反复调试中。

2.1 控制逻辑与流程图设计

任何自动化系统的大脑都是其控制逻辑。对于我们的草莓监控系统,逻辑必须基于草莓生长的生物学特性。我们假设一个简化的模型,为短日照草莓设定两个核心环境阈值:

  1. 温度阈值:假设草莓生长的适宜日间温度为15°C至25°C。低于15°C生长缓慢,高于25°C则可能抑制花芽分化或导致果实品质下降。
  2. 光周期阈值:设定每日光照时间需要低于13小时(即光周期<13h)来诱导开花。我们通过监测当前光照强度来间接判断是否处于“短日照”条件。例如,设定当光照强度低于某个值(代表夜晚或光照不足)时,才开始累计“短日照”时间,但在本简化模型中,我们先以实现实时光照强度判断为目标。

基于此,我们可以绘制出系统的核心决策流程图。这个流程图是后续编写代码的蓝图:

TEXT
开始
├─ 初始化系统(设置引脚模式,开启串口)
├─ 进入主循环:
│ ├─ 读取温度传感器电压值
│ ├─ 将电压值转换为摄氏度温度值
│ ├─ 读取光敏电阻电压值
│ ├─ 将电压值转换为光照强度值(勒克斯,Lux)
│ ├─ 判断逻辑:
│ │ ├─ 如果 温度 < 15°C:点亮红色LED(温度过低警报)
│ │ ├─ 否则,如果 温度 > 25°C:点亮红色LED(温度过高警报)
│ │ ├─ 否则:熄灭红色LED(温度正常)
│ │ │
│ │ ├─ 如果 光照强度 > 设定阈值(如300 Lux):点亮黄色LED(处于光照期)
│ │ ├─ 否则:点亮绿色LED(处于暗期/短日照条件满足)
│ │ └─ (注:更复杂的逻辑可以在此处加入计时器,累计暗期时长)
│ └─ 将当前温度和光照强度值发送到串口监视器显示
└─ 延迟一段时间(如500毫秒),返回循环开始

这个流程图清晰地定义了系统的输入(温度、光照)、处理(判断逻辑)和输出(LED指示、串口数据)。它告诉我们,我们需要两个模拟输入传感器,三个数字输出LED,以及一个负责计算和判断的大脑(Arduino)。

2.2 关键硬件组件深度剖析

选对传感器,项目就成功了一大半。下面我们来拆解每个硬件的原理和选型理由。

Arduino Uno R3:系统控制器 选择Uno是因为其经典的ATmega328P微控制器拥有6路模拟输入(A0-A5)和14路数字I/O口,完全满足本项目需求(2路模拟输入,3路数字输出)。其5V工作电压和简单的USB编程方式,极大降低了开发门槛。对于更复杂的、需要连接更多传感器或执行机构(如继电器控制加热器、补光灯)的未来扩展,Uno的I/O资源和处理能力也留有裕量。

TMP36温度传感器:精准的“体温计” TMP36是一款模拟输出温度传感器。为什么选它而不是更常见的DS18B20(数字输出)或DHT11(温湿度一体)?核心原因在于其输出线性度极好接口简单

  • 线性电压输出:TMP36的输出电压与温度成严格的线性关系,公式为 Vout (mV) = 10 * Temperature (°C) + 500。这意味着在2.7V至5.5V供电下,它能测量-40°C到+125°C的范围,在室温附近精度可达±2°C。这种线性特性使得在代码中进行换算非常直接和准确,不需要复杂的库或通信协议。
  • 接口简单:仅有三根引脚(VCC, GND, Vout),Vout直接接Arduino的模拟输入引脚即可。相比之下,DS18B20需要单总线协议,DHT11需要特定的时序信号,对初学者代码编写要求稍高。

注意:TMP36的电压输出是相对于电源地的。确保供电电压稳定是保证测量精度的关键。任何电源纹波都会直接反映为温度读数噪声。

光敏电阻(LDR):感知“天色”的眼睛 光敏电阻是一个其电阻值随光照强度增加而减小的元件。我们选择它来检测光照,是因为其成本低廉、使用简单。

  • 工作原理:它本身不能直接输出电压信号。我们需要将它连接成一个分压电路。通常的做法是将LDR与一个固定电阻串联,接在VCC(5V)和GND之间,然后从LDR和固定电阻的连接点引出信号线到Arduino的模拟输入引脚。这样,当光照变化引起LDR阻值变化时,中间点的电压也会随之变化。
  • 选型考量:不同的LDR有不同的亮电阻和暗电阻范围。本项目需要关注其在室内弱光(几十勒克斯)到日光灯下(几百勒克斯)这个区间的电阻变化是否明显。通常选用通用型GL5528等型号即可。固定电阻的阻值选择很关键,一般选择与LDR在中间光照强度下的阻值相近的电阻,以获得最佳的电压变化范围和灵敏度。经过实测和计算,项目中选用100Ω电阻可能并非用于分压,而是作为LED的限流电阻。LDR分压电路中的固定电阻通常需要根据LDR特性在1kΩ到10kΩ之间选择,这是一个常见的调试点。

LED与电阻:系统的“表情包” 三个LED(红、黄、绿)作为状态指示灯,是人机交互的核心。

  • 红色LED:代表温度异常(过高或过低),需要人工干预。
  • 黄色LED:代表当前处于光照条件下,不满足短日照的“暗期”要求。
  • 绿色LED:代表当前处于暗期,满足短日照的光照条件。
  • 限流电阻:LED必须串联限流电阻!直接连接5V到LED会瞬间烧毁它。对于标准的5mm LED,工作电流通常在10-20mA。根据欧姆定律 R = (Vcc - Vled) / I,其中Vcc=5V,Vled(LED正向压降)约为1.8V-2.2V(红色约1.8V,绿/黄约2.0V),I取15mA,则 R = (5 - 2.0) / 0.015 ≈ 200Ω。选择比计算值稍大的标准电阻(如220Ω)更安全。原文中使用的100Ω电阻,会使电流略大于30mA,虽然大部分现代LED能短时承受,但长期使用会缩短寿命并增加Arduino引脚负担,建议改用220Ω。

其他工具

  • 面包板和杜邦线:用于快速原型搭建,免焊接,方便调试。
  • 万用表必不可少。用于调试阶段测量分压电路的实际电压,验证传感器读数,排查接触不良或短路问题。

3. 电路搭建与硬件连接实操

理论清晰后,我们开始动手搭建。正确的连接是系统稳定运行的基础。

3.1 分步连接指南

请参照以下步骤和表格进行连接。在插线时,务必确保Arduino未连接USB线,以防误接短路损坏设备。

元件 引脚/端 连接至 Arduino Uno 说明
TMP36 VCC (正面平面对自己,左腿) 5V 引脚 提供工作电压
Vout (中腿) A0 模拟输入引脚 温度信号输出
GND (右腿) GND 引脚 接地
光敏电阻 LDR 一端 5V 引脚
另一端 A1 模拟输入引脚 以及 一个10kΩ电阻的一端 LDR与10kΩ电阻组成分压器,连接点接A1
10kΩ 电阻 另一端 GND 引脚 分压电阻接地
红色LED 长脚 (阳极+) 数字引脚 8 通过220Ω限流电阻
短脚 (阴极-) 220Ω电阻一端
220Ω电阻 另一端 GND 引脚 限流保护LED
黄色LED 长脚 (阳极+) 数字引脚 9 通过220Ω限流电阻
短脚 (阴极-) 220Ω电阻一端
220Ω电阻 另一端 GND 引脚 限流保护LED
绿色LED 长脚 (阳极+) 数字引脚 10 通过220Ω限流电阻
短脚 (阴极-) 220Ω电阻一端
220Ω电阻 另一端 GND 引脚 限流保护LED

连接要点与实操心得

  1. 电源一致性:确保所有元件的VCC和GND都分别连接到Arduino的5V和GND排针上,形成共同的参考地,这是模拟读数准确的基石。
  2. LDR分压电路:这是最容易出错的地方。务必形成“5V -> LDR -> A1引脚 -> 10kΩ电阻 -> GND”的回路。A1引脚测量的是LDR和10kΩ电阻之间的电压。光照越强,LDR电阻越小,A1点电压越接近5V;光照越弱,LDR电阻越大,A1点电压越接近0V。
  3. LED极性:务必分清长脚(正极)和短脚(负极)。接反了不会损坏,但灯不会亮。一个记忆口诀:“长正短负”。
  4. 面包板布局:建议将电源线(5V和GND)分别布置在面包板两侧的长排孔上,作为电源总线。元件尽量按功能模块分区摆放,例如传感器区、指示灯区,这样便于检查和排查故障。

3.2 上电前检查与初步测试

连接完成后,不要急于上传代码。先进行物理检查:

  • 用手触摸各个芯片和电阻,不应有异常发热。
  • 用万用表通断档,检查5V和GND之间是否短路(读数应为无穷大或非常高)。
  • 使用万用表电压档,在Arduino通电后,测量TMP36的Vout引脚对地电压。在室温下(约25°C),电压应在 10*25 + 500 = 750mV = 0.75V 左右。用手捏住传感器,读数应缓慢上升。
  • 同样,测量LDR分压点(A1)对地电压。用手遮住LDR,电压应下降;用手电筒照射,电压应上升。

如果上述检查都正常,恭喜你,硬件部分基本成功。任何异常读数都应立即断电,重新检查连接。

4. 核心算法与代码实现详解

硬件是躯干,软件是灵魂。接下来我们深入代码,看看如何让Arduino“读懂”传感器并“做出决策”。

4.1 数据采集与标定:从电压到物理量

Arduino的模拟输入引脚(ADC)能将0-5V的电压转换为0-1023的整数。我们的首要任务,就是建立这个整数值与实际物理量(温度、光照)之间的数学关系。

1. 温度转换:TMP36的线性方程 TMP36的数据手册给出了完美的线性公式:Vout (mV) = 10 * T (°C) + 500。 在代码中,我们需要逆向求解温度T:

  1. 读取模拟值:int sensorValue = analogRead(A0);
  2. 转换为电压(伏特):float voltage = sensorValue * (5.0 / 1023.0); 这里用5.0和1023.0是为了进行浮点数计算,提高精度。
  3. 转换为毫伏:float voltage_mV = voltage * 1000;
  4. 代入公式求温度:float temperature = (voltage_mV - 500) / 10.0;

2. 光照转换:LDR的标定与曲线拟合 这是本项目的难点和精髓。LDR的电阻-光照关系是非线性的,且不同型号、不同批次的元件特性差异很大。因此,我们不能直接使用一个通用公式,必须进行现场标定

原文中提到通过两个点(-1, 2.78)(8, 824)进行拟合,得到了公式 y = 91.26x + 94.03(y是电压mV,x是光照Lux)。这个方法的思路是正确的,但操作上有更严谨的做法:

  • 标定步骤
    1. 准备工具:一个已知精度相对较高的光照度计(勒克斯计),或者手机上有经过校准的光照度APP(可作为粗略参考)。
    2. 采集数据点:将组装好的系统(LDR+10kΩ电阻)置于不同光照环境下。例如:全暗的抽屉里(~0 Lux)、台灯下、室内自然光下、窗边阳光下(避免直射强光损坏LDR)。在每个环境下,用光照度计测量实际照度(x),同时从串口监视器读取Arduino测得的电压值(y,可先转换为毫伏)。记录至少5-8组数据,尽可能覆盖你关心的光照范围(如0-1000 Lux)。
    3. 曲线拟合:将数据点(Lux, Voltage)输入到Excel、Google Sheets或任何在线线性回归计算器中。由于LDR特性,在中等光照范围,其对数电阻与对数光照可能呈线性,但为了简化,我们可以在目标区间内用一次线性方程近似。计算器会给出最佳拟合直线 y = a * x + b 的斜率a和截距b。
    4. 得到公式:假设拟合结果为 电压(mV) = 95.5 * 光照(Lux) + 100.2。那么在代码中,我们需要反解出光照:光照(Lux) = (电压(mV) - 100.2) / 95.5

实操心得:标定是提升系统可靠性的关键一步。我自己的经验是,在室内灯光环境下(300-600 Lux),线性拟合度尚可;但在极暗和极亮环境下,误差会变大。因此,明确系统的使用场景(例如,只用于判断白天/黑夜,或需要精确的光照管理)至关重要。如果只需要判断明暗,可以简单设定一个电压阈值,无需换算成Lux。

4.2 控制逻辑编程:if语句的巧妙运用

有了准确的温度和光照数据,就可以实现流程图中的判断逻辑了。这里主要使用if...else if...else语句的嵌套。

CPP
// 假设我们已经得到了 temperature 和 lightIntensity 两个浮点数变量
// 以及定义了LED引脚
const int redLed = 8;
const int yellowLed = 9;
const int greenLed = 10;
 
void loop() {
// ... 数据采集和转换代码 ...
 
// 温度判断逻辑
if (temperature < 15.0) {
digitalWrite(redLed, HIGH); // 温度过低,红灯亮
// 可以同时关闭黄绿灯,确保状态清晰
digitalWrite(yellowLed, LOW);
digitalWrite(greenLed, LOW);
} else if (temperature > 25.0) {
digitalWrite(redLed, HIGH); // 温度过高,红灯亮
digitalWrite(yellowLed, LOW);
digitalWrite(greenLed, LOW);
} else {
digitalWrite(redLed, LOW); // 温度正常,红灯灭
// 温度正常时,再根据光照判断
if (lightIntensity > 300.0) { // 假设300 Lux为光照阈值
digitalWrite(yellowLed, HIGH); // 光照强,黄灯亮(光照期)
digitalWrite(greenLed, LOW);
} else {
digitalWrite(yellowLed, LOW);
digitalWrite(greenLed, HIGH); // 光照弱,绿灯亮(暗期/短日照条件)
}
}
 
// ... 串口打印代码 ...
}

代码结构解读

  1. 首先进行温度判断,这是一个优先级最高的安全警报。只要温度异常,就点亮红灯,并忽略光照状态。
  2. 只有在温度正常的情况下,才进入光照判断分支,决定点亮黄灯还是绿灯。
  3. 这种嵌套结构确保了逻辑的清晰和执行的优先级。

4.3 完整代码整合与串口调试

将数据采集、转换、逻辑控制整合起来,并加入串口打印功能,便于我们实时监控系统状态和调试标定公式。

CPP
// 定义引脚
const int tempSensorPin = A0;
const int ldrSensorPin = A1;
const int redLed = 8;
const int yellowLed = 9;
const int greenLed = 10;
 
// 标定参数(示例,需根据你的标定结果修改)
const float LDR_SLOPE = 91.26; // 斜率 a
const float LDR_INTERCEPT = 94.03; // 截距 b
const float LIGHT_THRESHOLD = 300.0; // 光照阈值 (Lux)
 
void setup() {
// 初始化串口通信,波特率9600
Serial.begin(9600);
 
// 设置LED引脚为输出模式
pinMode(redLed, OUTPUT);
pinMode(yellowLed, OUTPUT);
pinMode(greenLed, OUTPUT);
 
// 初始状态关闭所有LED
digitalWrite(redLed, LOW);
digitalWrite(yellowLed, LOW);
digitalWrite(greenLed, LOW);
 
Serial.println("草莓生长环境监控系统启动...");
}
 
void loop() {
// 1. 读取温度传感器
int tempRaw = analogRead(tempSensorPin);
float voltageV = tempRaw * (5.0 / 1023.0);
float voltage_mV = voltageV * 1000;
float temperature = (voltage_mV - 500) / 10.0;
 
// 2. 读取光照传感器
int ldrRaw = analogRead(ldrSensorPin);
float ldrVoltageV = ldrRaw * (5.0 / 1023.0);
float ldrVoltage_mV = ldrVoltageV * 1000;
// 应用标定公式,将电压转换为光照强度(Lux)
float lightIntensity = (ldrVoltage_mV - LDR_INTERCEPT) / LDR_SLOPE;
// 防止计算出现负值(在极暗环境下可能发生)
if (lightIntensity < 0) {
lightIntensity = 0;
}
 
// 3. 控制逻辑判断
if (temperature < 15.0 || temperature > 25.0) {
// 温度异常警报
digitalWrite(redLed, HIGH);
digitalWrite(yellowLed, LOW);
digitalWrite(greenLed, LOW);
} else {
// 温度正常
digitalWrite(redLed, LOW);
if (lightIntensity > LIGHT_THRESHOLD) {
digitalWrite(yellowLed, HIGH);
digitalWrite(greenLed, LOW);
} else {
digitalWrite(yellowLed, LOW);
digitalWrite(greenLed, HIGH);
}
}
 
// 4. 串口输出数据,用于监控和调试
Serial.print("温度: ");
Serial.print(temperature);
Serial.print(" °C | 光照: ");
Serial.print(lightIntensity);
Serial.print(" Lux | 状态: ");
 
if (digitalRead(redLed) == HIGH) {
Serial.println("温度警报!");
} else if (digitalRead(yellowLed) == HIGH) {
Serial.println("光照期");
} else {
Serial.println("暗期(短日照)");
}
 
// 延时500ms,避免串口输出过快
delay(500);
}

上传代码后,打开Arduino IDE的串口监视器(工具 -> 串口监视器,波特率设置为9600)。你应该能看到每秒两行左右的数据输出,实时显示当前的温度、光照强度和系统状态。这是调试和验证系统是否正常工作的最重要窗口。

5. 系统调试、优化与扩展思路

系统跑起来只是第一步,让它稳定、可靠、实用,还需要一番调试和打磨。

5.1 常见问题排查速查表

在调试过程中,你可能会遇到以下问题。这里提供一个快速排查指南:

现象 可能原因 排查步骤与解决方案
所有LED都不亮 1. Arduino未供电或程序未运行。
2. LED或电阻连接错误、虚焊。
3. 代码中LED引脚定义错误。
1. 检查USB连接,确认板载电源LED亮起。重新上传程序。
2. 用万用表检查LED通路电压。确认LED极性正确。
3. 核对代码pinModedigitalWrite中的引脚编号。
某个LED常亮或不亮 1. 该LED控制逻辑始终为真或假。
2. 引脚短路或损坏。
3. 限流电阻值过大或过小。
1. 通过串口监视器查看状态输出,分析逻辑条件。检查温度/光照读数是否异常。
2. 拔掉该LED,用万用表测量引脚输出电压是否随逻辑变化。
3. 测量LED两端电压,计算电流是否在合理范围(5-20mA)。
温度读数异常(如-50或150) 1. TMP36接线错误(引脚接反)。
2. 供电电压不稳或不足。
3. 模拟参考电压未设置正确(默认5V)。
1. 确认TMP36引脚顺序(平面朝自己,左VCC,中Vout,右GND)。
2. 用万用表测量Arduino 5V引脚电压,应在4.8V-5.2V之间。
3. 确保未在代码中使用analogReference()改变基准电压。
光照读数不变化或变化范围小 1. LDR分压电路连接错误。
2. 分压电阻阻值不匹配。
3. 标定公式参数错误。
4. LDR损坏或被遮挡。
1. 确认是“5V-LDR-A1引脚-10kΩ电阻-GND”的连接方式。
2. 用万用表测量A1引脚对地电压,用手遮挡LDR看电压变化范围是否明显(理想应有1V以上变化)。尝试更换不同阻值的分压电阻(如4.7kΩ, 20kΩ)。
3. 重新进行LDR标定。
4. 更换LDR测试。
串口监视器无输出或乱码 1. 波特率设置错误。
2. 串口被其他程序占用。
3. Serial.begin()未执行或代码卡死。
1. 确认串口监视器右下角波特率设置为9600,与代码中Serial.begin(9600)一致。
2. 关闭其他可能占用串口的软件(如其他串口调试助手)。
3. 在setup()函数开头添加一个简单的Serial.println("Start");测试。

5.2 从原型到实用的优化建议

当前的系统是一个功能完整的原型。但要投入实际使用,尤其是对稳定性要求较高的农业环境,还需要考虑以下优化:

  1. 软件滤波:传感器的原始读数会有噪声。可以通过滑动平均滤波来平滑数据。例如,创建一个数组存储最近10次的温度读数,每次输出这10个数的平均值,能有效消除偶然跳动。

    CPP
    const int numReadings = 10;
    float tempReadings[numReadings];
    int readIndex = 0;
    float tempTotal = 0;
    float tempAverage = 0;
    // 在loop中
    tempTotal = tempTotal - tempReadings[readIndex]; // 减去最旧的读数
    tempReadings[readIndex] = temperature; // 存入新读数
    tempTotal = tempTotal + tempReadings[readIndex]; // 加上最新的读数
    readIndex = (readIndex + 1) % numReadings; // 移动索引
    tempAverage = tempTotal / numReadings; // 计算平均值
    // 后续使用tempAverage进行逻辑判断
  2. 增加执行机构:让系统从“监控”升级为“控制”。可以通过继电器模块连接加热器、风扇或补光灯。

    • 温度控制:当tempAverage < 15°C时,启动继电器1(连接加热器);当tempAverage > 25°C时,启动继电器2(连接风扇)。
    • 光周期控制:这需要引入**实时时钟模块(如DS3231)**来记录真实时间。系统可以设定每日需要的光照时长(如8小时),通过RTC判断时间,在非光照时段点亮绿灯,在光照时段若自然光不足(lightIntensity < 设定值),则启动继电器3(连接补光灯)。
  3. 数据记录与远程监控:添加一个SD卡模块,定期将时间、温度、光照、状态记录到CSV文件中,便于后期分析。更进一步,可以结合ESP8266 WiFi模块,将数据上传到物联网平台(如Thingspeak、Blynk),实现手机远程监控和报警。

  4. 低功耗设计:如果用于电池供电的野外监测,需要优化功耗。使用Arduino的低功耗睡眠模式,让MCU大部分时间休眠,每隔几分钟唤醒一次进行测量和判断,可以极大延长电池寿命。

5.3 项目总结与延伸思考

完成这个项目,你收获的不仅仅是一个能闪灯的小盒子。你实践了从需求分析、方案设计、硬件选型、电路搭建、软件编程到系统调试的完整嵌入式开发流程。你深入理解了模拟传感器的工作原理、ADC转换、标定方法以及基于阈值的控制逻辑。

这个系统的核心思想——感知、判断、执行——是几乎所有自动化系统的通用范式。你可以轻易地将传感器换成土壤湿度传感器(如电容式传感器),用于自动灌溉;或者换成二氧化碳传感器,用于优化温室通风。控制对象也可以从LED扩展到水泵、电磁阀、步进电机等。

在农业这个领域,精准化、自动化是必然趋势。这套简单的系统,为我们打开了一扇窗,让我们看到如何用低成本的技术手段,去理解和优化动植物的生长环境。它可能还不够“工业级”坚固,算法还不够“智能”,但作为一个起点,它提供的思路和实践经验是无比宝贵的。下次当你吃到一颗香甜的草莓时,或许会想起,它的生长背后,也可以有这样一段人与代码、与电路、与自然规律对话的故事。