RAK3172 Arduino IDE RUI3 uploading problems

I am experiencing massive problems uploading code to my RAK3172 board. I am able to upload the code only once. Whenever I try to upload the code the second time, the upload process gets stuck at “Detecting Baudrate…” and then “Detect Baudrate fail, can not get the baudrate” (screenshot). When I try to send AT commands over Serial Monitor (115200 baud) I get no response (9600 as well just to be sure).

The connection to TTN is fine though (as observed from TTN console).

What is very annoying and strange is that I am able to upload code normally after I re-flash the firmware over DFU. Is there something going on with the way the RUI3 configures the Serial port such that it cannot be used to upload further code after it has been repurposed for Serial communication? Am I supposed to set the mode of Serial.begin() to RAK_API_MODE or RAK_DEFAULT_MODE? Seems very strange to me.

Anyways, here is the full code as well as the schematic of my custom PCB. Any help would be greatly appreciated.

#include <TinyGPS++.h>
TinyGPSPlus gps;

#define OTAA_BAND     (RAK_REGION_AS923)
#define OTAA_DEVEUI   {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x07, 0x81, 0x2B}
#define OTAA_APPEUI   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
#define OTAA_APPKEY   {0xD7, 0x65, 0xB7, 0x92, 0x5E, 0x9B, 0x82, 0x07, 0x84, 0x65, 0x6A, 0xE5, 0x55, 0x3C, 0x42, 0x0A}
#define OTAA_PERIOD   600000
uint8_t message[64] = { 0 };

uint64_t last = 0;

long latDec; //latDec = lattitude * 100000
long longDec; //longDec = longitude * 100000
unsigned int battery; //battery = voltage * 100
  
uint8_t latIsNegative;
uint8_t longIsNegative;
uint8_t latArray[3] = {0,0,0};
uint8_t longArray[3] = {0,0,0};

float GPSLatArray[10];
float GPSLongArray[10];
  
void recvCallback(SERVICE_LORA_RECEIVE_T * data)
{
  if (data->BufferSize > 0) {
    Serial.println("Something received!");
    for (int i = 0; i < data->BufferSize; i++) {
      Serial.printf("%x", data->Buffer[i]);
    }
    Serial.print("\r\n");
  }
}
void joinCallback(int32_t status)
{
  Serial.printf("Join status: %d\r\n", status);
}

void sendCallback(int32_t status)
{
  if (status == 0) {
    Serial.println("Successfully sent");
  } else {
    Serial.println("Sending failed");
  }
}

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200, RAK_CUSTOM_MODE);
Serial1.begin(9600, RAK_CUSTOM_MODE);

Serial.println("Ready");

pinMode(29, OUTPUT);
pinMode(32, INPUT);

// OTAA Device EUI MSB first
  uint8_t node_device_eui[8] = OTAA_DEVEUI;
  // OTAA Application EUI MSB first
  uint8_t node_app_eui[8] = OTAA_APPEUI;
  // OTAA Application Key MSB first
  uint8_t node_app_key[16] = OTAA_APPKEY;
if (!api.lorawan.appeui.set(node_app_eui, 8)) {
    Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.appkey.set(node_app_key, 16)) {
    Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.deui.set(node_device_eui, 8)) {
    Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");
    return;
  }

  if (!api.lorawan.band.set(OTAA_BAND)) {
    Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {
    Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.njm.set(RAK_LORA_OTAA))  // Set the network join mode to OTAA
  {
    Serial.printf
  ("LoRaWan OTAA - set network join mode is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.join())  // Join to Gateway
  {
    Serial.printf("LoRaWan OTAA - join fail! \r\n");
    return;
  }

  /** Wait for Join success */
  while (api.lorawan.njs.get() == 0) {
    Serial.print("Wait for LoRaWAN join...");
    api.lorawan.join();
    delay(10000);
  }

  if (!api.lorawan.adr.set(true)) {
    Serial.printf
  ("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.rety.set(1)) {
    Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.cfm.set(1)) {
    Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
    return;
  }
  Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF");  // Check Duty Cycle status
  Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED");  // Check Confirm status
  uint8_t assigned_dev_addr[4] = { 0 };
  api.lorawan.daddr.get(assigned_dev_addr, 4);
  Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]);  // Check Device Address
  Serial.printf("Uplink period is %ums\r\n", OTAA_PERIOD);
  Serial.println("");
  api.lorawan.registerRecvCallback(recvCallback);
  api.lorawan.registerJoinCallback(joinCallback);
  api.lorawan.registerSendCallback(sendCallback);
}
void uplink_routine()
{
  /** Payload of Uplink */
  uint8_t data_len = 0;
  message[data_len++] = (uint8_t) latIsNegative;
  message[data_len++] = (uint8_t) latArray[0];
  message[data_len++] = (uint8_t) latArray[1];
  message[data_len++] = (uint8_t) latArray[2];
  message[data_len++] = (uint8_t) longIsNegative;
  message[data_len++] = (uint8_t) longArray[0];
  message[data_len++] = (uint8_t) longArray[1];
  message[data_len++] = (uint8_t) longArray[2];
  message[data_len++] = (uint8_t) battery;

  Serial.println("Data Packet:");
  for (int i = 0; i < data_len; i++) {
    Serial.printf("0x%02X ", message[i]);
  }
  
  /** Send the data package */
  if (api.lorawan.send(data_len, (uint8_t *) & message, 2, true, 1)) {
    Serial.println("Sending is requested");
  } else {
    Serial.println("Sending failed");
  }
}
void loop() {
  
  if(millis() - last > OTAA_PERIOD){
    
    // Simulate the collection of data:
    //latDec = 12345678; //latDec = lattitude * 100000
    //longDec = 12345678; //longDec = longitude * 100000
    //battery = 100; //battery = voltage / 3.3 * 100

    digitalWrite(29, HIGH);
    delay(120000); //wait 2 min for the GPS to boot up

    while(Serial1.available() > 0){
      if(gps.encode(Serial1.read())){
        if(gps.location.isValid()){
          latDec = gps.location.lat()*100000;
          longDec = gps.location.lng()*100000;
          latIsNegative = (latDec<0)?1:0;
          longIsNegative = (longDec<0)?1:0;
          convert(abs(latDec),1,0);
          convert(abs(longDec),2,0);
          battery = analogRead(32)/930*100;
          uplink_routine();
        }else{
        Serial.println("GPS is present by no valid coordinates!");
        }      
      }else{
        Serial.println("No valid GPS found");
      }
     }
    last = millis();
    digitalWrite(29, LOW);
  }
  api.system.sleep.all(OTAA_PERIOD);
}

void convert(long number, int flag, int index){
  if(number >= 256) convert(round(number/256),flag,index+1);
  if(!flag==1){
    latArray[index]=number%256;
  }else if(flag==2){
    longArray[index]=number%256;
  }
}

Things I’ve tried:
Desoldering the GPS module on Serial1
Uploading a blank sketch to see if it was anything with my code that was causing this error
Trying different COM ports

I am inclined to think that it is a bug with the board files for Arduino IDE. Will be trying VSCode and see if it works.

Update: Now it seems that the board is flat out refusing to accept any updates, regardless of whether I reflashed the firmware or not.

Two possible causes:

  1. If your code (that you uploaded before) crashes, the Serial interface will get unresponsive and neither AT commands nor the uploading is working. In this case you could try (with luck) to reset the RAK3172 just before Arduino IDE starts the upload.

  2. Your RAK3172 is stuck in bootloader mode.
    Can you try to connect a terminal with 115200 baud and send AT+RUN and check if anything happens.

Thanks for your reply. I will try both of them, but I suspect it’s the first case since the Serial is unresponsive.

Does reflashing the firmware reset everything on the board to factory defaults and therefore erases the crashing program on the chip? If so it’s unclear why reflashing the chip doesn’t solve the problem.

Thanks.

If you flash a custom firmware from Arduino, the module is not reset to factory defaults. Settings like AppEUI, DevEUI, region, … are the same you set before.

What you can try is to flash the “standard” AT Command firmware from our Download Center and see if the serial communication works with it.

I’ve tried flashing RAK3172-E_latest.hex and .bin files using the STMCubeProgrammer and RAk DFU tool respectively but Serial still doesn’t work.

The RAK DFU Tool is using a similar method than the Arduino BSP to flash the firmware. Very strange that you can upload code with it but not with the Arduino IDE.

I will ask our R&D team about it.

What is your BSP version? Are you using the 3.4.2 version or the staging 3.5.2-beta version?

A workaround (for now) is to use the WisToolBox and try to connect to the device and upload the code with it. WisToolBox for Desktop.

There is a guide how to flash custom firmware with it.

WisToolBox is available for Windows, Linux and MacOS, but it is still in Beta phase.

Yes I am using the 3.4.2 version.

I should add that the DFU tool doesn’t work reliably. It takes a couple of restarting of the application as well as changing of COM ports for it to work. Otherwise it just says “upgrade timed out”.

STMCubeProgrammer as per the guide here: https://docs.rakwireless.com/Knowledge-Hub/Learn/STM32Cube-Programmer-Guide/ works perfectly every time though.

Thanks for your help.

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