2.1 Captura datos. Balizas y dispositivo – configuración algoritmo.ino

Instrucciones para el dispositivo en Arduino IDE

El esquema para baliza y dispositivo propuesto para el modelo de localización usa el modelo multipunto de LoRa que usa direcciones para identificar la función de cada elemento:

  • Baliza: d1,d2,d3
  • Dispositivo: c1

El esquema se muestra simplificado para un solo punto, se plantea usar el dispositivo ‘C1’ como punto de captura de datos hacia un archivo tipo texto mediante la conexión USB a un computador portatil.

En el dispositivo, por cada paquete recibido se toman los datos del paquete y valores medidos, creando un registro de trama con: el tipo rx/tx, id receptor, remitente, los datos recibidos y lecturas de RSSI y SNR del paquete recibido desde el remitente que es cada baliza.

    rssi_lorarx = LoRa.packetRssi();
    snr_lorarx = LoRa.packetSnr();

Registro de la trama de datos

El registro de la trama de datos recibida en el computador se compone de la parte de datos recibido y las lecturas de Rssi-SNR del paquete. El orden de los datos se muestra en la tabla:

esquema de trama de datos
 tipo receptor remitente dato1 dato2 dato3 Rssi recibido SNR recibido
rx, tx c1, ff d1, d2, d3 medido en el dispositivo medido en el dispositivo

Ejemplo de trama recibida:

rx,c1,d3,36,-62,6.00,-65,6.00
tx,ff,c1,2,-65,6.00,-65,6.00
rx,c1,d2,21,-130,6.00,-130,6.00
rx,c1,d1,138,-98,18.75,-131,10.25

Para obtener los valores de Rssi y SNR de recepción desde cada baliza, se emite periódicamente un paquete de difusión (‘ff’) desde el dispositivo c1. Los valores recibidos en la baliza se replican en los datos del próximo paquete de la baliza hacia el dispositivo c1, que corresponden a dato2 y dato3.

Para revisar la secuencia del paquete se registra un contador desde el emisor, enviado en la posición de dato1.

Configurar la función de baliza o dispositivo

se  establece mediante las direcciones de envío y recepción descritas en la sección principal del algoritmo.

Para el dispositivo la dirección local es C1 , para las balizas serán D1, D2, D3.

En el dispositivo se usa la dirección local ‘C1’, y como destino una trama de difusión ‘FF’ hacia todas las balizas de tal manera que cada baliza pueda medir el nivel de recepción de la señal emitida desde el dispositivo.

// Direcciones Enviar mensaje
byte dir_local   = 0xC1; // Concentrador 1
byte dir_destino = 0xFF; // Broadcast para medir Rssi
byte msjtxContador = 0;

En las balizas,  la dirección local de la baliza es D1, D2, D3, y la dirección destino es el dispositivo.

// Direcciones Enviar mensaje
byte dir_local   = 0xD1; // Baliza 1
byte dir_destino = 0xC1; // Dispositivo

Otros parámetros como tiempo entre paquetes, se configuran de acuerdo a las lecturas que se tomarán en un intervalo de tiempo. El parámetro t_ciclotx establece el intervalo de tiempo en que cada dispositivo o baliza emite un paquete.

Para LoRa, los tiempos de envio de paquetes son bastante largos de acuerdo al diseño básico de la red estándar, sin embargo durante el experimiento para tomar las lecturas más rápido en cada ubicación de prueba se puede reducir a por ejemplo, 10 segundos (10000ms)

int  t_ciclotx =10000;

otros detalles de configuración del dispositivo se pueden revisar en la sección de referencias al final de la hoja.


Módulos LoRa

El prototipo se implentó con los módulos de desarrollo Heltec Lora 32 V2 disponibles al momento de las pruebas. Los módulos son de 915MHz, y se usaron también con las pruebas de conexión multipunto descritas en LoRa Multipunto – Esquema


Instrucciones en Arduino

Las instrucciones del dispositivo escritas usando el IDE Arduino se presentan en secciones o bloques:

  • Principal: LoRa_Listener02
  • Receptor: LoRaReceptor
  • Transmisor: LoRaTransmisor
  • Sensor: Sensores


Sección principal

/* Pruebas de Rssi y SNR multipunto, esquema de triangulación
  Nodo- Receptor. http://blog.espol.edu.ec/girni/
  Septiembre-2020 */
#include "heltec.h"

// SENSOR Parpadeo
String sensorBlink = "ON"; // inicializa on/off: 1/0

// Direcciones Enviar mensaje
byte dir_local   = 0xC1; // Concentrador 1
byte dir_destino = 0xFF; // Broadcast para medir Rssi
byte msjtxContador = 0;
int  t_ciclotx = 10000;
long t_anterior = 0;
int  t_intervalo = 3000;

// Direcciones Mensaje Recibido
byte dir_envio = 0xC1;
int dir_remite = 0xFF; 
String paqueteRcb = "";
byte   paqrcbID = 0;
byte   paqrcbEstado = 0;
       // 0:vacio, 1: nuevo, 2:incompleto
       // 3:otro destinatario, 4:Broadcast

