0

SMS String format issues
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

SMS String format issues

by WesJoe on Sat Feb 27, 2021 5:28 pm

Hi all,

I'm new here, and I'm new to programming and Arduino in general.
I am building something to basically act as a remote weather station, and I want it to text(sms) me the sensor data.

I've posted my code below, and what I'm trying to figure out, is how come I can't seem to get the correct formatting for this project.
I can get it to message me all the data over multiple messages, but I can't understand why I can't format it into one message, because this would
certainly be under 140 characters.

I'm looking for something like the following example:

4012mV Battery pack
65.10% Relative humidity
14.62 'C Temperature
1023.44mb Barometric pressure

As I said, I have managed to get it to work over 2 or three separate messages, but when I try to string it all together, I either get a "Failed" message,
or just a blank message delivered to my phone.

I'm sure it's the way I'm formatting the text/strings and converting to charArray... which to be brutally honest, was really confusing and took me a
couple of days to figure out on its own :S

I hope someone might be able to help, and put me out of my misery :D

Wes

Code: Select all | TOGGLE FULL SIZE
#include "Adafruit_FONA.h"
#include <SFE_BMP180.h>
#include <Wire.h>
#include "DHT.h"

#define FONA_RX 5
#define FONA_TX 3
#define FONA_RST 4 //sms

#define DHTPIN 2
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

SFE_BMP180 pressure;
double pressNEW;

#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);

#define phoneNumber "phone number"


void setup() {
  // initialize serial communications and wait for port to open:
  Serial.begin(115200);

  dht.begin();

  if (pressure.begin())
    Serial.println("BMP180 init success");
  else
  {
    Serial.println("BMP180 init fail (disconnected?)\n\n");
    while(1); // Pause forever.
  }
 
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("SMS Data Sender");

  fonaSerial->begin(4800);
  if (! fona.begin(*fonaSerial)) {
    Serial.println(F("Couldn't find FONA"));
    while (1);
  }
  Serial.println(F("FONA is OK"));
  Serial.println(F("Found "));
  Serial.println("Allowing 25s for boot time and signal acquisition.");

  delay(25000);

}

void loop() {

/////////////////////////////////////////// read the battery voltage
        uint16_t vbat;
        if (! fona.getBattVoltage(&vbat)) {
          Serial.println(F("Failed to read Batt"));
        } else {
          Serial.print(F("VBat = ")); Serial.print(vbat); Serial.println(F(" mV"));
        }
String str1;
String str2="mV";
String str3;
str1=String(vbat);
//str3=str1 + str2;

/////////////////////////////////////////////////CHECK DHT

float h = dht.readHumidity();
float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

String str1dht;
String str2dht="% Humidity\n";
String str3dht;
String str4dht="'C Temperature";
String str5dht;
str1dht=String(h);
str3dht=String(t);
//str5dht=str1dht + str2dht + str3dht + str4dht;

////////////////////////////////////////////////CHECK BMP180

double pressNEW;
pressNEW=getPressure();

String baroSTR1;
String baroSTR2="mb barometric pressure";
baroSTR1=String(pressNEW);
//String baroSTR3=baroSTR1+baroSTR2;

///////////////////////////////////////////////////////////SEND ALL IN ONE

char completeMSG[141];

String space=" ";

String str1COMP;
str1COMP=str1; //batt mV
String battMV="mV battery, ";

String str2COMP;
str2COMP=str1dht; //humidity %
String hum="%RH, ";

String str3COMP;
str3COMP=str3dht; //temp C
String tem="'C, ";

String str4COMP;
str4COMP=baroSTR1; //baro pressure mb

String str5COMP;
str5COMP=str1COMP + battMV + str2COMP + space + str3COMP + tem + str4COMP;
str5COMP.toCharArray(completeMSG,140);

        flushSerial();
               
    if (!fona.sendSMS(phoneNumber, completeMSG)) {
    Serial.println(F("Failed"));
    } else {
    Serial.println(F("Sent!"));
    }

    Serial.println("\nCOMPLETE!\n");
    delay(20000);

}
//////////////////////////////////////////////////////////////////////////


void flushSerial() {
  while (Serial.available())
    Serial.read();
}

double getPressure()
{
  char status;
  double T,P,p0,a;

  // You must first get a temperature measurement to perform a pressure reading.
 
  // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.

  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:

    delay(status);

    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Use '&T' to provide the address of T to the function.
    // Function returns 1 if successful, 0 if failure.

    status = pressure.getTemperature(T);
    if (status != 0)
    {
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.

      status = pressure.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);

        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Use '&P' to provide the address of P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.

        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          return(P);
        }
        else Serial.println("error retrieving pressure measurement\n");
      }
      else Serial.println("error starting pressure measurement\n");
    }
    else Serial.println("error retrieving temperature measurement\n");
  }
  else Serial.println("error starting temperature measurement\n");
}

WesJoe
 
Posts: 11
Joined: Fri Feb 12, 2021 5:29 am

Re: SMS String format issues

by rskup on Mon Mar 01, 2021 12:47 am

I have an Adafruit Feather connected to a FONA 3G, and tried to duplicate your problem best I could. I don't have your same exact setup of course, but I played around with sending similar messages as yours using the same char array size as in your code, same punctuation (',%,\n), stuff like that.

Anyways, could not duplicate your problem, message was sent and received just fine. However, I am not using FONA.h, I prefer to code using the actual AT commands rather than use the FONA library.

So a couple of ideas, it doesn't seem you're printing out str5COMP to your serial monitor, maybe try that and see that the message you're trying to send looks ok. Better yet, add the following after your "str5COMP.toCharArray(completeMSG,140)" line:

Serial.println(completeMSG);

Does your message look right on the serial monitor?

Another thought, not a code expert, but maybe FONA.h is adding to your message length somehow, try shortening your descriptions (ie, Relative Humidity to RH, Temperature to Temp, and so on) and reducing the size of your char array and the "len" in the ".toCharArray" command. IE, rather than the 141 and 140, try 121 and 120.

Let me know what happens, maybe between the two setups the problem can be identified.

rskup
 
Posts: 84
Joined: Sat Aug 01, 2020 9:04 pm

Re: SMS String format issues

by WesJoe on Mon Mar 01, 2021 5:21 am

Hey rskup, and thanks for the reply.
As you suggested, I did try and lower the "len" of chars in the array, with the same results. I also tried to abbreviate things to RH and Temp, with the same results.
I think the problem is something to do with how the fona library formats the message.

So I would rather use AT commands to be honest.
Any advice on how I would start doing this? Is it as simple as starting the fona serial and then typing or coding in the AT commands as necessary?
Thank you for you time in trying to help!

WesJoe
 
Posts: 11
Joined: Fri Feb 12, 2021 5:29 am

Re: SMS String format issues

by EPD on Mon Mar 01, 2021 6:43 am

Hi WesJoe,
I've not been able to test your code as I don't have the hardware with me currently, I've had similar problems in the past, try putting .c_str() after all your string variables when generating the complete message variable, I've had a similar issue in the past when trying to send gps coordinates with .c_str() fixing the issue. .c_str() is used to convert a String into a null terminated string, a slightly different data type that is just "hello" instead of (String)"hello". hope this helps.

EPD
 
Posts: 6
Joined: Fri Feb 19, 2021 6:01 pm

Re: SMS String format issues

by WesJoe on Mon Mar 01, 2021 6:49 am

Ok great, thanks EPD. I will certainly give that a go and post my results here!

WesJoe
 
Posts: 11
Joined: Fri Feb 12, 2021 5:29 am

Re: SMS String format issues

by rskup on Mon Mar 01, 2021 10:20 am

Hi WesJoe,

Here's the code I added to my FONA project code to test your issue. Also added some comments, hope it works for you.

Note my Feather uses Serial1 to communicate to the FONA 3G, so I think(???) you need to replace my "Serial1" with your "fonaSerial".

Let us know what happens!

Code: Select all | TOGGLE FULL SIZE
    String str5COMP;
    char completeMSG[141];
   
    str5COMP = "SIM5320 Test \nTest 'Test \n%Test Test";
    str5COMP.toCharArray(completeMSG,140);

    // see how it looks on serial monitor
    Serial.println("");
    Serial.println(str5COMP);
    Serial.println("");
    Serial.println(completeMSG);
    Serial.println("");

    // tell FONA number
    Serial1.println("AT+CMGS=\"12223334444\"\r");   //your number here
    delay(100); // small delay for SIM5320 to respond
   
    // tell FONA message
    Serial1.println(completeMSG);
    Serial1.println((char)26);  // lets FONA know your message is done

rskup
 
Posts: 84
Joined: Sat Aug 01, 2020 9:04 pm

Re: SMS String format issues

by WesJoe on Mon Mar 01, 2021 10:33 am

Awesome! Thank you so much rskup! I will try as soon as i get home tonight.
Thank you very much and I'll keep you posted!

WesJoe
 
Posts: 11
Joined: Fri Feb 12, 2021 5:29 am

Re: SMS String format issues

by rskup on Mon Mar 01, 2021 1:07 pm

Sorry, me again, added some new lines to minimize possible issues.

Just dawned on me not sure when the FONA.h library lets the SIM chip know the SMS message format is "Text mode" rather than "PDU mode".

So since we're not using the FONA library for the SMS, added a new line for this SMS mode choice. I had the line up in my setup(), but moved it down to your test code to make sure it would work there too. Also added a line to make sure the "echo" option for the SIM chip is off...just to simplify things for now.

I realize the "delay()" here and there may look odd, but if you dig through the FONA library code they are in there as well.

Ok, new code below, hope things go well!

Code: Select all | TOGGLE FULL SIZE

    String str5COMP;
    char completeMSG[141];
   
    str5COMP = "SIM5320 Test \nTest 'Test \n%Test Test";
    str5COMP.toCharArray(completeMSG,140);

    // see how it looks on serial monitor
    Serial.println("");
    Serial.println(str5COMP);
    Serial.println("");
    Serial.println(completeMSG);
    Serial.println("");

    // turn echo off from SIM5320 to make things easier
    Serial1.println("ATE0");   // turns echo off
    delay(100); // small delay for SIM5320 to respond
    while (Serial1.available()) {
      Serial.print(Serial1.readString()); // if worked should see "OK" on serial monitor
    }

    // tell SIM5320 using text mode, rather than PDU mode, for SMS message format
    Serial1.println("AT+CMGF=1");   // 1 is Text mode (0 is PDU mode)
    delay(100); // small delay for SIM5320 to respond
    while (Serial1.available()) {
      Serial.print(Serial1.readString()); // if worked should see "OK" on serial monitor
    }

    // tell FONA number
    Serial1.println("AT+CMGS=\"12223334444\"\r");   // your number here
    delay(100); // small delay for SIM5320 to respond
       
    // tell FONA message
    Serial1.println(completeMSG);
    Serial1.println((char)26);  // lets FONA know your message is done

rskup
 
Posts: 84
Joined: Sat Aug 01, 2020 9:04 pm

Re: SMS String format issues

by WesJoe on Mon Mar 01, 2021 5:59 pm

WOOHOO!!

Success! Thank you both, but RSKUP, you helped me especially!
EPD, I did firstly try adding ".c_str()" as it was the easiest thing to try, but it made no difference at all :/

Next thing I tried was not using the fona lib, and just using fonaSS(software serial), which helped me pin point the next problem.
Which was, that i got the exact same issue as before! haha
So I started experimenting with the formatting of the messages, and eventually found that by just adding my variables into the final message bit of RSKUP's code, I could format it all and get it all to work the way that I wanted. *code line marked // THIS WAS IT!

Anyways, thanks again very much for your help! Hopefully I may be able to help in return one day!

Code: Select all | TOGGLE FULL SIZE
#include "Adafruit_FONA.h"
#include <SFE_BMP180.h>
#include <Wire.h>
#include "DHT.h"

#define FONA_RX 5
#define FONA_TX 3
#define FONA_RST 4 //sms

#define DHTPIN 2
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

SFE_BMP180 pressure;
double pressNEW; // baseline pressure

#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;

Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);



#define phoneNumber "123456789"


void setup() {
  // initialize serial communications and wait for port to open:
  Serial.begin(115200);

  dht.begin();

  if (pressure.begin())
    Serial.println("BMP180 init success");
  else
  {
    Serial.println("BMP180 init fail (disconnected?)\n\n");
    while(1); // Pause forever.
  }
 
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("SMS Data Sender");

  fonaSerial->begin(4800);
  if (! fona.begin(*fonaSerial)) {
    Serial.println(F("Couldn't find FONA"));
    while (1);
  }
  Serial.println(F("FONA is OK"));
  Serial.println(F("Found "));
  Serial.println("Allowing 25s for boot time and signal acquisition.");

  delay(25000);

}

void loop() {

/////////////////////////////////////////// read the battery voltage
        uint16_t vbat;
        if (! fona.getBattVoltage(&vbat)) {
          Serial.println(F("Failed to read Batt"));
        } else {
          Serial.print(F("VBat = ")); Serial.print(vbat); Serial.println(F(" mV"));
        }
String str1;
String str2="mV";
String str3;
str1=String(vbat);
//str3=str1 + str2;

/////////////////////////////////////////////////CHECK DHT

float h = dht.readHumidity();
float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

String str1dht;
String str2dht="% Humidity\n";
String str3dht;
String str4dht="'C Temperature";
String str5dht;
str1dht=String(h);
str3dht=String(t);
//str5dht=str1dht + str2dht + str3dht + str4dht;

////////////////////////////////////////////////CHECK BMP180

float pressNEW=getPressure();

String baroStr;
baroStr=String(pressNEW);

//////////////////////////////////////////////////////////////////////////CHECK RANGE

int range;
range=random(140);

String rangeStr;
rangeStr=String(range);


//RSKUP TEST CODE///////////////////////////////////////////////////////////////

flushSerial;

    Serial.println(baroStr + " baro reading");

    Serial.println("o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o");

delay(5000);

    // turn echo off from SIM5320 to make things easier
    fonaSS.println("ATE0");   // turns echo off
    delay(200); // small delay for SIM5320 to respond
    while (fonaSS.available()) {
      Serial.print(fonaSS.readString()); // if worked should see "OK" on serial monitor
    }

    // tell SIM5320 using text mode, rather than PDU mode, for SMS message format
    fonaSS.println("AT+CMGF=1");   // 1 is Text mode (0 is PDU mode)
    delay(200); // small delay for SIM5320 to respond
    while (fonaSS.available()) {
      Serial.print(fonaSS.readString()); // if worked should see "OK" on serial monitor
    }

    // tell FONA number
    fonaSS.println("AT+CMGS=\"07588018718\"\r");   // your number here
    delay(200); // small delay for SIM5320 to respond
       
    // tell FONA message
    fonaSS.print("Status: \n"+str1+" Batt mV \n"+str3dht+" 'C Temp \n"+str1dht+" % RH \n"+baroStr+" mb Pressure \n"+rangeStr+" cm range");    //THIS WAS IT!!
    fonaSS.println((char)26);  // lets FONA know your message is done

delay(15000);

}
//////////////////////////////////////////////////////////////////////////


void flushSerial() {
  while (Serial.available())
    Serial.read();
}

double getPressure()
{
  char status;
  double T,P,p0,a;

  // You must first get a temperature measurement to perform a pressure reading.
 
  // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.

  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:

    delay(status);

    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Use '&T' to provide the address of T to the function.
    // Function returns 1 if successful, 0 if failure.

    status = pressure.getTemperature(T);
    if (status != 0)
    {
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.

      status = pressure.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);

        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Use '&P' to provide the address of P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.

        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          return(P);
        }
        else Serial.println("error retrieving pressure measurement\n");
      }
      else Serial.println("error starting pressure measurement\n");
    }
    else Serial.println("error retrieving temperature measurement\n");
  }
  else Serial.println("error starting temperature measurement\n");
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

WesJoe
 
Posts: 11
Joined: Fri Feb 12, 2021 5:29 am

Please be positive and constructive with your questions and comments.