sending serial data to 3G module

I'm trying to send some serial data to a SIM5216 module to send an SMS

This is NOT the complete code but trying to work out why these two work differently

This works:

GSMSerial.println("AT+CMGS=\"00000000\"");    //where 00000000 would be replaced with a valid mobile number

This doesnt:

GSMSerial.print("AT+CMGS=\"");
GSMSerial.print(settings.RMN);
GSMSerial.println("\"");

settings.RMN contains a string of 00000000 (which would be replaced with a valid mobile number)

If I debug by sending the strings to the serial terminal I get what appears to be the same result of:

AT+CMGS="00000000"

for both variations which is what I would expect to get - but obviously there is a difference I cant see, because the first one works and the second doesn't.

Would it be because the first example the number string is treated differently to the second example? Hence the second example becomes an invalid AT command?

Once I finish editing all the garbage out of the code on the other computer I'll post the lot....standby

i

Full code for my test (spread over two posts)

#include <SoftwareSerial.h>          // For GSM/3G Module
#include <Time.h>                    // For Time
#include <SD.h>
#include <ctype.h>


//===================================================
// Setup for reading CONFIG.TXTfile from SD CARD
//===================================================
File myFile;
struct parameters {
  float TTP;
  String SiteName;
  String RMN;
  String SYSPIN;
} settings;

const int chipSelect = 4;              //Set SD CARD CS Line to Pin4
//****************************************************

//====================================================
// 3G module definitions & setup
//====================================================
#define unoTXPin (6)                                      // Uno -> GSM
#define unoRXPin (5)                                      // Uno <- GSM
#define powerGSMPin (8)                                   // GSM module power pin

#define AT_CREG_QUERY ("AT+CREG?")                        // Check for network registration
#define AT_CCLK ("AT+CCLK?")
#define EOS ('\0')
#define ESC (0x1A)
#define OK ("OK")
#define CTRL_Z ("\x1a")

SoftwareSerial GSMSerial(unoRXPin,unoTXPin);

char ATcomBuf[150];                                      //
char ATcomResp[100];                                     // 
char* valPos;                                            // 
//*****************************************************


int TimeHours, TimeMinutes, TimeSeconds;

