TTN Loop, keine Datenübertragung bei LoRaBee + SD-Bee + Display

Hallo liebe senseBox Community,

ich habe schon einige Projekte mit senseBox umgesetzt, doch bei diesem hier komme ich einfach nicht weiter. Ich möchte eine senseBox bauen, die Daten über das LoRaWAN überträgt, per Display anzeigt und zusätzlich per SD-Bee speichert. Jede Anwendung funktioniert problemlos einzen. SD-Bee und Display funktionieren zusammen. Die Kombination aller drei (oder auch nur einer Komponente + LoRa) macht jedoch Probleme.

Beim Programmieren habe ich diese Anleitung als Basis verwendet:

Wenn ich nur die Übertragung über das LoRaWAN verwende, kommen meine Daten problemlos an. Füge ich über Blockly dann noch die Bausteine für die SD-Speicherung und das Display hinzu, funktioniert LoRa plötzlich nicht mehr und im TTN wird ein Loop aus den Mitteilungen „Accept join request → sucessfully processed join request → forward join accept message“ angezeigt, bis sie nach einer Weile völig aufgibt und nichts mehr kommt

Meine Idee ist, dass sich durch die anderen Bausteine ein ungewollter Fehler eingebaut hat. Leider bin ich noch nicht genug im Thema, um den Fehler zu sehen. Ich kopiere den von Blockly erstellten Code immer in Arduino, um dort den Code zu überprüfen, doch auch Arduino zeigt mir keine Fehler an.

Hatte jemand vielleicht schon mal ein ähnliches Problem? Ich füge hier mal meinen Code ein. Sicherheitshalber habe ich die DevEUI und den AppKey ersetzt, daran liegt ja das Problem auch nicht.

#include <senseBoxIO.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h> // http://librarymanager/All#Adafruit_GFX_Library
#include <Adafruit_SSD1306.h> // http://librarymanager/All#Adafruit_SSD1306
#include <SD.h>
#include <lmic.h> // http://librarymanager/All#IBM_LMIC_framework
#include <hal/hal.h>
#include <bsec.h> // http://librarymanager/All#BSEC_Software_Library
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> // http://librarymanager/All#SparkFun_u-blox_GNSS_Arduino_Library
#include <CayenneLPP.h> // http://librarymanager/All#CayenneLPP

CayenneLPP lpp(51);
float bmeTemperatur;
float bmeHumidity;
double bmePressure;
float bmeIAQ;
float bmeIAQAccuracy;
int bmeCO2;
float bmeBreathVocEquivalent;

char tsBuffer[21];


  const long intervalInterval = 600000; // Intervall SD in ms
  long time_startInterval = 0;
  long time_actualInterval = 0;

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
File Data;

    static const u1_t PROGMEM APPEUI[8]= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI , 8);}

    static const u1_t PROGMEM DEVEUI[8]= {xxx};
    void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI , 8);}

    // This key should be in big endian format (or, since it is not really a
    // number but a block of memory, endianness does not really apply). In
    // practice, a key taken from ttnctl can be copied as-is.
    // The key shown here is the semtech default key.
    static const u1_t PROGMEM APPKEY[16] = {yyy};
    void os_getDevKey (u1_t* buf) {  memcpy_P(buf, APPKEY , 16);}

    static osjob_t sendjob;

    // Schedule TX every this many seconds (might become longer due to duty
    // cycle limitations).
    const unsigned TX_INTERVAL = 600; //LoRa Intervall in s

    // Pin mapping
    const lmic_pinmap lmic_pins = {
        .nss = PIN_XB1_CS,
        .rxtx = LMIC_UNUSED_PIN,
        .rst = LMIC_UNUSED_PIN,
        .dio = {PIN_XB1_INT, PIN_XB1_INT, LMIC_UNUSED_PIN},
    };
Bsec iaqSensor;
SFE_UBLOX_GNSS myGNSS;


    void initLora() {
      delay(2000);
      // LMIC init
      os_init();
      // Reset the MAC state. Session and pending data transfers will be discarded.
      LMIC_reset();
      LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);

      // Start job (sending automatically starts OTAA too)
      do_send(&sendjob);
    }

    void onEvent (ev_t ev) {
      Serial.print(os_getTime());
      Serial.print(": ");
      switch(ev) {
          case EV_SCAN_TIMEOUT:
              Serial.println(F("EV_SCAN_TIMEOUT"));
              break;
          case EV_BEACON_FOUND:
              Serial.println(F("EV_BEACON_FOUND"));
              break;
          case EV_BEACON_MISSED:
              Serial.println(F("EV_BEACON_MISSED"));
              break;
          case EV_BEACON_TRACKED:
              Serial.println(F("EV_BEACON_TRACKED"));
              break;
          case EV_JOINING:
              Serial.println(F("EV_JOINING"));
              break;
          case EV_JOINED:
              Serial.println(F("EV_JOINED"));

              // Disable link check validation (automatically enabled
              // during join, but not supported by TTN at this time).
              LMIC_setLinkCheckMode(0);
              break;
          case EV_RFU1:
              Serial.println(F("EV_RFU1"));
              break;
          case EV_JOIN_FAILED:
              Serial.println(F("EV_JOIN_FAILED"));
              break;
          case EV_REJOIN_FAILED:
              Serial.println(F("EV_REJOIN_FAILED"));
              break;
              break;
          case EV_TXCOMPLETE:
              Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
              if (LMIC.txrxFlags & TXRX_ACK)
                Serial.println(F("Received ack"));
              if (LMIC.dataLen) {
                Serial.println(F("Received "));
                Serial.println(LMIC.dataLen);
                Serial.println(F(" bytes of payload"));
              }
              // Schedule next transmission
              os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
              break;
          case EV_LOST_TSYNC:
              Serial.println(F("EV_LOST_TSYNC"));
              break;
          case EV_RESET:
              Serial.println(F("EV_RESET"));
              break;
          case EV_RXCOMPLETE:
              // data received in ping slot
              Serial.println(F("EV_RXCOMPLETE"));
              break;
          case EV_LINK_DEAD:
              Serial.println(F("EV_LINK_DEAD"));
              break;
          case EV_LINK_ALIVE:
              Serial.println(F("EV_LINK_ALIVE"));
              break;
           default:
              Serial.println(F("Unknown event"));
              break;
      }
  }

char* getTimeStamp()
{
  if (myGNSS.getTimeValid() == true)
    {
    sprintf(tsBuffer, "%04d-%02d-%02dT%02d:%02d:%02dZ",
    myGNSS.getYear(), myGNSS.getMonth(), myGNSS.getDay(), myGNSS.getHour(), myGNSS.getMinute(), myGNSS.getSecond());
    }
return tsBuffer;
}


    void printOnDisplay(String title1, String measurement1, String unit1, String title2, String measurement2, String unit2) {

      display.setCursor(0, 0);
      display.setTextSize(1);
      display.setTextColor(WHITE, BLACK);
      display.println(title1);
      display.setCursor(0, 10);
      display.setTextSize(2);
      display.print(measurement1);
      display.print(" ");
      display.setTextSize(1);
      display.println(unit1);
      display.setCursor(0, 30);
      display.setTextSize(1);
      display.println(title2);
      display.setCursor(0, 40);
      display.setTextSize(2);
      display.print(measurement2);
      display.print(" ");
      display.setTextSize(1);
      display.println(unit2);
    }




    void checkIaqSensorStatus(void)
  {
    if (iaqSensor.bsecStatus != BSEC_OK) {
      if (iaqSensor.bsecStatus < BSEC_OK) {
        for (;;)
          errLeds(); /* Halt in case of failure */
      }
    }

    if (iaqSensor.bme68xStatus != BME68X_OK) {
      if (iaqSensor.bme68xStatus < BME68X_OK) {
        for (;;)
          errLeds(); /* Halt in case of failure */
      }
    }
  }


  void errLeds(void)
  {
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
    digitalWrite(LED_BUILTIN, LOW);
    delay(100);
  }

  void do_send(osjob_t* j){
      // Check if there is not a current TX/RX job running
      if (LMIC.opmode & OP_TXRXPEND) {
          Serial.println(F("OP_TXRXPEND, not sending"));
      } else {
          lpp.reset();
            lpp.addTemperature(1, bmeTemperatur);
            lpp.addBarometricPressure(2, bmePressure);
            lpp.addRelativeHumidity(3, bmeHumidity);



          // Prepare upstream data transmission at the next possible time.
          LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0);
          Serial.println(F("Packet queued"));
      }
      // Next TX is scheduled after TX_COMPLETE event.
  }


void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3D);
display.display();
delay(100);
display.clearDisplay();
SD.begin(28);

Data = SD.open("Data.csv", FILE_WRITE);
Data.close();

Serial.begin(9600);
delay(1000);

  Data = SD.open("Data.csv", FILE_WRITE);
    Data.println("time, lat, long, temp, press, hum");
  Data.close();

Wire.begin();
iaqSensor.begin(BME68X_I2C_ADDR_LOW, Wire);
checkIaqSensorStatus();

bsec_virtual_sensor_t sensorList[13] = {
    BSEC_OUTPUT_IAQ,
    BSEC_OUTPUT_STATIC_IAQ,
    BSEC_OUTPUT_CO2_EQUIVALENT,
    BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
    BSEC_OUTPUT_RAW_TEMPERATURE,
    BSEC_OUTPUT_RAW_PRESSURE,
    BSEC_OUTPUT_RAW_HUMIDITY,
    BSEC_OUTPUT_RAW_GAS,
    BSEC_OUTPUT_STABILIZATION_STATUS,
    BSEC_OUTPUT_RUN_IN_STATUS,
    BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
    BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
    BSEC_OUTPUT_GAS_PERCENTAGE
};


iaqSensor.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP);
checkIaqSensorStatus();
 Wire.begin();

  if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
  {
    Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
    while (1);
  }

  myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
  myGNSS.saveConfiguration(); //Save the current settings to flash and BBR


initLora();


}


void loop() {

    if (iaqSensor.run()) {
      bmeTemperatur = iaqSensor.temperature;
      bmeHumidity = iaqSensor.humidity;
      bmePressure = iaqSensor.pressure;
      bmeIAQ = iaqSensor.iaq;
      bmeIAQAccuracy = iaqSensor.iaqAccuracy;
      bmeCO2 = iaqSensor.co2Equivalent;
      bmeBreathVocEquivalent = iaqSensor.breathVocEquivalent;
    } else {
      checkIaqSensorStatus();
    }

os_runloop_once();

time_startInterval = millis();

   printOnDisplay("Temp: ", String(bmeTemperatur), "C", "Zeit: ", String(getTimeStamp()), "");
display.display();
display.clearDisplay();

  if (time_startInterval > time_actualInterval + intervalInterval) {
  time_actualInterval = millis();
  Data = SD.open("Data.csv", FILE_WRITE);
    Data.println((String(getTimeStamp()) + String(",") + String(myGNSS.getLatitude()) + String(",") + String(myGNSS.getLongitude()) + String(",") + String(bmeTemperatur) + String(",") + String(bmePressure) + String(",") + String(bmeHumidity)));
  Data.close();
}

}