Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Septiembre 2021
Agradecimiento
Aunque este trabajo fue elaborado por mis conocimientos y esfuerzo puestos en él,
poder llegar a este punto de mi vida, si recibí bastante apoyo. Cumplo una meta mas en
mi vida y debo agradecer a muchas personas que me enseñaron a creer en mis sueños,
me impulsaron a seguir creciendo y me ayudaron ellos momentos mas difíciles. Poder
estar lejos de mi hogar y mi país no es fácil, ya que dejo atrás a todos mis familiares y
amigos, pero, aunque se encuentren en la distancia ellos siguen apoyándome para
seguir adelante. Mis padres, me enseñaron a tener dedicación y paciencia, a ir
disfrutando la vida y construyendo el futuro que deseo. Me apoyaron en todos mis
estudios realizados y aunque para esta meta se encuentra distantes, me siguen dando
ese apoyo incondicional como pueden. De igual manera a mi hermano, que me empujo
a expandir mis horizontes, a conocer nuevos lugares y nuevas personas. Le agradezco
por siempre presionarme para que sea una excelente persona y pueda valerme de mi
mismo disfrutando cada aventura. A mis amigos que, estando lejanos, en los momentos
más tristes me ayudan a levantarme, a reír y a distraerme. Grandes amigos que me han
acompañado y los considero como hermano. Agradezco también a los profesores que
tuvieron la paciencia y dedicación de enseñarnos, de tomarse su tiempo para que
comprendiéramos los temas y para que despertaran esa mente curiosa a la innovación
y por último a la Universidad Politécnica de Valencia, que estando desde tan lejos me
dio una gran oportunidad, me abrió sus puertas al conocimiento y me permitió conocer
un gran país como lo es España. A todos les debo un agradecimiento por ayudarme a
ser más fuerte, a ser una mejor persona, a ser un mejor profesional, a seguir cumpliendo
mis metas y disfrutando la vida.
Resumen
En este trabajo se abordará el diseño de un programa de protocolo de comunicación
utilizando la tecnología LoRa. Se dispondrá una red sensores que se conectaran en
forma de una topología Mesh. Para este sistema se diseñará un protocolo de envío y
recepción de mensajes proponiendo una estructura de paquete simple y se diseñará un
protocolo de enrutamiento epidémico, donde la comunicación debe llegar a todos los
dispositivos en su rango de alcance. De igual forma al ser LoRa una tecnología
deseñada para IoT, se tratarán de cumplir los requisitos para ser efectivos en áreas que
requieran sensores y ser de bajo consumo de potencia.
Objetivos
El objetivo del trabajo se encuentra realizar un protocolo de Lora para ser
utilizados dispositivos Lopy4 de la marca Pycom que permite crear una red Mesh de
dispositivos y permite ser usado en bajo consumo.
Impacto Esperado
El diseño de este protocolo de comunicación va a permitir crear una
comunicación entre varios dispositivos a una tasa baja de consumo de potencia. Con
esta idea en mente se puede diseñar programas para sensores que realizan mediciones
de temperatura o presión atmosférica. Los cuales no necesariamente deben estar
ubicados en un sitio estático. El protocolo se plantea diseñar para encontrarse en un
estado móvil, donde en cualquier sitio donde se encuentre tenga la posibilidad de
comunicarse con la red principal. Por eso, con el uso de la tecnología LoRa se puede
utilizar para comunicaciones de largo alcance y donde todos los nodos participantes se
convierten en canales de transmisión, mejorando así la red de comunicación. Partiendo
de esta idea, el sistema puede ser utilizado para geolocalización. Puede ser
implementado para personas que sufran enfermedades como el Alzheimer y se
extravíen o para uso de investigación de la fauna, donde se realiza localización de
animales, en donde mayor es la cantidad de dispositivo mejor es el comportamiento de
la red.
Metodología
Para la elaboración de este trabajo se partirá del uso de la experimentación. Se
iniciará en el diseño de un código de programación en lenguaje Python y se
implementará en dispositivos compatibles a esta para la realización de pruebas. Para la
recolección de datos el sistema cuenta con una terminal donde se ajustará el código
para obtener resultados en ciertas partes del programa. De igual manera se utilizará
equipo especializados para la medición de consumo de potencia en los dispositivos.
Estructura
Para la estructura del trabajo se realizará una breve explicación de los conceptos
teóricos que engloba este trabajo, con la idea de plantear las características de la
tecnología que se planea utilizar y explicar la topología de la red que se desea
implementar. Luego se realizará un planteamiento y descripción de los sistemas y
equipos que serán necesarios para realizar las pruebas del proyecto. Se propone un
plan de trabajo para el desarrollo del código, exponiendo las fases que se van a cubrir
hasta conseguir la estructura del código final. Seguidamente, se realiza una explicación
de la estructura del código, cumpliendo cada fase para luego seguir con la
implementación del código en los dispositivos y pruebas del sistema diseñado.
Finalmente se realiza un análisis general de los resultados y se concluye en posibles
mejoras del sistema para futuro.
2. Estado del arte
Internet de las Cosas (IoT)
LoRa
LoRa está diseñado para manejar una velocidad de datos variables, permitiendo
tolerar factores de dispersión ortogonales. Esto permite al sistema poder controlar la
velocidad de datos por el rango o potencia, permitiendo buscar la configuración óptima
que se adapte al rendimiento de la red en un ancho de banda constante. Los anchos de
bandas ISM compatibles para LoRa son: (5)
● 433MHz en Asia
Europa América
Canales 10 64 + 8 + 8
SF Up 7-12 7-10
Tabla 1 comparación de las especificaciones LoRa para Europa y Estados Unidos, dos regiones
donde se utilizan bandas ISM ampliamente. (Fuente de la imagen: LoRa Alliance)1
Topología Mesh
1
https://lora-alliance.org/
Ventajas:
Desventajas:
Protocolo de Enrutamiento
Propuesta
El diseño a implementar en este trabajo es utilizar la tecnología LoRa en la banda
de frecuencia de 868 MHz, permitida en la Unión Europea, para realizar conexiones con
topología de red Mesh o Malla. Para lograr esta topología es necesario plantearse el
uso de un enrutamiento Epidémico. Para lograr este enrutamiento se plantea diseñar un
protocolo que realice la transmisión epidémica entre los nodos y asociará en los
mensajes un identificador único para soportar el enrutamiento y tolerancia a fallas.
Además, se incluirá un recuento de saltos para realización de pruebas y de manera
opcional, solicitud de confirmación de recepción de mensajes. Como cada dispositivo
debe poseer un identificador único (ID), este se generará de una fracción de la MAC de
cada dispositivo. Como diseño para la implementación en IoT, se toma en considerar
abordar el diseño en conseguir bajo consumo de potencia en el protocolo de
comunicación, utilizando la capacidad de los dispositivos en entrar en estados de
suspensión.
3. Análisis del problema
Diseñar un protocolo que permita una topología de red Mesh mediante
tecnología de comunicación LoRa, esto mediante el uso de varios dispositivos de la
marca pycom.
Al realizar una conexión de red de dispositivos, cada uno de ellos debe saber
cómo diferenciarse. Para eso es necesario la asignación de un identificador único. Este
identificador como estará asociado en la estructura del mensaje debe poseer un tamaño
apropiado para hacer ligero el tamaño del paquete. De igual manera que los dispositivos.
Cada mensaje debe ser único, así el sistema puede diferenciar cada uno de los
mensajes en tráfico. Para eso es ideal plantear un identificador para los mensajes, que
permite la verificación en los dispositivos, donde se puede guardar en un buffer para los
ID de los mensajes que son recibidos en el dispositivo.
● Elaborar un código de verificación de mensaje
El diseño de la verificación del mensaje puede ser uno a uno, donde cada
paquete que un host envía debe esperar un paquete de respuesta. Esta manera, aunque
es efectiva ya que aseguras que cada paquete es recibido, causa un mayor uso de los
recursos de los host ya que se generan más paquetes que se encontraran en tránsito
en la red. Una manera de reducir la cantidad de estos paquetes es realizar la respuesta
del dispositivo para cada cierta cantidad de mensajes recibidos.
Plan de Trabajo
● Fases de desarrollo del código
Al ahora de escoger una ruta el sistema no gasta recursos para escoger ruta.
Los paquetes serán enviados por diferentes rutas para así tener mayor éxito de llegar al
destino. Esto consigue tolerancia a fallos en alguna ruta. De igual manera mientras el
sistema no se encuentra en uso se colocará un tiempo de suspensión. Se sincronizará
de tal manera que el sistema al recibir un mensaje pueda suspender sus funciones hasta
el período de recibir el próximo mensaje.
Ilustración 6 Enrutamiento epidémico entre los nodos
Diseño Detallado
Para el diseño del protocolo de comunicación entre dispositivos se realizará una
división de por fases. Con la estructura de fase que se realizara a continuación se va
realizando el código que será implementado y probado para cumplir los objetivos. Todo
el diseño se realizara en lenguaje Python, ya que este es el soportado por los sistemas
Pycom. La estructura de código se encontrara en el Anexo 1 y Anexo 2, y externamente
se cargara en un repositorio de Github
(https://github.com/damejias23/TFM_Mesh_Lora).
Para evitar que un nodo reciba un mensaje desde varias rutas es necesario
asignar un identificador único de mensaje. Esto permite verificar los mensajes que han
pasado por el nodo y descartar los mensajes repetidos con igual identificador. En los
nodos al generarse un mensaje se debe generar un número de ID aleatorio que no será
igual a ninguno de los ID enviados por otros nodos, esto se logra colocando parte de la
ID del nodo en el formato del ID del mensaje. Con esto se logra conocer el ID del nodo
que realizó el envío.
Tecnología Utilizada
Para el desarrollo del protocolo de comunicación es necesario utilizar un
dispositivo que cumpla como mínimo, un soporte de comunicación por Lora y recursos
básicos de procesamiento y memoria. Principalmente se desea realizar un programa
básico que no exige utilizar muchos recursos de cómputos para así diseñar un programa
que realice el menor consumo de potencia en los dispositivos. Estos dispositivos a su
vez, poseen la característica de generar un bajo consumo de potencia. A continuación
explicaremos el hardware utilizado para el desarrollo de las pruebas y el software
incorporado para su desarrollo:
Hardware
Pysense: es una placa con sensores que tiene la capacidad de ser utilizado con
cualquier módulo de redes múltiples de Pycom. Se adapta a todas las placas Pycom y
contiene una serie de sensores, como luz ambiental, presión y humedad. Incluye un
conector de 6 pines para sensores Pynode.2
Características:
● Sensor de humedad
● Sensor de temperatura
Tamaño:
2
https://pycom.io/product/pysense-2-0-x/
● Dimensiones 5,5 × 3,5 × 1 cm
● Dimensiones: 55 x 35 x 10 mm
Característica
3
https://pycom.io/
4
https://pycom.io/product/lopy4/
● MicroPython habilitado
Especificación LoRa
● Pila LoRaWAN
● Dispositivos de clase A y C
● Nano-gateway: hasta 22 km
Interfaces
● GPIO: hasta 24
Memoria
● RAM: 4 MB
● Flash externo: 8 MB
● Aceleración de punto flotante de hardware
● Python multiproceso
Poder
Tamaño
● Peso: 7g
5
https://pycom.io/
Firmware
El firmware es la aplicación de bajo nivel de los dispositivos. Se encarga del
control lógico de circuito en cada hardware. Para el diseño de este proyecto se realizó
la actualización del firmware de los dispositivo LoPy4 con la versión Pycom MicroPython
1.20.0.rc13 [v1.9.4-94bb382] con fecha de publicación del 22-08-2019. Esta es la última
actualización lanzada hasta la fecha de la publicación de este trabajo. Esto se debe a
mejoras y correcciones de errores en los dispositivos y esto a veces significa actualizar
el firmware de un hardware.
Software
Para el diseño del protocolo de comunicación es necesario utilizar un software
que permita cargar las instrucciones que se desea emplear. Para esto se necesita un
programa que sea compatible con la comunicación del dispositivo y que pueda
monitorizar la información procesada. Para los dispositivos Pycom, la marca recomienda
utilizar aplicaciones como Atom o Visual Code que cuentan con las funciones adecuadas
para la conexión con sus dispositivos. Para la ejecución de este proyecto se utilizó la
aplicación Atom, ya que cuenta con herramientas versátiles para el desarrollo del código
en Python y con los paquetes necesarios para la programación y monitoreo de los
dispositivos.
Atom es un editor de código fuente el cual cuenta con una gran variedad de
complementos para realizar programación en diferentes lenguajes. Por esto Atom se
convierte en una de los programas más completos e ideales para programadores.
Soporta cualquier ordenador con sistemas Windows, Linux o Mac con macOS. Además,
es un complemento perfecto para la misión principal de GitHub de crear un mejor
software trabajando juntos.
Para obtener el ID de los dispositivos se diseñó una función llamada Def_ID que
de valor de entrada se debe colocar la variable que contiene los datos del controlador
de LoRa y mediante la librería de ubinascii se solicita el valor de la MAC del dispositivo.
La función devuelve los primeros tres bits de la MAC leídos de derecha a izquierda en
su valor se transforma a decimal. La estructura de la invocación de la función queda de
la siguiente forma:
Def_ID(lora)
UID_message(id_device)
get_SendID(UID)
Al realizar los envío de paquete, se debe evaluar la cantidad de rutas que realiza
hasta llegar a su destino. Así se puede conocer si la ruta escogida fue la más corta o la
más larga. Para esto se agregara en el paquete un contador de saltos, que permitirá
conocer cuántos saltos realizó el paquete hasta llegar a su destino. Este contador de
salto también puede permitir descartar un mensaje. Si un paquete supera una cierta
cantidad de salto, este paquete puede ser descartado para liberar la red, ya que supera
la cantidad de salto para llegar a su destino. Esta cantidad de salto debe estar
relacionado a la cantidad de nodos en la red, ya que es la máxima cantidad de salto que
puede hacer en la red.
Estos cuatros datos conforman el encabezado del paquete, los cuales cada
dispositivo que recibe un paquete debe leer estos datos para conocer el destino y
conocer si el paquete ha sido recibido anteriormente. Al tener el encabezado del
paquete, solo queda agregar el mensaje a transmitir. Para fines prácticos de este
proyecto se supondrá que la información que se recibe es la localización de cada
dispositivo.
Se utilizará el signo “!” que representa el orden de bytes de la red que siempre
es big-endian como se define en IETF RFC 1700 .
_LORA_PKG_FORMAT = "!BBIBB"
get_IDdest(recv_pkg, recv_pkg_len)
Una vez que el nodo verifique la información del encabezado y catalogue como
un paquete de reenvío, se debe realizar la modificación ID del nodo de envío, ya que
este nodo se convierte ahora como nodo origen. La función contiene la capacidad de
analizar si un paquete es de respuesta o no, ya que un paquete de envío a un paquete
de respuesta posee diferentes tamaños y por ende, la función debe realizar diferentes
operaciones a cada uno. Además, el contador de salto se suma en uno para llegar al
próximo destino. La estructura de la invocación de la función queda de la siguiente
manera:
set_IDorigen(pack, ID_sent)
Para envío:
while(True):
lora_sock.send(pck)
sleep(15)
Para recepción
while(True):
recv_pkg = lora_sock.recv(256)
if(id_end == id_device):
lora_sock.send(pck_reenvio)
Identificación de mensaje
return
else:
list_recv.append(UID_msg)
def clear():
global list_recv
time.sleep(200)
list_recv = []
Para el diseño de esta etapa se creará una clase que se encargará en los
dispositivos ir contando los mensajes recibidos por cada dispositivo. Cuando un mensaje
nuevo llega a un dispositivo, éste agrega en su lista el ID del dispositivo emisor y crea
un contador para este. Los próximos mensajes recibidos deben sumar un valor más al
contador hasta un número finito de mensajes. Al llegar a la cantidad definida el sistema
retira de la lista el ID del dispositivo y genera el envío de respuesta al dispositivo emisor.
El emisor se encontrará esperando el mensaje de respuesta y en caso de no recibir el
mensaje en un tiempo esperado, el sistema asume que no está llegando a su destino.
6
https://docs.pycom.io/tutorials/networks/lora/
mensaje de cualquier nodo. Luego de esto, el dispositivo se sincronizará a la red sin
problemas.
T1 T2 T3 T4 T5 T6 T7 T8
Tiempo activo
Tiempo suspendido
Tabla 2 Tabla de actividad de suspensión de los dispositivos en el tiempo
5. Implementación
7
https://docs.pycom.io/tutorials/networks/lora/
lora.callback(trigger=(LoRa.RX_PACKET_EVENT|LoRa.TX_PACKET_
EVENT), handler=lora_cb)
_thread.start_new_thread(Send_buffer, ())
def Send(ID_send):
_thread.start_new_thread(Packet_buffer, (ID_send, ))
_thread.start_new_thread(clear,())
_thread.start_new_thread(ack_off, ())
Pruebas
Para la realización de las pruebas de la propuesta, es necesario diseñar en el
código una función para realizar test. Este sistema está diseñado para operar a largo
alcance. Al poseer los dispositivos en un laboratorio, es complicado realizar las pruebas
en un ambiente ideal. Para esto es necesario realizar un modo de prueba en el sistema
que permita limitar la conexión entre nodos.
if(modeTEST):
if id_to_send in ID_block:
return
Por último se realizaron pruebas con una topología de malla, donde todos
estarán enviando mensajes entre todos y veremos la capacidad de soportar los
mensajes y el comportamiento si hay un nodo saturado. Se medirán los saltos que
realizan hasta llegar a su destino para comprobar si utilizan la ruta óptima.
Ilustración 16 Diseño de prueba para topología Mesh
Resultados
Pruebas realizadas en topología anillo
Para este caso de prueba se observará más el dispositivo que realiza el envío
de mensaje, el cual, cada cierto tiempo recibirá una respuesta del envío de sus
mensajes. En la siguiente imágenes que se podrán observar se muestra el envío de
paquetes que se realiza y cada cinco paquetes enviado por el nodo 229, éste recibe una
respuesta del nodo 64. De igual manera el nodo 64, recibe sus mensajes del nodo 229
y no se evidencia alguna pérdida de paquete en la comunicación.
Para esta prueba se realizará conexión punto a punto entre dos parejas. Entre
ellos se realizará una comunicación y se intentará enviar la mayor cantidad de mensajes
entre dispositivos al mismo tiempo. Con esto se trata de medir la capacidad de tolerancia
a fallos cuando el canal se encuentra saturado de mensajes. Se trata de saturar el medio
de transmisión y el buffer del sistema al recibir mensajes del mismo equipo. En la
siguiente imagenes se muestra el envío y recepción de los mensajes por parte de las
parejas. Ambos sistemas se encuentran enviando simultáneamente y a su vez cada
dispositivo envía 5 mensajes a su pareja.
Ilustración 34 Resultados de envío y recepción de mensajes por los nodos 64 y 160
Ilustración 35 Resultados de envío y recepción de mensajes por los nodos 229 y 174
Ilustración 36 Envío de mensajes a los nodos 64, 160 y 174 por parte del nodo 229
Uno de los puntos que se puede plantear para trabajos futuros es el tema de la
seguridad entre dispositivos. Para este proyecto se planteó un código que pudo ser útil
para uso de seguridad, sin embargo, se utilizó de manera superficial para realización de
pruebas. Partiendo de este código se puede indagar mas y llegar a buenos resultados
mejorando la seguridad del sistema.
#lock = _thread.allocate_lock()
MAX_RECV = 1
MAX_BUFFER = 4
active_sleep = 0
if ACK_ACTV:
pycom.heartbeat(False)
def Send_buffer():
global lora, lora_sock, location, id_device, list_recv,
active_sleep
while(True):
if len(buffer)>0:
#if id_send not in list:
#ENVIO
send_pck = buffer.pop(0)
id_to_send, id_end, UID_msg =
get_IDdest(send_pck)
if(id_to_send == id_device):
lora_sock.send(send_pck)
else:
print("Reenvio de: %d" % id_to_send)
pck_reenvio = set_IDorigen(send_pck,
id_device)
lora_sock.send(pck_reenvio)
elif active_sleep and ModeSleep:
print("Sleep")
machine.sleep(1000*20,False)
lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868)
print("Wake up")
active_sleep = 0
if ModeSleep:
time.sleep(2)
def Packet_buffer(ID_send):
global location, id_device, list_recv, buffer,
active_sleep
cuenta_envio = 0
while(True):
if(ID_send):
#ENVIO AL BUFFER
if ModeSleep:
if not active_sleep:
time.sleep(4)
UID = UID_message(id_device)
list_recv.append(UID)
pck = pack_Lora(id_device, ID_send, UID,
0, location)
if(len(buffer) < MAX_BUFFER):
cuenta_envio = cuenta_envio + 1
print("Numero de paquetes enviados:
%d" % cuenta_envio)
buffer.append(pck)
active_sleep = 1
else:
UID = UID_message(id_device)
list_recv.append(UID)
pck = pack_Lora(id_device, ID_send, UID,
location, 0)
if(len(buffer) < MAX_BUFFER):
cuenta_envio = cuenta_envio + 1
print("Numero de paquetes enviados: %d"
% cuenta_envio)
buffer.append(pck)
time.sleep(15)
def Recv():
global lora, lora_sock, location, id_device, list_recv,
modeTEST, buffer, count, active_sleep, cuenta_recibo
#Recibo
recv_pkg = lora_sock.recv(256)
recv_pkg_len = recv_pkg[1]
id_to_send, id_end, UID_msg = get_IDdest(recv_pkg)
if(modeTEST):
if id_to_send in ID_block:
return
if UID_msg in list_recv:
return
else:
list_recv.append(UID_msg)
if (len(recv_pkg) > 7):
if(id_end == id_device):
id_to_send, id_end, UID_msg, TTL, location =
unpack_Lora(recv_pkg, recv_pkg_len)
cuenta_recibo = cuenta_recibo + 1
print("Mensaje para mi de %d. Saltos:%d" %
(get_SendID(UID_msg), TTL))
TTL = TTL + 1
print("Cuenta recibida de paquetes %d" %
cuenta_recibo)
if List_ack(get_SendID(UID_msg), List_send) and
ACK_ACTV:
send_ack(get_SendID(UID_msg))
if ModeSleep:
time.sleep(5)
if not len(buffer):
active_sleep = 1
else:
if(len(buffer) < MAX_BUFFER):
buffer.append(recv_pkg)
if ModeSleep:
time.sleep(5)
active_sleep = 1
def send_ack(id_respond):
global lora, lora_sock, list_recv, buffer
UID = UID_message(id_device)
list_recv.append(UID)
pkg_ack = pack_AckLora( id_device, id_respond, UID, 0)
buffer.append(pkg_ack)
def clear():
global list_recv
time.sleep(200)
list_recv = []
def ack_off():
global count , send_OK
while(ACK_ACTV):
time.sleep(1)
count = count - 1
if not count:
pycom.rgbled(0x7f0000)
send_OK = 0
def lora_cb(lora):
events = lora.events()
if events & LoRa.RX_PACKET_EVENT:
Recv()
lora.callback(trigger=(LoRa.RX_PACKET_EVENT |
LoRa.TX_PACKET_EVENT), handler=lora_cb)
def Send(ID_send):
_thread.start_new_thread(Packet_buffer, (ID_send, ))
time.sleep(10)
_thread.start_new_thread(Send_buffer, ())
_thread.start_new_thread(ack_off, ())
_thread.start_new_thread(clear,())
import os
import socket
import time
import struct
from network import LoRa
import uos
import ubinascii, network
_LORA_PKG_FORMAT = "!BBIBB"
_LORA_PKG_ACK_FORMAT = "!BBIB"
class ID_recv:
def __init__(self):
self.id = []
self.count = []
def new_id(self, id):
self.id.append(id)
self.count.append(0)
def add_count(self, id):
i = self.id.index(id)
self.count[i] = self.count[i] + 1
def remove_id(self, id):
i = self.id.index(id)
self.id.pop(i)
self.count.pop(i)
def get_IDdest(recv_pkg):
global _LORA_PKG_FORMAT, _LORA_PKG_ACK_FORMAT
ID_send, ID_end, UID = struct.unpack_from("!BBI",
recv_pkg, 0)
return ID_send, ID_end, UID
def Random():
result = (uos.urandom(1)[0] / 256) * 1000
return int(result)
def Def_ID(lora):
id = ubinascii.hexlify(lora.mac()).upper().decode('utf-
8')
id = id[14:16]
return int(id, 16)
def UID_message(id_device):
return (id_device * 1000) + Random()
def get_SendID(UID):
SendID = UID/1000
return int(SendID)
def Open_Test(file_test):
f = open (file_test,'r')
mensaje = f.readlines()
mensaje = [int(x) for x in mensaje]
f.close()
return mensaje