LoRaWan – Probador de campo con OLED Archivo.ino

Pantalla OLED con parametros RSSI UP/DOWN

Probador de Rssi de subida y bajada

Hardware: Heltec cubecell AB02, con pantalla OLED incorporada.

OLED_pantalla.ino

void displayconectando(){
	display2.setFont(ArialMT_Plain_16);
	display2.setTextAlignment(TEXT_ALIGN_CENTER);
	display2.clear();
	display2.drawString(58, 22, "Joining...");
	display2.display();
}
void displayConectado(){
	display2.clear();
	display2.drawString(64, 22, "Conectado_OK");
	display2.display();
	delay(500);
}
void displayTransmitiendo(){
	digitalWrite(Vext,LOW);
	display2.init();
	display2.setFont(ArialMT_Plain_16);
	display2.setTextAlignment(TEXT_ALIGN_CENTER);
	display2.clear();
	display2.drawString(58, 22, "Tx...");
	display2.display();
	delay(500);
}
void displayPaqRecibido(){
  char temp[25];
	display2.clear();
  display2.setFont(ArialMT_Plain_16);
  display2.setTextAlignment(TEXT_ALIGN_LEFT);
  sprintf(temp,"Rx snr:%d,dr:%d",Down_snr, Down_datarate);
	display2.drawString(0, 0, temp); //22
	sprintf(temp,"rssiDw: -%d",Down_rssi);
	display2.setFont(ArialMT_Plain_24);
	display2.setTextAlignment(TEXT_ALIGN_RIGHT);
	display2.drawString(128, 16, temp);
  sprintf(temp,"rssiUp: -%d",Up_rssi);
	display2.setFont(ArialMT_Plain_24);
	display2.setTextAlignment(TEXT_ALIGN_RIGHT);
	display2.drawString(128, 40, temp);

  display2.drawString(0,0, temp);
	if(loraWanClass==CLASS_A)	{
		display2.setFont(ArialMT_Plain_10);
		display2.setTextAlignment(TEXT_ALIGN_LEFT);
		display2.drawString(28, 50, "Into deep sleep in 2S");
	}
	display2.display();
  delay(10000);
  display2.clear();
	if(loraWanClass==CLASS_A){
		digitalWrite(Vext,HIGH);
		display2.stop();
	}
}

void displayAckRecibido(){
  char temp[25];
	display2.clear();
  display2.setFont(ArialMT_Plain_16);
  display2.setTextAlignment(TEXT_ALIGN_LEFT);
  sprintf(temp,"ACK snr:%d,dr:%d",confirmaSnr, confirmaDatarate);
	display2.drawString(0, 0, temp); //22
	sprintf(temp,"rssiDw: -%d",confirmaRssi);
	display2.setFont(ArialMT_Plain_24);
	display2.setTextAlignment(TEXT_ALIGN_RIGHT);
	display2.drawString(128, 16, temp);
	if(loraWanClass==CLASS_A)	{
		display2.setFont(ArialMT_Plain_10);
		display2.setTextAlignment(TEXT_ALIGN_LEFT);
		display2.drawString(28, 50, "Into deep sleep in 2S");
	}
	display2.display();
  delay(10000);
	if(loraWanClass==CLASS_A)	{
		digitalWrite(Vext,HIGH);
		display2.stop();
	}
}

CubeCell_Practicas2023OLED.ino

// Lectura de Rssi Snr, datarate Up/Downlink
// Datos Downlink de la trama de confirmación anterior
// http://blog.espol.edu.ec/girni/lorawan-enlaces-up-down-archivo-ino/
#include "LoRaWan_APP.h"
#include "Arduino.h"
#include <Wire.h>               
#include "HT_SH1107Wire.h"

SH1107Wire  display2(0x3c, 500000, SDA, SCL ,GEOMETRY_128_64,GPIO10); // addr, freq, sda, scl, resolution, rst

/* set LoraWan_RGB to Active,the RGB active in loraWan
 * red   |sending;   purple | joined done;
 * blue  |RxWindow1; yellow | means RxWindow2;
 * green | received done;
 */
/* Conexión LoRa: OTAA parametros*/
uint8_t devEui[] = { 0xa5, 0x3e, 0xc6, 0x15, 0xae, 0xde, 0x3f, 0x50 };
uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t appKey[] = { 0x88, 0xbe, 0x25, 0xca, 0x2c, 0xcf, 0x31, 0x85,
                     0x51, 0x2d, 0xee, 0xe2, 0x80, 0x31, 0x8e, 0x01 };
/* ABP parametros*/
uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe,
                      0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda,0x85 };
uint8_t appSKey[] = { 0x47, 0xdc, 0xac, 0x5f, 0xc2, 0x32, 0x24, 0x31, 
                      0xdf, 0xf1, 0xff, 0xf9, 0x46, 0xe5, 0x2e, 0x17 };
uint32_t devAddr =  ( uint32_t )0x007bc4150;
/*LoraWan channelsmask, default channels 0-7*/ 
uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 };

/*Select in arduino IDE tools*/
LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;
DeviceClass_t  loraWanClass = LORAWAN_CLASS;
bool overTheAirActivation = LORAWAN_NETMODE;
bool loraWanAdr = LORAWAN_ADR;
bool keepNet = LORAWAN_NET_RESERVE;
bool isTxConfirmed = LORAWAN_UPLINKMODE;

uint8_t duermemin = 0; //15
uint8_t duermeseg = 300; //0

uint32_t appTxDutyCycle = (duermemin*60 + duermeseg)*1000; // min*seg*ms

