2.2 Captura datos. Dispositivo con USB-Serial a un archivo.txt usando Python

La relación de valores de Rssi y distancia hacia cada punto de referencia (baliza), se estima a partir de las mediciones en varios puntos establecidos y ubicados en un mapa.

En cada punto, los valores se estiman considerando usar al menos 100 lecturas hacia cada baliza en cada punto.

En éste proceso usa un computador portátil que captura las tramas de cada paquete recibido por el dispositivo desde el puerto USB-Serial a un archivo.txt.

Cada baliza periodicamente emite un paquete que permite al dispositivo registar los valores de Rssi y SNR. Cada captura se registra en una línea de texto como un paquete recibido y etiquetado como «rx».

Para registrar el Rssi y SNR desde el otro extremo, la baliza, se emite un paquete de difusión desde el dispositivo, con el que la baliza al recibirlo toma los valores de Rssi y SNR y los envia al dispositivo en el próximo envío. El paquete de difusión del dispositivo se etiqueta como ‘tx’ en el archivo txt.

En la pantalla del computador portátil se muesta el estado del registro de datos en cada evento de recepción.

Configuración del algoritmo en Python

La captura de datos desde USB se realiza usando instrucciones en Python, con la que se pre-procesa cada paquete y se almacena en un archivo.

En el bloque de INGRESO es necesario indicar:

  • el puerto ‘com’ y los baudios del dispositivo conectado por USB
  • el nombre del archivo de texto que registra la captura de datos
  • las direcciones de las balizas, identificadores indicados en la sección anterior
  • la cantidad mínima de lecturas desde cada baliza

El puerto ‘com’ se puede verificar antes de iniciar la captura, usando el IDE de arduino, al conectar lo muestra en el menu de herramientas/puerto.

El proceso de captura se ejecuta en un lazo, en caso de ser necesario deterner se pueden usar las teclas «Ctrl-c».

En cada punto de referencia se requiere asignar un nombre a cada archivo, iniciando el nombre con «multipunto» añadiendo letras para identificar el sector y un número como identificador del punto.

En los puntos de prueba el nombre del archivo inicia con «mpcircuito». Observe que ambas palabras de inicio contienen la misma cantidad de caracteres, pues facilita el procesamiento de los archivos.

Los archivos se almacenan en una carpeta de donde se puedan leer por lotes en el siguiente proceso de los datos.


Algoritmo en Python

''' Rssi y SNR LoRa punto a punto
paquete de datos desde puerto Serial
generados desde dispositivo LoRa
modelo Heltec Lora 32 v.2
Girni 2020-10-07 propuesta: edelros@espol.edu.ec
'''
import numpy as np
import matplotlib.pyplot as plt
import serial, time

# INGRESO
# Puerto de captura de datos USB-Serial
puerto = 'com3'
baudios = 115200

# Archivo para el registro de cada evento rx,tx
nombrearchivo = 'multipuntoFIEC101.txt'

# identificadores de balizas
baliza = ['d1','d2','d3']

# Mínimo de lecturas por baliza
lecturasMin = 100

# PROCEDIMIENTO
# Crea registro de lecturas
n = len (baliza)
registro = {}
for elemento in baliza:
    registro[elemento] = {'cuenta': 0 ,
                          'rssi': np.array([0.0,0.0]),
                          'snr':  np.array([0.0,0.0]),
                          'SumaRssi': np.array([0.0,0.0]),
                          'SumaSnr':  np.array([0.0,0.0]),
                          'minmaxRssi': np.array([0.0,-200.0,0.0,-200.0]),
                          'minmaxSnr': np.array([100.0,0.0,100.0,0.0])
                          }

# inicializa archivo.txt a vacio
archivo = open(nombrearchivo,'w')
archivo.close()  # Cierra el archivo

# Abre puerto Serial
arduino = serial.Serial(puerto, baudios)
arduino.setDTR(False)
time.sleep(0.3)

