Comedero-Bebedero Inteligente
Introducción
A continuación explicaremos el proceso que hemos seguido para la creación de un comedero y bebedero para animales que también se activa por NFC. En primer lugar, desarrollaremos el funcionamiento del proyecto, y la parte de hardware y software del proyecto. A continuación, explicaremos los problemas que presenta nuestro proyecto, así como las mejoras que podría tener. Concluiremos con un vídeo donde se muestra el correcto funcionamiento del proyecto.
Funcionamiento
El proyecto presenta las siguientes funcionalidades:
- El bebedero se rellena automáticamente. Esto quiere decir que, sin importar como de vacío está (mucho, medio o poco), el bebedero se rellenará hasta que esté completamente lleno. Se detectará cuando el nivel de agua ha disminuido, y se procederá a rellenarlo hasta el tope.
- El comedero se rellenará automáticamente, pero únicamente cuando esté muy o completamente vacío. Cuando ocurra esto, el comedero se rellenará hasta el máximo. Se detectará el peso del comedero, y cuando alcance niveles muy bajos (se encuentre vació o casi vacío) se rellenará hasta el tope.
- Además, el usuario podrá rellenar usando un nfc el comedero independientemente de como de vacío esté. De esta forma, el usuario puede gestionar la cantidad de comida que habrá en el comedero.
- Cuando se usa el nfc, el comedero no se rellenará hasta el máximo, sino una cierta cantidad. De esta manera el usuario puede decidir cuando y cuanto llenar el comedero. En caso de que el comedero esté al máximo de cantidad, el nfc dejará de funcionar y se mostrará un mensaje avisando de que está al máximo.
- Hemos incorporado un led para que, durante el proceso de rellenado de los dos (del comedero y del bebedero) esté en rojo. Una vez finalizado el rellenado, el led pasará a estar de color verde, avisando de que se ha finalizado el proceso.
- Finalmente hemos incorporado un zumbador para que, una vez se rellene el comedero, el zumbador haga sonar una melodía avisando de que se ha rellenado con éxito.
Hardware
Para la realización de la parte hardware hemos usado los siguientes componentes:
Elemento | Descripción | Funcionalidad específica | Coste |
Ultrasonic Sensor | Sensor de ultrasonidos: emite ondas sonoras con las que mide la distancia a la que se encuentra un objeto. | Medir como de lleno está el bebedero. | – |
Válvula Solenoide 2V025 | Válvula solenoide: interruptor que regula el flujo de fluidos. Potencia: 12 voltios. Corriente continua. Normalmente cerrada PSI: 0 | Controlar el paso de agua para rellenar el bebedero. | 16 |
Sensor de Presión RP-C10-ST | Sensor de presión: mide la fuerza aplicada a través de una carga. Dimensiones: 1 x 2,5 x 0,1 cm; Grosor 0,4mm. Rango de detección de presión: 20 g – 2 kg Peso: 1g | Medir como de lleno está el comedero | 12 |
Servomotor MG 996R | Servomotor: proporciona un movimiento preciso y controlado en respuesta a señales de entrada específicas. | Controlar el paso de comida que cae al bebedero. | 6 |
Módulo RFID-RC522 | Sensor NFC: permite la comunicación inalámbrica de corto alcance entre dispositivos compatibles con tecnología NFC. NFC: Near Field Communication. | Rellenar el comedero cuando se activa. | 7 |
RGB Led | Led RGB: diodo emisor de luz que puede emitir luz en los tres colores primarios. | Mostrar cuando se está rellenando y cuando el proceso ha finalizado. | – |
Passive Buzzer | Zumbador: produce un sonido continuo o intermitente cuando se le aplica una corriente eléctrica. | Sonar una melodía al final del rellenado. | – |
Transistor MOSFET | Transistor MOSFET: dispositivo semiconductor que controla el flujo de corriente entre dos terminales. | Interruptor para la activación de la válvula. | 1 |
Diodo | Diodo: dispositivo electrónico que permite el flujo de corriente en una dirección y bloquea en la dirección opuesta. | Dirigir correctamente la corriente al transistor | – |
Resistencias | Resistencias: limitan la corriente y ajustan el voltaje en los circuitos conectados a los pines. (10k para el sensor de presión) | Asegurar el funcionamiento seguro del transistor y del sensor de peso. | – |
Cables | Cables: conductores eléctricos utilizados para conectar componentes entre sí o con la placa Arduino | Varias | . |
Materiales Fisicos | Maderas Escuadras Tornillos Recipientes… | Creación de la estructura del proyecto. | 20 |
Pintura | 8 | ||
TOTAL | 70 |
Notar que los costes son aproximados. No hemos dispuesto de los proveedores más baratos porque nos urgían y necesitábamos inmediatez. Además utilizamos materiales que ya teníamos, que nos hemos ahorrado, y servicios herramientas de alto coste que tampoco hemos alquilado ni comprado. Además hemos tenido que sustituir varios componentes defectuosos y compramos otros que no fuimos capaces según evolucionó el proyecto de darles un uso coherente.
Por tanto, el costo estimado es de unos 50-60€ con buenos proveedores y herramientas, lo que lo posiciona cerca de productos similares que se pueden encontrar en otras tiendas, pero tampoco es una gran diferencia.
Circuito
En la imagen anterior podemos ver como e el circuito montado sobre una placa de inserción. Es importante destacar que es necesario enchufar la placa de Arduino a una fuente de alimentación de 12V y 500 mA al menos puesto que el encendido y apagado de la válvula utilizada los requiere.
Podemos ver que para el circuito utilizamos un transistor MSOFET como interruptor para la activación de válvula (que requiere la alimentación externa), un diodo para dirigir correctamente la corriente y resistencias que evitan subidas de tensión para que no se caliente el transistor y para calibrar correctamente la sensibilidad de el sensor de presión.
Montaje físico
A continuación, una vez verificados (a priori) todos los componentes nos pusimos con el diseño y montaje del proyecto. Quisimos priorizar el esqueleto o estructura principal para poder intuir el montaje, para ello utilizamos unos cartones para intuir físicamente las dimensiones y colocación del proyecto. También elegimos y compramos los recipientes que consideramos adecuados para almacenar la comida y agua. Escogimos unos impermeables con el fondo plano. Uno lo recortamos por completo y al otro le perforamos un agujero donde pegaremos una pequeño tubo.
Tras la construcción de los prototipos a cartón comenzamos a tomar medidas y a diseñar bocetos. Observamos que íbamos a tener tres partes diferenciadas en la estructura: una para guardar los recipientes y almacenar la comida y el agua; otra para guardar la circuiría y por último los componentes hardware per sé.
Tras realizar los bocetos y comprobar empíricamente las medidas y corregirlas (medidas no finales en los bocetos) reunimos las piezas de madera y de DM para el montaje.
Para montar la estructura usamos tornillos para madera y tirafondos con una atornilladora eléctrica. También pegamos con silicona caliente las partes que no requerían de gran sujeción. Atornillamos una serie de escuadras que mantuviesen la estabilidad de los recipientes y los sujetasen así como un enganche para la tubería y la estructura que sujetará el motor, aunque esto último fue algo después puesto que tuvimos que cambiar la idea original y hacer una compuerta horizontal en lugar de inclinada o vertical por lo que tuvimos que cambiar de recipiente.
En el segundo montaje podemos observar que añadimos una serie de soportes más y maderas para alinear bien la salida de comida. También pegamos la rampa y atornillamos el serio motor para posteriormente poder pegar el recipiente a la altura correcta. Utilizamos unas comas para ajustar mejor los recipientes y que no se moviesen. Observar que ya pegamos la válvula a la tubería del recipiente que tendrá el agua.
A continuación pegamos unas pequeñas escuadras metálicas a las que se adherirán los imames que estarán pegados a los DMs pintados y así poder desmontarlos fácilmente para acceder al circuito y así montarlo e instalarlo correctamente.
Tras todo lo anterior, medimos los agujeros necesarios de salida de comida y agua y recortamos una placa de madera que atornillamos a la estructura a la que también pegamos tanto el sensor de ultrasonidos como el NFC.
Pintamos las placas de madera de plateado para que quedase bien integrado, pegamos un trocito de cartón en la salida de la comida, que ayudó a que cayese la comida de manera más ordenada y dibujamos una huella donde se encuentra el sensor NFC,
Pruebas
Una vez montada toda la estructura conectamos el circuito por dentro gracias a las planchas extraibles de madera. Añadimos tanto el LED como el zumbador para obtener respuesta según nuestro sistema funcione.
Se recomienda ajustar tanto el diámetro del agujereo como los tiempos del motor según la comida que se vaya a usar. También se recomienda usar un sensor de presión lo suficientemente sensible para obtener mejores resultados pero se puede adaptar también según el alimento. Sugerimos construir una estructura acolchada al rededor del comedero para que la presión del mismo se concentre sobre el centro del FSR y evitar que haya medidas nulas. Se puede variar la conexión del sensor de presión de 5v a 3.3v para ajustar la sensibilidad.
En el vídeo podemos ver funcionando correctamente la válvula y el sensor de ultrasonidos.
Software
Primero definimos los pines del Arduino e inicializamos algunas variables que usaremos.
//////////////////////// ULTRASONIDOS ////////////////////////
const int Trigger = 2; //Pin digital 2 para el Trigger del sensor
const int Echo = 3; //Pin digital 3 para el Echo del sensor
float t; //tiempo que demora en llegar el eco
float d; //distancia en centimetros
//////////////////////// VALVULA ////////////////////////
int solenoidPin = 7; //Pin solenoide
//////////////////////// SERVO ////////////////////////
#include <Servo.h>
Servo servoMotor; // Crea un objeto Servo
//////////////////////// FUERZA ////////////////////////
#define FORCE_SENSOR_PIN A0 // pin del FSR y 10K Ohm
//////////////////////// NFC ////////////////////////
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
byte llavero[] = {0x13, 0x07, 0xE7, 0xF6}; //13 07 E7 F6.
byte llavero2[] = {0xE1, 0x00, 0xC7, 0x0D}; //E1 00 C7 0D
byte llavero3[] = {0xD4, 0x2F, 0xE3, 0x94}; //D4 2F E3 94
//////////////////////// LED + ZUMBADOR ////////////////////////
const int LED_R = 4;
const int LED_G = 8;
const int ZUMBADOR = 6;
Posteriormente, hacemos el setup, inicializamos la comunicación con la placa para obtener los datos de lectura y establecemos el modo de cada pin siendo entrada o salida. Además ajustamos la posición de inicio de el motor y cerramos la válvula (aunque esta sea normalmente cerrada conviene hacerlo).
Para el sensor NFC, hemos inicializado el lector de tarjetas RFID MFRC522 para permitir la comunicación con el sensor NFC.
void setup() {
Serial.begin(9600);//iniciailzamos la comunicación
//////////////////////// ULTRASONIDOS ////////////////////////
pinMode(Trigger, OUTPUT); //pin como salida
pinMode(Echo, INPUT); //pin como entrada
digitalWrite(Trigger, LOW);//Inicializamos el pin con 0
//////////////////////// VALVULA ////////////////////////
pinMode(solenoidPin, OUTPUT);
digitalWrite(solenoidPin, LOW);
//////////////////////// SERVO ////////////////////////
servoMotor.attach(5); // Conecta el servomotor al pin 5
servoMotor.write(5);
//////////////////////// FUERZA ////////////////////////
//Solo inicializamos la entrada
//////////////////////// NFC ////////////////////////
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522
delay(4); // Optional delay. Some board do need more time after init to be ready, see Readme
mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details
Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
//////////////////////// LED + ZUMBADOR ////////////////////////
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(ZUMBADOR, OUTPUT);
}
Antes de loop definimos una serie de funciones que usaremos dentro, como una que recibe un float y lo evalúa para decidir si cerrar o no la válvula o uno que recibe un entero y lo evalúa para saber si el comedero está lleno, vacío o a medias. También métodos que comparan que la identificación de la tarjeta NFC sea igual a alguna de las tarjetas guardadas.
El método abrirVálvula contiene una doble comprobación más restrictiva para evitar que las pequeñas variaciones en el resultado hagan que abramos y cerremos la válvula muchas veces en poco tiempo.
void abrirValvula(float distancia){
//MICROSEGUNDOS
if(distancia<20.00){
delay(330);
// VOLVEMOS A MEDIR
digitalWrite(Trigger, HIGH);
delayMicroseconds(10); //Enviamos un pulso de 10us
digitalWrite(Trigger, LOW);
t = pulseIn(Echo, HIGH); //obtenemos el ancho del pulso
d = t/59; //escalamos el tiempo a una distancia en cm
Serial.print("el agua esta a:..................................");
Serial.println(d);
if(d<19.25){
digitalWrite(solenoidPin, LOW);
}
}
else{
digitalWrite(solenoidPin, HIGH);
}
}
void rellenarMotor(int peso){
if (peso<300){
servoMotor.write(54);
digitalWrite(LED_G, HIGH);
digitalWrite(LED_R, HIGH); //AMARILLO
tone(ZUMBADOR, 100); // Frecuencia de tono de 1000 Hz
delay(350);
// delay(1000); //CAMBIAR TIEMPO DE ESPERA ABIERTO
servoMotor.write(5);
delay(150);
tone(ZUMBADOR, 200); // Frecuencia de tono de 1000 Hz
delay(500);
tone(ZUMBADOR, 300); // Frecuencia de tono de 1000 Hz
delay(500);
noTone(ZUMBADOR);
delay(500);
tone(ZUMBADOR, 100); // Frecuencia de tono de 1000 Hz
delay(500);
tone(ZUMBADOR, 200); // Frecuencia de tono de 1000 Hz
delay(500);
tone(ZUMBADOR, 300); // Frecuencia de tono de 1000 Hz
delay(500);
noTone(ZUMBADOR);
delay(500);
// delay(5000);
if(peso > 200){
digitalWrite(LED_G, HIGH); //VERDE
digitalWrite(LED_R, LOW);
}
}
else{
Serial.print("El bowl de comida no está vacio del todo");
Serial.println();
digitalWrite(LED_G, HIGH); //VERDE
digitalWrite(LED_R, LOW);
}
}
void NFCMotor(int peso){
if(peso<650){ //CAMBIAR PESO
tone(ZUMBADOR, 100);
delay(200);
tone(ZUMBADOR, 200);
delay(100);
servoMotor.write(54);
delay(100);
digitalWrite(LED_R, HIGH); //AMARILLO
digitalWrite(LED_G, HIGH);
//digitalWrite(solenoidPin, LOW); CASO CERRAR EL GRIFO ANTES
tone(ZUMBADOR, 300);
delay(200);
noTone(ZUMBADOR);
delay(200);
//delay(0400); //CAMBIAR TIEMPO DE ESPERA ABIERTO
servoMotor.write(5);
digitalWrite(LED_G, HIGH); //VERDE
digitalWrite(LED_R, LOW);
}
else{
digitalWrite(LED_G, LOW); //ROJO
digitalWrite(LED_R, HIGH);
tone(ZUMBADOR, 1000); //Suena Zumbador
Serial.print("No se puede llenar más el bowl");
Serial.println();
delay(1000);
digitalWrite(LED_G, HIGH); //VERDE
digitalWrite(LED_R, LOW);
noTone(ZUMBADOR); //apaga Zumbador
}
}
void imprimirNFC(byte *buffer, byte bufferSize) {
Serial.print("UID de la tarjeta: ");
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
Serial.println();
}
bool compareUid(byte *uid1, byte uid1Size, byte *uid2, byte uid2Size) {
// Verificar que los tamaños de los UID sean iguales
if (uid1Size != uid2Size) {
return false;
}
// Comparar byte a byte
for (byte i = 0; i < uid1Size; i++) {
if (uid1[i] != uid2[i]) {
return false; // No son iguales
}
}
return true; // Son iguales
}
Luego realizamos el loop. Primero leemos en el sensor de ultrasonidos, y en función del valor obtenido llamamos al método de abrir válvula . Posteriormente hacemos lo propio con el sensor de presión, llamando también a la función de evaluación del motor. Y mantenemos activa la lectura de nuestro lector NFC, para que siempre pueda detectar si hay o no tarjeta, en el caso que la haya se evalúa con el método que compara las identificaciones.
Mientras funciona el motor hacemos un delay en el que aprovechamos para cambiar el color del LED y hacer sonar al zumbador hasta que el motor se vuelva a accionar para cerrar la compuerta. Por otra parte, nos aseguramos que mientras haya un delay activo la válvula permanezca cerrada puesto que el ultrasonidos no está haciendo lectura y podría desbordar el agua en caso de permanecer abierta mucho tiempo. Finalmente, en caso de las lecturas incorrectas de NFC también controlamos el color del LED y al zumbador.
void loop(){
delay(200);
//////////////////////// ULTRASONIDOS y VALVULA ////////////////////////
digitalWrite(Trigger, HIGH);
delayMicroseconds(10); //Enviamos un pulso de 10us
digitalWrite(Trigger, LOW);
t = pulseIn(Echo, HIGH); //obtenemos el ancho del pulso
d = t/59; //escalamos el tiempo a una distancia en cm
Serial.print("Distancia: ");
Serial.print(d); //Enviamos serialmente el valor de la distancia
Serial.print("cm");
Serial.println();
abrirValvula(d);
//////////////////////// PESO Y SERVO ////////////////////////
int analogReading = analogRead(FORCE_SENSOR_PIN);
Serial.print("1 Force sensor reading = ");
Serial.print(analogReading); // print the raw analog reading
Serial.println();
rellenarMotor(analogReading);
//abrirValvula(d); CASO CERRAR EL GRIFO ANTES
//////////////////////// NFC ///////////////////////////////
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
imprimirNFC(mfrc522.uid.uidByte, mfrc522.uid.size); //LEE UN NFC
if ((compareUid(mfrc522.uid.uidByte, mfrc522.uid.size, llavero2, sizeof(llavero2))) || (compareUid(mfrc522.uid.uidByte, mfrc522.uid.size, llavero, sizeof(llavero))) || (compareUid(mfrc522.uid.uidByte, mfrc522.uid.size, llavero3, sizeof(llavero3)))) { //COMPARAR QUE ES EL LLAVERO/TARJETA
int analogReading = analogRead(FORCE_SENSOR_PIN);
Serial.print("2 Force sensor reading = ");
Serial.print(analogReading); // print the raw analog reading
Serial.println();
NFCMotor(analogReading);
}
else{
digitalWrite(LED_G, LOW); //ROJO
digitalWrite(LED_R, HIGH);
tone(ZUMBADOR, 1000); // Suena Zumbador
Serial.print("Tarjeta incorrecta");
delay(1000);
digitalWrite(LED_G, HIGH); //VERDE
digitalWrite(LED_R, LOW);
noTone(ZUMBADOR); // Apaga Zumbador
}
}
mfrc522.PICC_HaltA(); // Detener la tarjeta actual
mfrc522.PCD_StopCrypto1(); // Detener la comunicación
}
Valoramos utilizar el método millis para no usar delys pero nos parecía demasiado complicado para ser de tan pocos segundos y nos evitamos problemas de desbordamiento de memoria ya la idea del proyecto es que siempre pueda estar enchufado funcionando pasivamente.
Seguimos estableciendo un ligero delay de 0.1 segundos para que el los sensores no se saturen por la lectura continuada ya que tampoco requerimos de un tiempo de respuesta ultra bajo.
Mejoras
Como posibles retoques o mejoras podemos sugerir que se pudiese cambiar el deposito de agua por una entrada de tubería de agua y tratar el proyecto como un electrodoméstico mas, y así dejar más espacio para la comida. También podríamos pintar la base de espuma del comedero para que fuese mas discreta. y por último añadir que habría que modificar el software para calibrar el rellenado del comedero según el tipo de alimento sea mas grande o más pequeño.
Vídeo
Por último un breve vídeo explicando y demostrando el correcto funcionamiento de nuestro proyecto: