Hallo,
Ich möchte mir eine Wetterstation mit dem o.g. Board, einem BME280 und einem Solarpanel aufbauen.
Das Board kommt mit einer eigenen Bordverwalter-URL (im Gegensatz zu den ESP32 Heltec LoRa Bords) für die Arduino IDE und eigenen Bibliotheken. Hier das einzige LoRa-Beispiel "SendReceive", welches unter LoRaWanMinimal in den Beispielscripten auftaucht:
/**
* This is an example of joining, sending and receiving data via LoRaWAN using a more minimal interface.
*
* The example is configured for OTAA, set your keys into the variables below.
*
* The example will upload a counter value periodically, and will print any downlink messages.
*
* please disable AT_SUPPORT in tools menu
*
* David Brodrick.
*/
#include "LoRaWanMinimal_APP.h"
#include "Arduino.h"
/*
* set LoraWan_RGB to Active,the RGB active in loraWan
* RGB red means sending;
* RGB purple means joined done;
* RGB blue means RxWindow1;
* RGB yellow means RxWindow2;
* RGB green means received done;
*/
//Set these OTAA parameters to match your app/node in TTN
static uint8_t devEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t appKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 };
static uint8_t counter=0;
///////////////////////////////////////////////////
//Some utilities for going into low power mode
TimerEvent_t sleepTimer;
//Records whether our sleep/low power timer expired
bool sleepTimerExpired;
static void wakeUp()
{
sleepTimerExpired=true;
}
static void lowPowerSleep(uint32_t sleeptime)
{
sleepTimerExpired=false;
TimerInit( &sleepTimer, &wakeUp );
TimerSetValue( &sleepTimer, sleeptime );
TimerStart( &sleepTimer );
//Low power handler also gets interrupted by other timers
//So wait until our timer had expired
while (!sleepTimerExpired) lowPowerHandler();
TimerStop( &sleepTimer );
}
///////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
if (ACTIVE_REGION==LORAMAC_REGION_AU915) {
//TTN uses sub-band 2 in AU915
LoRaWAN.setSubBand2();
}
LoRaWAN.begin(LORAWAN_CLASS, ACTIVE_REGION);
//Enable ADR
LoRaWAN.setAdaptiveDR(true);
while (1) {
Serial.print("Joining... ");
LoRaWAN.joinOTAA(appEui, appKey, devEui);
if (!LoRaWAN.isJoined()) {
//In this example we just loop until we're joined, but you could
//also go and start doing other things and try again later
Serial.println("JOIN FAILED! Sleeping for 30 seconds");
lowPowerSleep(30000);
} else {
Serial.println("JOINED");
break;
}
}
}
///////////////////////////////////////////////////
void loop()
{
//Counter is just some dummy data we send for the example
counter++;
//In this demo we use a timer to go into low power mode to kill some time.
//You might be collecting data or doing something more interesting instead.
lowPowerSleep(15000);
//Now send the data. The parameters are "data size, data pointer, port, request ack"
Serial.printf("\nSending packet with counter=%d\n", counter);
//Here we send confirmed packed (ACK requested) only for the first five (remember there is a fair use policy)
bool requestack=counter<5?true:false;
if (LoRaWAN.send(1, &counter, 1, requestack)) {
Serial.println("Send OK");
} else {
Serial.println("Send FAILED");
}
}
///////////////////////////////////////////////////
//Example of handling downlink data
void downLinkDataHandle(McpsIndication_t *mcpsIndication)
{
Serial.printf("Received downlink: %s, RXSIZE %d, PORT %d, DATA: ",mcpsIndication->RxSlot?"RXWIN2":"RXWIN1",mcpsIndication->BufferSize,mcpsIndication->Port);
for(uint8_t i=0;i<mcpsIndication->BufferSize;i++) {
Serial.printf("%02X",mcpsIndication->Buffer[i]);
}
Serial.println();
}
Wenn ich meine TTN Keys eintrage, kann ich eine Verbindung herstellen, aber es wird keine Payload übertragen (dabei benutzte ich den Default Payload Formatter von TTN).
Nun habe ich das Script folgendermaßen angepasst, damit ich Werte für Temperatur und Feuchtigkeit übertragen kann:
/**
* This is an example of joining, sending and receiving data via LoRaWAN using a more minimal interface.
*
* The example is configured for OTAA, set your keys into the variables below.
*
* The example will upload a counter value periodically, and will print any downlink messages.
*
* please disable AT_SUPPORT in tools menu
*
* David Brodrick.
*/
#include "LoRaWanMinimal_APP.h"
#include "Arduino.h"
/*
* set LoraWan_RGB to Active,the RGB active in loraWan
* RGB red means sending;
* RGB purple means joined done;
* RGB blue means RxWindow1;
* RGB yellow means RxWindow2;
* RGB green means received done;
*/
//Set these OTAA parameters to match your app/node in TTN
uint8_t devEui[] = {0x70, 0xB3, 0xD5, ...};
uint8_t appEui[] = {0x49, 0x85, 0x55, ...};
uint8_t appKey[] = {0x9E, 0x92, 0x86, ...};
uint16_t userChannelsMask[6] = {0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000};
static uint8_t counter = 0;
// New: declare appData array
uint8_t appData[4];
///////////////////////////////////////////////////
//Some utilities for going into low power mode
TimerEvent_t sleepTimer;
//Records whether our sleep/low power timer expired
bool sleepTimerExpired;
static void wakeUp()
{
sleepTimerExpired = true;
}
static void lowPowerSleep(uint32_t sleeptime)
{
sleepTimerExpired = false;
TimerInit(&sleepTimer, &wakeUp);
TimerSetValue(&sleepTimer, sleeptime);
TimerStart(&sleepTimer);
//Low power handler also gets interrupted by other timers
//So wait until our timer had expired
while (!sleepTimerExpired) lowPowerHandler();
TimerStop(&sleepTimer);
}
///////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
if (ACTIVE_REGION == LORAMAC_REGION_AU915) {
//TTN uses sub-band 2 in AU915
LoRaWAN.setSubBand2();
}
LoRaWAN.begin(LORAWAN_CLASS, ACTIVE_REGION);
//Enable ADR
LoRaWAN.setAdaptiveDR(true);
while (1) {
Serial.print("Joining... ");
LoRaWAN.joinOTAA(appEui, appKey, devEui);
if (!LoRaWAN.isJoined()) {
//In this example we just loop until we're joined, but you could
//also go and start doing other things and try again later
Serial.println("JOIN FAILED! Sleeping for 30 seconds");
lowPowerSleep(30000);
} else {
Serial.println("JOINED");
break;
}
}
}
///////////////////////////////////////////////////
void loop()
{
//Counter is just some dummy data we send for the example
counter++;
//In this demo we use a timer to go into low power mode to kill some time.
//You might be collecting data or doing something more interesting instead.
lowPowerSleep(15000);
//Now send the data. The parameters are "data size, data pointer, port, request ack"
Serial.printf("\nSending packet with counter=%d\n", counter);
//Here we send confirmed packed (ACK requested) only for the first five (remember there is a fair use policy)
bool requestack = counter<5?true:false;
prepareTxFrame();
if (LoRaWAN.send(1, appData, 2, requestack)) {
Serial.println("Send OK");
} else {
Serial.println("Send FAILED");
}
}
///////////////////////////////////////////////////
//Example of handling downlink data
void downLinkDataHandle(McpsIndication_t *mcpsIndication)
{
Serial.printf("Received downlink: %s, RXSIZE %d, PORT %d, DATA: ",mcpsIndication->RxSlot?"RXWIN2":"RXWIN1",mcpsIndication->BufferSize,mcpsIndication->Port);
for(uint8_t i=0;i<mcpsIndication->BufferSize;i++) {
Serial.printf("%02X",mcpsIndication->Buffer[i]);
}
Serial.println();
}
/* Prepares the payload of the frame */
static void prepareTxFrame()
{
/*appData size is LORAWAN_APP_DATA_MAX_SIZE which is defined in "commissioning.h".
*appDataSize max value is LORAWAN_APP_DATA_MAX_SIZE.
*if enabled AT, don't modify LORAWAN_APP_DATA_MAX_SIZE, it may cause system hanging or failure.
*if disabled AT, LORAWAN_APP_DATA_MAX_SIZE can be modified, the max value is reference to lorawan region and SF.
*for example, if use REGION_CN470,
*the max value for different DR can be found in MaxPayloadOfDatarateCN470 refer to DataratesCN470 and BandwidthsCN470 in "RegionCN470.h".
*/
float temperature = 20.30; // Example
float humidity = 65.2; // Example
int int_temp = temperature * 100; // Remove comma
int int_hum = humidity * 10; // Remove comma
appData[0] = int_temp >> 8;
appData[1] = int_temp;
appData[2] = int_hum >> 8;
appData[3] = int_hum;
}
Dazu habe ich folgenden Payload Formatter hinterlegt:
function decodeUplink(input) {
var temp = input.bytes[0] << 8 | input.bytes[1];
var hum = input.bytes[2] << 8 | input.bytes[3];
return {
data: {
temperature: temp/100,
humidity: hum/10
}
};
}
Allerdings bekomme ich immer nur die folgende Ausgabe in den 'Live data':
{ humidity: 0, temperature: 17.2 } … also statt 62.5 und 20.30
Kann mir jemand sagen, wo mein Fehler liegt?
Vielen Dank!
Martin