Está en la página 1de 19

Pavlov’s Feeder.

Un dispensador
automático de comida para
mascotas con Arduino
POR ADMIN · ABRIL 11, 2019

Contenidos

1. Introducción
2. Autoría
3. Componentes utilizados
4. Montaje
5. Código
6. Conclusiones
7. Anexo: Manual de funcionamiento
Introducción

El proyecto consiste en un dispensador automático de comida para


mascotas que incluye un reloj para poder programar la dispensa de
comida en un horario determinado. Cuando se ha rellenado el bol, el
dispensador emite un sonido que intenta emular el de una campana
para avisar a la mascota.

Este dispositivo ha sido pensado con el fin de alimentar a la mascota


cuando sus dueños no están en casa durante periodos de tiempo
cortos, como cuando se han ido a trabajar.

En el siguiente vídeo podéis ver la explicación de nuestro código y un


ejemplo de funcionamiento del aparato:

Autoría

Proyecto realizado por el grupo 4 de la asignatura Sistemas


Empotrados y Tiempo Real del curso 2018/2019 en el Campus de
Móstoles de la URJC, formado por:
 Marina Cabeza González
 Patricia Sánchez Fernández
 Celia Velasco Martínez

Componentes utilizados
Los componentes de los que no se indica el precio son aquellos que
ya teníamos o hemos reciclado.

Componentes electrónicos

 Placa de Arduino Uno (proporcionada por el profesor)


 Servomotor (9,99€)
 Pantalla LCD 16×2 con botones de Keyestudio (8,99€)
 RTC DS3231 (7,09€)
 Altavoz 
 Cables de puente hembra a hembra (3,90€)
 Cables macho a macho
 Protoboard

Componentes no electrónicos

 Tubo de PVC (3,08€)


 Codo de PVC (0,52€)
 Botella de agua de 2,5L (0,49€)
 Cuenco de plástico (0,75€)
 Caja de madera
 Bridas y cinta aislante
 Placa de metacrilato
 Clip

Montaje
Diseño inicial

En el diseño inicial teníamos pensado poner una báscula que pesara


la comida necesaria para la mascota. En el diseño final no incluimos
báscula y
la cantidad de comida se mide en el tiempo que se deja abierto el
paso de esta
por el tubo (que se bloquea y desbloquea mediante una pestaña
accionada por el
servomotor). También se disponía de ledes para indicar el estado del
dispensador, que finalmente no se incluyeron al realizar la pantalla
LCD la
misma función.

A continuación, se muestra un boceto inicial del proyecto.


Componentes electrónicos

Hemos montado el circuito de nuestro proyecto como se indica en el


siguiente diagrama de conexiones realizado en la herramienta Fritzing
(puedes hacer click en la imagen para verla más de cerca).

Hemos utilizado una pantalla LCD para mostrar la hora actual y la hora
programada para la dispensa de comida. También se muestra un
mensaje cuando se sirve la comida y otro cuando termina de servirse.
La pantalla cuenta con unos botones que se utilizarán para modificar
la hora de la comida.

El servomotor mueve una trampilla que permite o bloquea el paso del


pienso. Cuando este se haya servido, el altavoz emitirá un sonido que
intenta emular el de una campana.

Para mantener la hora actual se dispone de un chip RTC DS3231 con


una pila integrada.
A continuación, se muestra una imagen de los componentes
electrónicos conectados antes de montarlos en la estructura.
Estructura del dispensador

En cuanto a la estructura del dispensador, hemos reciclado una caja


de madera que hemos pintado de blanco y a la que hemos realizado
los agujeros necesarios para incluir una garrafa de 3L que almacena el
pienso y un bol, ambos comunicados mediante un tubo y un codo de
PVC. La caja incluye una tapa extraíble que permite acceder al resto
de componentes con facilidad.

El tubo de PVC cuenta con una muesca en la que se introduce la


trampilla (una placa de metacrilato) conectada al servomotor que se
ha mencionado anteriormente.

En el siguiente GIF se muestra el funcionamiento del servomotor.

Aquí podemos ver algunas imágenes del proceso de montaje:


Añadimos un trozo de una botella de producto lavavajillas para hacer
una especie de rampa para el pienso y que este no cayese demasiado
rápido desde la botella por el tubo.

Problemas encontrados

En un principio pensamos incluir una báscula para comprobar


