Question about Serial data pass to char Array

This is a part of my program , I want to know ,below mentioned GSM Serial data is possible to pass a char array.?

this is the serial data of GSM Module to be pass at the time of receiving the SMS.

+CMT: "+917987553768","","21/12/13,23:06:59+22"


sms content


When i assigned to this a char array[80],Only the fist line stored,"sms content" not stored Please help me to solve the problem.

Like this?

Nope

:slightly_smiling_face:

here is my program

#include <SoftwareSerial.h>

SoftwareSerial SIM900A(11, 10);

#include <Wire.h>


// Array to hold the number a SMS is retreived from
String textMessage;
const byte numChars = 80;
char receivedChars[numChars];
boolean newData = false;
char tempChars[numChars];
char messageFromPC[numChars] = {0};
char messageFromPC1[numChars] = {0};
void setup()
{
  SIM900A.begin(9600);   // Setting the baud rate of GSM Module
  Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
  Serial.println ("SIM900A Ready");
  delay(1000);
  Serial.println ("Type s to send message or r to receive message");
  SIM900A.println("AT+CMGF=1");
  delay(500);
  SIM900A.println("AT+CNMI=2,2,0,0,0\r");
  delay(100);

}
void loop()
{

  strcpy(tempChars, receivedChars);
  recvWithEndMarker();
  if (Serial.available() > 0)
    switch (Serial.read())

    {
      case 's':

        SendMessage();
        break;

    }

}


void recvWithEndMarker()
{

  static byte ndx = 0;
  char endMarker = '\n';
  char rc;


  while (SIM900A.available() > 0 && newData == false) {
    rc = SIM900A.read();
    //Serial.println(rc);
    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars)
      {

        // Serial.println(receivedChars);
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;

    }

  }
  showNewData();
}


void showNewData() {
  if (newData == true) {
    // Serial.print("This just in ... ");
    Serial.println(receivedChars);
    newData = false;
  }
}
void SendMessage()
{
  Serial.println ("Sending Message");
  SIM900A.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);

  SIM900A.println("AT+CMGS=\"+917987553768\"\r"); //Mobile phone number to send message*/
  delay(1000);

  SIM900A.println("hipp");// Messsage content
  delay(1000);

  SIM900A.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

}

Looks like you are telling it to stop at the first NewLine character (end of the first line). You will have to pick a different way to determine when to stop waiting for more characters.

Yes...but how ?...

const byte numChars = 80;
char receivedChars[numChars];

You are sizing the received message to 80 bytes.
My understanding of the SIM900 is that the full message is received before you are notified. In that case, blocking code is not an issue, and you can use the .readBytes() function.

actualNumberRead = SIM900A.readBytes(receivedChars, numChars).

The return from the function which will give the actual number of bytes read and you null terminate the message with receivedChars[actualNumberRead] = '\0';

where i have to insert this line,"actualNumberRead" how to initialise?

What have you tried?

#first i want above serial data in single char array
#secondly i need to assign this "+917987553768" and this "sms content" to separate char arrays for further reference.

First thing you need to do is better understand what data you are receiving. The modem will often send a message that has multiple newline & carriage returns. As @johnwasser said... your logic is too simplistic... you are stopping at the first newline.

I suggest printing out every character you receive in HEX... only then will you be sure that what you see is what you received. Then you need to see if there is something unique that terminates your message.

You might be better looking for the "+CMT:" substring (that is quite unique)... from there you can move along the message and look for the phone number in between quotes ""xxx"".. as for the message text itself... if you use AT+CNMI=2,1,0,0,0\r, then instead of getting the message directly, it will return a reference to the message stored within the modem. You can then use that to retrieve the message text.

Now i have changed! with your suggestion , (if anything wrong please pin out)

here is my code

#include <SoftwareSerial.h>

SoftwareSerial SIM900A(11, 10);

#include <Wire.h>


// Array to hold the number a SMS is retreived from
String textMessage;
const byte numChars = 80;
int actualNumberRead;//[];//= 83;
char receivedChars[numChars];
boolean newData = false;
char tempChars[numChars];
char messageFromPC[numChars] = {0};
char messageFromPC1[numChars] = {0};
void setup()
{
  SIM900A.begin(9600);   // Setting the baud rate of GSM Module
  Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
  Serial.println ("SIM900A Ready");
  delay(1000);
  Serial.println ("Type s to send message or r to receive message");
  SIM900A.println("AT+CMGF=1");
  delay(500);
  SIM900A.println("AT+CNMI=2,2,0,0,0\r");
  delay(100);

}
void loop()
{

  strcpy(tempChars, receivedChars);
  recvWithEndMarker();
  //  showNewData();
  /*if (Serial.available() > 0)
    switch (Serial.read())

    {
      case 's':

        SendMessage();
        break;

    }*/

}


void recvWithEndMarker()
{

  static byte ndx = 0;
  char endMarker = '\n';
  char rc;


  while (SIM900A.available() > 0 && newData == false) {
    rc = SIM900A.read();
    //Serial.println(rc);
    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      actualNumberRead = SIM900A.readBytes(receivedChars, numChars);
      Serial.println(receivedChars);
      if (ndx >= numChars)
      {

        // Serial.println(receivedChars);
        ndx = numChars - 1;
      }

    }

    else {

      // receivedChars[ndx] = '\0'; // terminate the string
      receivedChars[actualNumberRead] = '\0';
      ndx = 0;
      newData = true;

    }

  }


}


/*void showNewData() {
  if (newData == true) {
    // Serial.print("This just in ... ");
    Serial.println(receivedChars);
    newData = false;
  }
  }*/
