Unstable UDP data transmission

Hi,

I’m working on a battery powered project that will have to send some data via NB-IOT about once or twice per day.
I want to use the SARA R410M, so I’m using the SODAQ SARA R410M board for testing purposes. Because it’s a battery powered project, I want my mcirocontroller to be awake as short as possible.

I have written a piece of code that sends a sequence of AT commands to the SARA in order to connect and send a single message. Yet I’ve found my code to be quite unreliable. It works sometimes, but other times it just doesn’t. I have been tweaking a lot with delays in my code, which seemed to help a lot. But the “AT+USOST” command (for sending data) errors quite a lot. If I decrease any of the delays in my code, USOST just won’t work. Yet when I try to manually enter the AT commands, it works every single time. So I don’t suspect it to be a connection issue.

My question: are there any mandatory delays for the R410M or does somebody have a simple piece of code that doesn’t have this issue?

I have worked with some code examples before, but I have found them quite complex compared to what I want to do. I’ve used the SARA R4 Maker software, but that takes about 1 minute to send 1 messages, comapred to about 15-20 seconds with my code.

Please help!

~Michael
My code:

#include <Arduino.h>
#define DEBUG_STREAM Serial
#define MODEM_STREAM Serial1
#define powerPin SARA_ENABLE
#define enablePin SARA_TX_ENABLE
#define voltagePin SARA_R4XX_TOGGLE

unsigned long baud = 115200;

void setup() {
// Put voltage on the nb-iot module
pinMode(powerPin, OUTPUT);
digitalWrite(powerPin, HIGH);

// Switch module voltage
pinMode(voltagePin, OUTPUT);
digitalWrite(voltagePin, LOW);

// Set state to active 
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, HIGH);

// Start communication
DEBUG_STREAM.begin(baud);
MODEM_STREAM.begin(baud);
}
int shrt = 50;

void loop() {
  //ping untill sara is awake
  ATsend("AT","OK",1);
  //set LTE/NB
  ATsend("AT+URAT=8","OK",1);
  //enable errors
  ATsend("AT+CMEE=2","OK",1);
  //set vodafone server
  ATsend("AT+CGDCONT=1,\"IP\",\"nb.inetd.gdsp\"","OK",1);
  //enable antenna
  ATsend("AT+CFUN=1","OK",1);
  //set operator
  ATsend("AT+COPS=1,2,\"20404\"","OK",1);
 //enable HEX format
  ATsend("AT+UDCONF=1,1","OK",1);
 //register to network
  ATsend("AT+CEREG=2","OK",1);
  //open socket
  ATsend("AT+USOCR=17","OK",100);
  //send data
  delay(2000);
  ATsend("AT+USOST=0,\"40.68.172.187\",8891,20,\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"","+",1);
  //close socket
  ATsend("AT+USOCL=0","OK",shrt);
  
  //Enter a loop that waits for manual AT commands.
  while(1){
    while (DEBUG_STREAM.available())
  {
    MODEM_STREAM.write(DEBUG_STREAM.read());
  }

  while (MODEM_STREAM.available())
  {     
    DEBUG_STREAM.write(MODEM_STREAM.read());
  }
  }
}

//sends AT commands to SARA. check is a string that will be scanned for in the Sara response to determine a 'good'reply.
//dur determines the delay after each character gets read from the serial buffer. 
void ATsend(String command, String check, int dur){
  String Answer = "";                       //create an empty string
  do{
    MODEM_STREAM.println(command);               //send at command to sara
    DEBUG_STREAM.println(command);                //send at command to serial monitor
    delay(500);                             //retry the at command 2 times per second untill 'good' reply.
    while (MODEM_STREAM.available())        //keep reading characters untill buffer is empty.
      {     
        char data = MODEM_STREAM.read();    
        Answer = Answer + data;             //append individual characters into a string.
        delay(dur);                         //dur determines the delay after each character gets read from the serial buffer. 
      }
  }while (Answer.indexOf(check)<0);         //keep looping until 'good' reply is found. indexOf returns -1 if check isn't found in reply.
  
  DEBUG_STREAM.println(Answer);             //when a 'good' reply is found, print it to the serial monitor and continue.
}

Good afternoon,

Is this just an example or are you trying to send exactly this string?
Because ‘aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa’ is 40 bytes, while you ‘tell’ the device that there will be 20.

@Alex_Bijmolt, this is just an example. I want to send my data in HEX format, thus the ATsend(“AT+UDCONF=1,1”,“OK”,1); command to put it in HEX mode. In HEX mode, the amount of bytes is actually halved. Every 2 chars is 1 HEX char in ASCII.
So unfortunately that isn’t the issue. But I admire how sharp you are!

Have you checked that you have attached correctly to the network after
ATsend("AT+COPS=1,2,“20404"”,“OK”,1);?

Use AT+CEREG?

I have to do this in my python code to check if I am connected or not. Even if the AT command is returning OK.

def _await_connection(self, roaming, timeout=180): 
          """ 
          The process to verify that connection has occured is a bit different on 
          different devices. On R4xx we need continiously poll the connection 
          status and see if the connection status has changed. 
          """ 
          logging.info(f'Awaiting Connection') 
          start_time = time.time() 
          while True: 
              time.sleep(2) 
              self._at_action('AT+CEREG?') 
 
 
              if self.registration_status == 0: 
                  continue 
  
 
              if roaming: 
                  if self.registration_status == 5: 
                      break 
  
 
              else: 
                 if  self.registration_status == 1: 
                      break 
  
 
              elapsed_time = time.time() - start_time 
              if elapsed_time > timeout: 
                  raise ConnectionTimeoutError(f'Could not connect') 

You can check out all code here:

Thanks for the tip. I’ve written a piece of code that checks the network registration status now and only continues if it is completely registered. Works like a charm!

1 Like