//=======================================================
// Initialize
//=======================================================
void setup() {
  Serial.begin(9600);                               // Start serial comms for Debug 9600 baud
  delay(500);                                       // 
  Serial.println(F("SMS test"));             // DEBUG MESSAGE OUTPUT
  
  
//=======================================================
// Read configuration settings from SD card
//=======================================================
Serial.println(F("Init SD card"));
pinMode(4, OUTPUT);
  if (!SD.begin(chipSelect)) {
    Serial.println(F("SD CARD ERROR"));
    return;
  }

  myFile = SD.open("config.txt");                        //Open file
  char character;
  String description = "";
  String value = "";
  boolean valid = true;

  while (myFile.available()) {                        //read file until the end
    character = myFile.read();                        //
      if(character == '/')         {                  // Ignore lines with "/"
        while(character != '\n'){
        character = myFile.read();
        };
    } else if(isalnum(character))      {                // Add a character to the description
        description.concat(character);
    } else if(character =='=')         {                // start checking the value for possible results
      do {                                              // First going to trim out all trailing white spaces  
        character = myFile.read();
      } while(character == ' ');

     if(description == "TTP") {
          value = "";
          while(character != '\n') {
            if(isdigit(character)) {
              value.concat(character);
            } else if(character != '\n') {
              valid = false;                                     // Use of invalid values
            }
            character = myFile.read();            
          };
          if (valid = true) { 
            char charBuf[value.length()+1];                      // Convert string to array of chars
            value.toCharArray(charBuf,value.length()+1);
            settings.TTP = atof(charBuf);                        // Convert chars to float
          } else {
            settings.TTP = 0;                                   // revert to default value for invalid entry in settings
          }
     
              
        } else if(description == "SiteName") {              // Check & set SiteName
           value = "";
           do {
             value.concat(character);
             character = myFile.read();
           } while(character != '\n');
           settings.SiteName = value;
           

        } else if(description == "RMN") {                  // Check & set Recipient Mobile Number
           value = "";
           do {
             value.concat(character);
             character = myFile.read();
           } while(character != '\n');
           settings.RMN = value;      
        
        } else if(description == "SYSPIN") {                  // Check & set Recipient Email Address
           value = "";
           do {
             value.concat(character);
             character = myFile.read();
           } while(character != '\n');
           settings.SYSPIN = value;      
           
        }else {                                            // ignore unknown parameters
          while(character != '\n')
          character = myFile.read();
        }
        description = "";
        
     } else {                                            // Ignore this character (could be space, tab, newline, carriage return or something else)
      }
    }
    myFile.close();                                       // close the file:
  
  Serial.print(F("Site Name: "));
  Serial.println(settings.SiteName);
  Serial.print(F("Recipient Mobile Number: "));
  Serial.println(settings.RMN);
  Serial.print(F("System PIN: "));
  Serial.println(settings.SYSPIN);
  Serial.print(F("Temp Trigger Point: "));
  Serial.println(settings.TTP);

delay(2000);
   
  Serial.println("");                             //
  Serial.println(F("SYS : Initializing"));        //


//-----------------------------------------------
// GSM/3G module startup
//-----------------------------------------------
GSMSerial.begin(9600);                                      // start serial comms for GSM 9600 baud 
GSM_power_on();                                             // check module is on 
  Serial.println(F("3G : Ready"));                          // DEBUG : Module ON 
delay(2000);                                                // 2 second delay
while( (sendATcommand(AT_CREG_QUERY, "+CREG:0,1", 500) ||   // check is module is registered to network
    sendATcommand(AT_CREG_QUERY, "+CREG:0,5", 500)) == 0);  //
  Serial.println(F("3G : Registered"));                     // DEBUG : Registered

//-----------------------------------------------
// Sync RTC to Network Time
//-----------------------------------------------
  strcpy_P(ATcomBuf, PSTR("AT+CTZU=1"));             // enable clock sync to network 
    ATResponseOK();
      sendATcommand(ATcomBuf, ATcomResp, 500);
delay(200);                                                 // 
SyncTime();                                                 // set system clock 
  Serial.print(F("SYS : Time Set  "));                      // DEBUG : Display time 
    if (hour() < 10)                                        //
      Serial.print(F("0"));                                    //
  Serial.print(hour());                                     // 
  Serial.print(F(":"));                                        //
    if (minute() < 10)                                      //
      Serial.print(F("0"));                                    //
  Serial.println(minute());                                 // 
        
//delay(5000);

 Serial.println(F("SYS: Startup Complete"));
 
SMSsend();

}

//=======================================================
//=======================================================
// Main loop.
//=======================================================
//=======================================================
void loop(){
}
//==============================================
// Send SMS
//==============================================
void SMSsend(){
  GSMSerial.println("AT+CMGF=1");
  Serial.println("AT+CMGF=1");
  delay(1000);
  GSMSerial.println("AT+CSCA=\"+61418706700\"");
  Serial.println("AT+CSCA=\"+61418706700\"");
  delay(1000);
  
  GSMSerial.println("AT+CMGS=\"00000000\"");
//  GSMSerial.print("AT+CMGS=\"");
//  GSMSerial.print(settings.RMN);
//  GSMSerial.println("\"");
  delay(2000);
  GSMSerial.println(settings.SiteName);
  GSMSerial.println("This is the message body");
  GSMSerial.write(26);
  
  Serial.println("AT+CMGS=\"00000000\"");
//  Serial.print("AT+CMGS=\"");
//  Serial.print(settings.RMN);
//  Serial.println("\"");
  delay(2000);
  Serial.println(settings.SiteName);
  Serial.println("This is the message body");
  Serial.write(26);

}
//**********************************************

//===================================================================
// RTC & Time Sync
//===================================================================
void SyncTime(){
  sendATcommand(AT_CCLK, "+CCLK:  ", 500);                //Read the RTC from the GSM/3G Module
    char* valPos = ATcomResp +  19;               //Find the HOURS position in the response string
    TimeHours = atoi(valPos);                             //Read HOURS Value
    TimeMinutes = atoi(valPos + 3);                       //Find and read the MINUTES value
    TimeSeconds = atoi(valPos + 3);                       //Find and read the SECONDS value
  setTime(TimeHours,TimeMinutes,TimeSeconds,0,0,0);       //Set the clock from the RTC values
}                                                         //