la cantidad de pienso que se vertía al bol y también la que quedaba en
la
garrafa, pero nos encontramos con que la construcción de una
báscula para
Arduino casi requería de un proyecto paralelo por su complejidad. Por
lo tanto,
decidimos no incluirla y controlar el pienso dispensado mediante el
tiempo de
apertura de la trampilla controlada por el servomotor.

El principal problema con el que nos hemos encontrado a la


hora de llevar a cabo nuestro proyecto definitivo ha sido el
de almacenar la
hora actual en el RTC. Nos llevó un tiempo dar con la librería
adecuada para el chip que adquirimos y conseguir que el tiempo no se
inicializase cada vez a la hora en la que
se compiló nuestro programa.
Además, tuvimos que añadir raíles para la pestaña manejada por el
servomotor porque se movía descontroladamente. Al principio
pusimos un alambre
para conectar el servo a la placa, pero este se acababa doblando y
terminamos
poniendo un clip más resistente.

Posibles mejoras

Nuestro dispensador es compacto y de un tamaño reducido


porque está pensado para mascotas de talla pequeña o mediana. En
el caso de
necesitarse para una mascota más grande, se podría sacar el
cuenco fuera de la
caja, alargar el tubo y sujetar el cuenco a la caja mediante un soporte
para
que no se mueva.
Otra posible mejora sería incluir una báscula bajo el cuenco
para comprobar si la mascota ha comido o si por el contrario queda
pienso en el
cuenco. Incluso se podría utilizar IoT y enviar un mensaje al móvil del
dueño
indicándole que su mascota no se ha terminado el pienso.
El proyecto también se podría mejorar añadiendo una opción para
poder
cambiar la hora actual sin tener que cargar en la placa el sketch para
inicializar la hora en el RTC, lo que convertiría el producto en algo más
usable para personas sin conocimientos de informática.

Código

La explicación de nuestro código podéis encontrarla en los


comentarios dentro del mismo y en el vídeo que se incluye más arriba.
El código lo hemos implementado y subido a la placa mediante el IDE
oficial de Arduino para Windows.

Librerías utilizadas

Hemos utilizado las librerías Arduino.h, LiquidCrystal.h, Wire.h y


Servo.h, incluidas por defecto en el IDE de Arduino, y también la
librería RTClib.h, que puede encontrarse en el siguiente repositorio de
GitHub: https://github.com/adafruit/RTClib.

Para utilizar esta librería, debes descargarla y guardarla en el


directorio Arduino/libraries, que se crea al instalar el IDE de Arduino y
seguramente se encuentre en tu carpeta Documentos.

