meta data de esta página
  •  

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
electronica:arduino:lcd [2016/07/31 22:57] lcelectronica:arduino:lcd [2023/01/18 14:36] (actual) – editor externo 127.0.0.1
Línea 1: Línea 1:
 +{{tag>arduino lcd}}
 ===== 3 . Añadir LCD ===== ===== 3 . Añadir LCD =====
-Continuamos con nuestro proyecto y ahora vamos a añadirle un LCD del tipo [[http://www.prometec.net/producto/lcd-keypad/|LCD KEY PAD SHIELD]]+Continuamos con nuestro proyecto y ahora vamos a añadirle un LCD del tipo [[http://www.prometec.net/producto/lcd-keypad/|LCD KEY PAD SHIELD]] de 16x2 líneas 
 +{{ :electronica:arduino:lcd16x2.png?300 |}} 
 +Este tipo de LCD ya viene preparada para conectar directamente encima del arduino Uno o del Mega, pero en nuestro caso al utilizar el nano  
 +tenemos que hacer las conexiones siguientes: 
 +<note>Se ha cambiado la lectura del sensor DHT al A1 para dejar el A0 para los botones del LCD</note> 
 +{{ :electronica:arduino:sensor_lcd_bb.png?600 |}}
  
 +El esquema de conexión sería:
 +
 +^ LCD  ^ Arduino Nano  ^
 +| A0   | A0            |
 +| D4   | D4            |
 +| D5   | D5            |
 +| D6   | D6            |
 +| D7   | D7            |
 +| D8   | D8            |
 +| D9   | D9            |
 +
 +El código:
 +<sxh javascript>
 +//// wiki.intrusos.info
 +// modificación del código de http://webdelcire.com/wordpress/archives/2471
 +
 +
 +
 +//---------------------------Sensor DHT ------------------------------------------------
 +#include "DHT.h" // Libreria para Sensores DHT
 +#define DHTPIN 2     // Pin del Arduino al cual esta conectado el pin 2 del sensor
 +// Descomentar segun el tipo de sensor DHT usado
 +#define DHTTYPE DHT11   // DHT 11 
 +DHT dht(DHTPIN, DHTTYPE);// Inicializa el sensor
 +
 +//---------------LCD ---------------------------------------------------------------------
 +#include <LiquidCrystal.h>  //Libreria LCD
 +// Inicializa el objeto LCD con los pines de la interfaz
 +LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
 +
 +// Pines digitales
 +byte pinLedVerde = 10;
 +byte pinLedRojo = 11;
 +byte pinMotor = 12;
 +
 +// Pines analógicos
 +byte pinSensorHumedad = 1;
 +
 +// definición teclado
 +int lcd_key     = 0;
 +int adc_key_in  = 0;
 +#define btnRIGHT  0
 +#define btnUP     1
 +#define btnDOWN   2
 +#define btnLEFT   3
 +#define btnSELECT 4
 +#define btnNONE   5
 +
 +// Constantes para los posibles modos de funcionamiento
 +byte MODO_TIEMPO_HUMEDAD = 0;
 +byte MODO_SOLO_TIEMPO = 1;
 +byte MODO_SOLO_HUMEDAD = 2;
 +
 +
 +int modoElegido = 0; // Modo de funcionamiento
 +
 +int umbralHumedad = 0; // Umbral de humedad seleccionado para empezar a regar
 +
 +int diasTemporizacion = 0;
 +int horasTemporizacion = 0;
 +int minutosTemporizacion = 0;
 +
 +int duracionRiego = 0; // Duración del riego en segundos una vez alcanzado el evento de activación
 +
 +String linea1; // Contenido para la línea superior del display
 +String linea2; // Contenido para la línea inferior del display
 +
 +int humedadMinima = 0; // Lectura mínima por defecto para el sensor de humedad (se ajusta dinámicamente)
 +int humedadMaxima = 100; // Lectura máxima por defecto para el sensor de humedad (se ajusta dinámicamente)
 +
 +int lecturasHumedad[10]; // Ultimas 10 lecturas del sensor para hacer la media
 +int indiceLecturasHumedad = 0; // Indice para saber que valor toca rellenar del array previo
 +boolean mediaLista = false; // Indicador de que ya están rellenos los 10 valores del array
 +int mediaHumedad = 0; // Media de las últimas 10 lecturas de humedad
 +int riegos = 0;                 // Numero de riegos realizados
 +int limiteRiegos = 10;          // Limite de seguridad del número de riegos
 +
 +int read_LCD_buttons();  // para leer los botones
 +
 +int read_LCD_buttons()
 +{ adc_key_in = analogRead(0);      // Leemos A0
 +  if (adc_key_in > 900)  return btnNONE;     // Ningun boton pulsado
 +  if (adc_key_in < 50)   return btnRIGHT;
 +  if (adc_key_in < 200)  return btnUP;
 +  if (adc_key_in < 400)  return btnDOWN;
 +  if (adc_key_in < 600)  return btnLEFT;
 +  if (adc_key_in < 800)  return btnSELECT;
 +  return btnNONE;  // Por si todo falla
 +}
 +
 +
 +//----------------------------------inicio setup ----------------------------------
 +void setup()
 +{
 +  
 +  // Inicializa el número de columnas y filas del LCD
 +  lcd.begin(16, 2);
 +
 +  // Establece a modo salida los pines para controlar la bomba y los led de señalización
 +  pinMode(pinMotor,OUTPUT);
 +  pinMode(pinLedRojo,OUTPUT);
 +  pinMode(pinLedVerde,OUTPUT);
 +
 +  // Activa el led rojo y muestra la pregunta sobre el modo en el que va a funcionar
 +  digitalWrite(pinLedRojo, HIGH);
 +  mostrarPregunta(modoElegido);
 +
 +  // Pregunta por el modo de funcionamiento: tiempo + humedad, sólo tiempo o sólo humedad
 +  boolean respuesta = false;
 +  while (!respuesta)
 +  {
 +    lcd_key = read_LCD_buttons();
 +    delay(200);  //para evitar lecturas seguidas
 +    if ( lcd_key == btnDOWN)
 +    {
 +      modoElegido--;
 +      if (modoElegido == -1) modoElegido = 2;
 +      mostrarPregunta(modoElegido);
 +    }
 +    else if ( lcd_key == btnUP)
 +    {
 +      modoElegido++;
 +      if (modoElegido == 3) modoElegido = 0;
 +      mostrarPregunta(modoElegido);
 +    }
 +    else if ( lcd_key == btnSELECT)
 +    {
 +      respuesta = true;
 +    }
 +  }
 +
 +
 +  // Si el modo elegido incluye riego por tiempo, pregunta cada cuantos días, horas y minutos
 +  if (modoElegido == MODO_TIEMPO_HUMEDAD || modoElegido == MODO_SOLO_TIEMPO)
 +  {
 +    // No permite elegir un tiempo cero
 +    while (diasTemporizacion + horasTemporizacion + minutosTemporizacion == 0)
 +    {
 +      diasTemporizacion = preguntarValor("Numero de dias:", 0, 30);
 +      horasTemporizacion = preguntarValor("Numero de horas:", 0, 23);
 +      minutosTemporizacion = preguntarValor("Numero minutos:", 0, 59);
 +    }
 +
 +    // Muestra un resumen del tiempo elegido
 +    linea1 = "  DD : HH : MM";
 +    linea2 = "  " + str(diasTemporizacion) + " : " + str(horasTemporizacion) + " : " + str(minutosTemporizacion);
 +    mostrarTexto();
 +    delay(1000);
 +  }
 +
 +  // Si el modo elegido incluye riego por sensor de humedad, pregunta cual es el umbral de humedad para regar
 +  if (modoElegido == MODO_TIEMPO_HUMEDAD || modoElegido == MODO_SOLO_HUMEDAD)
 +  {
 +    umbralHumedad = preguntarValor("Umbral humedad:", 40, 99);
 +  }
 +
 +  // Pregunta cuantos segundos deberá durar el riego cuando se active
 +  duracionRiego = preguntarValor("Duracion riego:", 15, 300);
 +
 +  // Finalizada la programación desactiva el led rojo y activa el verde
 +  digitalWrite(pinLedRojo, LOW);
 +  digitalWrite(pinLedVerde, HIGH);
 +}
 +
 +
 +void loop()
 +{
 +  // inicializa las variables de tiempo para el riego por temporización
 +  int diasPendientes = diasTemporizacion;
 +  int horasPendientes = horasTemporizacion;
 +  int minutosPendientes = minutosTemporizacion;
 +  int segundosPendientes = 0;
 +
 +  if (modoElegido == MODO_TIEMPO_HUMEDAD)
 +  {
 +    // Continua el bucle hasta que el tiempo llegue a cero
 +    while ((diasPendientes + horasPendientes + minutosPendientes + segundosPendientes) > 0)
 +    {
 +      // Espera un segundo y decrementa las variables el equivalente a un segundo
 +      delay(987);
 +      segundosPendientes--;
 +      if (segundosPendientes == -1)
 +      {
 +        segundosPendientes = 59;
 +        minutosPendientes--;
 +      }
 +      if (minutosPendientes == -1)
 +      {
 +        minutosPendientes = 59;
 +        horasPendientes--;
 +      }
 +      if (horasPendientes == -1)
 +      {
 +        horasPendientes = 23;
 +        diasPendientes--;
 +      }
 +
 +      // Actualiza la variable con la humedad actual
 +      leerHumedad();
 +
 +      // Actualiza el display con el tiempo hasta el siguiente riego y la humedad actual
 +      linea1 = str(diasPendientes) + ":" + str(horasPendientes) + ":" + str(minutosPendientes) + ":" + str(segundosPendientes);
 +      linea2 = "Humedad:" + str(mediaHumedad) + "\x25" + " [" + str(umbralHumedad) + "]";
 +      mostrarTexto();
 +
 +      // Si la media de humedad de las últimas 10 lecturas está lista y es inferior al umbral configurado, activa el riego
 +      if ((mediaHumedad < umbralHumedad) && mediaLista)
 +      {
 +        regar();
 +        // Reinicia la media de humedad para que le tiempo a la tierra a empaparse
 +        indiceLecturasHumedad = 0;
 +        mediaLista = false;
 +      }
 +    }
 +
 +    // Activa lo bomba de riego durante el tiempo configurado
 +    regar();
 +  }
 +  else if (modoElegido == MODO_SOLO_TIEMPO)
 +  {
 +    // Continua el bucle hasta que el tiempo llegue a cero
 +    while ((diasPendientes + horasPendientes + minutosPendientes + segundosPendientes) > 0)
 +    {
 +      delay(990);
 +      segundosPendientes--;
 +      if (segundosPendientes == -1)
 +      {
 +        segundosPendientes = 59;
 +        minutosPendientes--;
 +      }
 +      if (minutosPendientes == -1)
 +      {
 +        minutosPendientes = 59;
 +        horasPendientes--;
 +      }
 +      if (horasPendientes == -1)
 +      {
 +        horasPendientes = 23;
 +        diasPendientes--;
 +      }
 +
 +      // Actualiza el display con el tiempo hasta el siguiente riego
 +      linea1 = "Proximo riego:";
 +      linea2 = str(diasPendientes) + ":" + str(horasPendientes) + ":" + str(minutosPendientes) + ":" + str(segundosPendientes);
 +      mostrarTexto();
 +    }
 +
 +    // Activa lo bomba de riego durante el tiempo configurado
 +    regar();
 +  }
 +  else if (modoElegido == MODO_SOLO_HUMEDAD)
 +  {
 +    while (true)
 +    {
 +      delay(1000);
 +
 +      // Actualiza la variable con la humedad actual
 +      leerHumedad();
 +
 +      // Actualiza el display con la humedad actual y el número de riegos efectuados hasta el momento
 +      linea1 = "Humedad: " + str(mediaHumedad) + "\x25" + " [" + str(umbralHumedad) + "]";  // \x25 es el símbolo ascii de %
 +      linea2 = "Riegos: " + str(riegos);
 +      mostrarTexto();
 +
 +      // Si la media de humedad de las últimas 10 lecturas está lista y es inferior al umbral configurado, activa el riego
 +      if ((mediaHumedad < umbralHumedad) && mediaLista)
 +      {
 +        regar();
 +        // Reinicia la media de humedad para que le tiempo a la tierra a empaparse
 +        indiceLecturasHumedad = 0;
 +        mediaLista = false;
 +      }
 +    }
 +  }
 +}
 +
 +
 +// Pregunta el modo de funcionamiento con la última opción elegida
 +void mostrarPregunta(byte modo)
 +{
 +  lcd.clear();
 +  lcd.print("Modo de riego?");
 +  lcd.setCursor(0, 1);
 +  if (modo == MODO_TIEMPO_HUMEDAD) lcd.print("Tiempo + Humedad");
 +  else if (modo == MODO_SOLO_TIEMPO) lcd.print("Solo Tiempo");
 +  else if (modo == MODO_SOLO_HUMEDAD) lcd.print("Solo Humedad");
 +}
 +
 +// Muestra el texto configurado en el display
 +void mostrarTexto()
 +{
 +  lcd.clear();
 +  lcd.print(linea1);
 +  lcd.setCursor(0, 1);
 +  lcd.print(linea2);
 +}
 +
 +
 +// Muestra una pregunta y recoge un valor numérico
 +int preguntarValor(String texto, int inicial, int maximo)
 +{
 +  linea1 = texto;
 +  linea2 = str(inicial);
 +  mostrarTexto();
 +  boolean respuesta = false;
 +  int valor = inicial;
 +  while (!respuesta)
 +  {
 +    lcd_key = read_LCD_buttons();
 +    delay(200); //para evitar lecturas seguidas
 +    if ( lcd_key == btnDOWN)
 +    { valor--;
 +      if (valor == -1) valor = maximo;
 +      linea2 = str(valor);
 +      mostrarTexto();
 +    }
 +
 +    else if ( lcd_key == btnUP)
 +    {
 +      valor++;
 +      if (valor > maximo) valor = 0;
 +      linea2 = str(valor);
 +      mostrarTexto();
 +    }
 +
 +    else if ( lcd_key == btnSELECT)
 +    {
 +      respuesta = true;
 +    }
 +  }
 +  return valor;
 +}
 +
 +// Devuelve una cadena numérica de al menos 2 caractes, rellenando con un cero por la izquierda si hace falta
 +String str(int valor)
 +{
 +  if (valor < 10) return "0" + String(valor);
 +  else return (String(valor));
 +}
 +
 +
 +// Actualiza la variable con la media de humedad de las últimas 10 lecturas
 +void leerHumedad()
 +{
 +  lecturasHumedad[indiceLecturasHumedad] = analogRead(pinSensorHumedad);
 +  lecturasHumedad[indiceLecturasHumedad] = map (lecturasHumedad[indiceLecturasHumedad], 0, 1023, 100, 0); // Mapeamos el valor del sensor de 0 a 100
 +  indiceLecturasHumedad++;
 +  if (indiceLecturasHumedad > 9)
 +  {
 +    indiceLecturasHumedad = 0;
 +    mediaLista = true;
 +  }
 +
 +  mediaHumedad = 0;
 +  for (int i = 0; i < 10; i++) mediaHumedad += lecturasHumedad[i];
 +  mediaHumedad /= 10;
 +  if (mediaHumedad > humedadMaxima) humedadMaxima = mediaHumedad;
 +  if (mediaHumedad < humedadMinima) humedadMinima = mediaHumedad;
 +  mediaHumedad -= humedadMinima;
 +
 +  mediaHumedad = (double)((double)mediaHumedad / (double)(humedadMaxima - humedadMinima)) * 100;
 +  if (mediaHumedad == 100) mediaHumedad = 99;
 +}
 +
 +
 +// Activa lo bomba de riego durante el tiempo configurado
 +void regar()
 +{
 +  if (riegos == limiteRiegos)
 +  {
 +    linea1 = " - BLOQUEADO - ";
 +    linea2 = "Limite de riegos";
 +    mostrarTexto();
 +    while (true) {
 +      delay(999999);
 +    }
 +  }
 +  int riegoPendiente = duracionRiego;
 +  digitalWrite(pinMotor, HIGH);
 +  while (riegoPendiente > 0)
 +  {
 +    linea1 = " -- REGANDO -- ";
 +    linea2 = "Restante: " + str(riegoPendiente);
 +    mostrarTexto();
 +    delay(990);
 +    riegoPendiente--;
 +  }
 +  digitalWrite(pinMotor, LOW);
 +  riegos++;
 +}
 +
 +</sxh>
  
  
Línea 7: Línea 405:
 ==== Referencias ==== ==== Referencias ====
   * http://www.prometec.net/lcd-keypad-shield/   * http://www.prometec.net/lcd-keypad-shield/
 +  * http://forum.arduino.cc/index.php?topic=303135.105