# limpia buffer de datos anteriores
arduino.flushInput()  
arduino.setDTR()  
time.sleep(0.3)
print('\nEstado del puerto: ',arduino.isOpen())
print('Nombre del dispositivo conectado: ', arduino.name)
print('Dump de la configuración:\n ',arduino)
print('\n###############################################\n')

# Lectura de datos
np.set_printoptions(precision=2)
conteo = 0
difunde = 0
while conteo<lecturasMin:
    #esperar hasta recibir un paquete
    while (arduino.inWaiting()==0):
        pass 

    # leer linea desde puerto serial
    linea = arduino.readline()
    # binario a texto, elimina /r/n
    texto = linea.decode()
    texto = linea.strip()
    
    # identificar la trama como rx, tx
    cond1 = texto.startswith('tx')
    cond2 = texto.startswith('rx')
    if cond1 or cond2:
        archivo = open(nombrearchivo,'a')
        archivo.write(texto+'\n')
        archivo.close()
        
        if (texto.startswith('tx')):
            difunde = difunde + 1
        if (texto.startswith('rx')):
            texto = texto.split(',')
            tipo  = texto[0]
            dir_remite = texto[2]
            paqrcbvID  = texto[3]
            rssi_tx    = float(texto[4])
            snr_tx     = float(texto[5])
            rssi_rx    = float(texto[6])
            snr_rx     = float(texto[7])
            if tipo == "rx":
                # conteo de lecturas
                cual = dir_remite
                registro[cual]['cuenta']=registro[cual]['cuenta']+1
                if registro[cual]['cuenta']<conteo:
                    conteo = registro[cual]['cuenta']

                # acumulado
                registro[cual]['SumaRssi'][0] = registro[cual]['SumaRssi'][0]+rssi_tx
                registro[cual]['SumaSnr'][0]  = registro[cual]['SumaSnr'][0]+snr_tx
                registro[cual]['SumaRssi'][1] = registro[cual]['SumaRssi'][1]+rssi_rx
                registro[cual]['SumaSnr'][1]  = registro[cual]['SumaSnr'][1]+snr_rx

                # promedios
                cuantos = registro[cual]['cuenta']
                registro[cual]['rssi'] = registro[cual]['SumaRssi']/cuantos
                registro[cual]['snr']  = registro[cual]['SumaSnr']/cuantos

                # minimos y maximos
                registro[cual]['minmaxRssi'][0] = np.min([rssi_tx,registro[cual]['minmaxRssi'][0]])
                registro[cual]['minmaxRssi'][1] = np.max([rssi_tx,registro[cual]['minmaxRssi'][1]])
                registro[cual]['minmaxRssi'][2] = np.min([rssi_rx,registro[cual]['minmaxRssi'][2]])
                registro[cual]['minmaxRssi'][3] = np.max([rssi_rx,registro[cual]['minmaxRssi'][3]])

                registro[cual]['minmaxSnr'][0] = np.min([snr_tx,registro[cual]['minmaxSnr'][0]])
                registro[cual]['minmaxSnr'][1] = np.max([snr_tx,registro[cual]['minmaxSnr'][1]])
                registro[cual]['minmaxSnr'][2] = np.min([snr_rx,registro[cual]['minmaxSnr'][2]])
                registro[cual]['minmaxSnr'][3] = np.max([snr_rx,registro[cual]['minmaxSnr'][3]])

            # Muestra en pantalla el estado de recepción
            print('\n difusion: ',difunde)
            print(texto)
            for elemento in baliza:
                print(elemento,registro[elemento]['cuenta'],
                      '\tprom Rssi[tx,rx] \t   Snr[tx,rx]')
                print("prom   :",registro[elemento]['rssi'],"\t  ",
                      registro[elemento]['snr'])
                print("min,max:",registro[elemento]['minmaxRssi'],
                      registro[elemento]['minmaxSnr'])

# Cerrar el puerto serial.
serial.Serial.close