Issues with my first RUI3 code for RAK3172!

Hi

Not being very familiar with C/C++ and Arduino world, trying to get my RAK3172 and two sensors to work properly on Lora (for now I’m just getting the VOC sensor to work as the temp/humidity one has a hardware issue for now). I got lot of help from Rak staffs and used also blog posts to find out at best how to do it ! It runs but has following issues:

→ sends Lora payload only one time after programming (I’d like it sends payload with all datas every 20 minutes for example)
→ unable anymore to use AT commands on the RAK3172 and if I try to use the ATC+SENDINT command to setup sleep interval, it states it’s an unknown command :frowning:

Here is the code (be cool as it’s my first code in Arduino and also with RUI3 :see_no_evil:

#include "rak1906.h"
#include <SensirionI2CSgp40.h> // Click here to get the library: http://librarymanager/All#SensirionI2CSgp40
#include <Wire.h>
#include <Arduino.h>
#include <CayenneLPP.h>
#define LPP_CHANNEL_BATT 1    // Base Board
#define LPP_CHANNEL_SWITCH 48 // RAK13011
/* rak1906 rak1906;
float Temperature;
float Humidity; */
/** Flag if TX is active */
volatile bool tx_active = false;
volatile uint8_t events_queue[50] = {0};
volatile uint8_t event_ptr = 0;
/** LoRaWAN packet */
CayenneLPP g_solution_data(255);
/** fPort to send packages */
uint8_t set_fPort = 2;
/** Packet is confirmed/unconfirmed (Set with AT commands) */
bool g_confirmed_mode = false;
/** If confirmed packet, number or retries (Set with AT commands) */
uint8_t g_confirmed_retry = 0;
/** Data rate  (Set with AT commands) */
uint8_t g_data_rate = 3;
/** Frequent data sending time */
uint32_t g_send_repeat_time = 30000;
SensirionI2CSgp40 sgp40;

void setup()
{
  uint16_t error;
  char errorMessage[256];
  uint16_t serialNumber[3];
  uint8_t serialNumberSize = 3;
  uint8_t ret;
  
  pinMode(WB_IO2, OUTPUT);
  digitalWrite(WB_IO2, HIGH);

  // Initialize Serial for debug output
  time_t timeout = millis();
  Serial.begin(115200);
  while (!Serial)
  {
    if ((millis() - timeout) < 5000)
    {
      delay(100);
    }
    else
    {
      break;
    }
  }
  
  Serial.println("RAK12047 SGP40 example");

  Wire.begin();
  sgp40.begin(Wire);

  error = sgp40.getSerialNumber(serialNumber, serialNumberSize);
  if (error) 
  {
    Serial.print("Error trying to execute getSerialNumber(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } 
  else 
  {
    Serial.print("Serial Number:");
    Serial.print("0x");
    for (size_t i = 0; i < serialNumberSize; i++) 
    {
      uint16_t value = serialNumber[i];
      Serial.print(value < 4096 ? "0" : "");
      Serial.print(value < 256 ? "0" : "");
      Serial.print(value < 16 ? "0" : "");
      Serial.print(value, HEX);
    }
    Serial.println();
  }

  uint16_t testResult;
  error = sgp40.executeSelfTest(testResult);
  if (error) 
  {
    Serial.print("Error trying to execute executeSelfTest(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } 
  else if (testResult != 0xD400) 
  {
    Serial.print("executeSelfTest failed with error: ");
    Serial.println(testResult);
  }
  /* Serial.begin(115200);
  pinMode(LED_BLUE, OUTPUT);
  digitalWrite(LED_BLUE, HIGH);
  Wire.begin(); // Begin function for I2C
  rak1906.init(); //Start rak1901 */

  // OTAA Device EUI MSB
    uint8_t node_device_eui[8] = {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x09, 0x61, 0x7B};
    // OTAA Application EUI MSB
    uint8_t node_app_eui[8] = {0xAC, 0x1F, 0x09, 0xFF, 0xF8, 0x68, 0x31, 0x72};
    // OTAA Application Key MSB
    uint8_t node_app_key[16] = {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x09, 0x61, 0x7B, 0xAC, 0x1F, 0x09, 0xFF, 0xF8, 0x68, 0x31, 0x72};

    // Set App EUI
    if (!(ret = api.lorawan.appeui.set(node_app_eui, 8)))
    {
        Serial.printf("RUI3 - set device EUI failed! \r\n");
        return;
    }
    // Set App Key
    if (!(ret = api.lorawan.appkey.set(node_app_key, 16)))
    {
        Serial.printf("RUI3 - set application EUI failed! \r\n");
        return;
    }
    // Set Device EUI
    if (!(ret = api.lorawan.deui.set(node_device_eui, 8)))
    {
            Serial.printf("RUI3 - set application key failed! \r\n");
        return;
    }
    // Set LoRaWAN Region
    if (!(ret = api.lorawan.band.set(RAK_REGION_EU868)))
    {
        Serial.printf("RUI3 - set band failed! \r\n");
        return;
    }
    // Set device class
    if (!(ret = api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)))
    {
        Serial.printf("RUI3 - set device class failed! \r\n");
        return;
    }
    // Set network join mode
    if (!(ret = api.lorawan.njm.set(RAK_LORA_OTAA)))
    {
        Serial.printf("RUI3 - set network join mode failed! \r\n");
        return;
    }
    // Start to join the network
    if(!(ret = api.lorawan.join()))                   
    {
        Serial.printf("RUI3 - join fail! \r\n");
        return;
    }
  g_confirmed_mode = api.lorawan.cfm.get();
  g_confirmed_retry = api.lorawan.rety.get();
  g_data_rate = api.lorawan.dr.get();
}

bool has_joined = false;

void loop()
{
  uint16_t  error;
  char      errorMessage[256];
  uint16_t  srawVoc   = 0;
  float     vocIndex  = 0;

  /* 
   * @brief Set the relative humidity and temperature in the current environment.
   *        Temperature and humidity calibration has been performed inside the sensor.
   *        RH/ticks=RH/%×65535/100
   *        T/ticks=(T/°C + 45)×65535/175
   */
  uint16_t  defaultRh = 0x8000;  // 50 %RH
  uint16_t  defaultT  = 0x6666;  // 25 ℃
  
  // delay(1000);
  
  error = sgp40.measureRawSignal(defaultRh, defaultT, srawVoc);
  if (error) 
  {
    Serial.print("Error trying to execute measureRawSignal(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } 
  else 
  {
    Serial.print("SRAW_VOC:");
    Serial.print(srawVoc);
    vocIndex = (float)srawVoc/131.07 ;

   /* VOC index.
    * The voc index can directly indicate the quality of the air. The higher the value, the worse the air quality.
    *   0-100,no need to ventilate,purify.
    *   100-200,no need to ventilate,purify.
    *   200-400,ventilate,purify.
    *   400-500,ventilate,purify intensely.
    */
    Serial.print("  VOC Index:");
    Serial.println(vocIndex);
  }
  /* // put your main code here, to run repeatedly:
  digitalWrite(LED_BLUE, HIGH);
  delay(1000);
  digitalWrite(LED_BLUE, LOW);
  delay(1000);
  /* if (rak1906.update()) {
    Temperature = rak1906.temperature();
    Humidity = rak1906.humidity();
    } else {
    Serial.println("Please plug in the sensor RAK1906 and Reboot");
    }
  Serial.printf("Temperature = %.2f%°C\r\n", Temperature);
  Serial.printf("Humidity = %.2f%%\r\n", Humidity);
  delay(5000); */
  if (!tx_active && api.lorawan.njs.get())
  {
    event_ptr -= 1;

    // Clear payload
    g_solution_data.reset();

    // g_solution_data.addPresence(LPP_CHANNEL_SWITCH, events_queue[event_ptr] == 0 ? 0 : 1);
    g_solution_data.addAnalogInput(1, vocIndex);

    // Add battery voltage
    g_solution_data.addVoltage(LPP_CHANNEL_BATT, api.system.bat.get());

    // Send the packet
    Serial.printf("Send packet with size %d on port %d\n", g_solution_data.getSize(), set_fPort);

    // Send the packet
    if (api.lorawan.send(g_solution_data.getSize(), g_solution_data.getBuffer(), set_fPort)) // , g_confirmed_mode, g_confirmed_retry))
    {
      tx_active = true;
      Serial.println("Packet enqueued");
    }
    else
    {
      Serial.println("Send failed");
    }
  }
  else
  {
    Serial.println("Busy or not connected");
  }

  if (event_ptr != 0)
  {
    // Event queue is not empty. Trigger next packet in 5 seconds
    api.system.timer.start(RAK_TIMER_3, 5000, NULL);
  }
  // api.system.scheduler.task.destroy();
}

Thanks a lot for help,

Vincèn

Succeeded to correct the problem of only one payload with this updated code (although it still doesn’t accept the RUI AT command and I don’t understand why :frowning:

#include "rak1906.h"
#include <SensirionI2CSgp40.h> // Click here to get the library: http://librarymanager/All#SensirionI2CSgp40
#include <Wire.h>
#include <Arduino.h>
#include <CayenneLPP.h>
#define LPP_CHANNEL_BATT 1    // Base Board
#define LPP_CHANNEL_SWITCH 48 // RAK13011
/* rak1906 rak1906;
float Temperature;
float Humidity; */
/** Flag if TX is active */
volatile bool tx_active = false;
volatile uint8_t events_queue[50] = {0};
volatile uint8_t event_ptr = 0;
/** LoRaWAN packet */
CayenneLPP g_solution_data(255);
/** fPort to send packages */
uint8_t set_fPort = 2;
/** Packet is confirmed/unconfirmed (Set with AT commands) */
bool g_confirmed_mode = false;
/** If confirmed packet, number or retries (Set with AT commands) */
uint8_t g_confirmed_retry = 0;
/** Data rate  (Set with AT commands) */
uint8_t g_data_rate = 3;
/** Frequent data sending time */
uint32_t g_send_repeat_time = 30000;
SensirionI2CSgp40 sgp40;

void setup()
{
  uint16_t error;
  char errorMessage[256];
  uint16_t serialNumber[3];
  uint8_t serialNumberSize = 3;
  uint8_t ret;
  
  pinMode(WB_IO2, OUTPUT);
  digitalWrite(WB_IO2, HIGH);

  // Initialize Serial for debug output
  time_t timeout = millis();
  Serial.begin(115200);
  while (!Serial)
  {
    if ((millis() - timeout) < 5000)
    {
      delay(100);
    }
    else
    {
      break;
    }
  }
  
  Serial.println("RAK12047 SGP40 example");

  Wire.begin();
  sgp40.begin(Wire);

  error = sgp40.getSerialNumber(serialNumber, serialNumberSize);
  if (error) 
  {
    Serial.print("Error trying to execute getSerialNumber(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } 
  else 
  {
    Serial.print("Serial Number:");
    Serial.print("0x");
    for (size_t i = 0; i < serialNumberSize; i++) 
    {
      uint16_t value = serialNumber[i];
      Serial.print(value < 4096 ? "0" : "");
      Serial.print(value < 256 ? "0" : "");
      Serial.print(value < 16 ? "0" : "");
      Serial.print(value, HEX);
    }
    Serial.println();
  }

  uint16_t testResult;
  error = sgp40.executeSelfTest(testResult);
  if (error) 
  {
    Serial.print("Error trying to execute executeSelfTest(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } 
  else if (testResult != 0xD400) 
  {
    Serial.print("executeSelfTest failed with error: ");
    Serial.println(testResult);
  }
  /* Serial.begin(115200);
  pinMode(LED_BLUE, OUTPUT);
  digitalWrite(LED_BLUE, HIGH);
  Wire.begin(); // Begin function for I2C
  rak1906.init(); //Start rak1901 */

  // OTAA Device EUI MSB
    uint8_t node_device_eui[8] = {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x09, 0x61, 0x7B};
    // OTAA Application EUI MSB
    uint8_t node_app_eui[8] = {0xAC, 0x1F, 0x09, 0xFF, 0xF8, 0x68, 0x31, 0x72};
    // OTAA Application Key MSB
    uint8_t node_app_key[16] = {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x09, 0x61, 0x7B, 0xAC, 0x1F, 0x09, 0xFF, 0xF8, 0x68, 0x31, 0x72};

    // Set App EUI
    if (!(ret = api.lorawan.appeui.set(node_app_eui, 8)))
    {
        Serial.printf("RUI3 - set device EUI failed! \r\n");
        return;
    }
    // Set App Key
    if (!(ret = api.lorawan.appkey.set(node_app_key, 16)))
    {
        Serial.printf("RUI3 - set application EUI failed! \r\n");
        return;
    }
    // Set Device EUI
    if (!(ret = api.lorawan.deui.set(node_device_eui, 8)))
    {
            Serial.printf("RUI3 - set application key failed! \r\n");
        return;
    }
    // Set LoRaWAN Region
    if (!(ret = api.lorawan.band.set(RAK_REGION_EU868)))
    {
        Serial.printf("RUI3 - set band failed! \r\n");
        return;
    }
    // Set device class
    if (!(ret = api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)))
    {
        Serial.printf("RUI3 - set device class failed! \r\n");
        return;
    }
    // Set network join mode
    if (!(ret = api.lorawan.njm.set(RAK_LORA_OTAA)))
    {
        Serial.printf("RUI3 - set network join mode failed! \r\n");
        return;
    }
    // Start to join the network
    if(!(ret = api.lorawan.join()))                   
    {
        Serial.printf("RUI3 - join fail! \r\n");
        return;
    }
  g_confirmed_mode = api.lorawan.cfm.get();
  g_confirmed_retry = api.lorawan.rety.get();
  g_data_rate = api.lorawan.dr.get();
}

bool has_joined = false;

void loop()
{
  uint16_t  error;
  char      errorMessage[256];
  uint16_t  srawVoc   = 0;
  float     vocIndex  = 0;

  /* 
   * @brief Set the relative humidity and temperature in the current environment.
   *        Temperature and humidity calibration has been performed inside the sensor.
   *        RH/ticks=RH/%×65535/100
   *        T/ticks=(T/°C + 45)×65535/175
   */
  uint16_t  defaultRh = 0x8000;  // 50 %RH
  uint16_t  defaultT  = 0x6666;  // 25 ℃
  
  // delay(1000);
  
  error = sgp40.measureRawSignal(defaultRh, defaultT, srawVoc);
  if (error) 
  {
    Serial.print("Error trying to execute measureRawSignal(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } 
  else 
  {
    Serial.print("SRAW_VOC:");
    Serial.print(srawVoc);
    vocIndex = (float)srawVoc/131.07 ;

   /* VOC index.
    * The voc index can directly indicate the quality of the air. The higher the value, the worse the air quality.
    *   0-100,no need to ventilate,purify.
    *   100-200,no need to ventilate,purify.
    *   200-400,ventilate,purify.
    *   400-500,ventilate,purify intensely.
    */
    Serial.print("  VOC Index:");
    Serial.println(vocIndex);
  }
  /* // put your main code here, to run repeatedly:
  digitalWrite(LED_BLUE, HIGH);
  delay(1000);
  digitalWrite(LED_BLUE, LOW);
  delay(1000);
  /* if (rak1906.update()) {
    Temperature = rak1906.temperature();
    Humidity = rak1906.humidity();
    } else {
    Serial.println("Please plug in the sensor RAK1906 and Reboot");
    }
  Serial.printf("Temperature = %.2f%°C\r\n", Temperature);
  Serial.printf("Humidity = %.2f%%\r\n", Humidity);
  delay(5000); */
  /* if (!tx_active && api.lorawan.njs.get())
  { */
    event_ptr -= 1;

    // Clear payload
    g_solution_data.reset();

    // g_solution_data.addPresence(LPP_CHANNEL_SWITCH, events_queue[event_ptr] == 0 ? 0 : 1);
    g_solution_data.addAnalogInput(1, vocIndex);

    // Add battery voltage
    g_solution_data.addVoltage(LPP_CHANNEL_BATT, api.system.bat.get());

    // Send the packet
    Serial.printf("Send packet with size %d on port %d\n", g_solution_data.getSize(), set_fPort);

    // Send the packet
    if (api.lorawan.send(g_solution_data.getSize(), g_solution_data.getBuffer(), set_fPort)) // , g_confirmed_mode, g_confirmed_retry))
    {
      tx_active = true;
      Serial.println("Packet enqueued");
    }
    else
    {
      Serial.println("Send failed");
    } /*
  }
  else
  {
    Serial.println("Busy or not connected");
  }

  if (event_ptr != 0)
  {
    // Event queue is not empty. Trigger next packet in 5 seconds
    api.system.timer.start(RAK_TIMER_3, 5000, NULL);
  }
  api.system.scheduler.task.destroy(); */
  api.system.sleep.all(600000);
}

_ATC+SENDINT (or ATC+SENDFREQ in some of my older examples) is a custom AT command that I included in my examples, it is not a part of the standard AT commands of RUI3.

Unless you include this custom AT command in your code and write your code to use a timer and the interval time set by this custom AT command it will be useless for you.

Here is the code to add ATC+STATUS and ATC+SENDINT custom AT commands to your code.

But to get the send interval to work, you need to change your code

  • do nothing in the loop
  • handle sensor events in a timer callback

RUI3-Modular is using this technique.

@beegee Thanks a lot for your very good advices as usual :slight_smile: I’ll try to adapt my code for that.

I gave a try again with the RUI3-Modular. If I configure it for the 3 sensors I have (RAK-1906/1902/12047), it fails to compile (error in the way code pass temp/hum from 1906 to 12047.
If I keep only the 12047 it compiles and I have been able to upload it but all I get is the startup banner in console indicating it found the sensor and indicating he found an interval time already setup but I can’t send any AT commands :frowning:
WistoolBox is partially able to connect at it (stating I have to switch to AT mode but it fails to do it if I ask to do it) and as previously I’m unable now to reload a program in the board with Arduino IDE :frowning: Got caught in same problem than previously with that code, are you sure there is no error in code that implements these extra AT commands as it looks that code makes a mess with the serial port no ?

That is a bug that I need to fix.

For your other problems, what version of RUI3 BSP do you have installed?

Not sure to understand well your question :confused: you mean on the board ? on the board it shows up like that at command ATC+STATUS=? (just obfuscated the lora keys)

[08:34:49:479] ersion: RUI_3.5.3_RAK3172-E␊
[08:34:49:479] Send time: 300 s␊
[08:34:49:482] Network mode LoRaWAN␊
[08:34:49:485] Network joined␊
[08:34:49:485] Region: 4␊
[08:34:49:485] Region: EU868␊
[08:34:49:488] OTAA mode␊
[08:34:49:488] DevEUI = AC1F09FFXXXXXXX␊
[08:34:49:491] AppEUI = AC1F09FFXXXXXXX␊
[08:34:49:494] AppKey = AC1F09FFXXXXXXXC1F09FFF8683172␊
[08:34:49:498] OK␍␊

:

I compile the code using Arduino IDE so I guess it uses the latest version of RUI avalaible each time it compiles no ?
For now I’m using the RUi Air Node Quality code and going to tweak that one that works quite well already and doesn’t crash/bug the wisblock module :slight_smile:

It would be nice also to publish a documentation on how to flash/reflash RUI3 on some modules using STM32Cube GUI :wink:

V3.5.3 is the latest published, but it has some problems. New version will be published (hopefully) end of February.
You can try to go back to V3.4.2 BSP version.

STM32CubeProgrammer Guide for RAK Modules

Wouhou succeeded to downgrade easily my RAK3172 into 3.4.2 using Wistoolbox :partying_face: Should I do the same with other modules for better stability ?

Thanks for the link, will save it in bookmarks :slight_smile:

I would suggest to give 3.4.2 a try on one module first.

Well it works really great since in 3.4.2 and Wistoolbox also detects module well better than with 3.5.3 ! Is there an easy way to keep that version ? as each time I reload a program with Arduino IDE for sure it installs latest version of RUI :frowning:
No beta yet of the new RUI release ?

In Arduino IDE

  • Goto Tools
  • Goto Board Manager…
  • Type RAK
  • Goto RAKwireless RUI STM32 Boards
  • Open version selection
  • Choose 3.4.2

New Beta is not ready to share.

One option to get informed is to sign up for our news letter RAKwireless Documentation Center

Thanks for the trick, should have thought about it :wink:

Thanks I subscribed to it although the Release-Notes page doesn’t list all updates (Wistoolbox had some updates that are not listed there) and also please stop uploading new releases of software in downloads.rakwireless.com without version in name just last release as it’s a complete non sense to organise files and keep tracks of versions :frowning:

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.