{{tag>arduino 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]] 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: Se ha cambiado la lectura del sensor DHT al A1 para dejar el A0 para los botones del LCD {{ :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: //// 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 //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++; } ==== Referencias ==== * http://www.prometec.net/lcd-keypad-shield/ * http://forum.arduino.cc/index.php?topic=303135.105