String length showing Zero value

Hello,

I am getting the string length value Zero, when I want to check the length.
Longitude and Latitude are showing as expected. But the string length not showing correctly and always showing as Zero.
The below is the sketch

#include <DFRobot_sim808.h>
#include <SoftwareSerial.h>
#define DEBUG true

#define PIN_TX    4
#define PIN_RX    5
SoftwareSerial mySerial(PIN_TX,PIN_RX);

DFRobot_SIM808 sim808(&mySerial);


String strlat;
String strlon;

void setup(){
  mySerial.begin(9600);
  Serial.begin(9600);
  mySerial.println("AT+CIPSHUT");
  ShowSerialdata();
  mySerial.println("AT+CIPMUX=0");
  ShowSerialdata();
 mySerial.println("AT+CGATT=1");
 ShowSerialdata();
 delay(1000);
mySerial.println("AT+CIPMODE=1");
ShowSerialdata();
delay(1000);
mySerial.println("AT+CSTT=\"airtelgprs.com\",\"\",\"\"");
ShowSerialdata();
delay(1000);
mySerial.println("AT+CIICR");
ShowSerialdata();
delay(2000);
mySerial.println("AT+CIFSR");
ShowSerialdata();
delay(1000);
mySerial.println( "AT+CGNSPWR=1");
ShowSerialdata();
delay(2000); 
//mySerial.println( "AT+CGNSSEQ=GGA");
mySerial.println("AT+CIPSPRT=1");
//mySerial.println("AT+CIPSTART=\"TCP\",\"xx.xx.xx.xx\",\"4001\"");
//ShowSerialdata();
delay(2000);
}
void loop(){
if (sim808.getGPS()) {
  //Serial.print("latitude :");
      Serial.println(sim808.GPSdata.lat);
      read_String_lat();
      Serial.println(strlat); // Value is coming as expected
      Serial.println(strlen(strlat)); /// Here I am getting Zero length
      //Serial.print("longitude :");
      Serial.print(sim808.GPSdata.lon);
      read_String_lon(); 
      Serial.println(strlon); // Value is coming as expected
      Serial.println(strlon.length()); /// Here I am getting Zero length
      
}
}

void ShowSerialdata()
{
  if (mySerial.available())
  {
  while (mySerial.available() != 0)
   {
  Serial.write(mySerial.read());
   }
  }
  if (Serial.available())
  {
  while (Serial.available() != 0)
  {
  mySerial.write(Serial.read());
  }
  }
}

void read_String_lat() 
{
  if (Serial.available() > 0)
  {
    strlat = Serial.readStringUntil('\n');
  }
  }

void read_String_lon() 
{
  if (Serial.available() > 0)
  {
    strlon = Serial.readStringUntil('\n');
  }
  }

Instead ofSerial.println(strlen(strlat));
try:Serial.println(strlat.length());

Jacques

I have tried yet.. But still no luck... Why the value is coming Zero?

Show the code you used

