Categoría: LoRaWan - Probador con OLED en campo

  • LoRaWan - Probador con OLED en Chirpstack y HomeAssistant

    ChirpStack

    DECODER

    function Decode(fPort, bytes, variables) {
      var Down_rssi = -1*parseInt(bytes[0]);
      var Down_snr = bytes[1];
      var Down_datarate = bytes[2];
      // usando entero
      var unalectura = (bytes[4] << 8) |(bytes[3]);
      unalectura = (unalectura/1000);
      unalectura = +unalectura.toFixed(2);
      var appData = {'Down_rssi':Down_rssi,'Down_snr':Down_snr,
                     'Down_datarate':Down_datarate,
                     'bateria_V': unalectura}
      return appData;
    }
    

    ENCODER

    function Encode(fPort, obj, variables) {
      var UP_rssi = obj["UP_rssi"];
      // var Up_snr = obj["UP_snr"];
      var mensaje = [UP_rssi];
      return mensaje;
    }
    

    Home Assistant

    configuration.yaml

    mqtt:
      sensor:
        - name: "rssi_up_cc50"
          unique_id: cc27rssiup
          state_topic: "application/1/device/a53ec615aede3f50/event/up"
          unit_of_measurement: "dBm"
          value_template: "{{ value_json.rxInfo[0].rssi}}"
          #availability:
          #  - topic: "home/sensor1/status"
          payload_available: "online"
          payload_not_available: "offline"
          json_attributes_topic: "application/1/device/a53ec615aede3f50/event/up"
    
    

    Automation

    Desencadenante

    platform: mqtt
    topic: application/1/device/a53ec615aede3f50/event/up
    

    Accion

    service: mqtt.publish
    data:
      qos: 0
      retain: false
      topic: application/1/device/a53ec615aede3f50/command/down
      payload: '{"confirmed":false,"fPort":4,"object":{"UP_rssi":{{(states("sensor.rssi_up_cc50") | int)*(-1)}}}}'
    
  • 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();
    }