我们热爱电子和植物,因此我们在 Juan de Lanuza 学校的“家庭机器人”活动中创建了一个水培系统。我们想创建一个便携式系统,以便向所有学校展示它并在一年中种植区域植物。
水培法
对我们来说,水培不仅是一种愉快的爱好,也是一种绿色的爱好。
水培法仅使用在泥土中生长的植物所需的 10% 的水,并且由于植物在需要时总能获得必要的养分,因此产量更高。
作为一个封闭系统,这也意味着肥料不会进入地下水位,这对环境非常有益。
我们的项目是水培,一种基于水培的室内种植,一种使用矿物质溶液代替土壤来种植植物的方法。一般结构由铝制成。水循环的结构由手工切割和粘合的 PVC 管组成,由 6 层水通过。每个级别都已钻孔以放置花盆。还设计了 3D 部件,使花盆不会移动并支持照明。在下部有一个水箱,系统的水落入其中,通过该水箱可以将不同的成分添加到水中。如果必须排空水箱,我们有一个手动排水。
我们的平台由三个不同的部分组成:
该设备允许通过感应几个参数来控制植物的状态:
然后它使用不同类型的执行器通过灌溉、激活灯光或释放养分来改变植物的状态:
该设备使用 WiFi 定期将信息发送到网络服务器。我们还设计了一个应用程序,允许从 Android 设备可视化这些数据。我们已将其作为开源代码发布。
结构材料:
电子/电工材料:
其他:
工具:
为该项目设计了一个模块化的低成本水培系统。使用不同尺寸的连接器连接 PVC 管道,如主图所示。
施工步骤
支撑架
我们需要一个框架来支撑我们的管道。框架由铝制成,具有模块化特性(易于将多个模块安装在一起)和易于使用的尺寸(易于使用基本工具直接切割)。
模块化底座
我们集成了一个带有 4 个轮子的模块化木底座,以创建一个便携式系统。
我们将各个腿部组件粘合在一起以增加稳定性。
结构的尺寸决定了水培系统的大小和系统可以支持的行数。
我们当前的模型包括 6 个级别。可以通过减小行间距来修改间距以支持更多的生长区域。
注意:该项目的 PVC 管最好使用斜切锯切割。这些很容易以两种类型获得:便宜的手动锯或省时的电动锯。
我们在每根管子上钻了 5 到 7 个孔。首先,标记每个孔的点。用磨头获取您的 dremel 工具并清理孔,直到杯子符合您的预期。我们使用塑料玻璃作为植物地块。如果您也使用它们,请在底部和边缘钻孔,以便根部可以接触玻璃外的水。
用杯子量出粘土球放入一桶水中。水会洗掉球中可能存在的任何灰尘。
在水培中,这一切都是为了将富含营养的水输送到植物的根部,同时确保水中仍有足够的氧气。我们创建了 NFT(营养膜技术)系统。为此,我们需要植物根部可以接触到的少量但恒定的水流。
水含有植物所需的所有营养物质,而恒定的流量确保水中有足够的氧气。
植物需要一些东西来支撑它们,虽然我们没有土壤来支撑它们,但这就是水培介质的用武之地。我们使用了上面提到的膨胀粘土球。这些给植物提供支持,并提供一个小的缓冲来保持水分。
我们使用铝框架作为支撑连接所有电缆和电气系统。它使用 3A 12V 电源连接到 220V。在结构顶部,我们连接了生长灯。我们的是 12V LED 灯条,每米长度消耗大约 0.5A。在底部,我们连接了使用 1A 的水泵。
主电路消耗在0.5A左右。
我们设计了不同的 3D 打印部件以支持不同的元素:
我们使用了 Tinkercad,这是一个非常简单的在线 3D CAD 程序,您可以在此处使用:www.tinkercad.com
在这里您可以找到水培电路的主图和项目的引脚排列。
我们使用防水泵将水从地板的水箱中提升到结构的顶部。
水培需要特殊的养分,因为普通肥料的配方是与土壤一起使用的,不应该用于水培。根据植物生长的不同阶段和作物类型,水培肥料可以有不同的类型。
我们破解了一个“喂鱼器”,以便用 Arduino 控制它。这是我们的个性化营养喂食器。我们在需要的时候控制它,以便我们可以向水箱释放更多的营养。然后我们重新打开水泵,让植物获得营养。
必须定期添加营养物质,很难说何时需要添加。人们每周一次到每月一次,这取决于您每次添加多少肥料。另一种选择是控制 pH 值和电导率水平以相应地调整肥料量。
我们为水培系统集成了 2 个特定传感器。
PH传感器
pH 传感器探头有一个 BNC 连接器,它集成了传感器的所有不同电线。
特征:
校准传感器
为了校准 pH 传感器,需要一个 pH 校准套件。
电导率传感器
电导率传感器探头有两个非极化触点,因此可以互换。
特征:
校准传感器
为了校准 EC 传感器,您需要一个电导率校准套件
目标是使用 Arduino MEGA 实现自动化。这包括:
我们附上了项目的主要 Arduino 代码。如果您使用不同的 pH 或电导率传感器,则可能需要更改计算以获得真实值。
Arduino程序
图书馆:
我们已经包含了所有使用的库。
代码:
// HidroponicoCole_v5.8 NO CLAVES//
// bluetooht RX3-TX3
// DALLAS pin 3
// DHT pin 2
// Bomba pin 6
// Luz pin 7
// Shield ESP 8266 con comandos AT
// Utiliza libreria TimeLib para la fecha y hora
// Envia datos cada 15 minutos
// LCD con ALARMAS
// Invierte salida Bomba y Luz 0= activo, 1= inactivo
// -----------------------------------------------------------#define DEBUG 0 // change value to 1 to enable debuging using serial monitor
String network = "SSID NAME"; // your access point SSID
String password = "PASSWORD"; // your wifi Access Point password
#define IP "184.106.153.149" // IP address of thingspeak.com 184.106.153.149
String GET = "GET /update?key=CHANNEL_KEY"; // replace with your channel key#include "OpenGarden.h"
#include
#include
#include
#include
#include // initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 51, en = 53, d4 = 39, d5 = 37, d6 = 35, d7 = 33;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);// Establece valores inicio de fecha y hora
int hora = 9;
int minuto = 0;
int segundo = 0;
int dia = 1;
int mes = 1;
int ano = 17;bool nuevoSegundo;
int viejoSegundo = 0;bool nuevoMinuto;
int viejoMinuto = 0;bool nuevaHora;
int viejaHora = 0;// variables telegrama recibido de bluethooh
// cabecera, cuerpo1, cuerpo2, cuerpo3, fin
int cabecera = 0;
int cuerpo1 = 0;
int cuerpo2 = 0;
int cuerpo3 = 0;
int fin = 0;// Sensores PH y EC
#define calibration_point_4 2246 //Write here your measured value in mV of pH 4
#define calibration_point_7 2080 //Write here your measured value in mV of pH 7
#define calibration_point_10 1894 //Write here your measured value in mV of pH 10#define point_1_cond 40000 // Write here your EC calibration value of the solution 1 in µS/cm
#define point_1_cal 40 // Write here your EC value measured in resistance with solution 1
#define point_2_cond 10500 // Write here your EC calibration value of the solution 2 in µS/cm
#define point_2_cal 120 // Write here your EC value measured in resistance with solution 2/* SENSOR DHT22 (AIRE) */
#define DHTPIN 2
#define DHTTYPE DHT22float TemperaturaAire;
float HumedadAire;
DHT dht(DHTPIN, DHTTYPE);/* SENSOR Temperatura DALLAS (TemperaturaAgua) */
#define ONE_WIRE_BUS 3
OneWire oneWireBus (ONE_WIRE_BUS);
DallasTemperature sensors (&oneWireBus);
float TemperaturaAgua;/* BOMBA y LUZ */
#define PinBombaAgua 6 // Bomba en pin 6
#define PinLuz 7 // Luces en pin 7
#define Amanece 8 // Hora de encendido Luz
#define Anochece 20 // Hora apagado Luz
#define MinutosBomba 20 // Minutos funcionando bomba
bool BombaAgua = 0; // 0=parada , 1= marcha
bool Luz = 0; // 0= apagada , 1= encendida// VALORES DE ALARMAS
#define PhAlto 10 // Valor alto alarma Ph
#define PhBajo 5 // Valor bajo alarma Ph
#define EcAlto 3000 // Valor alto alarma Ec
#define EcBajo 900 // Valor bajo alarma Ec
// Valor EcMuyBajo activa "Falta de agua". NO PERMITE FUNCIONAMIENTO BOMBA
#define EcMuyBajo 200
#define TempAguaAlto 40 // Valor alto alama Temp Agua
#define TempAguaBajo 5 // Valor bajo alama Temp Agua
int AlarmaPH; // alarma Ph
int AlarmaTempAgua; // alarma Temp
int AlarmaEC; // alarma Ecfloat pH;
float EC;void setup() {
lcd.begin(16, 2); // Inicia LCD 16 caracteres, 2 filas
// Mensaje de arranque en LCD
borrarLCD();
lcd.setCursor(0, 0); // posiciona cursor linea 0, columna 0
lcd.print("INICIANDO");
lcd.setCursor(0, 1);
lcd.print("ESPERE ....."); setupEsp8266(); // inicia conexión WiFi
pinMode(PinBombaAgua, OUTPUT);
pinMode(PinLuz, OUTPUT); Serial3.begin(9600);
Serial.begin(115200); // establece fecha y hora al arrancar
setTime(hora, minuto, segundo, dia, mes, ano); // Start up the libraries
sensors.begin(); // DALLAS
dht.begin(); // DHT OpenGarden.initSensors(); //Initialize sensors power
OpenGarden.sensorPowerON();//Turn On the sensors
OpenGarden.calibratepH(calibration_point_4, calibration_point_7, calibration_point_10);
OpenGarden.calibrateEC(point_1_cond, point_1_cal, point_2_cond, point_2_cal);
delay(500);
}void loop() {
// Read DALLAS
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
sensors.requestTemperatures(); // Send the command to get temperatures
TemperaturaAgua = (sensors.getTempCByIndex(0)); // Why "byIndex"?
// You can have more than one IC on the same bus.
// 0 refers to the first IC on the wire // Lee DHT 22
HumedadAire = dht.readHumidity();
TemperaturaAire = dht.readTemperature(); //Read the pH sensor
int mvpH = OpenGarden.readpH(); //Value in mV of pH
pH = OpenGarden.pHConversion(mvpH); //Calculate pH value
if ( pH < 0 || pH > 14) {
pH = 0 ;
} //Read the conductivity sensor in µS/cm
float resistanceEC = OpenGarden.readResistanceEC(); //EC Value in resistance
EC = OpenGarden.ECConversion(resistanceEC); //EC Value in µS/cm // Alarmas datos Agua
AlarmaPH = 0; // Resetea el valor de la alarma Ph
if ( pH > PhAlto ) {
AlarmaPH = 2 ;
}
if ( pH < PhBajo ) {
AlarmaPH = 1 ;
} AlarmaTempAgua = 0; // Resetea el valor de la alarma Temp Agua
if ( TemperaturaAgua > TempAguaAlto ) {
AlarmaTempAgua = 2 ;
}
if ( TemperaturaAgua < TempAguaBajo ) {
AlarmaTempAgua = 1 ;
} AlarmaEC = 0; // Resetea el valor de la alarma EC
if ( EC > EcAlto ) {
AlarmaEC = 2 ;
}
if ( EC < EcBajo ) {
AlarmaEC = 1 ;
}
if ( EC < EcMuyBajo ) {
AlarmaEC = 3 ;
} // Construye y envia a ESP 8266
if (viejoMinuto != minute()) {
nuevoMinuto = true;
viejoMinuto = minute();
} else {
nuevoMinuto = false;
} if (minute() % 15 == 0 && nuevoMinuto) { // 5= cada 5 minutos, 15= cada 15 minutos
updateTemp(String(pH) , String(EC), String(TemperaturaAgua), String(TemperaturaAire), String(HumedadAire));
} // comprobar recepción datos desde bluetooth
if (Serial3.available () > 10) {
cabecera = Serial3.parseInt ();
cuerpo1 = Serial3.parseInt ();
cuerpo2 = Serial3.parseInt ();
cuerpo3 = Serial3.parseInt ();
fin = Serial3.parseInt ();
String basura = Serial3.readString(); // vacía el buffer de lectura
} if (cabecera == fin && cabecera == 20) { // si cabecera=fin=20 actualiza hora
setTime(cuerpo1, cuerpo2, cuerpo3, dia, mes, ano);
cabecera = 0; // borra cabecera y fin para no repetir
fin = 0;
} // Envía datos por Bluetooth
Serial3.print("<");
Serial3.print(pH);
Serial3.print(", ");
Serial3.print(EC);
Serial3.print(", ");
Serial3.print(TemperaturaAgua);
Serial3.print(", ");
Serial3.print(HumedadAire);
Serial3.print(", ");
Serial3.print(TemperaturaAire);
Serial3.print(", ");
Serial3.print(hour()); // envia hora actual
Serial3.print(", ");
Serial3.print(minute()); // envia minuto actual
Serial3.print(", ");
Serial3.print(second()); // envia segundo actual
Serial3.print(", ");
Serial3.print(BombaAgua); //envia estado BombaAgua
Serial3.print(", ");
Serial3.print(Luz); // envia estado Luz
Serial3.print(">"); // control bomba de agua minutos cada hora
if (minute() < MinutosBomba && EC > EcMuyBajo) { // EC muy bajo implica riego de falta de agua
digitalWrite (PinBombaAgua, LOW); // LOW = Bomba on
BombaAgua = 1;
}
else {
digitalWrite (PinBombaAgua, HIGH); // HIGH = Bomba off
BombaAgua = 0;
} // control luz encendida de Amanece a Anochece
if (hour() > Amanece && hour() < Anochece) {
digitalWrite (PinLuz, LOW); // LOW = Luz on
Luz = 1;
}
else {
digitalWrite (PinLuz, HIGH); // HIGH = Luz off
Luz = 0;
} // refresca LCD cada segundo
if (viejoSegundo != second()) {
nuevoSegundo = true;
viejoSegundo = second();
} else {
nuevoSegundo = false;
} if (nuevoSegundo == true) {
visualiza ();
}}
//-------------------------------------------------------------------
// Following function setup the esp8266, put it in station mode and
// connect to wifi access point.
//------------------------------------------------------------------
void setupEsp8266()
{
if (DEBUG) {
//Serial3.println("Reseting esp8266");
}
Serial.flush();
Serial.println(F("AT+RST"));
delay(7000); if (Serial.find("OK"))
{
if (DEBUG) {
Serial3.println("Found OK");
Serial3.println("Changing espmode");
}
Serial.flush();
changingMode();
delay(5000);
Serial.flush();
connectToWiFi();
}
else
{
if (DEBUG) {
Serial3.println("OK not found");
}
}
}//-------------------------------------------------------------------
// Following function sets esp8266 to station mode
//-------------------------------------------------------------------
bool changingMode()
{
Serial.println(F("AT+CWMODE=1"));
if (Serial.find("OK"))
{
if (DEBUG) {
Serial3.println("Mode changed");
}
return true;
}
else if (Serial.find("NO CHANGE")) {
if (DEBUG) {
Serial3.println("Already in mode 1");
}
return true;
}
else
{
if (DEBUG) {
Serial3.println("Error while changing mode");
}
return false;
}
}//-------------------------------------------------------------------
// Following function connects esp8266 to wifi access point
//-------------------------------------------------------------------
bool connectToWiFi()
{
if (DEBUG) {
Serial3.println("inside connectToWiFi");
}
String cmd = F("AT+CWJAP=\"");
cmd += network;
cmd += F("\",\"");
cmd += password;
cmd += F("\"");
Serial.println(cmd);
delay(15000); if (Serial.find("OK"))
{
if (DEBUG) {
Serial3.println("Connected to Access Point");
}
return true;
}
else
{
if (DEBUG) {
Serial3.println("Could not connect to Access Point");
}
return false;
}
}//-------------------------------------------------------------------
// Following function sends sensor data to thingspeak.com
//-------------------------------------------------------------------
void updateTemp(String valor1, String valor2, String valor3, String valor4, String valor5)
{
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
Serial.println(cmd);
if (DEBUG) {
Serial3.println (cmd);
} delay(5000);
if (Serial.find("Error")) {
if (DEBUG) {
Serial3.println("ERROR while SENDING");
}
return;
}
cmd = GET + "&field1=" + valor1 + "&field2=" + valor2 + "&field3=" + valor3 + "&field4=" + valor4 + "&field5=" + valor5 + "\r\n";
if (DEBUG) {
Serial3.println (valor1);
Serial3.println (valor2);
Serial3.println (valor3);
Serial3.println (valor4);
Serial3.println (valor5);
Serial3.println (cmd);
} Serial.print("AT+CIPSEND=");
Serial.println(cmd.length());
delay(15000);
if (Serial.find(">"))
{
Serial.print(cmd);
if (DEBUG) {
Serial3.println("Data sent");
}
} else
{
Serial.println("AT+CIPCLOSE");
if (DEBUG) {
Serial3.println("Connection closed");
}
}
}// -------------------------------------
// Muetra datos LCD
// -------------------------------------
void visualiza() { // visualiza fecha y hora
if (second() % 30 >= 0 && second() % 30 < 7) {
borrarLCD();
lcd.setCursor(0, 0); // posiciona cursor linea 0, columna 0
lcd.print("HORA ACTUAL"); lcd.setCursor(0, 1);
lcd.print(format(hour()));
lcd.print(":");
lcd.print(format(minute()));
lcd.print(":");
lcd.print(format(second()));
} // visualiza datos AGUA
if (second() % 30 >= 7 && second() % 30 < 14) {
borrarLCD();
lcd.setCursor(0, 0); // posiciona cursor linea 0, columna 0
lcd.print("AGUA: ");
lcd.print((int)EC);
lcd.print(" uS/cm"); lcd.setCursor(0, 1);
lcd.print("pH=");
lcd.print(pH);
lcd.print("; ");
lcd.print(TemperaturaAgua);
lcd.print(" C"); }
// visualiza datos AIRE
if (second() % 30 >= 14 && second() % 30 < 21) {
borrarLCD();
lcd.setCursor(0, 0); // posiciona cursor linea 0, columna 0
lcd.print(" AIRE "); lcd.setCursor(0, 1); // posiciona cursor linea 0, columna
lcd.print((int)TemperaturaAire);
lcd.print(" C ; ");
lcd.print((int)HumedadAire);
lcd.print("%"); }
// visualiza ALARMAS
if (second() % 30 >= 21 && second() % 30 < 30) {
borrarLCD();
lcd.setCursor(0, 0); // posiciona cursor linea 0, columna 0
lcd.print(" ALARMAS "); lcd.setCursor(0, 1); // posiciona cursor linea 0, columna
if (AlarmaPH == 0 && AlarmaTempAgua == 0 && AlarmaEC == 0) { // verifica si hay alarmas
lcd.print("NO HAY ALARMAS");
}
else {
if (AlarmaPH > 0) {
lcd.print("pH;");
}
if (AlarmaTempAgua > 0) {
lcd.print("Temp Agua;");
}
if (AlarmaEC > 0 && AlarmaEC < 3 ) {
lcd.print("EC");
}
if (AlarmaEC == 3 ) {
lcd.print("No Agua");
}
}
}
}void borrarLCD() {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
}String format(int info) {
String infoEditada;
if (info < 10) {
infoEditada += 0;
}
infoEditada += info; return infoEditada;
}
我们集成了一个 LCD 显示屏,以便查看所有传感器数据,而无需无线连接到水培栽培。
我们使用 App Inventor 创建了一个特定的应用程序。在这里您可以找到源文件。
应用程序
我们使用 ESP8266 模块将系统连接到 Thingspeak(提供数据存储和分析的服务)。
最后!我们在学校创建了一个可工作的模块化水培系统!:)
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !