PiSupply / RAK811-Arduino

Arduino Library for Pi Supply LoRa Node Shield
MIT License
7 stars 7 forks source link

Either I2C or Send Bytes is causing the library to crash. #6

Closed ryanteck closed 3 years ago

ryanteck commented 4 years ago

When using I2C, Serial and a mixture of libraries we seem to be facing issues of crashing out.

ryanteck commented 4 years ago

Here's the example code that we're having an issue with, it seems to crash at 21 loops no matter what we do.

//Import the RAK811 Library
#include "RAK811.h"
//Include Serial Library
#include "SoftwareSerial.h"
#include "SparkFun_Si7021_Breakout_Library.h"
#include <Wire.h>
#include <CayenneLPP.h>
#include <ArduinoJson.h>

float humidity = 0;
float tempC = 0;

int power = A3;
int GND = A2;

//Create Instance of HTU21D or SI7021 temp and humidity sensor and MPL3115A2 barrometric sensor

Weather sensor;

//Set here if you want to use LoRaWAN or P2P Modes
#define WORK_MODE LoRaWAN   //  LoRaWAN or LoRaP2P
//This sets the code to ABP
#define JOIN_MODE ABP

//Define your ABP Keys here, you can usually find these in the console of the LoRa Provider.
String NwkSKey = "";
String AppSKey = "";
String DevAddr = "26011CE1";

//Specify Data Rate
//For EU This is recommended to be 5 for SF7, For US use 0
String dataRate = "5";

//The Pi Supply shield uses pins 11 & 10 for serial.
#define TXpin 11
#define RXpin 10
#define RESET_PIN 12
//The DebugSerial allows the board to respond back via the USB Serial
#define DebugSerial Serial
//Setup the serial port for the board
SoftwareSerial RAKSerial(RXpin, TXpin);   // Declare a virtual serial port

bool InitLoRaWAN(void);
RAK811 RAKLoRa(RAKSerial, DebugSerial);

CayenneLPP lpp(42);

void setup()
{
  setupLoRa();
  setupSi1702();
}

void loop()
{
  readSi1702();
  LoRaData();
  //readSi1702();

  //delay(1000);
}

void setupLoRa() {

  //Define Reset Pin
  pinMode(RESET_PIN, OUTPUT);
  //Setup Debug Serial on USB Port
  DebugSerial.begin(9600);
  while (DebugSerial.read() >= 0) {}
  while (!DebugSerial);
  //Print debug info
  DebugSerial.println("StartUP");
  DebugSerial.println("Reset");
  //Reset the RAK Module
  digitalWrite(RESET_PIN, LOW);   // turn the pin low to Reset
  digitalWrite(RESET_PIN, HIGH);    // then high to enable
  DebugSerial.println("Success");
  RAKSerial.begin(9600); // Arduino Shield
  delay(100);
  DebugSerial.println(RAKLoRa.rk_getVersion());
  delay(200);
  DebugSerial.println(RAKLoRa.rk_getBand());
  delay(200);

  Serial.println("Setting data rate");
  RAKLoRa.rk_setConfig("dr", dataRate);
  delay(200);

  while (!InitLoRaWAN());

}

void setupSi1702()
{
  Serial.begin(9600);   // open serial over USB at 9600 baud

  pinMode(power, OUTPUT);
  pinMode(GND, OUTPUT);

  digitalWrite(power, HIGH);
  digitalWrite(GND, LOW);

  //Initialize the I2C sensors and ping them
  sensor.begin();

}