If Serial.println(strlat); is really the line of code displaying the Value in the console (and not an echo mode that you used to empty buffers with ShowSerialdata() then it’s 100% sure - if the next line in code is Serial.println(strlat.length()); - that you’ll see proper length.

I would be tempted to think that if this is what you have done then your first print is not the one displaying the string and your strlat = Serial.readStringUntil('\n'); never executed or timed out because you emptied the buffer elsewhere

To find out you can print something else in the loop like

Serial.print(”found latitude: [“);Serial.print(strlat); Serial.println(”]”);
Serial.print(”length = “); Serial.println(strlat.length());

Then you can tell if this is really coming from the loop or elsewhere

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

...R

yes… I am using char array instead of String, as this is really causing memory fragmentation.

Even after using the array, I am not able to store the value strlat at char array. How Do I capture the value and store at strlat from GPS sheild?

The below is my modified sketch…

#include <DFRobot_sim808.h>
#include <SoftwareSerial.h>

#define PIN_TX    4
#define PIN_RX    5
SoftwareSerial mySerial(PIN_TX,PIN_RX);


DFRobot_SIM808 sim808(&mySerial);
char buffer[512];
char strlat[20]= {'\0'};

void setup(){
  mySerial.begin(9600);
  Serial.begin(9600);
while(!sim808.init()) { 
      delay(3000);
      Serial.print("Sim808 init error\r\n");
  }
  if( sim808.attachGPS()){
      Serial.println("Open the GPS power success");
  }
  else{ 
  
      Serial.println("Open the GPS power failure");
  }

 if(!sim808.connect(TCP,"xxx.xxx.xxx.x", 4001)) {
      Serial.println("Connect error");
  }else{
      Serial.println("Connect to Server success");
  }
}

void loop(){

  read_String_lat();
}

void read_String_lat() 
{
  if (sim808.getGPS()) {
    
  while (Serial.available())
  {
    for (byte i=0; i<19; i++)
    strlat[i] = Serial.read();
    Serial.println(strlen(strlat));
  }
  }
  }

This is doomed and will fail you

while (Serial.available())
  {
    for (byte i=0; i<19; i++)
    strlat[i] = Serial.read();
    Serial.println(strlen(strlat));
  }

You can’t expect to read super fast 19 bytes when you only tested for the availability of possibly only 1 being there (especially at 9600 bauds your for loop spins so much faster than bytes are coming in so you exit the for loop, go back to the while and if by “luck” a ext byte has arrived then you start over for another 19 bytes… won’t work)

Also Don’t forget that a c-string needs to be null (’\0’) terminated to be well formed and to use it with c-string functions like strlen()

Study Serial Input Basics to understand how to correctly handle the serial port and the fact it is asynchronous and study also some of the typical c-string functions from stdlib.h and string.h

Yes… Thats correct… I have put a 2 secs delay. Also I made the ‘\0’ when I declared char array

But still no luck…

void read_String_lat() 
{
  if (sim808.getGPS()) {
    
  while (Serial.available())
  {
    for (byte i=0; i<19; i++)
    strlat[i] = Serial.read();
    delay(2000);
    
  }
  Serial.println(strlen(strlat));
  }
  }

Pokhraj:
Yes.... Thats correct... I have put a 2 secs delay.

Take out the delay and do the job properly.

...R

the delay won’t help

  while (Serial.available())
  {
    for (byte i=0; i<19; i++)  strlat[i] = Serial.read();
   ...

as you still read 19 bytes without any guarantee that they are available

You can’t second guess what’s going to happen on the Serial port by adding random delays … dealing with the Serial port is not black magic, wait for a byte to be available, read it, deal with it. if your response is complete, proceed to next stage in your code, if response is not complete, keep listening for new bytes to come in - best done in a non active wait way for the sake of your program responsiveness.

→ really read Robin’s tutorial.

Better go for actual sketch. It will give you the clear picture, as what I am trying to do.

The below is my new sketch. All the values are coming at serial monitor. When I am trying to store values at variable it is fails. Can you please help me to write the sketch to store values at variables please?

#include <DFRobot_sim808.h>
#include <SoftwareSerial.h>

#define PIN_TX    4
#define PIN_RX    5
SoftwareSerial mySerial(PIN_TX,PIN_RX);

DFRobot_SIM808 sim808(&mySerial);


char buffer[512];
char strlat[7]= {'\0'};   //char terminator
char strlon[7]= {'\0'};  //char terminator 

void setup(){
  mySerial.begin(9600);
  Serial.begin(9600);
  mySerial.println("AT");
  ShowSerialdata();
delay(2000);
while(!sim808.init()) { 
      delay(3000);
      Serial.print("Sim808 init error\r\n");
  }
  if( sim808.attachGPS())
      Serial.println("Open the GPS power success");
  else 
      Serial.println("Open the GPS power failure");
}

void loop(){
  read_String_lat();
  read_String_lon();
}


void ShowSerialdata()
{
  if (mySerial.available())
  {
  while (mySerial.available() != 0)
   {
  Serial.write(mySerial.read());
   }
  }
  if (Serial.available())
  {
  while (Serial.available() != 0)
  {
  mySerial.write(Serial.read());
  }
  }
}

void read_String_lat() 
{
  if (sim808.getGPS()) {
    Serial.println(sim808.GPSdata.lat); //Here Longitude value prints at Serial Monitor properly
  while (Serial.available() > 0)
  {
    for (byte i=0; i<6; i++)
    strlat[i] = Serial.read();
   // Serial.println(strlat); //No Value is coming at Serial Monitor.
  }
  }
  }

void read_String_lon() 
{
  if (sim808.getGPS()) {
    Serial.println(sim808.GPSdata.lon);  //Here Longitude value prints at Serial Monitor properly
  while (Serial.available() > 0)
  {
    for (byte j=0; j<6; j++)
    strlon[j] = Serial.read();
    //Serial.println(strlat); //No Value is coming at Serial Monitor.
  }
  }
  }

Not sure why it’s better... I know how to do it... just suggesting you need to study more

Your library can parse the GPS stream, why aren’t you using it?

Your library can parse the GPS stream, why aren't you using it?

Could you please suggest on this?

I know how to do it... just suggesting you need to study more

Yes.. Thats a good idea.. But I have no time in my hand. Day after tomorrow I need to submit the project.

Hence please help me.

Just have a look at the GPS example in your library's github repo. It is all there.