WorthEat
Nunca desperdiciar comida fue tan difícil.
MOTIVACIÓN
Al recibir las instrucciones de la práctica y conocidos los grados de libertad, planteamos una serie de objetivos que el equipo esperaba de este proyecto.
En primer lugar buscábamos un proyecto poco común, algo que no tuviera mucha audiencia para exponer nuestra mente ingenieril y tomar nuestras propias decisiones potenciando así ese aspecto de nuestra formación. En segundo lugar, buscábamos en el proyecto una aplicación real, en el sentido de que el dispositivo fuera usable y realmente útil para la vida cotidiana. Y en último lugar, bien precedido por el segundo objetivo, buscábamos ayudar a la sociedad en la medida de lo posible combatiendo alguno de los problemas sobrevenidos planteados en la Agenda 2030 por Naciones Unidas.
Para alcanzar el objetivo de combatir un problema, pensamos que donde más podríamos calar en la sociedad es con un tema donde todos estamos concienciados, donde todo el mundo pudiera poner su grano de arena, pero a la vez del que no se habla tanto, el desperdicio alimentario. Y es que ¿a quién no se le ha caducado alguna vez el yogur del fondo de la nevera? Es entonces que necesitábamos montar un dispositivo de alarma y tracking de los alimentos así como su fecha de caducidad.
Pero para que realmente fuese usable y tuviese éxito en la sociedad, necesitábamos dar con una técnica que supusiera el mínimo esfuerzo para el usuario a la hora de registrar los alimentos, y un dispositivo de comunicación que todo el mundo pudiera consultar cuando fuera necesario y de manera sencilla.
¿Qué fue lo que se nos ocurrió?
Se nos ocurrió que el arduino pudiera de alguna manera registrar los alimentos que transcurrieran por casa y hacérselo llegar al usuario con lo que todos consultamos varias veces al día, el teléfono móvil. En definitiva una aplicación de alerta que entre otras funcionalidades, nos avisará de los próximos alimentos caducos.
A continuación explicamos detalladamente como lo hemos resuelto especificando la tecnología usada, justificando nuestras decisiones, el proceso, el software y todo lo necesario para haber llegado al prototipo inicial de WorthEat.
DESPERDICIO ALIMENTARIO EN DATOS
“En la UE, se generan anualmente alrededor de 88 millones de toneladas de desperdicio de alimentos con costos asociados estimados en 143 mil millones de euros (FUSIONS, 2016). Si bien se estima que el 20 % del total de alimentos producidos se pierde o se desperdicia, 33 millones de personas no pueden permitirse una comida de calidad cada dos días (Eurostat, 2018).
A nivel mundial, aproximadamente un tercio de todos los alimentos producidos para el consumo humano se pierden o desperdician (FAO, 2011).
Según el índice de desperdicio de alimentos 2021 del PNUMA, en 2019 se generaron alrededor de 931 millones de toneladas de desperdicio de alimentos, de los cuales el 61 % proviene de los hogares, el 26 % del servicio de alimentos y el 13 % del comercio minorista. Del mismo modo, en la UE, los hogares generan más de la mitad del desperdicio total de alimentos en la UE (47 millones de toneladas) y el 70 % del desperdicio de alimentos se origina en el hogar, el servicio de alimentos y el comercio minorista […]”.
TECNOLOGÍA
El primer paso suponía el reto de cómo registrar los alimentos para que fuera sencillo para el usuario inicial.
Investigando la forma en la que supermercados o grandes comercios como Decathlon son capaces de identificar objetos y su precio únicamente poniéndolos en la cesta de pago dimos con la clave, RFID.
El RFID en inglés (´Radio Frequency Identification´) es un medio de comunicación entre objetos por medio de ondas de radio. El proceso consiste en 2 principales actores, por un lado tenemos el lector (transceptor) RFID que es en realidad un emisor-receptor, se encarga de mandar estas ondas continuamente y esperando que reboten así en el segundo actor, los tags (transpondedores). Éstas mediante unas tecnologías inalámbricas para almacenar información hacen rebotar la onda con dicha información, la cual es recogida de nuevo por el lector.
La maravilla del RFID radica en la posibilidad de almacenar información en un dispositivo físico, tag pasivo, sin estar sujeto a ningún tipo de alimentación para ello y responder cuando sea requerido correctamente.
Existen tipos de tags y mientras una prescinde de energía la otra no, pero es únicamente una cuestión de que los tags activos (con alimentación) pueden alcanzar longitudes mayores, de unos 100 m, mientras que los pasivos (sin alimentación) alcanzan hasta 25 m de distancia. Todo ello dependiendo del lector. También cabe destacar que estas tags son re-escribibles un número casi ilimitado de veces.
El RFID llevado a distancias cortas se conoce como NFC (Near Field Communication) y está presente en infinidad de casos de uso diarios, pago con tarjetas, accesos restringidos por identificador, abono transportes…
El lector que nosotros escogimos es un lector arduino por debajo de 60€ (concretamente 10€) que mejor distancia otorga: el PN5180.
Un conocimiento compartido que añadiremos a esta memoria, es que es muy trabajoso (si no imposible) con los lectores arduinos detectar dos tags simultáneamente y, en ninguno de los casos que hayamos podido investigar, se supera la barrera de lectura de cuatro tags simultáneos.
Una noticia agridulce respecto de los problemas anteriores es que el dinero lo puede comprar prácticamente todo y, por unos 80-100€, te puedes hacer con un magnífico lector RFID que llega a largas distancias y detecta varios objetos a la vez.
Como dato, la distancia va en función de la frecuencia de onda que emita el transceptor, aquí van algunos datos:
- Menos de 125 – 140 KHz kHz, menos de 8-10 cm
- 13,56 MHz hasta 1,5 metros
- 433 Mhz, 868 – 915 MHz 10-12 metros
Aunque insistimos, depende del lector, no fiarse del fabricante.
Inicialmente se nos propuso una placa Arduino UNO con la que nos funcionaba bien en primera instancia, pero supuso 2 problemas: Por un lado los pines del arduino UNO trabajan a 5V mientras que nuestro PN5180 trabaja a 3,3V (aunque se puede comprar un shifter de voltaje) y, por otro lado, el Arduino UNO no dispone de módulo WiFi con el que queríamos mandar información a nuestra API.
Casi como caído del cielo dimos con una placa idónea, el ESP32 Devkit C.
Los pines de esta placa trabajan a 3,3V y por si fuera poco tiene módulo Wifi y Bluetooth incorporado. Pero esta placa ha sido una caja de sorpresas debido a las diferentes funcionalidades que venían “de regalo”, como su modo deep-sleep que gasta 10 microamperios, o su reloj interno de 240MHz (15 veces más rápido que un Arduino UNO) y por supuesto compatible con Arduino IDE.
REPARTO DE TAREAS Y PASOS SEGUIDOS
Para la realización del proyecto hemos seguido la metodología del camino crítico. Definimos en un primer lugar los objetivos y dividimos establecimos las tareas que había que hacer para cumplirlo. No hemos divido estrictamente las tareas ya que nos íbamos organizando según salían los problemas.
CASOS DE USO
El usuario de WorthEat llega de la compra con unos productos que tienen tags RFID con los datos de la fecha de caducidad contenidos en los tags. Escanea los productos uno a uno y salta la luz verde para confirmar que el usuario tiene el producto en la aplicación móvil . Ahora solo tendrá que esperar a que la aplicación le avise si su fecha de caducidad esta próxima.
Cuando el usuario acaba un producto y quiere reciclarlo deberá volver a escanear el producto, el dispositivo emitirá una luz roja a modo de confirmación que el producto ya no esta en la aplicación.
El usuario recibirá un aviso de que vuelva a escanear el producto con un triple parpadeo amarillo y sonido para indicar al usuario que vuelva a repetir la acción en caso de fallo en el proceso de guardar/eliminar el producto.
COMPONENTES Y CIRCUITO
Para llevar a cabo el proyecto hemos usado el sensor PN5180 mencionado anteriormente, tres diodos LED y un buzzer que notificarán el estado del sistema.
En primer lugar, hay que hablar de la pieza central del proyecto, la placa ESP32 Devkit C, es un SoC que trabaja a 3,3V y contiene un módulo de WiFi y de Bluetooth. El ESP32 tiene un consumo bajo ya que puede configurarse en varios modos en base a las necesidades de cada momento (Active mode, Modem-sleep mode, Light-sleep mode, Deep-sleep mode y Hibernation mode).
La placa tiene 38 pines, de los cuales usamos 13 (5,16,17,18,19,23,25,26,32,33, 3.3V, 5V y GRND). Nuestro esquema de conexiones es el siguiente:
Por otro lado, el PN5180 es un sensor de lectura y escritura que tiene compatibilidad con las ISO 14443,15693, 18092, 21481, 18000. Tiene una tasa de transferencia de hasta 7 Mbit/s. Los pines necesarios para desarrollar el proyecto fueron:
El 5V, ya que aunque el sensor trabaja a un voltaje de 3,3V se necesitan 5V para alimentarlo.
El 3,3V, que sirve para proporcionar voltaje a los pines.
El Reset.
El NSS (“Not slave select”) cuya función es seleccionar un dispositivo esclavo (se ponen en un voltaje bajo cuando se transfieren los datos entre el ESP32 y el sensor).
El MOSI (“Master out Slave in”), que sirve para indicar que se manda datos desde el maestro al esclavo.
El MISO (“Master in Slave out”), para mandar datos desde el esclavo al maestro.
El SCK, para sincronizar ambos relojes (es importante a la hora de mandar los datos que ambos relojes están sincronizados, ya que en todo momento tienen que darse cuenta de si las señales MOSI o MISO que son los dos bits más significativos están encendidas).
El BUSY, que indica si está ocupado para que no envíen al PN5180 más datos, esto es útil cuando tienes una estructura con más de un sensor.
Finalmente, el GRND.
En cuanto a la otra parte del circuito, la más simple, debemos comentar que tenemos tres LEDs distintos y un buzzer conectados cada uno a un pin distinto. El LED verde está asociado al pin 25, el rojo al 26 y el amarillo al 32, estando el buzzer conectado al 33. Debemos mencionar que los LEDs no están siendo protegidos por ningún tipo de resistencia; esto es voluntario. En la teoría sabíamos que debíamos poner una pequeña resistencia en serie, pero en la práctica nos dimos cuenta que al utilizar la resistencia más pequeña de nuestro kit, los LEDs apenas brillaban. Esto se debe a que el ESP32 trabaja a 3,3V a diferencia de la FPGA que nos venía en el pack entregado en clase, por lo que decidimos no poner resistencia adicional y confiar en la que tienen intrínseca los pines.
CÓDIGO
Debido a que tenemos el código comentado de forma secuencial y específica en la práctica, hemos decidido explicar aquí con mayor profundidad aquellos aspectos que no hemos podido recoger bien en los comentarios.
Para llevar a cabo la lectura de la etiqueta RFID y su posterior envío al servidor hemos usado dos librerías que comentaremos a continuación:
Las primeras librerías son las que engloban el funcionamiento del sensor RFID (PN5180.h y PN5180ISO15693.h), centrándose una en el sensor y la otra en la comunicación con los tags. Durante la ejecución del proyecto, hemos usado las siguientes funciones:
- getInventory(uint8_t *uid), esta función se encarga de cargar en el array de enteros uid los 8 bytes que forman el uid de la tarjeta. Estos bytes se usan para identificar la tarjeta y saber que se está leyendo correctamente. Lo que hace esta función internamente es llamar a otra función, issueISO15693Command(uint8_t *cmd, uint8_t cmdLen, uint8_t **resultPtr),que se encarga de leer los registros de la tarjeta.
- getSystemInfo(uint8_t *uid, uint8_t *blockSize, uint8_t *numBlocks), esta función se encarga de leer la estructura de la pegatina que se intenta reconocer, obteniendo de aquí el número de bloques que tiene la tarjeta y el tamaño de cada bloque. A raíz de esto podremos ir leyendo la información contenida en la tarjeta bloque por bloque.
- readSingleBlock(uint8_t *uid, uint8_t blockNo, uint8_t *blockData, uint8_t blockSize), esta función se encarga de leer cada bloque del tag.
Las 3 funciones hacen uso de la función issueISO15693Command que devuelve la información de la tarjeta y también un código de error en caso de fallo.
De forma adicional, decidimos aprovechar el módulo WIFI para enviar los productos leídos por el sensor a una API que más tarde se encarga de guardarlos en una base de datos y servirlos en la aplicación móvil.
Para ello, usamos las siguientes librerías (WiFi.h, WiFiClient.h y HTTPClient.h). A continuación vamos a explicar cómo hemos procedido para mandar todas las señales:
- En primer lugar, inicializamos el Wifi con la función WiFi.begin(ssid, password) donde el ssid es el nombre de la wifi y la password, la contraseña.
- Posteriormente, nos cercioramos de que el Wifi se ha conectado correctamente con la función WiFi.status(), también hemos añadido información adicional como la ip asignada al dispositivo usando WiFi.localIP().
- En la función loop, verificamos constantemente que la wifi siga conectada. Después de leer el contenido de la etiqueta realizamos un postRequest().
En esta función enviamos un JSON al servidor haciendo uso de la función http.POST(request) y recibimos el código de respuesta devuelto por el servidor. La API es la encargada de saber si un objeto ya ha sido procesado y por tanto hay que eliminarlo de la base de datos o simplemente incluirlo. Por ello la API responderá con un código de error si se ha incluido el ítem y usará otro en caso contrario.
El apartado final del proyecto ha sido comunicar el estado del sistema al usuario. Para ello hemos destacado 3 estados: introducido, eliminado y error. Los hemos representado con 3 leds, verde, rojo y amarillo, respectivamente. Adicionalmente hemos introducido un buzzer que emite un sonido cuando se ha recibido la respuesta del servidor.
Cabe mencionar que la función tone(pin,frequency,duration) ha sido cambiada a tone(pin,frequency,duration,led) para añadir un parámetro más que se encarga de que el LED asociado brille el mismo tiempo que está sonando el buzzer.
Adicionalmente, hemos construido una API Rest con NodeJS, la api recibe las peticiones enviadas por el sistema y las almacena en una base de datos (MySQL). Además, la API sirve los datos a nuestra aplicación programada en IONIC, desde aquí se podría construir una lógica para que te lleguen notificaciones sobre cuándo van a caducar ciertos productos o qué recetas puedo hacer con los productos que tengo en la despensa.
PROBLEMAS ENCONTRADOS Y CÓMO SOLUCIONARLOS
El primer problema con el que nos encontramos fue que no todos los fabricantes indican la ISO que utilizan. Esto fue un gran inconveniente ya que cada ISO funciona a una determinada frecuencia, en particular la ISO15693 trabaja a 13.56MHz, por lo que habrá que indicarle al sensor que lea esa frecuencia. Desde un primer momento queríamos trabajar con las pegatinas de la ISO15693 ya que ofrecen un mayor alcance frente a otras como la ISO14443 (al menos en la práctica). Afortunadamente, en el kit del sensor RFID venían ambas y pudimos probarlas.
El segundo y mayor problema que nos encontramos fue la falta de documentación en internet, si bien es cierto que en la documentación del sensor PN5180 relata cómo hay que proceder para realizar la lectura de una etiqueta:
Para el conocimiento que teníamos en un comienzo era resolver un rompecabezas imposible:
La imagen anterior muestra los pasos que hay que seguir para leer una única etiqueta, sin embargo con esto únicamente conseguimos el identificador de la etiqueta ni si quiera los elementos que están escritos en ella.
Afortunadamente, encontramos una librería en internet que permitía la ejecución de estos procedimientos en C++. https://github.com/ATrappmann/PN5180-Library
Otro gran inconveniente que tuvimos, fue la diferencia que había entre las especificaciones que el fabricante facilitaba y la cruda realidad. Según el fabricante, el PN5180 tenía un rango de 50cm, pero una vez probado, el rango no superaba los 7 u 8 cm. Nuestro proyecto estaba pensado en un principio para leer varios tags a la vez, pero este problema sumado a la dificultad del software del PN5180, hizo que descartaramos esta implementación.