El desarrollo del ejercicio se simplifica al tratarse como una extensión del ejemplo base de comunicación Lora al que se añade el Sensor DHT11.
ChirpStack - Añadir un dispositivo
El archivo de instrucciones se presenta en tres secciones o pestañas. La primera contiene la declaración de variables, la parte de configuración y el lazo principal. Las siguientes dos secciones son procedimientos para preparación de trama y lectura de sensor.
Preparación de trama
El valor de temperatura se almacena en tipo real (float) que usa 4 bytes. En la trama se separan los bytes en orden LSB (Byte menos significativo primero, detalle que hay que recordar para decodificar en ChirpStack.
unsigned char *puc;
puc = (unsigned char *)(&temperaturaC);
appDataSize = 8;//AppDataSize max value is 64
appData[0] = puc[0];
appData[1] = puc[1];
appData[2] = puc[2];
appData[3] = puc[3];
De utilizar el mismo formato para el valor de Humedad, el formato es muy semejante.
Intrucciones Principales
/*
* HelTec Automation(TM) LoRaWAN 1.0.2 OTAA example use OTAA, CLASS A
* Solo ESP32+LoRa series boards con licencia http: / /www.heltec.cn /search /);
*https: / /github.com /HelTecAutomation /ESP32_LoRaWAN
* /
#include <ESP32_LoRaWAN.h>
#include "Arduino.h"
#include <DHT.h>
/*licencia Heltec ESP32 LoRaWan http: / /resource.heltec.cn /search * /
uint32_t license[4] = {0xBE21335B, 0xAEC3C5CE, 0xCC0A1CF4, 0xB836F981};
/* OTAA parametros* /
uint8_t DevEui[] = { 0x01, 0x20, 0x08, 0x93, 0xdf, 0x80, 0x37, 0x74 };
uint8_t AppEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t AppKey[] = { 0x05, 0x8e, 0xeb, 0xff, 0x24, 0xf1, 0x01, 0x84, 0xd0, 0x07, 0xbe, 0xd4, 0x65, 0xe7, 0x6b, 0xb5 };
/* ABP parametros* /
uint32_t DevAddr = ( uint32_t )0x0174b1fd;
uint8_t NwkSKey[] = { 0xc1, 0x45, 0x31, 0x28, 0x5f, 0xb2, 0x56, 0x3b, 0x9d, 0x5f, 0x27, 0x15, 0xed, 0x3a, 0x0e, 0xbc};
uint8_t AppSKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/ /LoraWan channelsmask, default channels 0-7 /
uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 };
DeviceClass_t loraWanClass = CLASS_A; /*Soporte de A and C* /
uint32_t appTxDutyCycle = 300000; /*15000; en [ms]* /
bool overTheAirActivation = true; /*OTAA or ABP* /
bool loraWanAdr = true; /*ADR enable* /
bool isTxConfirmed = true; /*confirmed or unconfirmed messages * /
uint8_t appPort = 2; /* Application port * /
/* reintentos de transmisión, en caso de no recibir ack * /
uint8_t confirmedNbTrials = 8;
/* Seleccionado de Arduino IDE tools * /
uint8_t debugLevel = LoRaWAN_DEBUG_LEVEL;
LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;
/ / variables de sensor /actuador
uint8_t contador = 0;
float humedad = 0;
float temperaturaC = 0;
float temperaturaF = 0;
/ / Mensajes por Puerto Serial
volatile boolean serial_msg = true;
/ / Sensor humedad y temperatura
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
void setup(){
if (serial_msg){
Serial.begin(115200);
while (!Serial);
}
SPI.begin(SCK,MISO,MOSI,SS);
Mcu.init(SS,RST_LoRa,DIO0,DIO1,license);
deviceState = DEVICE_STATE_INIT;
/ / SENSOR Temperatura&Humedad
dht.begin();
}
void loop(){
switch( deviceState ) {
case DEVICE_STATE_INIT: {
LoRaWAN.init(loraWanClass,loraWanRegion);
break;
}
case DEVICE_STATE_JOIN: {
LoRaWAN.join();
break;
}
case DEVICE_STATE_SEND: {
prepareTxFrame( appPort );
LoRaWAN.send(loraWanClass);
deviceState = DEVICE_STATE_CYCLE;
break;
}
case DEVICE_STATE_CYCLE: {
/ / Schedule next packet transmission
txDutyCycleTime = appTxDutyCycle + randr( -APP_TX_DUTYCYCLE_RND,
APP_TX_DUTYCYCLE_RND );
LoRaWAN.cycle(txDutyCycleTime);
deviceState = DEVICE_STATE_SLEEP;
break;
}
case DEVICE_STATE_SLEEP: {
LoRaWAN.sleep(loraWanClass,debugLevel);
break;
}
default: {
deviceState = DEVICE_STATE_INIT;
break;
}
}
}
Preparación de trama
// Trama - integra datos
static void prepareTxFrame( uint8_t port ){
contador = contador + 1;
// Sensor de Temperatura y Humedad
SensorTempHum();
if (isnan(humedad) || isnan(temperaturaC) || isnan(temperaturaF)) {
humedad = 0;
temperaturaC = 0;
temperaturaF = 0;
}
unsigned char *puc;
puc = (unsigned char *)(&temperaturaC);
appDataSize = 8;//AppDataSize max value is 64
appData[0] = puc[0];
appData[1] = puc[1];
appData[2] = puc[2];
appData[3] = puc[3];
puc = (unsigned char *)(&humedad);
appData[4] = puc[0];
appData[5] = puc[1];
appData[6] = puc[2];
appData[7] = puc[3];
if (serial_msg){
Serial.print("tx: "+String(temperaturaC)+" ");
Serial.print(appData[0]);
Serial.print(appData[1]);
Serial.print(appData[2]);
Serial.println(appData[3]);
Serial.print("tx: "+String(humedad)+" ");
Serial.print(appData[4]);
Serial.print(appData[5]);
Serial.print(appData[6]);
Serial.println(appData[7]);
}
}
Lectura de sensor
void SensorTempHum(){
// SENSOR Temperatura&Humedad
dht.begin(); // regresa de sleep
delay(2000); // espera minina entre lecturas de sensor
humedad = dht.readHumidity();
temperaturaC = dht.readTemperature();
temperaturaF = dht.readTemperature(true);
if (isnan(humedad) || isnan(temperaturaC) || isnan(temperaturaF)) {
if (serial_msg){
Serial.println(F("Failed to read from DHT sensor!"));
}
// espera minina entre lecturas de sensor
delay(100);
return;
}
float hif = dht.computeHeatIndex(temperaturaF, humedad);
float hic = dht.computeHeatIndex(temperaturaC, humedad, false);
if (serial_msg){
Serial.print(F(" Humidity: "));
Serial.print(humedad);
Serial.print(F("% \n Temperature: "));
Serial.print(temperaturaC);
Serial.print(F("°C "));
Serial.print(temperaturaF);
Serial.print(F("°F \n Heat index: "));
Serial.print(hic);
Serial.print(F("°C "));
Serial.print(hif);
Serial.println(F("°F"));
}
}