uint8_t appPort = 4; /* Application port */
/* trials to transmit frame, if didn't receive ack.
 * The MAC performs a datarate adaptation,
 * Tx nb|Data Rate
 * -----|----------
 * 1    |DR           * 5    | max(DR-2,0)
 * 2    |DR           * 6    | max(DR-2,0)
 * 3    |max(DR-1,0)  * 7    | max(DR-3,0)
 * 4    |max(DR-1,0)  * 8    | max(DR-3,0)
*/
uint8_t confirmedNbTrials = 4;

// Ack parametros de recepción
uint8_t confirmaRssi = 0;
uint8_t confirmaSnr = 0;
uint8_t confirmaDatarate = 0;

// Ack parametros de recepción
uint8_t Down_rssi = 0;
uint8_t Down_snr = 0;
uint8_t Down_datarate = 0;

uint8_t Up_rssi = 0;

uint8_t itera = 0;
uint8_t estado = 0; //0x00, 0x01,"OFF","ON"

void setup() {
	Serial.begin(115200);
 
#if(AT_SUPPORT)
	enableAt();
#endif

  // OLED display status
  //LoRaWAN.displayMcuInit();
  
	deviceState = DEVICE_STATE_INIT;
	//LoRaWAN.ifskipjoin(); //if joinned,skip

  display2.init();
  display2.setFont(ArialMT_Plain_10);
}

void loop() {
  Serial.print(".");
  itera = itera + 1;
  if (itera>6){
    itera = 0;
    Serial.println(" ");
  }
	switch( deviceState ) {
		case DEVICE_STATE_INIT: {
#if(LORAWAN_DEVEUI_AUTO)
			LoRaWAN.generateDeveuiByChipID();
#endif
#if(AT_SUPPORT)
			getDevParam();
#endif
			printDevParam();
			LoRaWAN.init(loraWanClass,loraWanRegion);
			deviceState = DEVICE_STATE_JOIN;
			break;
		}
		case DEVICE_STATE_JOIN: {
      //LoRaWAN.displayJoining();
      displayconectando();
			LoRaWAN.join();
			break;
		}
		case DEVICE_STATE_SEND:	{
      //LoRaWAN.displaySending();
      displayTransmitiendo();
			prepareTxFrame( appPort );
			LoRaWAN.send();
			deviceState = DEVICE_STATE_CYCLE;
			break;
		}
		case DEVICE_STATE_CYCLE: {
			// Schedule next packet transmission
			txDutyCycleTime = appTxDutyCycle + randr( 0, APP_TX_DUTYCYCLE_RND );
			LoRaWAN.cycle(txDutyCycleTime);
			deviceState = DEVICE_STATE_SLEEP;
			break;
		}
		case DEVICE_STATE_SLEEP: {
      //LoRaWAN.displayAck();
			LoRaWAN.sleep();
			break;
		}
		default: {
			deviceState = DEVICE_STATE_INIT;
			break;
		}
	}
}

LoRaWanEnvia.ino

/* Prepares the payload of the frame */
static void prepareTxFrame( uint8_t port ) {
  // enciende sensor
  pinMode(Vext, OUTPUT);
  digitalWrite(Vext, LOW);
  //Lectura de Sensor

  //apaga sensor
  digitalWrite(Vext, HIGH);
  
  // lectura de bateria  
  uint16_t batteryVoltage = getBatteryVoltage();
  unsigned char *puc;

  // trama
  appDataSize = 5;
  appData[0] = confirmaRssi; //Ack leido en dispositivo
  appData[1] = confirmaSnr;
  appData[2] = confirmaDatarate;
  appData[3] = (uint8_t)batteryVoltage;
  appData[4] = (uint8_t)(batteryVoltage>>8);

  Serial.print("%, Bateria = ");
  Serial.println(batteryVoltage);
}

LoRaWanRecibe.ino

//downlink data handle function example
void downLinkDataHandle(McpsIndication_t *mcpsIndication){
  // parametros de recepcion
  Down_rssi = uint8_t(abs(mcpsIndication->Rssi));
  Down_snr  = uint8_t(mcpsIndication->Snr);
  Down_datarate = uint8_t(mcpsIndication->RxDoneDatarate);
  // recibido de trama
  Up_rssi = uint8_t(mcpsIndication->Buffer[0]);

  //
  Serial.print("Rx Down_rssi:-"); Serial.print(Down_rssi);
  Serial.print(", Down_snr:");Serial.print(Down_snr);
  Serial.print(", Down_datarate: ");Serial.println(Down_datarate);
  Serial.print(" UP_rssi:");
  Serial.print(-1*Up_rssi);
  Serial.printf(" +REV DATA:%s,RXSIZE %d,PORT %d\r",mcpsIndication->RxSlot?"RXWIN2":"RXWIN1",mcpsIndication->BufferSize,mcpsIndication->Port);
  Serial.println();
  
  displayPaqRecibido();
}

LoRaWanRecibeConfirma.ino

void downLinkAckHandle(McpsIndication_t *mcpsIndication){
  // ACK parametros de recepcion
  confirmaRssi = uint8_t(abs(mcpsIndication->Rssi));
  confirmaSnr  = uint8_t(mcpsIndication->Snr);
  confirmaDatarate = uint8_t(mcpsIndication->RxDoneDatarate);

  Serial.println("");
  Serial.print(" ack received(rssi,snd,datarate): -");
  Serial.print(confirmaRssi);Serial.print(" ,");
  Serial.print(confirmaSnr);Serial.print(" ,");
  Serial.println(confirmaDatarate);
  
  displayAckRecibido();
}