void SendMessage()
{
  Serial.println ("Sending Message");
  SIM900A.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);

  SIM900A.println("AT+CMGS=\"+917987553768\"\r"); //Mobile phone number to send message*/
  delay(1000);

  SIM900A.println("hipp");// Messsage content
  delay(1000);

  SIM900A.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

}
/*

   void parseData() {      // split the data into its parts

   char * strtokIndx; // this is used by strtok() as an index

   strtokIndx = strtok(tempChars," ");      // get the first part - the string
   if(strcmp(strtokIndx,"+CMT:")==0)
  {

   strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

   strtokIndx = strtok(NULL,"\",\"" ); // this continues where the previous call left off
   strcpy(messageFromPC1, strtokIndx);
  }
  }

   Serial.print("masfg ");
       Serial.println(messageFromPC);
       Serial.print("Integer ");
       Serial.println(messageFromPC1);*/

Serial o/p is

SIM900A Ready
Type s to send message or r to receive message
T+CMGF=1

OK
AT+CNMI=2,2,0,0,0


OK


+CMT: "+917987553768","","21/12/14,08:57:51+22"
Sms contents

Here you can see two arrays
one is+CMT: "+917987553768","","21/12/14,08:57:51+22"
second is Sms contents .
I need this data in in a single array.

please reffer thread #11

+CMT: "+917987553768","","21/12/14,08:57:51+22"
Sms contents

you can see my GSM serial o/p of "sms content" itself in fresh line.

I have insert this line for waiting for read the complete the serial data, but its work with only first sms. After that serial out become in two line.

 else
        {
          unsigned long currentMillis = millis();
            if(currentMillis-counter>=period)
           { 
            receivedChars[ndx] = '\0'; // terminate the string
           //receivedChars[actualNumberRead] = '\0';
            ndx = 0;
            newData = true;
           counter=currentMillis;
           }
        }

The data is NOT arriving in 2 arrays... YOU are putting it in 2 arrays because you are not handling the newline character.

Did you even read my previous post?

once i get the total serial data in single line then after i will do this.

but how can read the full serial data in a stretch. i know i have using endMaker='\n' is creating the problem.In place of endMaker what will be i supposed to use.

Using the String in place of char, i have completed the program and result also good what i expected. But i want to know how can achieve the same result by using char in place of String. :slightly_smiling_face:

As I said in my original post... you need to understand the data you receive... and by "understand"... I mean you need to know EXACTLY what to expect - every newline, every carriage return.

Run this sketch (change the software serial pins)... and send the modem a text.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(7, 8);


byte          buffer[256];
uint16_t      idx           = 0;
unsigned long lastRead      = 0;


void setup()
{
  Serial.begin(115200);
  mySerial.begin(19200);
  delay(100);

  mySerial.println("AT+CMGF=1");         // SMS text mode
  delay(50);

  mySerial.println("AT+CNMI=2,2,0,0,0"); // How incoming SMS are handled
  delay(50);
}


void loop()
{
  // Send commands from the monitor.
  while (Serial.available())
  {
    mySerial.write(Serial.read());
  }

  idx = 0;
  
  do
  {        
    while (mySerial.available())
    {
      lastRead = millis();
      buffer[idx++] = mySerial.read();
    }
  } while (idx > 0 && millis() - lastRead < 10);


  if (idx > 0)
    displayMessage();
}

void displayMessage()
{
  Serial.println();


  // Display raw data in HEX.
  for (uint16_t i = 0; i < idx; i++)
  {
    if (buffer[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(buffer[i], HEX);
  }
  Serial.println();


  // Display ASCII
  for (uint16_t i = 0; i < idx; i++)
  {
    if (buffer[i] == 0x0D)
      Serial.print("CR");
    else if (buffer[i] == 0x0A)
      Serial.print("NL");
    else
    {
      Serial.print(char(buffer[i]));
      Serial.print(" ");
    }
  }
}

As you will see... the response comes as a single string. BUT it contains CR (0x0D) and NL (0x0A) characters. So you will need to look for these in the response... and find the message in between them.

Note that this is just an example... to show you the data received.

this is the o/p

41542B434D47463D310D0D0A4F4B0D0A
A T + C M G F = 1 CRCRNLO K CRNL

41542B434E4D493D322C322C302C302C300D0D0A4F4B0D0A
A T + C N M I = 2 , 2 , 0 , 0 , 0 CRCRNLO K CRNL

0D0A2B434D543A20222B393137393837353533373638222C22222C2232312F31322F31342C31323A34373A31392B3232220D0A48690D0A
CRNL+ C M T :   " + 9 1 7 9 8 7 5 5 3 7 6 8 " , " " , " 2 1 / 1 2 / 1 4 , 1 2 : 4 7 : 1 9 + 2 2 " CRNLH i CRNL

0D0A2B434D543A20222B393137393837353533373638222C22222C2232312F31322F31342C31323A34383A30332B3232220D0A436F6E74656E740D0A
CRNL+ C M T :   " + 9 1 7 9 8 7 5 5 3 7 6 8 " , " " , " 2 1 / 1 2 / 1 4 , 1 2 : 4 8 : 0 3 + 2 2 " CRNLC o n t e n t CRNL

So as you can see there are carriage returns, and newlines in the message. But it is all returned together. DO you see what I mean?

yes.

In my earlier program ,after a line the data will be in new char array. Because the serial reading stopped when the CRNL happened.
How i can overcome that problem in the program mentioned in thread#11.

convert the byte Array (buffer) in to Char array (receivedChars) is it possible ?