void LoRaData() {

lpp.reset();
    //Testing for Leo
    //float tempUnion = 32;
    //float humidityUnion = 64;

    //float humidity = 0;
    //float tempC = 0;

    lpp.addTemperature(1, tempC);
    lpp.addRelativeHumidity(2, humidity);

    int packetsflag = 0; // 0: unconfirmed packets, 1: confirmed packets
    if (RAKLoRa.rk_sendBytes(packetsflag, 1, lpp.getBuffer(), lpp.getSize()))
    {
      for (unsigned long start = millis(); millis() - start < 90000L;)
      {
        String ret = RAKLoRa.rk_recvData();
        if (ret.startsWith(STATUS_TX_COMFIRMED) || ret.startsWith(STATUS_TX_UNCOMFIRMED))
        {
          DebugSerial.println("Send data ok!");
          delay(6000);
          return;
        }
      }
      DebugSerial.println("Send data error!");
      while (1);
    }
  }

  bool InitLoRaWAN(void)
{
    RAKLoRa.rk_setWorkingMode(WORK_MODE);
    RAKLoRa.rk_recvData();
    RAKLoRa.rk_recvData();
    if ( RAKLoRa.rk_recvData() == "OK")
    {
      if (RAKLoRa.rk_initABP(DevAddr, NwkSKey, AppSKey))
      {
        Serial.println("You init ABP parameter is OK!");
        if (RAKLoRa.rk_joinLoRaNetwork(JOIN_MODE))
        {
          Serial.println("You join Network success!");
          return true;
        }
      }
    }
    return false;
  }

  void readSi1702()
  {
    //Get readings from all sensors
    getWeather();
    printInfo();
    //delay(10000);

  }
  //---------------------------------------------------------------
  void getWeather()
  {
    // Measure Relative Humidity from the HTU21D or Si7021
    delay(100);
    humidity = sensor.getRH();
    delay(100);
    // Measure Temperature from the HTU21D or Si7021
    tempC = sensor.getTemp();
    // Temperature is measured every time RH is requested.
    // It is faster, therefore, to read it from previous RH
    // measurement with getTemp() instead with readTemp()
  }
  //---------------------------------------------------------------
  void printInfo()
  {
    //This function prints the weather data out to the default Serial Port

    Serial.print("Temp:");
    Serial.print(tempC);
    Serial.print("C, ");

    Serial.print("Humidity:");
    Serial.print(humidity);
    Serial.println("%");
  }
Mat8008 commented 4 years ago

Hey Ryan

Any news on this? I seem to have a similar problem with a Seeeduino Nano and the pisupply Lora Shield. I've disconnected all sensors and still get only 7 packages sent to TTN. The code is kept as simple as possible, see below. Any ideas?

Mat

//GENERAL
#include "SoftwareSerial.h"

//LORA
#include "RAK811.h"

#include "CayenneLPP.h"

#define WORK_MODE LoRaWAN   //  LoRaWAN or LoRaP2P
#define JOIN_MODE OTAA    //  OTAA or ABP

String DevEui = ""; // Fill this out
String AppEui = ""; // Fill this out
String AppKey = ""; // Fill This out

#define TXpin 11   // Set the virtual serial port pins
#define RXpin 10
#define DebugSerial Serial
SoftwareSerial RAKSerial(RXpin, TXpin);   // Declare a virtual serial port

int RESET_PIN = 12;
bool InitLoRaWAN(void);
RAK811 RAKLoRa(RAKSerial, DebugSerial);

int counter = 0;

CayenneLPP lpp(20);

void setup() {
  //Define Reset Pin
  pinMode(RESET_PIN, OUTPUT);

  //Reset the RAK Module
  digitalWrite(RESET_PIN, LOW);   // turn the pin low to Reset
  digitalWrite(RESET_PIN, HIGH);    // then high to enable

  RAKSerial.begin(9600); // Arduino Shield
  delay(100);

  delay(200);

  while (!InitLoRaWAN());

}

bool InitLoRaWAN(void)
{
  RAKLoRa.rk_setWorkingMode(WORK_MODE);
  RAKLoRa.rk_recvData();
  RAKLoRa.rk_recvData();
  if ( RAKLoRa.rk_recvData() == "OK")
  {
    if (RAKLoRa.rk_initOTAA(DevEui, AppEui, AppKey))
    {
      while (!RAKLoRa.rk_joinLoRaNetwork(JOIN_MODE))
      {

        delay(5000);
        bool flag = false;
        for (unsigned long start = millis(); millis() - start < 120000L;)
        {

          delay(9000L);
          String ret = RAKLoRa.rk_recvData();

          if (ret.startsWith(STATUS_JOINED_SUCCESS))
          {
            return true;
          }
          else if (ret.startsWith(STATUS_RX2_TIMEOUT) || ret.startsWith(STATUS_JOINED_FAILED))
          {

            flag = true;
            delay(1000);
          }
        }
        if (flag == false)
        {
          DebugSerial.println("Pleases Reset the module!");
          delay(1000);
          return false;
        }
      }
    }
  }
     return false;
}