//===============================================================
// GSM/3G Module AT Command send routine #1
//===============================================================
int8_t sendATcommand(char* ATcomBuf, char* expected_answer1,
unsigned int timeout)
{
  uint8_t x=0, answer=0;
  unsigned long previous;                                     //char response[100];
  memset(ATcomResp, EOS, 100);                                 // Initialize the string
  delay(100);
  while( GSMSerial.available() > 0) GSMSerial.read();         // Clean the input buffer
  GSMSerial.println(ATcomBuf);                               // Send the AT command
  x = 0;
  previous = millis();
  do{                                                         // this loop waits for the answer
    if(GSMSerial.available() != 0){
      ATcomResp[x] = GSMSerial.read();
      x++;
      
      if (strstr(ATcomResp, expected_answer1) != NULL){        // check if the desired answer is in the response of the module
        answer = 1;
      }
    }
 }
  while((answer == 0) && ((millis() - previous) < timeout));  // Waits for the answer with time out
  return answer;
}

//==============================================================
// GSM/3G Power On Command
//==============================================================
void GSM_power_on(){
  Serial.println(F("3G : Module Powering Up"));                 // DEBUG : Power on message
  uint8_t answer=0;                                          //   
  answer = sendATcommand("AT", "OK", 2000);                  // Checks if the module is started
  if (answer == 0){                                          // If no reply from module, turn module ON
    digitalWrite(powerGSMPin,HIGH);                          // Power on "pulse" to the module
    delay(400);                                              //    
    digitalWrite(powerGSMPin,LOW);                           //
    delay(6000);                                             // 
    while(answer == 0){                                      // Waits for an answer from the module.....
      answer = sendATcommand("AT", OK, 2000);                // Checks if the module is started
      Serial.println(F("Wait..."));                          // DEBUG : wait message
    }                                                        //
  }                                                          //  
}

void ATResponseOK(){
    strcpy_P(ATcomResp, PSTR("OK"));
}

I think I may be getting a clearer idea as to why it doesnt work after studying the received SMS

When I use the first option (which works) I seem to have some extra line breaks in the message after the SITENAME.
So I wonder if I am getting an extra line break (or two) after the number stored in (settings.RMN) which is causing the command to fail.

ie I would expect the received message to be:

SITENAME
This is the message body

But I am getting:

SITENAME

This is the Message body

Now to work out why that is happening and how I can change my config .txt file and the way its being read to overcome that....

Here is a sample of the config.txt file stored on the SD Card for reference:

// CONFIGURATION FILE - DO NOT DELETE

// TEMP TRIGGER POINT
TTP = 1

// SITE NAME
SiteName = TESTSITE

// RECIPIENT MOBILE NUMBER
RMN = 00000000

//SYSTEM PIN
SYSPIN = 1234

I thing you're looking at your problem in the right place. There must be something wrong with the content RNM.

Be aware that the serial monitor the Arduino enviroment is using will not display all control code correctly. Try to use an other terminal program for further debugging.

But remember to turn it off when uploading programs as 2 programs can not access the COM interace at the same time

Thanks larsv for the tip.

Just used a different term program and there it was - a nice CR at the end of the RMN value when using the 2nd code version

Now how to remove it?

Can i somehow limit the string to 10 digits effectively dropping the CR?
Or is the way I'm reading the string including the CR in the value and I could do it differently? Use a different char to show the end of the valid data in the config file?

Now how to remove it?

The easiest way is to not put it there in the first place.

          while(character != '\n' && character != '\r')
          {
            if(isdigit(character)) 
            {
              value.concat(character);
            } 
            else if(character != '\n' && character != '\r')
            {
              valid = false;                                     // Use of invalid values
            }
            character = myFile.read();            
          };

Thanks PaulS

I was looking at that section wondering if it was including the stray CR - of course it was as each line would be ended with a CR LF and I was ending on the LF so the CR would be included in my string

Hadn't got as far as working out how to stop the CR being included.

Modified my code with your suggestion and now the CR is gone and the strings are correctly being passed to the SIMCOM module and SMS's now work with the parameters sourced from the SD CARD :slight_smile:

Was good to learn the serial terminal issue too and I'll be sure to use a different one now so I dont get caught with that next time :frowning:

I have the above working quite nicely with the temperature alarm trigger point being an integer read from the config file.

Now I want the trigger temperature to be specified to one decimal place.

ie in the config file on the SD card:

TTP = 10.5

instead of the current:

TTP = 10

So I have changed:

TTP to a float instead of int
and changed atoi to atof

I thought that would then read in the value for TTP as 10.5
But it shows it as 105............what have I done wrong (apart from everything....)

Here is the section that reads the data from the SD for the variable TTP as it stands now:
As far as I understand it, it reads all the chars after the "TTP" "=" and whitespace until the CRLF - which means the buffer should contain "10.5" (without quotes) - but it seems to hold "105" (without quotes) - why did it lose the decimal?

     if(description == "TTP") {
          value = "";
            while(character != '\n' && character != '\r'){
            if(isdigit(character)) {
              value.concat(character);
            }  else if(character != '\n' && character != '\r'){
              valid = false;                                     // Use of invalid values
            }
            character = myFile.read();            
          };
          if (valid = true) { 
            char charBuf[value.length()+1];                      // Convert string to array of chars
            value.toCharArray(charBuf,value.length()+1);
            settings.TTP = atof(charBuf);                        // Convert chars to float
          } else {
            settings.TTP = 0;                                   // revert to default value for invalid entry in settings
          }

For the time being I have just added the the following to get the correct value - is this a valid fix???

settings.TTP = settings.TTP/10
what have I done wrong

You posted just a snippet. AGAIN!

I, for one, refuse to try to help you anymore until you post ALL of your code.

PaulS - FULL code was posted previously and has been updated..............I felt there no need to waste numerous posts to repost the code all over again when the changes I made where clearly stated above.

          if (valid = true) {

Someone is not paying attention.

I AM paying attention

If by your cryptic comment above you are saying that line should be:

if (valid == true) {
or maybe

if (valid) {

well they both stop the program from working.....

Currently the code as previously posted correctly assigns a value to TTP if the value is present in the config.txt file, or assigns a value of 0 to TTP if the value is missing from the config.txt file.

I'm unsure as to why that has anything to do with my missing decimal point, so I'll just stick with my /10 option as that means you don't have to help me anymore.

well they both stop the program from working.....

No. They stop the program from producing the results you expect. That is NOT the same as stopping working.

Using a single equal sign means that you are assigning the value of true to the variable, not testing that the value in the variable is true.

          while(character != '\n') {
            if(isdigit(character)) {
              value.concat(character);
            } else if(character != '\n') {
              valid = false;                                     // Use of invalid values
            }
            character = myFile.read();            
          };

After this loop is done, what is in value?

          if (valid = true) { 
            char charBuf[value.length()+1];                      // Convert string to array of chars
            value.toCharArray(charBuf,value.length()+1);

After this, what is in charBuf?

I fully agree PaulS -that line SHOULD be:

if (valid == true) {

As the double equals things has caught me out before (many times - bangs head on table!)

So i will re-phrase my previous statement:

if (valid = true) {

produces the correct results with the value from TTP being retrieved from the SD Card if its present or returns the "default" value of "0" if its not present.

If i change the code to what it SHOULD read:

if (valid == true) {

then it always returns the default value of "0" no matter what, ignoring the TTP value on the SD Card.

This is why I am stumped on this - when the code is OBVIOUSLY WRONG it works how I want it to, when its CORRECTED it fails to produce what is expected.

In reply to your other questions about the content of those two variables:

value = 105

charBuf = 105

So it seems whilst value is a string it doesn't seem to contain the decimal place which means its not correctly reading it from the card for some reason.

as a test I forced value to what I expected it to be by inserting this after the loop:

value = ("10.5");

I then get the expected result in charBuf and the atof function works with settings.TTP also holding 10.5, so its back to how the routine is reading the SD card and why its dropping the decimal out of the string.

I freely admit I don't fully grasp how its reading the card so I'll study those few lines a bit harder to see if I can work out whats wrong - as that's how you learn this stuff!

then it always returns the default value of "0" no matter what, ignoring the TTP value on the SD Card.

I'd question exactly what value is in valid.

Apparently, valid does NOT ever contain true, until you assign it the value of true in the incorrect if statement. Without having the SD card in hand, I'd have to guess that there is not a '\n' to define the end of the record, thus valid is not being set to true, thus the proper if test never evaluates to true.

PaulS - just FYI this is the content of the file on the SD Card

// CONFIGURATION FILE - DO NOT DELETE
// ALARM TRIGGER POINT
TTP = 10.5

// SITE NAME
SiteName = Test Bench

// RECIPIENT MOBILE NUMBER
RMN = 0000000000

I'll run some tests to see what the value of valid holds for the two possible outcomes with the two versions of code and see what that shows up.

Hi Stocky, sorry to resurrect an old thread, was wondering how your testing got on and how this card is going for you?