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:
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