6 7 2 8 72 9 # % 5 3 5 - # * : ; : - 1 < - 1 ... · el voltaje de alimentación externa: se...
Post on 24-Mar-2020
2 Views
Preview:
TRANSCRIPT
�������� ����� ����������������������������������������
����� ���������������������������������������� ���
���� !"#$ #% &���'()*+,-./*#01#2+*3*4567�28729#%535-#*:;:-1<-1#=*+*#/*#1<-+1>*#01#?5++1:=5<01<?;*#1<5@;?;<*:#2A-./5#01/#-+*3*45##BCDDE65;<-1+#6:1.0F<;G5#01#;<-1>+*<-1:H�IJ���#K���##L����#M��N��O�##P���������#Q�����JN���#R��������SS�T���#U����#��#V�������J�
POSTBOT: Robot asistente para la entrega de correspondencia en oficinas
Resumen
Con el fin de facilitar la entrega de correspondencia en una oficina, se creó un prototipo
de robot que conjunta un seguidor de línea con un elevador. El autómata se conecta a
una computadora que cuenta con un sistema que implementa un algoritmo de
optimización de rutas. Así, mediante una comunicación inalámbrica la computadora
envía al robot una serie de pasos a seguir para que transporte la correspondencia, a
través de la oficina por el camino más efectivo. El dispositivo elevador fue diseñado
para facilitar el alcance de la correspondencia, no obstante el robot es pequeño para
tener un mejor desplazamiento por los espacios. Cabe señalar, que el software
implementado en el arduino fue desarrollado en el lenguaje de programación C++.
Por otra parte, la interfaz con el usuario se desarrolló en Javascript lo que permite su
fácil implementación, ya que no requiere de una instalación de software extra en la
computadora, más allá de un navegador.
Introducción
La tecnología avanza a pasos agigantados en nuestra época y es importante saber
usarla a nuestro favor; cada vez más la intervención humana en la realización de
acciones iterativas, ha sido reemplazada por el trabajo de máquinas que realizan desde
labores simples, hasta aquellos con alto grado de complejidad, siempre con el objetivo
de facilitar la vida de las personas.
Este trabajo propone el diseño y construcción de un robot que pueda ser utilizado en la
entrega de correspondencia dentro de una oficina, trabajo que si bien resulta repetitivo,
tiene su grado de complejidad si se desea que se realice con las rutas más cortas para
eficientar los tiempos.
1
Marco Teórico
Robot
La Asociación Francesa de Normalización (AFNOR) dene un robot como “un
manipulador automático servocontrolado, reprogramable, polivalente, capaz de
posicionar y orientar piezas, útiles o dispositivos especiales, siguiendo trayectorias
variables reprogramables, para la ejecución de tareas variadas; su unidad de control
incluye un dispositivo de memoria y ocasionalmente de percepción del entorno;
normalmente su uso es el de realizar una tarea de manera cíclica pudiéndose adaptar a
otra sin cambios permanentes en su material” (Barrientos, A., Peñín, L. y Balaguer, C.,
2007).
Así, resulta fundamental el hecho de que un robot se emplea en un entorno real con el
que establece una conexión “inteligente” entre percepción y acción por medio de
sensores que aportan información para la resolución de un problema.
Existen distintos tipos de robots, sin embargo, los que resultan más importantes para
este trabajo de acuerdo a sus características son los siguientes:
● Robot seguidor de línea
Es un dispositivo sencillo cuya única misión es, mediante el uso de sensores y
motores, seguir un camino denotado en forma de una línea que contrasta con el
resto del entorno. Dicha línea normalmente es blanca en fondo negro o negra en
un fondo blanco (De Frutos, M., 2013).
● Robot de servicio
Es un tipo de robot que cuenta con la capacidad de asistir a los seres humanos
en entornos de complejidad baja o moderada. Su objetivo es simplificar el trabajo
humano. Debe realizar acciones tales como: moverse evitando obstáculos, llevar
2
y entregar objetos, etc. También tienen que contar con la capacidad de planear
conductas y tomar decisiones (Pineda, 2017).
Estructura y funcionamiento de una computadora
De acuerdo con Vasconcelos (2011), una computadora es una máquina capaz de
procesar y transformar gran cantidad de datos rápidamente. Cuando se trata de una
computadora digital, estas acciones las realiza a través del trabajo con señales que
saltan entre un valor bajo y uno alto, sin pasar por valores intermedios.
A los unos y ceros que manejan las computadoras digitales se les conoce como bits
(Binary DigiT) y constituyen la unidad mínima de información. Un byte es una
agrupación de bits consecutivos que suele representar un caracter.
De manera general, el funcionamiento de las computadoras digitales se se puede
describir mediante el modelo de Von Neumann (Vasconcelos, 2011), el cual cuenta por
cinco partes:
1. Unidad de entrada: Parte de la computadora que recibe información del exterior y la
conduce hacia la sección de procesamiento.
2. Unidad de salida: Parte que permite que los datos procesados salgan de la
computadora.
3. Unidad de memoria: Medio de almacenamiento de datos de entrada, datos
procesados e instrucciones.
4. Unidad de control: Sección de la computadora que dirige y coordina los procesos a
realizar.
5. Unidad aritmética y lógica: Parte encargada de realizar las operaciones.
Lo anterior corresponde a un diseño teórico, por lo que su implementación práctica
corresponde a una serie de componentes electrónicos que aplican la lógica booleana y
3
la aritmética binaria. Por ejemplo, la unidad aritmética lógica y la unidad de control
están en un mismo componente conocido como procesador.
El procesador está integrado por cuatro bloques de circuitos especializados:
1. Unidad de control: Circuito que decodifica la instrucción recibida y activa o desactiva
los demás bloques del procesador para efectuar la instrucción.
2. Unidad aritmética-lógica (ALU): Circuito que efectúa las operaciones aritméticas,
comparaciones y operaciones de lógica booleana.
3. Registros: Colección de circuitos que guardan los datos necesarios para realizar las
operaciones requeridas por la ALU.
4. Contador de programa: Registro especial que usa la unidad de control para ubicar en
qué parte de la memoria se encuentra la siguiente instrucción a ser ejecutada. Una vez
que la instrucción se realiza, el procesador busca en la memoria otra instrucción
utilizando como referencia la posición que indica el contador del programa. Dicho
contador se actualiza automáticamente para que en el siguiente ciclo detecte la nueva
instrucción.
Para sincronizar el trabajo de los diferentes bloques del procesador se utiliza un reloj
electrónico que emite pulsos a intervalos constantes, su trabajo se mide en hertz. Dicho
reloj también sincroniza el trabajo hacia y desde el exterior.
Por su parte, los dispositivos de entrada y salida, según Vasconcelos (2011), son
aparatos que trabajan junto con la computadora sin formar parte de su arquitectura
básica. En general, le permiten comunicación al exterior o le proporcionan servicios
adicionales. Los dispositivos de entrada permiten al usuario o a otro sistema de
cómputo enviar información a la computadora; mientras que los de salida envían al
usuario o a otros sistemas, los resultados de los procesos efectuados.
Microcontrolador Arduino
4
Angulo y Hernández (2011) consideran que un microcontrolador es un computador
completo dentro de un circuito integrado; aunado a la CPU o microprocesador, contiene
las memorias, las unidades de entrada/salida y otros recursos complementarios.
Es importante señalar que en este proyecto el microcontrolador arduino es lo que nos
permitió desarrollar el robot, el cual se convirtió en un dispositivo de salida con respecto
a la computadora.
Según la página oficial de arduino (2019), Arduino Uno es una plataforma de hardware
libre, basada en una placa con un microcontrolador. El microcontrolador es del
fabricante Atmel y usa el modelo Atmega328.
Las características principales de arduino son:
El voltaje de alimentación externa: se encuentra en un rango de 7 a 12V, pero el voltaje
con que trabaja el microcontrolador es de 5V. La frecuencia de trabajo del procesador
de dicho microcontrolador es de 16 MHz. Tiene una memoria flash para almacenar un
programa con una capacidad de 32 Kbytes. La comunicación con el exterior es a través
de 6 entradas o puertos analógicos y 14 puertos digitales que pueden ser configurados
como entradas o salidas, siendo así un total de 20 puertos E/S (Crespo, E., 2016).
Las entradas analógicas: se caracterizan por leer valores de voltaje de 0 a 5 Volts con
una resolución de 1024 (10 bits). Por lo que es capaz de detectar variaciones en el nivel
de la señal de entrada de casi 5 mV (Crespo, E., 2016).
Los puertos digitales sólo tienen dos estados: 0 lógico o 1 lógico; en términos de la
electrónica de la tarjeta arduino 0 lógico es de 0 a 0.2 Volts y 1 lógico es de 4.5 a 5,
Volts que puede ser como voltaje de entrada o de salida de la tarjeta. Los puertos
digitales corresponden a los pines del 0 al 13 marcados en la tarjeta (Crespo, E., 2016).
Componentes eléctricos
Un circuito eléctrico es un arreglo de componentes conectados entre sí, que permite el
flujo de electrones denominado corriente eléctrica bajo la fuerza de un voltaje. Tal como
lo explica Serway Raymond y Beichner (1999), el voltaje, tensión o diferencia de
5
potencial es la fuerza que ejerce una fuente de suministro de energía eléctrica o fuerza
electromotriz (FEM) sobre las cargas eléctricas o electrones para moverse en un
circuito eléctrico cerrado.
La corriente eléctrica consiste en la circulación de cargas o electrones a través de un
conductor en un circuito eléctrico cerrado, que se mueven de la terminal negativa a la
positiva de la fuente de suministro de fuerza electromotriz (FEM).
A continuación se definen los componentes eléctricos que se utilizaron en el desarrollo
de este proyecto:
● Motores reductores rectos (modelo AR-DCMOTOR)
Motor de corriente directa diseñado para ser utilizado en aplicaciones integradas
que requieren movimiento. Cuenta con un motor ensamblado directamente a un
sistema de engranajes, esto permite al motor reducir o aumentar su velocidad
dependiendo de la configuración de los engranes que se usen. Se pueden
alimentar desde 3 hasta 6 Vcc (Rodríguez L. 2019).
● Puente H
El puente H es un circuito electrónico que permite que un motor eléctrico DC
gire en ambos sentidos.
Se construyen con 4 interruptores (mecánicos o mediante
transistores). Cuando los interruptores S1 y S4 están
cerrados (S2 y S3 abiertos) se aplica una tensión haciendo
girar el motor en un sentido. Si se abren los interruptores S1 y S4 (cerrando S2 y
S3), el voltaje se invierte en las terminales del motor, permitiendo el giro en
sentido inverso (Frank Mecafenix, 2017).
● Sensores
6
Un sensor es un dispositivo capaz de detectar magnitudes físicas o químicas,
llamadas variables de instrumentación (temperatura, intensidad lumínica,
distancia, aceleración, inclinación, desplazamiento, presión, fuerza, torsión,
humedad, movimiento, pH, etc), y transformarlas en variables eléctricas
(Jecrespom, 2016).
Éstos se pueden clasificar en función de los datos de salida en:
○ Digitales
○ Analógicos
Sensor CNY70
El dispositivo CNY70 es un sensor óptico infrarrojo capaz de detectar colores de
objetos y superficies. Cuenta con un rango de alcance menor a 5 mm y,
dependiendo de la cantidad de luz recibida, el dispositivo envía una señal de
retorno a arduino.
El sensor está conformado por un emisor de radiación infrarroja (fotodiodo), el
cual emite un haz de luz; y un receptor (fototransistor) que se encarga de recibir
ese haz cuando se refleja sobre alguna superficie u objeto (Tecnosefarad, 2014).
Tarjeta XBEE
Son soluciones integradas que brindan un medio inalámbrico para la
interconexión y comunicación entre dispositivos. Para éstas se utiliza el protocolo
de red llamado IEEE 802.15.4, con el fin de crear redes FAST
POINT-TO-MULTIPOINT (punto a multipunto); o para redes PEER-TO-PEER
(punto a punto). Fueron diseñadas para aplicaciones que requieren de un alto
tráfico de datos, baja latencia y una sincronización de comunicación predecible
(XBee.cl, sf).
Componentes mecánicos
Los componentes mecánicos utilizados en este proyecto fueron:
● Brazo de extensión tipo tijera
7
Es una estructura que tiene movimiento relativamente corto y puede extenderse
proporcionalmente. Se arma con vigas que poseen orificios para que sea fácil el
armado.
● Espárrago o tornillo
Pieza metálica, cilíndrica con un resalte helicoidal que la recorta en toda su
longitud.
● Cople flexible
Pieza diseñada para unir dos piezas cilíndricas. Cuenta con flexibilidad para
tolerar vibraciones o movimiento del eje. Los elementos flexibles compensan la
falta de alineación, y absorben moderadamente los choques de cargas
(ElectroCrea, s.f.).
Lenguajes
En el contexto de la computación un lenguaje puede ser una herramienta que permite a
los humanos dar instrucciones a una computadora, ya bien sea para que realice ciertas
acciones, o para modificar la forma en la que se muestra la información en una pantalla
(Ceballos, F. J.,2004).
Los lenguajes utilizados en este proyecto son:
● C++
Este es un lenguaje de programación que combina la velocidad de ejecución de
C y un paradigma de programación orientado a objetos, lo cual facilita el
desarrollo de grandes proyectos. También es el lenguaje en el que se desarrolla
en arduino (Olivares L., 2008).
● JavaScript
Es un lenguaje de programación interpretado, asíncrono y que tiene un
paradigma de programación orientado a prototipos (Clarii, 2018).
● HTML
Significa Lenguaje de Marcado para Hipertextos (HyperText Markup Language).
Se utiliza para crear y representar visualmente una página web. Así, permite
8
definir el contenido de la página web, mas no su funcionalidad. Constituye el
elemento de construcción más básico de una página web. (Yesenia M., 2019).
Algoritmos
Un algoritmo es una secuencia de instrucciones que conducen a la solución de un
problema (Vasconcelos, 2011).
● Algoritmos de optimización de rutas
El problema de la ruta más corta consiste en encontrar una ruta entre dos
vértices (o nodos) en un gráfico de tal manera que la suma de los pesos de las
aristas que lo constituyen sea mínima (J.B. Hayet, 2008).
Se puede clasificar de la siguiente manera:
El problema de los caminos más cortos desde un origen:
Se tiene que encontrar la ruta más corta de un vértice origen a todos los demás
vértices del grafo.
El problema de los caminos más cortos con un destino:
Se tienen que encontrar los caminos más cortos desde todos los vértices del
grafo a un único vértice destino.
El problema de los caminos más cortos entre todos los pares de vértices:
Consiste encontrar los caminos más cortos entre cada par de vértices (v, v') en el
grafo.
Protocolos
Un protocolo es un conjunto de reglas que deben seguirse en ciertos actos. En
sistemas informáticos, se crean para la transmisión de datos e información de una red
de comunicación (WordReference, 2005).
● Protocolos de comunicación
9
Para establecer una comunicación es necesario un protocolo, esto es, las reglas
para determinar la frecuencia a la que se envía una señal y cómo se debe
interpretar esa sucesión de bits que representan la información (Anónimo, 2018).
● Protocolo DigiMesh®
Es un protocolo propietario desarrollado por Digi International Inc que genera una
red entrelazada (meshed), permite nodos routers y controladores.
Objetivo del proyecto
Diseñar y construir un robot que cuente con una aplicación de software a la medida
para que realice la distribución de correspondencia en oficinas, eficientando las rutas de
entrega.
Problema
¿Cómo integrar los conocimientos de programación, electrónica y mecánica básica para
la construcción de un robot que distribuya la correspondencia en oficinas eficientando
las rutas de entrega?
Desarrollo
El desarrollo de nuestro prototipo está basado en la idea de automatizar tareas
cotidianas que suelen ser repetitivas, tales como la entrega de correspondencia en
oficinas, para dejar tiempo libre a los humanos para el desarrollo de actividades más
creativas.
El producto final se realizó dos etapas principales. La primera corresponde al diseño y
desarrollo del robot, y la segunda, al diseño y desarrollo del software de administración.
1. Diseño y desarrollo del robot
Esta etapa se dividió en cuatro fases. Cabe señalar que aunque se enuncian de manera
secuencial, algunas de ellas se llevaron a cabo de manera paralela.
Fase a. Diseño y desarrollo de un robot seguidor de línea
10
A fin de poder iniciar con el diseño y construcción del prototipo del robot, en primera
instancia, proyectamos hacer un robot seguidor de línea. Así, iniciamos una
investigación en torno a los componentes electrónicos, para orientar su selección.
En cuanto al microcontrolador, buscamos una opción que nos resultara familiar y
accesible, tuviera un procesamiento rápido y cumpliera con condiciones seguras para el
circuito. Esto nos llevó a elegir la tarjeta arduino, la cual, además de las características
antes señaladas, cuenta con un Entorno de Desarrollo Integrado (IDE) que permite la
codificación simple e inteligible de algoritmos.
En el caso de los sensores, investigamos el tipo requerido. Propusimos dos de
los más comerciales: el sensor CNY70 y el QTR-8A. La diferencia entre ambos,
consistió en que el sensor QTR-8A constituye una línea de sensores, es decir, está
integrado por ocho sensores individuales. Mientras que el CNY70 cuenta con un led
infrarrojo y un fotosensor, lo que permite que se puedan colocar en paralelo en una
superficie, permitiendo ajustar la distancia entre ellos. Este fue el criterio de peso que
guió nuestra decisión para la elección de la segunda opción.
En cuanto a los circuitos integrados requeridos, comparamos el TB6612FNG
contra el L298D, de los cuales se decidió trabajar con el TB6612FNG,
fundamentalmente por dos razones: al tener sus puentes-H formados por transistores
MOSFET, reduce considerablemente su tamaño, comparado con el L298D; por otra
parte, su capacidad de controlar corrientes superiores, permite dar una mayor
velocidad; esto, aunado a su capacidad de controlar dos motores de corriente continua
mediante el arduino, permite que trabaje en dos distintas velocidades de manera
independiente.
Hardware: Inicialmente, utilizamos un rectángulo como chasís. Seleccionamos MDF
como material de estructura porque es: fácil de cortar; ligero; difícil de romper; carga
bastante peso. También centramos una rueda loca (que no gira sobre su propio eje) en
la parte trasera del seguidor. Colocamos dos motores en la parte delantera. Decidimos
poner dos sensores (CNY70) perpendiculares a la línea, delante de las llantas,
centrados en el chasís.
11
Software de prueba para el robot seguidor de línea: Consideramos que la
programación orientada a objetos facilita el desarrollo y da mayor legibilidad al código,
por eso creamos una biblioteca para arduino en lenguaje C++. La cual se compone de
tres clases: motores, sensores, y el seguidor en conjunto
Problemas: El problema principal fue que el robot seguidor de línea quedaba
estancado. Iba de atrás hacia delante sin avanzar ni retroceder. La rueda loca, al no
poder girar sobre su propio eje, evitaba que el seguidor cambiará de dirección. De esta
suerte, no pudo seguir la trayectoria marcada.
Los sensores ubicados perpendicularmente a la línea impedían hacer vueltas de 90
grados. Decidimos colocarlos de forma paralela a la línea, pero cuando daba una
vuelta, no sabíamos a qué dirección girar el seguidor.
Aciertos: El código es fácil de entender y modificar. El objeto Tracker facilitó generar
cambios en el hardware sin cambios radicales en el código. Pudimos probar varias
formas de usar los sensores modificando sólo un método de la clase.
Cambios en hardware: El rectángulo no nos permitía hacer giros sobre su eje, así que
usamos un octágono como forma del robot. Quisimos imitar un círculo a fin de girar
sobre su propio eje.
Ruedas: Intercambiamos la rueda loca con dos motores. De esta manera,
tuvimos un chasis octagonal, con dos motores adelante y dos atrás. Lo anterior
proporcionó mayor tracción y lograr transportar más peso.
Sensores: Decidimos emplear tres sensores para detectar intersecciones. Los
situamos en paralelo para que pudiéramos decidir en qué estado se encontraba.
También implementamos sensores ajustables para evitar conflictos con el grosor de la
línea.
Fase b. Diseño y construcción de plataforma elevadora móvil
En esta fase del trabajo el objetivo fue construir un dispositivo capaz de acercar los
objetos transportados por el seguidor de línea. La plataforma fue pensada para soportar
un peso aproximado de 2.5 kg. Consideramos que cuando el seguidor enviara una
12
señal al arduino, la plataforma subiera. Una vez arriba, las dos opciones en las que
descendería serían: presionando el botón del usuario o pasado un tiempo razonable.
Hardware: Para la construcción de la plataforma elevadora móvil, como primer paso,
utilizamos brazos largos universales para hacer una estructura extensible en forma de
tijera, con el fin de acercar la base que contiene el paquete al usuario. Seguido de esto,
elegimos un rectángulo de MDF que fungió como base estructural de la plataforma.
Posteriormente, realizamos las mediciones necesarias para fijar los brazos a la base y
también hicimos ranuras que sirvieron como rieles para el movimiento óptimo de la
tijera. Finalmente, ejecutamos la misma mecánica con otro rectángulo de MDF para la
parte superior, el cual, debido al movimiento de tijera, pudo subir o bajar a manera de
elevador.
Colocamos un palo como travesaño que sirvió para unir ambos brazos, a fin de que no
solo se movieran al mismo tiempo, sino que también dieran soporte a la estructura.
Asimismo, colocamos un motor unido a un tornillo sin fin por medio de un cople, este
tornillo se ensambló al palo del soporte de ambos brazos a fin de que con su giro, los
brazos se recorrieran adelante o atrás, provocando, por el método de tijera, que la
estructura superior subiera o bajara deslizándose por un riel en la tabla MDF.
Para evitar que el motor se dañe por el giro continuo, colocamos dos botones en el
extremo de cada riel. Los cuales fungen como sensores que indican el momento en el
que se debe apagar el motor, al mismo tiempo la señal proveniente del botón indica la
posición en el que se encuentra la plataforma.
Software: Después desarrollamos un programa, mediante el IDE de arduino que
controla el motor a través de dos pines y de la recepción de la señal proveniente de los
botones colocados en la plataforma.
Fase c. Diseño y desarrollo del protocolo de transmisión arduino-arduino
Los arduinos se comunican con la ayuda de la biblioteca SoftwareSerial. Para
comenzar, es necesario instanciar un objeto de la clase SoftwareSerial y enviar como
parámetros al constructor los pines en los que se encuentra el transmisor y receptor,
13
respectivamente. Este proceso se repite en el otro arduino invirtiendo los parámetros
del constructor. El arduino maestro le envía una ‘a’ o una ‘b’ al esclavo dependiendo de
si es necesario que la plataforma suba o baje. El segundo contesta una ‘s’ cuando ha
terminado el proceso de movimiento.
Fase d. Integración final
Para el armado completo del dispositivo móvil, fue necesaria la conformación de dos
tarjetas arduino. Una de ellas que actuó como maestra. Esta tarjeta se encargó de la
conexión directa con el seguidor. Es decir, a partir de ésta se dictaron las órdenes a
ejecutar que desencadenaron en el movimiento de la plataforma elevadora. Al término
del proceso, ésta se encarga de enviar la señal a la interfaz para seguir con la ruta
establecida. La segunda tarjeta actuó como esclavo. Se conectó directamente con el
motor de los brazos del mecanismo de tijera. Es la que ejecuta las órdenes y
accionando el mecanismo, una vez terminado el proceso, le envía una señal a la tarjeta
maestra, y esta la rebota a la interfaz para seguir con el proceso.
2. Diseño y desarrollo del software de administración
Esta etapa se dividió en tres fases. Cabe señalar que en este caso también se llevaron
a cabo de manera paralela.
Fase a. Diseño y desarrollo del algoritmo de optimización de rutas
Decidimos usar la teoría de grafos para manejar el sistema. Esto fue porque
necesitábamos encontrar la ruta más corta. Para cada bifurcación del camino,
decidimos poner un nodo y un camino una conexión entre ellas. Diseñamos dos
algoritmos para obtener las rutas más cortas usando búsqueda exhaustiva y la
búsqueda de Dijkstra. La primera fue de implementar pero presenta costos excesivos
en almacenamiento y procesamiento. La segunda es más compleja, pero reduce en
gran medida la cantidad de procesamiento necesario
Algoritmo 1: búsqueda exhaustiva (fuerza bruta).
14
La forma más simple de encontrar la ruta más rápida es a través de búsqueda
exhaustiva. La búsqueda exhaustiva consiste en enlistar todas las posibilidades de un
problema y luego revisar si están correctas, además de ser fácil de implementar se
puede mejorar al analizar el problema a fondo.
Para las rutas óptimas este algoritmo consiste en enlistar todas las rutas posibles y
luego buscar la más rápida entre ellas, para esto se debe considerar que la cantidad de
rutas posibles es infinita y entre esas rutas también pueden existir rutas de distancia
infinita que impidan la finalización del programa. Para reducir la cantidad de rutas a un
número finito añadimos una restricción a nuestro algoritmo: no se podrán repetir los
nodos. Una vez que la ruta pase por un nodo, éste ya no será accesible durante el resto
de la caminata.
Almacenamos la información en un árbol, donde cada rama es una posible ruta. Para
cada nodo, empezando con el inicial se ejecuta el siguiente proceso :
Escribimos el nodo en el árbol y añadimos al árbol todos los vecinos del nodo que no
hayan sido visitados aun. Si el siguiente nodo es el nodo final entonces añadimos un
valor verdadero como último nodo y en el caso de que se genere una ruta inviable
asignamos un estado falso.
Cuando todos los caminos han sido explorados se agrupan las rutas con el valor de
verdadero y se suma el valor de cada una de sus aristas, éste se compara con las
sumas del resto y se toma como el camino más corto la rama de menor suma.
Algoritmo 2: Dijkstra
Mientras que la búsqueda exhaustiva es suficiente para casos pequeños, en gráficas
con cientos de nodos hay un problema: la memoria y el tiempo de procesos se
extienden demasiado.
Para no tener que comparar todos los casos posibles, se puede usar el algoritmo de
Dijkstra. El cual consiste en encontrar el nodo que tiene el menor peso conectado al
nodo inicial. El peso se añade al nodo que nos movimos, y guardamos que se caminó
15
por cierta ruta. Por ejemplo, llegamos a un nodo “a” a través de inicio y el costo fue de
5. Ahora, buscamos el nodo que, al dar un paso, tiene el menor peso. De esta manera
siempre se avanza por el camino que requiere el menor costo. Como llegar al nodo “a”
tuvo un costo de 5, llegar a los nodos accesibles por “a” se les sumarán 5.
Al igual que la búsqueda exhaustiva, se tiene que evitar regresar a un nodo que ya se
visitó. Esto con el objetivo de que el algoritmo no entre en un ciclo infinito. Una vez
teniendo lo anterior en cuenta, podemos aplicar el procedimiento recursivamente hasta
encontrar el nodo final. Sin embargo, se puede continuar con el algoritmo para
encontrar todos los caminos más rápidos. Mientras la suma de los pesos sean menor
que la ruta encontrada, sigue con los pasos. Finalmente encontramos todos los
caminos más rápidos posibles. Esto se logra sin tener que buscar en todos los caminos,
por lo que mejora considerablemente el tiempo en el que se ejecuta el programa.
Fase b. Diseño y desarrollo del protocolo de transmisión computadora-arduino
Para poder comunicarnos con el arduino usando las antenas, desarrollamos un
protocolo que le permitiera al servidor enviarle la ruta y acciones al seguidor de linea.
Para esta comunicación tuvimos que tomar en cuenta el minúsculo tamaño de la
memoria dinámica de el micro controlador. Decidimos asignarle a cada acción del
seguidor de linea disponible al servidor un carácter y predecir que entre cada una de
estas acciones siempre se seguirá el camino o línea hasta la siguiente intersección.
Fase c. Diseño y desarrollo del sistema de usuario
Creamos un sistema con el fin de que los trabajadores de la oficina puedan
comunicarse con Postbot.
Selección de lenguaje: Decidimos utilizar tecnologías web para crear una interfaz
multiplataforma, que permitiera que el usuario tuviese la mínima dificultad para su uso,
16
ya que actualmente la mayoría de las personas está familiarizada con este tipo de
aplicaciones.
Analizando las diferentes opciones que teníamos para instalar el servidor, decidimos
utilizar NodeJS, el cual: cuenta con diferentes herramientas ya desarrolladas, entre
éstas, las que permiten la conexión serial con el arduino; facilita la integración de
sockets, los cuales necesitamos para que sea instantánea la comunicación; simplifica
las consultas a la base de datos; y aporta una sencilla conexión con las API de otros
emporios, tales como Rappi, UberEats, FedEx y DHL, lo que permitiría un mayor
alcance del software.
Implementación: Primero delimitamos las necesidades del sistema. Decidimos que
sería necesario tener una base de datos, una interfaz y un sistema de control. Con eso
ya definido, diseñamos la base de datos con fundamento en los elementos del proyecto.
Así, realizamos un diagrama ER(entidad relación) que nos ayudó clarificar los atributos
de las tablas. La base fue pensada a futuro, con el fin de implementar más prototipos.
Cuando ya estaba lista la base, comenzamos con el desarrollo simultáneo de la interfaz
y del software que se comunica con el robot.
Interfaz de usuario
Para la interfaz del usuario planeamos cuatro páginas principales:
Index : Página de inicio de sesión
Homepage: Muestra los paquetes enviados. Pueden estar pendientes, en proceso de
envío o entregados.
Perfil: Permite ver y editar la información del usuario.
Nuevo envío: Presenta un formulario en el cual se muestran las entradas necesarias
para la generación de un nuevo registro en la tabla package. Esta solicitud se anexará a
la pila de pendientes del robot.
17
Postbot avisa cuando llegó al punto de entrega y cuando parte hacia otro destino.
Todas estas notificaciones se envían al usuario.
Software de comunicación con el robot
La manera en la que la computadora del usuario encargado de la entrega de
correspondencia se comunica con Postbot, es a partir del envío de una cadena, por
medio de una conexión inalámbrica, que representa una serie de instrucciones que el
robot deberá seguir. Dicha cadena resulta del procesamiento, mediante un algoritmo de
optimización de rutas, de los puntos que el robot visitará, los cuales provienen de la
consulta de los destinatarios realizada a la base de datos.
Resultados
Se logró diseñar y construir el prototipo de un robot para entregar correspondencia,
capaz de seguir las rutas más cortas para la entrega de correspondencia en una oficina.
Dicho robot fue dotado de un elevador, el cual acerca el paquete al destinatario para
hacer más cómoda la interacción en el momento de la entrega.
Se redujeron los tiempos de viaje para el robot gracias al diseño de un algoritmo de
optimización de rutas por búsqueda exhaustiva, y luego, su mejora a través de la
implementación del algoritmo de Dijkstra.
Se creó un sistema que permite la interfaz con el usuario, y que se comunica con el
robot mediante una antena XBEE y le envía una cadena con las instrucciones que debe
ejecutar para realizar las entregas
Análisis e interpretación de resultados
Si bien es un robot que puede recorrer diferentes puntos de una oficina una limitante
que tiene es la cantidad de comandos que puede ejecutar el seguidor, en un sólo
trayecto, es limitada debido a la memoria primaria que posee el arduino. Por lo que el
robot no podrá recorrer un camino con demasiadas paradas.
18
Para su funcionamiento es necesario que los nodos se muestren como cruces, estos
deben estar conformados por ángulos de noventa grados. Así, el mapa está limitado a
estas intersecciones. También es indispensable que la línea que indica el camino que
deberá seguir el robot esté colocada sobre un fondo blanco para su correcto
funcionamiento.
En comparación con otros dispositivos es pequeño, por lo que puede trabajar en
interiores y no requiere de grandes espacios para poder moverse.
El elevador no trabajará adecuadamente si la carga es mayor a 2.5 kilogramos. Esto se
debe a que sobrepasa la fuerza de torque provocando que éste se queme. El punto
más alto que puede alcanzar la elevación de la plataforma no sobrepasa los 54
centímetros, lo cual ocasiona que el usuario deba agacharse levemente para recoger el
paquete.
El dispositivo cuenta con baterías recargables, cuando éstas se descargan
completamente tendrán que ser reemplazadas manualmente. Se corre el riesgo de que
el robot quede a mitad de la trayectoria perdiendo su progreso.
Conclusiones
A partir de este proyecto podemos concluir que la realización de un robot de entrega
requiere de múltiples elementos mecánicos, eléctricos y de software. La conformación
de un sistema de entrega comienza en el registro y organización de los paquetes a
distribuir. Una vez teniendo esta información, es necesario calcular una ruta específica.
Dependiendo de los puntos a visitar para la repartición, debe ser analizada y
comparada con otras con el objetivo de hallar la más óptima. Cuando la unidad móvil
recibe la información, debe ubicar el camino con la ruta especificada . Para lograr esto,
hicimos uso de la teoría de grafos para representar nuestros mapas y de estos nodos
calcular las rutas más eficientes. Para la unidad móvil, se utilizaron componentes que
resultaron en un robot seguidor de línea capaz de transportar paquetes con una
plataforma elevable.
19
Fuentes de información
● Angulo, J., Hernández, J., Prieto, M., Etxebarria M. y Angulo, M. (2010).
Electrónica digital y microprogramable. España: Paraninfo.
● Arduino (2019). Página oficial de Arduino. Recuperado el 10 de enero del 2019
de: https://store.arduino.cc/usa/arduino-uno-rev3.
● Barrientos, A., Peñín, L. y Balaguer, C. (2007). Fundamentos de robótica.
España: McGraw-Hill/Interamericana.
● Crespo, E. (2016). Aprendiendo Arduino: Aprendiendo a manejar Arduino en
profundidad. Recuperado el 4 de diciembre de 2018 de:
https://aprendiendoarduino.wordpress.com/2016/11/09/alimentacion-arduino/ .
● De Frutos, M. (2013). Diseño de un "Robot seguidor de líneas" utilizando
circuitos combinacionales. Recuperado el 10 de enero de 2019 de:
http://aerobotclubderobticadeaeronuticos.blogspot.com/2013/10/diseno-de-un-rob
ot-seguidor-de-lineas.html.
● Saha, S. (2010) Introducción a la robótica. México: McGrawHill.
● Serway, R. y Beichner, R.(1999). Physics for scientists and Engineers with
Modern Physics.(2° ed.). United States of America: Brooks Cole.
● Vasconcelos, J. (2011). Introducción a la Computación. México: Grupo Editorial
Patria.
● Rodríguez L. (2019). Motorreductor recto. Master, Innovación que se vive.
Recuperado el 5 de enero de 2019 de:
https://shop.master.com.mx/product/detail?id=7677
● Frank Mecafenix (2017). ¿Qué es un puente H?. Ingeniería Mecafenix.
Recuperado el 12 de diciembre de 2018 de:
https://www.ingmecafenix.com/electronica/puente-h-control-motores/
● Jecrespom (2016). Electrónica, Sensores, Actuadores y Periféricos. Aprendiendo
Arduino. Recuperado el 12 de diciembre de 2018 de:
20
https://aprendiendoarduino.wordpress.com/2016/11/06/electronica-sensores-actu
adores-y-perifericos/
● Tecnosefarad (2014). Sensor de infrarrojos CNY70 como entrada digital.
tecnosefarad. Recuperado el 12 de diciembre de 2018 de:
http://www.tecnosefarad.com/2014/03/sensor-de-infrarrojos-cny70-como-entrada-
digital/
● XBee.cl (sf). ¿Qué es XBEE?. XBee.cl. Recuperado el 12 de diciembre de 2018
de: https://xbee.cl/que-es-xbee/
● Gutiérrez R.(sf). Tornillo sin fin. EcuRed. Recuperado el 12 de diciembre de 2018
de: https://www.ecured.cu/Tornillo_sin_fin
● ElectroCrea (sf). Cople flexible. ElectroCrea. Recuperado el 12 de diciembre de
2018 de: https://electrocrea.com/products/cople-flexible-5mm-8mm
● Ceballos, F. J. (2004). Enciclopedia del lenguaje C. México: Alfaomega/RaMa.
Recuperado el 5 de noviembre del 2018, de: https://programas.cuaed.unam.mx/repositorio/moodle/pluginfile.php/1023/mod_resource/
content/1/contenido/index.html.
● Olivares L. (2008). Manual de Programación en Lenguaje C++.
DGSCA-UNAM.Recuperado el 5 de noviembre del 2018, de:
https://paginas.matem.unam.mx/pderbf/images/mprogintc++.pdf
● Clarii(2018). Javascript. MDN web docs. Recuperado el 12 de diciembre de 2018
de: https://developer.mozilla.org/es/docs/Web/JavaScript
● Pineda, L (2017). La computación en México por especialidades académicas. 15
de diciembre 2018, de amexcomp Sitio web:
http://amexcomp.mx/files/libro/Portada.pdf
● Yesenia Mariela (2019). HTML. MDN web Docs. Recuperado el 02 de enero de
2019, de: https://developer.mozilla.org/es/docs/Web/HTML
● WordReference (2005). Protocolo. Recuperado en enero del 2019, de:
http://www.wordreference.com/definicion/protocolo
● J.B. Hayet.(2008). PAII-11: caminos más cortos (2). Recuperado en enero del
2019,
21
de:https://web.archive.org/web/20121224082311/http://www.cimat.mx/~jbhayet/C
LASES/PROGRAMACIONII/clase11.pdf
● Anónimo. (2018). Protocolos de comunicación, Qué son, tipos y ejemplos.
Recuperado en febrero de 2019, de:
http://247tecno.com/protocolos-de-comunicacion-tipos-ejemplos/
Anexos
Programa que controla el elevador #define AIN0 2 //E1 que está en la parte superioor del motor #define AIN1 3 //Cuando es 0 sube #define BOTON0 5 //BOTÓN ATRÁS #define BOTON1 6 // #define BOTON2 7 // ENTREGA #include <SoftwareSerial.h> bool arriba = false; char letra; SoftwareSerial mySerial(10, 11); // RX, TX //Recibe el boton que debe ser picado, el motor que avanza y el que no void upDown (int btAct, int mtrAct, int mtrDesact, int readBoton){ //Moverlos while(btAct != 1){ //Mientras no se haya pisado el botón digitalWrite(mtrAct, HIGH);
digitalWrite(mtrDesact, LOW); btAct = digitalRead(readBoton); //Vuelve a leer la señal delay(50); } //Desactivar los motorers digitalWrite(mtrAct, LOW); digitalWrite(mtrDesact, LOW); //Cuando ya no se cumple, significa que se picó y para } void setup() { int i; Serial.begin(9600); for (i=1; i<=3; i++) pinMode(i, OUTPUT); for (i=5; i<=7; i++) pinMode(i, INPUT); mySerial.begin(9600);
22
mySerial.write('t'); } void loop() { if (mySerial.available()) { //Cuando se recibe la señal letra = mySerial.read(); } if (letra == 'a'){ //ARRIBA mySerial.write(letra); upDown(digitalRead(BOTON0), AIN1, AIN0, BOTON0); //Baja hasta que el de adelante se pique arriba = true;
letra=' '; mySerial.write('d'); } else if(arriba == true && (digitalRead(BOTON2)== 1 || letra == 'b')){ //Si pasa el minuto o pican el botón... upDown(digitalRead(BOTON1), AIN0, AIN1, BOTON1); //Baja hasta que el de adelante se pique mySerial.write('s'); arriba = false; letra=' '; } }
Algoritmo de optimización de rutas
class Vertex{ // class for a node with position constructor(id,x,y){ this.id = id; this.links = []; this.x = x; this.y = y; } } class Link{ //class for links between nodes constructor(nodes,weight, position){ this.nodes = nodes; this.position = {}; this.position[nodes[0]] = position[0]; this.position[nodes[1]] = position[1]; this.weight = weight; } has_vertex(vertex){ //checks if the link has a vertex return this.nodes[0]==vertex || this.nodes[1]==vertex; } get_other_end(known_vertex){ let other_v = Number(known_vertex == this.nodes[0]); return this.nodes[other_v]; } } class Graph{ //represents the whole graph constructor(graph_descriptor){ this.nodes = []; this.links = []; for(let node in graph_descriptor){ let active = graph_descriptor[node];
this.nodes.push(new Vertex(node,active.x,active.y)); for(let connection of active.l) this.links.push(new Link([connection.connect, node],connection.weight, connection.pos)); } } get_nodes(){ return this.nodes; } get_node_names(){ let names = []; for(let node of this.nodes) names.push(node.id); return names; } add_node(name,x,y,neighbors){ let nodes_non_existent = []; this.nodes.push(new Vertex(name,x,y)); let names = this.get_node_names(); for(let conn of neighbors){ if(names.includes(conn.connect))//If node exists this.links.push(new Link([name,conn.connect],conn.weight)) else nodes_non_existent.push(conn); } return nodes_non_existent; } create_link(node_a,node_b,weight){ let names = this.get_nodes(),created = false; if(names.includes(node_a) && names.include(node_b)){
23
this.links.push(new Link([node_a,node_b],weight)) created = true; } return created; } get_link(index){ let exists = false; if(index < this.links.length) exists = this.links[index]; return exists; } get_link_between_nodes(nodeA, nodeB){ let links = this.get_node_links(nodeA); let link_index = 0; while(links[link_index].get_other_end(nodeA)!=nodeB && link_index<links.length) link_index++; return links[link_index]; } get_neighbors(node_name){ //gets adjacent nodes of a given node let exists = this.get_node_names().includes(node_name); let neighbors = exists; if(exists){ neighbors = []; for(let link of this.links) if(link.has_vertex(node_name)) neighbors.push(link.get_other_end(node_name)); } return neighbors; } get_node_links(node){ let adjacent_links=[]; for(let link of this.links) if(link.has_vertex(node)) adjacent_links.push(link); return adjacent_links; } weigh_path(path){ let total_weight=0; for(let node=0; node<path.length-1; node++){ let node_links = this.get_node_links(path[node]); let i=0; while(!node_links[i].has_vertex(path[node+1]) && i<node_links.length) i++; total_weight += node_links[i].weight; }
return total_weight; } shortest_brute(initial,end){ let paths = [],those = this; function get_paths(path,current_node){ if(current_node != end){ let neighs = those.get_neighbors(current_node); neighs = neighs.filter(elem=>!path.includes(elem)); for(let n of neighs) get_paths([n].concat(path), n); }else paths.push(path); } get_paths([initial], initial); let shortest_paths = [paths[0]]; for(let path=1; path<paths.length; path++){ if(this.weigh_path(paths[path])<=this.weigh_path(shortest_paths[0])){ if(this.weigh_path(paths[path])<this.weigh_path(shortest_paths[0])) shortest_paths = []; shortest_paths.push(paths[path]); } } return shortest_paths; } shortest_dijkstra(initial, end){ class Path{ constructor(){ this.nodes = []; this.total_weight = 0; } } let possible_paths = []; let next_shortest = initial; possible_paths.push(new Path()); possible_paths[0].nodes.push(initial); while(next_shortest != end){ let path_to_expand = possible_paths.splice(0,1)[0]; let neighs = this.get_neighbors(next_shortest); // Quitar caminos con nodos ya visitados neighs = neighs.filter(elem=>!path_to_expand.nodes.includes(elem)); // Quitar caminos que llegan al mismo punto mas lento for(let neigh of neighs){ // Crear nuevos caminos y sortearlos let newPath = new Path();
24
newPath.nodes = [neigh].concat(path_to_expand.nodes); newPath.total_weight = path_to_expand.total_weight; newPath.total_weight += this.get_link_between_nodes(neigh, path_to_expand.nodes[0]).weight; let index = 0; // sortear nuevo path while(index<possible_paths.length && possible_paths[index].total_weight < newPath.total_weight) index++; possible_paths.splice(index, 0, newPath); } next_shortest = possible_paths[0].nodes[0]; } return possible_paths[0].nodes; } parse_path(myPath, ini_pos){ let degreePath = []; function parse_angles(unparsed){ let pos = ini_pos; let angles = []; for(let node_index = unparsed.length-1; node_index>0; node_index--){ let link = this.get_link_between_nodes(unparsed[node_index], unparsed[node_index-1]); let delta = link.position[unparsed[node_index]] - pos; pos = link.position[link.get_other_end(unparsed[node_index])]; let degrees; if(delta==0) degrees=180;
else degrees = (delta*90) - ((delta/Math.abs(delta))*180); let command; if(degrees==180){ command = 1; // Atras } else if (degrees==-90){ command = 2; // Derecha } else if (degrees==0){ command = 3; // Frente } else if (degrees==90){ command = 4; // Izquierda } degreePath.push(command); } } parse_angles.call(this, myPath); return degreePath; } parse_many_paths(manyPaths, pos_init){ let final_path = []; let pos = pos_init; for(let path of manyPaths){ let shortest = this.shortest_brute(path[0], path[1])[0]; final_path = final_path.concat(this.parse_path(shortest, pos)); pos = final_path[final_path.length-1]; final_path = final_path.concat([0]); } return final_path; } }
Anexo de imágenes
25
top related