int  rssi_lorarx = 0;
float snr_lorarx = 0;

// Mensajes por Puerto Serial
volatile boolean serial_msj = true;

#define BAND    915E6  // 868E6,915E6

void setup() {
  Heltec.begin(false /*DisplayEnable Enable*/,
               true /*Heltec.LoRa Disable*/,
               serial_msj /*Serial Enable*/,
               true /*PABOOST Enable*/,
               BAND /*long BAND*/);
  LoRa.setSpreadingFactor(8);
  LoRa.receive();
}

void loop() {

  // LoRa enviar mensajes entre intervalos
  long t_ahora = millis();
  long t_transcurrido = t_ahora - t_anterior;
 
  if (t_transcurrido >= t_intervalo){
    t_anterior = t_ahora;
    t_intervalo = t_ciclotx + random(1000);
    
    // sensorParpadea(); //actualiza sensor
    sensorBlink = String(rssi_lorarx)+","+String(snr_lorarx);
    
    String paqueteEnv = String(sensorBlink).c_str() ;
    enviarlora(dir_destino, dir_local,
               msjtxContador, paqueteEnv);
    yield();

    // mensaje a serial
    if (serial_msj==true){
      // muestra todos paqrcbEstado
      Serial.print("tx,");
      Serial.print(String(dir_destino,HEX)+",");
      Serial.print(String(dir_local,HEX)+",");
      Serial.print(String(msjtxContador)+",");
      Serial.print(String(paqueteEnv)+",");
      Serial.print(String(rssi_lorarx)+",");
      Serial.println(snr_lorarx);
    }
    
    msjtxContador = msjtxContador + 1;
    
    // LED parpadea envio LoRa
    digitalWrite(LED, HIGH); delay(100);
    digitalWrite(LED, LOW);  delay(100);
    yield(); // procesa wifi
  }

  // LoRa revisar mensajes entrantes
  int msjRcbLoRa = LoRa.parsePacket();
  if (msjRcbLoRa !=0){ //¿mensaje no vacio?
    recibirlora(msjRcbLoRa);
    rssi_lorarx = LoRa.packetRssi();
    snr_lorarx = LoRa.packetSnr();
    
    if (serial_msj==true){
      // muestra todos los tipos
      //Serial.print("Paquete recibido, Estado: ");
      //Serial.println(paqrcbEstado);
      Serial.print("rx,");
      Serial.print(String(dir_envio,HEX)+",");
      Serial.print(String(dir_remite,HEX)+",");
      Serial.print(String(paqrcbID)+",");
      Serial.print(String(paqueteRcb)+",");
      Serial.print(String(rssi_lorarx)+",");
      Serial.println(String(snr_lorarx));
    }
    yield(); // procesa wifi
  }
}

Sección Receptor

En esta sección se revisa la trama, separando cada una de las partes del paquete recibido: dirección de envío, dirección de remitente, identificador del paquete generado por un contador de secuencia.

Se verifica que el destinatario del paquete, si el tamaño de la trama indica que el mensaje está completo, si la trama es de difusión (broadcast) usada para registrar los niveles de recepción.

void recibirlora(int tamano){
  if (tamano == 0){ 
    paqrcbEstado = 0; //vacio
    return;
    }
    
  // lectura de paquete
  paqueteRcb = "";
  dir_envio = LoRa.read();
  dir_remite  = LoRa.read();
  paqrcbID = LoRa.read();
  byte paqrcbTamano = LoRa.read();
  while(LoRa.available()){
    paqueteRcb += (char)LoRa.read();
  }
  if (paqrcbTamano != paqueteRcb.length()){
    paqrcbEstado = 2; // Tamaño incompleto
    return;
  }
  if (dir_envio != dir_local){
    if (dir_envio == 0xFF) {
      paqrcbEstado = 4; // Broadcast
    }else{
      paqrcbEstado = 3; // otro destino
    }
    return;
  }
  paqrcbEstado = 1;  // mensaje Nuevo
}

Sección de transmisor

En esta sección se verifica que el canal no se encuentre ocupado o que el dispositivo este listo para transmitir.

Se arma el paquete a enviar y se transmite.

void enviarlora(byte destino, byte remite,
                byte paqueteID, String paquete) {
  // espera que el radio esté listo
  // para enviar un paquete
  while(LoRa.beginPacket() == 0){
    if (serial_msj==true){
      Serial.println("Esperando radio disponible...");
    }
    yield(); // procesa wifi
    delay(100);
  }
  // envio del mensaje LoRa
  LoRa.beginPacket();
  LoRa.write(destino);
  LoRa.write(remite);
  LoRa.write(paqueteID);
  LoRa.write(paquete.length());
  LoRa.print(paquete);
  LoRa.endPacket();
}

Sección Sensor

La sección del sensor no es requerida para el registro de Rssi y SNR, por lo que se simula con un parpadeo de LED.

// Sensor Simulado
void sensorParpadea(){
    if (sensorBlink == "ON"){
      sensorBlink = "OFF";
    }else{
      sensorBlink = "ON";
    }
   return;
}

Referencias: LoRa Multipunto – Esquema