Sketch principal
1 #include <Arduino.h>
2 #include <LiquidCrystal.h> /* Library for the LCD */
3
4 #include <Wire.h>
5 #include "RTClib.h"
6
7 #include <Servo.h>
8
9 /* Initialize the library with interface pins numbers: */
10 LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
11 int val;
12
13 /* Speaker (buzzer): */
14 int speakerPin = 13;
15
16 /* Real time clock: */
17 RTC_DS3231 rtc;
18
19 /* Servo: */
20 Servo myservo;
21 int pos = 0; /* Variable to store the servo position */
22 int servoPin = 10;
23
24 DateTime now;
25 byte hour, minute;
26 String h, m;
27
28 int feedHour = 14;
29 int feedMin = 0;
30 boolean foodTime = true;
31
32 void setup() {
33
34 /* Set speaker pin as an output pin: */
35 pinMode(speakerPin, OUTPUT);
36 /* Set up LCD's number of columns and rows: */
37 lcd.begin(16, 2);
38 /* Start RTC: */
39 rtc.begin();
40
41 }
42
43 void loop() {
44
45 now = rtc.now();
46 printTime(now);
47
48 /* LCD buttons are all connected to A0 pin with this values:
49 * 0-50: UP
50 * 50-150: RIGHT
51 * 150-300: DOWN
52 * 300-500: LEFT
53 * 500-750: SELECT
54 */
55 val = analogRead(A0);
56 if ((val >= 500) && (val <= 750)) { // SELECT
57 setFeedHour();
58 delay(1000);
59 }
60
61 now = rtc.now();
62 printTime(now);
63
64 delay(2000);
65
66 if ((feedHour == now.hour()) && (feedMin == now.minute())
67 && foodTime) {
68 feed();
69 }
70
71 /* We use 'foodTime' so food doesn't get served twice
72 * if the feed routine ends in less than a minute. */
73 if (feedMin != now.minute()) {
74 foodTime = true;
75 }
76
77 }
78
79 void feed() {
80
81 lcd.clear();
82 lcd.setCursor(0, 0);
83 lcd.print("Sirviendo comida");
84
85 /* Food gets served: */
86 /* Attach servo on pin 10 (We attach servo only when
87 * we need it and detach it afterwards to stop it
88 * from shaking) */
89 myservo.attach(servoPin);
90 /* Servo moves to open lid for food to fall through.
91 * 'pos' goes from 0 to 180 degrees in steps of 1 degree
92 * and then gets written to servo*/
93 for (pos = 0; pos <= 120; pos += 1) {
94 myservo.write(pos);
95 /* Wait 15ms for the servo to reach the position */
96 delay(15);
97 }
98 delay(1000);
99 /* Go back from 180 to 0 degrees to close the lid: */
100 for (pos = 120; pos >= 0; pos -= 1) {
101 myservo.write(pos);
102 delay(15);
103 }
104 delay(3000);
105 /* Detach servo: */
106 myservo.detach();
107
108 bell();
109
110 foodTime = false;
111
112 }
113
114 void bell() {
115
116 for (int i=0; i<6; i++) {
117
118 /* Bell sound: */
119 tone(speakerPin, 1915);
120 delay(700);
121 tone(speakerPin, 1700);
122 delay(700);
123 tone(speakerPin, 1519);
124 delay(700);
125 noTone(speakerPin);
126
127 lcd.clear();
128 lcd.setCursor(0, 0);
129 lcd.print("Hora de la");
130 lcd.setCursor(0, 1);
131 lcd.print("comida!!!!");
132
133 delay(5000);
134
135 now = rtc.now();
136 printTime(now);
137
138 delay(5000);
139
140 }
141
142 }
143
144 /* Prints actual time and feed time.
145 * If hour or minute is just one digit, a zero
146 * will be added for formatting purposes */
147 void printTime(DateTime t) {
148
149 /* Actual time */
150 lcd.setCursor(0, 0);
151 lcd.print("H. actual: ");
152 hour = t.hour();
153 if (hour < 10) {
154 h = "0" + String(hour);
155 } else {
156 h = String(hour);
157 }
158 lcd.print(h);
159 lcd.print(':');
160 minute = t.minute();
161 if (minute < 10) {
162 m = "0" + String(minute);
163 } else {
164 m = String(minute);
165 }
166 lcd.print(m);
167
168 /* Feed hour */
169 lcd.setCursor(0, 1);
170 lcd.print("H. comida: ");
171 if (feedHour < 10) {
172 h = "0" + String(feedHour);
173 } else {
174 h = String(feedHour);
175 }
176 lcd.print(h);
177 lcd.print(':');
178 if (feedMin < 10) {
179 m = "0" + String(feedMin);
180 } else {
181 m = String(feedMin);
182 }
183 lcd.print(m);
184
185 return;
186
187 }
188
189 void setFeedHour() {
190
191 lcd.clear();
192 lcd.setCursor(0, 0);
193 lcd.print("Cambiar hora de");
194 lcd.setCursor(0, 1);
195 lcd.print("comida: ");
196
197 int hourAux = feedHour;
198
199 while(true) {
200
201 lcd.setCursor(8, 1);
202 if (hourAux < 10) {
203 lcd.print("0");
204 lcd.print(hourAux);
205 } else {
206 lcd.print(hourAux);
207 }
208 lcd.setCursor(10, 1);
209 lcd.print(':');
210 lcd.setCursor(11, 1);
211 if (feedMin < 10) {
212 m = "0" + String(feedMin);
213 } else {
214 m = String(feedMin);
215 }
216 lcd.print(m);
217
218 delay(200);
219
220 /* We check which button is being pressed */
221 val=analogRead(A0);
222 if ((val>=50) && (val<=150)) { /* UP + 1 hour */
223 hourAux = (hourAux + 1) % 24;
224 } else if ((val>=150) && (val<=300)) { /* DOWN - 1 hour */
225 hourAux = hourAux - 1;
226 if (hourAux < 0) {
227 hourAux = 23;
228 }
229 }
230 else if ((val>=300)&&(val<=500)) { /* LEFT cancel */
231 break;
232 }
233 if ((val>=0)&&(val<=50)) { /* RIGHT save */
234 feedHour = hourAux;
235 setFeedMin();
236 break;
237 }
238
239 }
240
241 return;
242
243 }
244
245 void setFeedMin() {
246
247 lcd.clear();
248 lcd.setCursor(0, 0);
249 lcd.print("Cambiar min. de");
250 lcd.setCursor(0, 1);
251 lcd.print("comida: ");
252
253 int minAux = feedMin;
254
255 while(true) {
256
lcd.setCursor(8, 1);
257
if (feedHour < 10) {
258
h = "0" + String(feedHour);
259
} else {
260
h = String(feedHour);
261
}
262
lcd.print(h);
263
lcd.setCursor(10, 1);
264
lcd.print(':');
265
lcd.setCursor(11, 1);
266
if (minAux < 10) {
267
m = "0" + String(minAux);
268
} else {
269
m = String(minAux);
270
}
271
lcd.print(m);
272
273
delay(200);
274
275
276 /* We check which button is being pressed */
val = analogRead(A0);
277
if((val>=50) && (val<=150)) { /* UP + 1 min */
278
minAux = (minAux + 1) % 60;
279
} else if((val>=150) && (val<=300)) { /* DOWN - 1 min */
280
minAux = minAux - 1;
281
if (minAux < 0) {
282
minAux = 59;
283
}
284
} else if((val>=300) && (val<=500)) { /* LEFT cancel */
285
break;
286
} else if((val>=500) &&( val<=750)) { /* SELECT save */
287
feedMin = minAux;
288
break;
289
}
290
291
}
292
293
return;
294
295
}
296

