Go Down

Topic: Cultivo Indoor Automata (Read 365 times) previous topic - next topic

loopua

Jul 07, 2020, 07:13 am Last Edit: Jul 14, 2020, 04:37 am by surbyte
Hola comunidad de arduino, saludos desde Chile

Debido a la pandemia, hemos tenido que parar y quedarnos en casa, a reflexionar. Mi acercamiento a las
entidades de estudio no ha sido muy buena(como para estudiar una ingeniería), pero siempre he intentado aprender de manera independiente. Y en esta oportunidad me gustaría aprender a automatizar algunos procesos y a programar arduino, no esperar el codigo listo, sino comprender la magia detras.
A favor de esto, estoy dispuesto a leer toda la internet con tal de aprender, me gustaria que me recomendaran informacion ad hoc para esta mision

Me ha cautivado un proyecto que esta cerrado el dia de hoy que es el cutivo autonomo de Hiddennotebook
(https://forum.arduino.cc/index.php?topic=303135.0)

Cuento con el mismo Hardware:

- Arduino Mega

- ESP8266-01 Modulo wifi

- Display QVGA 2.2 TFT SPI 240x320

- DHT22 digital temperature and humidity sensor

- Soil Hygrometer Humidity Detection Module

- 5V two 2 Channel Relay Module With optocoupler

- Dispenser Flowmeter Flow Sensor. Inner diameter 3mm DC 5-24v

- DS3231 AT24C32 Reloj en tiempo real de precisión.

- Bomba de riego a 12v 60w 5L/min

- Una bomba peristáltica, para mezclar fertilizantes.

He armado el sistema y me ha funcionado de lo mejor, y a lo largo del tiempo he descubierto que los soil sensor son toxicos y dejan de funcionar, asi que intente darle un upgrade, sacando los sensores y cambiando la fuente de poder por un YwRobot mb102. Haciendo esto me di cuenta que todo el sistema estaba en funcion de la humedad de suelo.

y ha quedado esto


Code: [Select]

//Se retira ATX,LED,BOTON
//5-7-20: se retiran sensores de suelo, por toxicidad

// TFT:
  #include "Adafruit_GFX.h" // Librerias para pantalla QVGA 2.2 TFT SPI 240*320
  #include "Adafruit_ILI9341.h"
 
// RTC:
  #include "RTClib.h"      // Cargar Libreria RTC.
  #include <Wire.h>       // Cargar Libreria comunicacion I2C.
  #include "SPI.h"       // Cargar Libreria comunicacion SPI.
  RTC_DS1307 RTC;       // Crear RTC
  const char* DayTXT[7]= {"Domingo ", "Lunes ", "Martes ", "Miercoles ","Jueves ", "Viernes ", "Sabado "};

// DHT22
  #include "DHT.h"             // Cargar Librería DHT.
  #define DHTPIN 25           // Seleccionamos el pin en el que se conectará el sensor.
  #define DHTTYPE DHT22      // Se selecciona el DHT22(hay otros DHT).
  DHT dht(DHTPIN, DHTTYPE); // Variable usada para comunicarse con el sensor DHT22.
 
// ARDUINO MEGA:
  #define TFT_DC 47
  #define TFT_CS 48
  #define TFT_RST 49
  Adafruit_ILI9341 tft = Adafruit_ILI9341 (TFT_CS, TFT_DC, TFT_RST);

  // RELAY PUMP1
  #define RELAY_ON 0  // Rele encendido en estado 0
  #define RELAY_OFF 1 // Rele apagado en estado 1
  #define RELAY_1 39   // Rele pin 1 al 39
  // END RELAY PUMP1
  
  char textBuff[50];   // Buffer Para imprimir datos de sensores en TFT.
  int botonAnt;  
  unsigned long updateScreen; // Creamos variable para refrescar la pantalla
  unsigned long  moistureTest; // Variable para refrescar datos del sensor de suelo
                                                                                                    
void setup() {
//-------------- RELAY PUMP1 ------------------------

    pinMode(RELAY_1, OUTPUT); // define el pin 39 como salida activa rele 1 para la bomba.

//-------------- TFT SETTINGS -----------------------
 
  tft.begin();                      // Inicia TFT 2.2"
  tft.setRotation(3);              // Rotación de pantalla.
  tft.setTextWrap(true);          // Si el texto no cabe pasarlo a la siguiente linea.
  tft.fillScreen(ILI9341_BLACK); // Rellenar la pantalla con fondo negro.

//-------------- RTC --------------------------------
 
  Wire.begin();   // Inicia el puerto I2C.
  RTC.begin();   // Inicia la comunicacion con el RTC.
  //RTC.adjust(DateTime(2000,001,01, 00,00,00));

//-------------- DHT --------------------------------
 
  dht.begin();   //Se inicia el sensor DHT22.
}

void loop() {
  if (millis() - updateScreen > 1000UL) //refrescamos la pantalla cada segundo
  {
    display();
    updateScreen = millis();
  }
}

void display() { // Rutina para mostrar datos en TFT
 
//-------------- RTC --------------------------------

  DateTime now = RTC.now(); // Obtiene la fecha y hora del RTC.

//-------------- DHT --------------------------------

  int h = dht.readHumidity();     // Lee la humedad DHT22.
  int t = dht.readTemperature(); // Lee la temperatura DHT22.
  
//-------------- TFT DISPLAY DATA --------------------

//(header)
   // DAY ON TEXT:
    tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
    tft.setTextSize(2);
    tft.setCursor(0, 0);
    tft.println(DayTXT[now.dayOfTheWeek()]); // Aqui tengo que arreglar la sobreescritura de caracteres
    tft.setCursor(160, 0);
    tft.println("ArduIndoor");

   // DATE:
    char DateBuffer[16];
    sprintf(DateBuffer, "%02d:%02d:%02d", now.day(), now.month(), now.year());
    tft.print(DateBuffer);
    tft.setCursor(160, 30);
  
   // CLOCK RTC:
    char ClockBuffer[16]; // Creamos myBuffer para mostrar bien los digitos del 1 al 9.
    sprintf(ClockBuffer, "%02d:%02d", now.hour(), now.minute());
    tft.setTextSize(3);
    tft.println(ClockBuffer);
  
   // DATA:
    tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
    tft.setTextSize(2);
    tft.println("\nDatos del ambiente:\n");

//(body)
   // DHT:
    tft.setTextSize(2);
      sprintf(textBuff, "Humedad aire:    %3d%", h);
        tft.print(textBuff);
          tft.println("%");
    sprintf(textBuff, "\nTemperatura aire:%3d%cC\n", t, (char)247);
        tft.println(textBuff);
  
//(footer)
   // REFERENCES:
    tft.setTextColor(ILI9341_CYAN);
    tft.setTextSize(2);
    tft.setCursor(15, 200);
    tft.print("Te amo Lulita Hermosita");
  
//-------------- END TFT ----------------------------

}



Como en realidad no funciona muy bien este proyecto sin esas partes, he decidido replantearlo en base a esta tabla:


Realmente me ha costado centrar mis ideas y mi intencion hacia este proyecto, ya que con youtube (una de mis fuente de documentacion y tutoriales) me surgen ideas locas y no puedo concentrarme en solucionar mi problema. Como por ejemplo, tengo la idea de tener un estanque para el agua donde se mezclen los fertilizantes (todos medidos con un sensor de flujo y la cantidad de agua con un sensor ultrasonico)y el riego sea por goteo (controlado por otro sensor de flujo y una bomba de diafragma)

Info:
medidor de flujo: https://naylampmechatronics.com/blog/47_tutorial-sensor-de-flujo-de-agua.html
medidor de nivel:https://programarfacil.com/blog/arduino-blog/sensor-de-nivel-de-agua-con-arduino/


Mi duda es como debería afrontar este problema, he visto videos de maquinas de estados finitos, time sheduler y time alarms. Pero realmente no se muy bien como aplicarlos a este topico.
Tampoco se si deberia cambiar de pantalla a una lcd, no he encontrado mucha informacion sobre la tft screen, no se si se pueden configurar diferentes pantallas para mostrar la informacion.
(He tenido en cuenta este post: https://forum.arduino.cc/index.php?topic=346755.0)

Esta es mi idea de la informacion mostrada en tft:



Info:
maquina de estados finitos:https://www.luisllamas.es/maquina-de-estados-finitos-arduino/

time alarms: https://www.pjrc.com/teensy/td_libs_TimeAlarms.html

Tengo un intento de estados finitos en papel, pero esta en proceso de arreglos

Estoy estancado, confundido y un poco desmotivado.
Cualquier ayuda es bien recibida.

surbyte

Bueno, ve con paciencia, que no se ganó Zamora en una hora como decía mi Abuela EspaÑola por cierto.

Los soil sensor son de juguete. Lo hemos dicho muchas veces en este foro. Lo mejor es que los replantees o que evites tenerlos conectados todo el tiempo. Asi que lo mejor sería que cuando los vayas a usar le des alimentación. Como consumen poco, un PIN puede alimentarlos pero tu lectura entonces será dependiente del valor de tensión que entregue el pin.
Otra solución es que uses una fuente de valor conocido y que uses un mosfet canal P (tal vez no sepas que es) pero básicamente es una llave digital que le dará energia al sensor cuando lo uses.
Eso... alarga la vida util del sensor que seguirá siendo tóxico pero mucho menos.

Quote
Mi duda es como debería afrontar este problema, he visto videos de maquinas de estados finitos, time sheduler y time alarms.
Con respecto a las máquinas de estados desde ya que te la aconsejo. Nada de usar delay() en tu código.
Por ahora tu código va bien, solo presentas cosas pero conforme crezca y quieras hacer ajustes empezaran los problemas.

Time schedule no se para que lo quieres.
time alarms se usa para que hacer acciones a intervalos determinados. Yo no estoy de acuerdo con que un sistema use intervalos periódicos. La planta tiene necesidades y determinarlas es lo que obliga a que tomes acciones. Como vas a decirle que lo haga a las 8:00 o las 15:30 hs?

En este foro en la sección Documentación tenemos buenas explicaciones. Hay ejemplos que varios foreros hemos aplicado a casos comunes que te pueden ayudar a entenderlo. La referencia de Luis Llamas también es recomendable.

Veo que tu código usa millis() asi que vas por buen camino.

loopua

Hola, estoy leyendo sobre las maquinas de estados para poder aplicarlo.

por el momento tengo un picadillo de codigo (un poco de alla y un poco de aca), pero creo que en el fondo no se lo que estoy haciendo jajaja...  :o , no tengo mucha claridad aun si el codigo funciona como un puzzle o tendre que enfocarme en aprender bien el idioma.

estos son mis recortes:

Code: [Select]
//****************TFT:
  #include "Adafruit_GFX.h" // Librerias para pantalla QVGA 2.2 TFT SPI 240*320
  #include "Adafruit_ILI9341.h"
 
//****************RTC:
  #include "RTClib.h"      // Cargar Libreria RTC.
  #include <Wire.h>       // Cargar Libreria comunicacion I2C.
  #include "SPI.h"       // Cargar Libreria comunicacion SPI.
  RTC_DS1307 RTC;       // Crear RTC
  const char* DayTXT[7]= {"Domingo ", "Lunes ", "Martes ", "Miercoles ","Jueves ", "Viernes ", "Sabado "};

//****************DHT22
  #include "DHT.h"             // Cargar Librería DHT.
  #define DHTPIN 22           // Seleccionamos el pin en el que se conectará el sensor.
  #define DHTTYPE DHT22      // Se selecciona el DHT22(hay otros DHT).
  DHT dht(DHTPIN, DHTTYPE); // Variable usada para comunicarse con el sensor DHT22.

 char textBuff[50];   // Buffer Para imprimir datos de sensores en TFT.
 unsigned long updateScreen; // Creamos variable para refrescar la pantalla
 int botonAnt; //  variable luz manual
 int botonAnt1; //  variable ventilador manual
 int estado; //variable estado floracion o vegetacion
 bool encendido = false;     // Variable booleana para el encendido con el Boton.
 bool PowerON= false;
 

//****************MEDIDOR NIVEL DE AGUA - ULTRASONICO
 // Configuramos los pines del sensor Trigger y Echo
const int PinTrig = 7;
const int PinEcho = 6;

// Constante velocidad sonido en cm/s
const float VelSon = 34000.0;

// Número de muestras
const int numLecturas = 100;

// Distancia a los 100 ml y vacío
const float distancia100 = 2.15;
const float distanciaVacio = 11.41;

float lecturas[numLecturas]; // Array para almacenar lecturas
int lecturaActual = 0; // Lectura por la que vamos
float total = 0; // Total de las que llevamos
float media = 0; // Media de las medidas
bool primeraMedia = false; // Para saber que ya hemos calculado por lo menos una

//****************MEDIDOR DE FLUJO DE AGUA - FERTILIZANTE - RIEGO
volatile int NumPulsos; //variable para la cantidad de pulsos recibidos
int PinSensor = 2;    //Sensor conectado en el pin 2
float factor_conversion=7.11; //para convertir de frecuencia a caudal
float volumen=0;
long dt=0; //variación de tiempo por cada bucle
long t0=0; //millis() del bucle anterior

//---Función que se ejecuta en interrupción---------------
void ContarPulsos () 
{
  NumPulsos++;  //incrementamos la variable de pulsos
}

//---Función para obtener frecuencia de los pulsos--------
int ObtenerFrecuecia()
{
  int frecuencia;
  NumPulsos = 0;   //Ponemos a 0 el número de pulsos
  interrupts();    //Habilitamos las interrupciones
  delay(1000);   //muestra de 1 segundo
  noInterrupts(); //Deshabilitamos  las interrupciones
  frecuencia=NumPulsos; //Hz(pulsos por segundo)
  return frecuencia;
}

void setup()
{
 
  pinMode(PinSensor, INPUT); //Volumen de agua
  attachInterrupt(0,ContarPulsos,RISING);//(Interrupción 0(Pin2),función,Flanco de subida)
  t0=millis();
}
{
   // Ponemos el pin Trig en modo salida
  pinMode(PinTrig, OUTPUT);
  // Ponemos el pin Echo en modo entrada
  pinMode(PinEcho, INPUT);

  // Inicializamos el array
  for (int i = 0; i < numLecturas; i++)
  {
    lecturas[i] = 0;
  }
}
{
  pinMode(25, OUTPUT);      // Led de Riego
  pinMode(, OUTPUT);     // Led Luz
  pinMode(, OUTPUT);    // led Ventilazion
  pinMode(, OUTPUT);     // led humedad
  pinMode(35, OUTPUT);     //led calefaccion
  pinMode(, OUTPUT);     // rele  Luz
  pinMode(, OUTPUT);     // rele ventilador
  pinMode(26, OUTPUT);    // rele riego
  pinMode(23, OUTPUT);     // rele humeidificador
  pinMode(36, OUTPUT);     // rele  calefaccion
  pinMode(8, INPUT_PULLUP); // Boton manual luz
  pinMode(9, INPUT_PULLUP); // Boton manual Ventilacion
  pinMode(10, INPUT_PULLUP); // boton humidificador
  pinMode(24, INPUT_PULLUP);// estado floracion o vegetacion
  pinMode(37, OUTPUT); //led floracion
  pinMode(, OUTPUT); //led vegetacion
  Wire.begin();             // Inicia el puerto I2C
  RTC.begin();              // Inicia la comunicación con el RTC
    // RTC.adjust(DateTime(__DATE__, __TIME__));
  dht.begin();              //Se inicia el sensor DHT22.

//-------------- TFT SETTINGS -----------------------
 
  tft.begin();                      // Inicia TFT 2.2"
  tft.setRotation(3);              // Rotación de pantalla.
  tft.setTextWrap(true);          // Si el texto no cabe pasarlo a la siguiente linea.
  tft.fillScreen(ILI9341_BLACK); // Rellenar la pantalla con fondo negro.

}

void loop ()   

//SENSOR DE FLUJO
{
  if (Serial.available()) {
    if(Serial.read()=='r')volumen=0;//restablecemos el volumen si recibimos 'r'
  }
  float frecuencia=ObtenerFrecuecia(); //obtenemos la frecuencia de los pulsos en Hz
  float caudal_L_m=frecuencia/factor_conversion; //calculamos el caudal en L/m
  dt=millis()-t0; //calculamos la variación de tiempo
  t0=millis();
  volumen=volumen+(caudal_L_m/60)*(dt/1000); // volumen(L)=caudal(L/s)*tiempo(s)
}
 {
  if (millis() - updateScreen > 1000UL) //refrescamos la pantalla cada segundo
  {
    display();
    updateScreen = millis();
  }
}

//SENSOR DE NIVEL
{
  // Eliminamos la última medida
  total = total - lecturas[lecturaActual];

  iniciarTrigger();

  // La función pulseIn obtiene el tiempo que tarda en cambiar entre estados, en este caso a HIGH
  unsigned long tiempo = pulseIn(PinEcho, HIGH);

  // Obtenemos la distancia en cm, hay que convertir el tiempo en segudos ya que está en microsegundos
  // por eso se multiplica por 0.000001
  float distancia = tiempo * 0.000001 * VelSon / 2.0;

  // Almacenamos la distancia en el array
  lecturas[lecturaActual] = distancia;

  // Añadimos la lectura al total
  total = total + lecturas[lecturaActual];

  // Avanzamos a la siguiente posición del array
  lecturaActual = lecturaActual + 1;

  // Comprobamos si hemos llegado al final del array
  if (lecturaActual >= numLecturas)
  {
    primeraMedia = true;
    lecturaActual = 0;
  }

  // Calculamos la media
  media = total / numLecturas;

  // Solo mostramos si hemos calculado por lo menos una media
  if (primeraMedia)
  {
    float distanciaLleno = distanciaVacio - media;
    float cantidadLiquido = distanciaLleno * 100 / distancia100;
    int porcentaje = (int) (distanciaLleno * 100 / distanciaVacio);

 
  }

  delay(500);
}
// Método que inicia la secuencia del Trigger para comenzar a medir
void iniciarTrigger()
{
  // Ponemos el Triiger en estado bajo y esperamos 2 ms
  digitalWrite(PinTrig, LOW);
  delayMicroseconds(2);

  // Ponemos el pin Trigger a estado alto y esperamos 10 ms
  digitalWrite(PinTrig, HIGH);
  delayMicroseconds(10);

  // Comenzamos poniendo el pin Trigger en estado bajo
  digitalWrite(PinTrig, LOW);
}




Aun no me han llegado todas las piezas para probar bien. (aun no conecto todo)

Go Up