Using a const *char in a GSM AT command string fails. Syntax question

I'm trying to get a declared const *char value to work in an AT command line, strangely to me, it works in a Serial.print statement, but not in a mySerial.print for an AT command for a GSM module. Using String values to pass to an SMS message like this has always worked fine.

//Highlights 
const char * number = "1727nnnnnnn";
const char * message = "Test message";

// Works perfect
Serial.println(number);

// The AT commands produces an error because the word "number" is in the AT command line, not the 11-digit number.
mySerial.print("AT+CMGS=\" number \"\r");

// Works perfectly with the number hard-coded like this.
mySerial.print("AT+CMGS=\"1727nnnnnnn\"\r");

I cannot find an example of this.
What would be the correct syntax?

There are many possibilities.

Core which doesn't support printf

char buf[80];
snprintf( buf, sizeof buf, "AT+CMGS=\" %s \"\r", number);
mySerial.print(buf);

Core which does support printf

mySerial.printf("AT+CMGS=\" %s \"\r", number);

Any core

mySerial.print("AT+CMGS=\"");
mySerial.print(number);
mySerial.print("\"\r");

Edit: and I suspect you really didn't want the " characters around the number itself but were hoping for string constant concatenation, in which case it'd be:

Core which doesn't support printf

char buf[80];
snprintf( buf, sizeof buf, "AT+CMGS=%s\r", number);
mySerial.print(buf);

Core which does support printf

mySerial.printf("AT+CMGS=%s\r", number);

Any core

mySerial.print("AT+CMGS=");
mySerial.print(number);
mySerial.print("\r");
2 Likes

It would be helpful if you posted the actual error message instead of just saying "produces an error".

1 Like

The OP could have expressed themselves clearer, I agree.

Their print statement produces AT+CMGS=" number " rather than AT+CMGS=1727nnnnnnn, so it would be the GSM module coming back with (I expect) the generic AT ERROR response.

you could get it to work using string literal concatenation if you were using a define instead of a const char * and of course add a couple double quotes

something like this

#define number1  "1727nnnnnnn"
void setup() {
  Serial.begin(115200);
  Serial.println("AT+CMGS=\"" number1 "\"\r"); // AT+CMGS="1727nnnnnnn"\r
}
void loop() {}
1 Like

Now you are just showing off LOL

Or:

void setup() {
  Serial.begin(115200);
  delay(1000);

  const char * number = "1727nnnnnnn";
  Serial.print("AT+CMGS=\"" + String(number) + "\"\r");
}

void loop() {
}

I'd look very closely at what you put in your sketch to come up with that output. Very. Closely.

And perhaps try one of the several other alternatives that have already been proposed to you.

Serial.print("AT+CMGS=\"" + String(number) + "\"\r");

This solved it gfvalvo and van der decken.

What got me started on this was the below code by John Wasser, a big contributor here.

#include <SoftwareSerial.h>

SoftwareSerial ATCommandStream(2, 3);
unsigned long ATComandBaudRate = 19200;

const char * DestinationNumber = "+639358861057";
const char * SMSMessage = "Test Message";

void setup()
{
  // start th serial communication with the host computer
  Serial.begin(115200);
  while (!Serial);
  delay(200);
  Serial.println("Sketch started.");

  ATCommandStream.begin(ATComandBaudRate);
  Serial.print("ATCommandStream started at baud rate ");
  Serial.println(ATComandBaudRate);

  // Turn on verbose messages
  SendShortCommand("AT+CMEE");

  // Set character set to GSM:
  SendShortCommand("AT+CSCS=\"GSM\"");

  // Set the SMS output to text mode
  SendShortCommand("AT+CMGF=1");

  // Check the phone number type
  SendShortCommand("AT+CSTA?");
  Serial.println("Note: 129=Unknown, 161=National, 145=International, 177=Network Specific");

  // Test for CMGS command support:
  SendShortCommand("AT+CMGS=?");

  SendSMSMessage(DestinationNumber, SMSMessage);

  SendShortCommand("AT"); // Just checking that it responds with OK
}

void loop() {}

bool WaitForResponse()
{
  unsigned long startTime = millis();
  while (millis() - startTime < 5000)
  {
    String reply = ATCommandStream.readStringUntil('\n');
    if (reply.length() > 0)
    {
      Serial.print("Received: \"");
      Serial.print(reply);
      Serial.println("\"");

      if (reply.startsWith("OK"))
        return true;
        
      if (reply.startsWith("ERROR"))
        return false;
    }
  }
  Serial.println("Did not receive OK.");
  return false;
}

bool SendShortCommand(String command)
{
  Serial.print("Sending command: \"");
  Serial.print(command);
  Serial.println("\"");

  ATCommandStream.print(command);
  ATCommandStream.print("\r\n");

  return WaitForResponse();
}

void SendSMSMessage(const char *number, const char *message)
{
  Serial.println("Sending SMS text");

  Serial.print("Sending: ");
  Serial.print("AT+CMGS=\"");
  Serial.print(number);
  Serial.println("\"(CR)");
  Serial.print(message); // The SMS text you want to send
  Serial.println("(EM)");

  ATCommandStream.print("AT+CMGS=\"");  // Send SMS
  ATCommandStream.print(number);
  ATCommandStream.print("\"\r"); // NOTE: Command ends with CR, not CRLF
  ATCommandStream.print(message); // The SMS text you want to send
  ATCommandStream.write(26); // ASCII EndMessage (EM) CTRL+Z character

  WaitForResponse();
}

He apparently uses this code without the String modification you suggested.
I'm still studying it.

True. But nowhere in that code did he attempt to do what you tried: