Actuate on incoming serial data (NB - IoT)

Hello, I am currently doing a project with NB - IoT. I am using a modem that sends data at 9600 baud to my serial interface. I can control the modem with AT commands. For example, sending AT to the modem returns “OK” over the same interface. I want to respond to that OK by flashing an LED. The ultimate goal is to read incoming data and act on it accordingly. I have done a lot of research and tried everything before I came here but now I’m stuck.

The code works when reading a single character, like “O” or “K” but it doesn’t read a combination like “OK”.

  while (UBLOX.available())
  {    
    int len = 6; //buffer length
    char buf[len]; //array buffer
    int index = 0; //array index
    String input = "";
    
    uint8_t d = UBLOX.read(); //reads incoming serial data
    
    input = (char)d; //puts serial data into a string as readable ASCII characters
   
    for(index = 0; index < len; index++) //puts serial data in an array
    {
      buf[index] = char(d);

      if(input = "LF")
      {
        break;
      }
    }   
    
    char * pch;
    pch = strstr (buf,"OK");

    USB.print(buf);

    if(pch != 0) //if character wasn't found, pointer returns 0. If it was found, flesh LED.
    {
      flashLED();
    }
  }

The code also has a few problems. It sometimes garbles the serial monitor with weird ascii signs in between the responses to AT commands.

Any help would be appreciated :slight_smile:

This is not complete code but just a small excerpt. Post only complete code, any problem might be in a part of your code you don't imagine.

Also provide as much information about the used hardware as you have.

pylon:
This is not complete code but just a small excerpt. Post only complete code, any problem might be in a part of your code you don't imagine.

Also provide as much information about the used hardware as you have.

Thank you for your response, I will tomorrow. It's quite a complicated project and this is only a small part of it but I will try to post as much relevant info as possible.

Complete code is posted below. I am using a Arduino M0 with a SODAQ NB-IoT shield on top of it.
I modified an example given by sodaq, which was just a serial passthrough to send and receive AT commands.

#include "Arduino.h"

#if defined(ARDUINO_SODAQ_EXPLORER)
#define USB SerialUSB
#define UBLOX Serial

#elif defined(ARDUINO_SAM_ZERO)
#define USB SerialUSB
#define UBLOX Serial1

#else
#error "Please use a Sodaq ExpLoRer, Arduino M0 or add your own board."
#endif

// Pin to turn on/off the nb-iot module
#define powerPin 7 
unsigned long baud = 9600;  //start at 9600 allow the USB port to change the Baudrate



void setup() 
{
  // Turn the nb-iot module on
  pinMode(powerPin, OUTPUT); 
  digitalWrite(powerPin, HIGH);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  // Start communication
  USB.begin(baud);
  UBLOX.begin(baud);
}

void flashLED()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
}

// Forward every message to the other serial
void loop() 
{
  
  
  while (USB.available())
  {
    uint8_t c = USB.read();
    UBLOX.write(c);
  }

  while (UBLOX.available())
  {    
    int len = 6; //buffer length
    char buf[len]; //array buffer
    int index = 0; //array index
    String input = "";
    
    uint8_t d = UBLOX.read(); //reads incoming serial data
    
    input = (char)d; //puts serial data into a string as readable ASCII characters
   
    for(index = 0; index < len; index++) //puts serial data in an array
    {
      buf[index] = char(d);

      if(input = "LF")
      {
        break;
      }
    }   
    
    char * pch;
    pch = strstr (buf,"OK");

    USB.print(buf);

    if(pch != 0)
    {
      flashLED();
    }
  } 
  
  // check if the USB virtual serial wants a new baud rate
  if (USB.baud() != baud) 
  {
    baud = USB.baud();
       UBLOX.begin(baud);
  }
}

Alright so I investigated a little more. With the code like this the output looks like this:

13
10
79O75K13
10

So it always starts with a carriage return and ends with a linefeed.

I placed a USB.print(d) and a USB.print(input) inside my code for debugging purposes. If you look at the output you can see it first reads the value, outputs an ascii character, reads in a new value and outputs the second ascii character. This means there is never more than one ascii character in my buffer which is exactly what I was trying to avoid. I need to check multiple characters at the same time to see if there is an “OK” in my buffer.

How do I improve my loop so it stores multiple ascii characters in my buffer?

#include "Arduino.h"

#if defined(ARDUINO_SODAQ_EXPLORER)
#define USB SerialUSB
#define UBLOX Serial

#elif defined(ARDUINO_SAM_ZERO)
#define USB SerialUSB
#define UBLOX Serial1

#else
#error "Please use a Sodaq ExpLoRer, Arduino M0 or add your own board."
#endif

// Pin to turn on/off the nb-iot module
#define powerPin 7 
unsigned long baud = 9600;  //start at 9600 allow the USB port to change the Baudrate



void setup() 
{
  // Turn the nb-iot module on
  pinMode(powerPin, OUTPUT); 
  digitalWrite(powerPin, HIGH);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  // Start communication
  USB.begin(baud);
  UBLOX.begin(baud);
}

void flashLED()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
}

// Forward every message to the other serial
void loop() 
{
 
  while (USB.available())
  {
    uint8_t c = USB.read();
    UBLOX.write(c);
  }
  
  String input = "";
  
  while (UBLOX.available())
  {    
    int len = 6; //buffer length
    char buf[len]; //array buffer
    int index = 0; //array index
 
    uint8_t d = UBLOX.read(); //reads incoming serial data
    
    input += (char)d; //puts serial data into a string as readable ASCII characters
    USB.print(d);
    
//    for(index = 0; index < len; index++) //puts serial data in an array
//    {
//      buf[index] = (char)d;
//      
//      USB.print(buf[index]);
//
//      if(input = "\0")
//      {
//        break;
//      }
//    }   
    
    char * pch;
    pch = strstr (buf,"OK");

    if(pch != 0)
    {
      flashLED();
    }
  } 

  USB.print(input);
  
  // check if the USB virtual serial wants a new baud rate
  if (USB.baud() != baud) 
  {
    baud = USB.baud();
       UBLOX.begin(baud);
  }
}

langestefan:
So it always starts with a carriage return and ends with a linefeed.

The 3rd example in Serial Input Basics should be suitable if you change the start and end markers to '\r' and '\n'

...R

Robin2:
The 3rd example in Serial Input Basics should be suitable if you change the start and end markers to '\r' and '\n'

...R

Thank you so much!!!

I modified the code and added a strstr function to suit my needs, it works now!
I will be testing with the NB - IoT network soon. In theory I should be able to receive a code on the modem, analyse it and actuate on it now. So if I receive 1234 for instance I turn led 1 on etc.

#include "Arduino.h"
#if defined(ARDUINO_SAM_ZERO)
#define USB SerialUSB
#define UBLOX Serial1
#endif

// Pin to turn on/off the nb-iot morcule
#define powerPin 7 
unsigned long baud = 9600;  //start at 9600 allow the USB port to change the Baudrate

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

  //led setup
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  // Start communication
  USB.begin(baud);
  UBLOX.begin(baud);
}

void flashLED()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
}

const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;

// Forward every message to the other serial
void loop() 
{
  while (USB.available())
  {
    uint8_t c = USB.read();
    UBLOX.write(c);
  }
 
  recvWithStartEndMarkers();
  showNewData(); 
  

  // check if the USB virtual serial wants a new baud rate
  if (USB.baud() != baud) {
    baud = USB.baud();
       UBLOX.begin(baud);
  }
}

void recvWithStartEndMarkers()
{
  static boolean recvInProgress = false;
  static byte ndx = 0;
  
  char startMarker = '\n';
  char endMarker = '\r';
  
  char rc;

  uint8_t newValue = 0;
  

  while (UBLOX.available() > 0 && newData == false)
  { 
     newValue = UBLOX.read(); //reads incoming serial data

     rc = (char) newValue;
     //USB.print(newValue);

     
     if (recvInProgress == true)
     {
      //USB.print("receive in progress");
      //USB.print(rc);
      if (rc != endMarker)
      {
        receivedChars[ndx] = rc;
        
        
        ndx++;
        
        if (ndx >= numChars)
        {
          ndx = numChars -1;
        }
      }

      else 
      {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
     }
     
     else if (rc == startMarker) 
     {
        recvInProgress = true;
        //USB.print("seen start marker");
     }
  }
}

void showNewData()
{
  if (newData == true) 
  {
        USB.print(receivedChars);

        char * pch;
        pch = strstr (receivedChars,"OK");
    
        if(pch != 0)
        {
          flashLED();
        }

        newData = false;
  }
}

Just tested with the NB - IoT network, it works. Very happy with the way this turned out!!

langestefan:
Thank you so much!!!

I modified the code and added a strstr function to suit my needs, it works now!
I will be testing with the NB - IoT network soon. In theory I should be able to receive a code on the modem, analyse it and actuate on it now. So if I receive 1234 for instance I turn led 1 on etc.

#include "Arduino.h"

#if defined(ARDUINO_SAM_ZERO)
#define USB SerialUSB
#define UBLOX Serial1
#endif

// Pin to turn on/off the nb-iot morcule
#define powerPin 7
unsigned long baud = 9600;  //start at 9600 allow the USB port to change the Baudrate

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

//led setup
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

// Start communication
  USB.begin(baud);
  UBLOX.begin(baud);
}

void flashLED()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
}

const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;

// Forward every message to the other serial
void loop()
{
  while (USB.available())
  {
    uint8_t c = USB.read();
    UBLOX.write(c);
  }

recvWithStartEndMarkers();
  showNewData();

// check if the USB virtual serial wants a new baud rate
  if (USB.baud() != baud) {
    baud = USB.baud();
      UBLOX.begin(baud);
  }
}

void recvWithStartEndMarkers()
{
  static boolean recvInProgress = false;
  static byte ndx = 0;
 
  char startMarker = ‘\n’;
  char endMarker = ‘\r’;
 
  char rc;

uint8_t newValue = 0;

while (UBLOX.available() > 0 && newData == false)
  {
    newValue = UBLOX.read(); //reads incoming serial data

rc = (char) newValue;
    //USB.print(newValue);

if (recvInProgress == true)
    {
      //USB.print(“receive in progress”);
      //USB.print(rc);
      if (rc != endMarker)
      {
        receivedChars[ndx] = rc;
       
       
        ndx++;
       
        if (ndx >= numChars)
        {
          ndx = numChars -1;
        }
      }

else
      {
        receivedChars[ndx] = ‘\0’; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }
   
    else if (rc == startMarker)
    {
        recvInProgress = true;
        //USB.print(“seen start marker”);
    }
  }
}

void showNewData()
{
  if (newData == true)
  {
        USB.print(receivedChars);

char * pch;
        pch = strstr (receivedChars,“OK”);
   
        if(pch != 0)
        {
          flashLED();
        }

newData = false;
  }
}