void loop()
{
    delay(30000L);

    counter ++;

    lpp.reset();
    lpp.addTemperature(2, 100);

    RAKLoRa.rk_sendBytes(0, 1, lpp.getBuffer(), lpp.getSize());

}
ryanteck commented 4 years ago

Hi Mat, I haven't had much time to look at this issue since. However if that new code is also causing an issue then I think it possibly indicates more towards an issue possibly with the LPP library we're using / recommend as if you're using different sensors / code with no sensor it does indeed seem weird. Almost as if the arduino is running out of memory.

Mat8008 commented 4 years ago

I think that there's something strange with the convertBytesToString function. Changed my code to:

lpp.reset();
lpp.addTemperature(2, 10);
String s;
Serial.println(counter);
counter++;
for (int i = 0; i<lpp.getSize(); i++)   {
    char buffer []={0, 0};
    if (strlen(itoa(lpp.getBuffer()[i], buffer, 16)) ==  1) {
        buffer[1]=buffer[0];
        buffer[0] = '0';
    }
    s += buffer[0];
    s += buffer[1];   
} 
s +='\0';

Serial.println(s);
char* buffer = &s[0];
RAKLoRa.rk_sendData(0, 1, buffer);

However, I've now added an I2C TOFL-Sensor, and yes, there seems to be a problem with that combo.

ryanteck commented 4 years ago

Hi @Mat8008

I haven't made progress with this issue yet sorry as currently have another project at the top of the list.

As soon as this ones over I should hopefully have more time to work on this.

I'm suspectng memory a memory issue somewhere as it's as if it's running out of RAM. But I'm not fully sure.

ryanteck commented 3 years ago

Issue replication has begun.

In the first test it happened after 39 transmissions, second test was after 39 transmissions.

After applying the fix we've got past 40, going to continue to run but I'm happy it's improved so will merge #10

ryanteck commented 3 years ago

I'll wait for some feedback before closing the issue.

rbricheno commented 3 years ago

@Mat8008 can you post what TOF sensor you were using please, and what microcontroller, if you are still having trouble? I'll buy one and test this.

Mat8008 commented 3 years ago

The library works now with "RAKLoRa.rk_sendByte()", thanks a lot. However, I still struggle with my seeeduino nano and a VL53L0X TOFL-Sensor. I'll get a board with more memory for further testing.

pedbry commented 3 years ago

Hi @ryanteck

I'm using the RAK811 library (downloaded in may 2021) in my devices (Arduino Uno with a RAK811-shield) and I have had no problem sending simple payloads to my application in The Things Network. They are picked up by my two local TTIG:s and I can check them in the TTN-Console (V2).

But I did get a little problem men I wanted to read from a set of DS20B18 temperature-sensors with CayenneLPP and then send the resulting buffer to my application with rk_sendBytes() function in the RAK811 library. When I checked in my TTN-Console the payloads were not decoded to temperature-fields etc. The payload seemed to end with some random extra characters.

So I made i little sketch where I compared the result from the conversion-routine suggested by Mat8008 and the result from the conversion-code in the library (by bricheno).

This is my version of Mats code: image

This is my version of the code in the library: image

My test made it clear that the conversion-code in the library delivers a payload with some random extra characters at the end. Here is an example:

Payloadstring 1: 016700e4026700e4036700e5 ( from Mats code)

Payloadstring 2: 016700E4026700E4036700E500294A4 (from the library code)

When I saw the result and had a closer look at the code I realized that the compositionBuffer in the library-code probably must be provided with a finishing zero to indicate the end of the coming string. So I tested inserting a finishing zero in the following way. image

And it worked!

I have now inserted the extra line of code in my RAK811.cpp and my problems with using rk_Lora.sendBytes() are gone.

I'm not quite sure if I should have increased the memory allocation. But I have had my solution running with over 100 upploads so I consider the change as stable for the moment.

Pedbry