Sketch auxiliar para poner el reloj en hora

Este código solo necesita ejecutarse una vez para inicializar el chip
RTC con la hora actual. El chip RTC mantendrá la hora gracias a la
pila que lleva incorporada.
#include <Wire.h>
1
#include "RTClib.h"
2
3
RTC_DS3231 rtc;
4
5
void setup() {
6
7
rtc.begin();
8
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
9
10
11 /* The rest of the code is not necessary to set the time,
12 * we're just making sure it was set correctly: */
Serial.begin(9600);
13
14
DateTime now = rtc.now();
15
printDate(now);
16
17
}
18
19
void loop() {
20
21
}
22
23
void printDate(DateTime date) {
24
25
Serial.print(date.year(), DEC);
26
Serial.print('/');
27
Serial.print(date.month(), DEC);
28
Serial.print('/');
29
Serial.print(date.day(), DEC);
30
Serial.print(" ");
31
Serial.print(date.hour(), DEC);
32
Serial.print(':');
33
Serial.print(date.minute(), DEC);
34
Serial.print(':');
35
Serial.print(date.second(), DEC);
36
Serial.println();
37
38
}
39

Conclusiones

Este proyecto nos ha servido para familiarizarnos con Arduino y su


entorno de desarrollo, así como todas las posibilidades que ofrece.
En cuanto al precio del dispensador, el hecho de haberlo construido
nosotras mismas no lo ha reducido respecto a adquirir uno similar en
una tienda o en Internet. Esto se debe a la baja estandarización del
producto. 
Este proyecto también nos ha servido como experiencia para saber
cómo es un proyecto real en el ámbito laboral.

Anexo: Manual de funcionamiento

Este dispositivo es un dispensador automático de comida de


mascotas que incorpora un reloj programable. Para utilizar este
producto siga
los siguientes pasos:
1. Enchufe el producto a la corriente.
2. Se iluminará la pantalla, en la que aparecerá la hora actual y la
hora de la comida predeterminada (las 14:00).
3. Para modificar dicha hora pulse el botón SELECT durante 1-2
segundos.
4. Una vez pulsado aparecerá un mensaje pidiendo el cambio de
hora. Mediante los botones UP y DOWN puede incrementar o
disminuir la hora.
5. Cuando haya modificado la hora pulse RIGHT para cambiar los
minutos igual que en el paso 4.
6. Puede cancelar cualquiera de estas acciones pulsando LEFT.
7. Para guardar la nueva hora de la comida pulse SELECT.
8. Espere a la hora programada y el dispensador echará la comida
para su mascota.
9. Recuerde rellenar el dispositivo con el pienso favorito de su
mascota.

También podría gustarte