How to set the APN for GSM /SMS texting?

For the background, code, and what I’ve already tried, I have a topic here, but am not getting any replies… TOPIC

At this point my GSM shield is able to receive text messages, but I have been unable to send any messages.

The next thing I thought would be worth a try is to set the APN, username and password. I don’t know if it’s actually required, most example code does not do this, but I’ve exhausted everything else I can think of.

I’m looking for the AT+ code to send to the board to set the APN and if needed the username and password.

Here’s my existing code:

#include <SoftwareSerial.h>
  SoftwareSerial CellularSerial(7, 8);
#include<stdio.h>
#include<string.h>
#define DEBUG true

void setup()
{
  Serial.begin(9600);
  CellularSerial.begin(19200);
  delay(10000);
  int pon=3;
  int poff=9;
  int lowp=2;
  pinMode(pon, OUTPUT);
  pinMode(poff, OUTPUT);
  pinMode(lowp, OUTPUT);
  digitalWrite(poff, LOW);
  digitalWrite(lowp, HIGH);   
  digitalWrite(pon, HIGH);
  delay(3000); 
  digitalWrite(pon, LOW);
  sendData("AT ",1000,DEBUG);
  baudrate();
  Serial.println("After 3s, test begin!!");
  delay(3000);
  sendData("AT+CMGF=1",1000,DEBUG);
}

void loop()
{
  // Attemp to set the APN -- didn't fix the problem
    sendData("AT+CSTT=TM,23450",1000,DEBUG);
    
  sendData("AT+CPIN?",1000,DEBUG);
  sendData("AT+CNUM",1000,DEBUG);
  sendData("AT+CMGF?",1000,DEBUG);
  sendData("AT+CREG?",1000,DEBUG);
  sendData("AT+CMGS=\"+12563129195\"",1000,DEBUG);
  sendData("hello from Arduino",1000,DEBUG);
  sendData("0x1A",1000,DEBUG);
  delay(10000);
}
void baudrate()
{
      int i=0;
      for(i=0;i<10;i++)
      {
           String msg = String("");
           msg=sendData("AT",2000,DEBUG);
           if( msg.indexOf("OK") >= 0 ){
              return;
           }
      }
}

String sendData(String command, const int timeout, boolean debug)
{
    String response = "";    
    if(command=="0x1A")
    {
      // From example code, this didn't fix the problem
          //CellularSerial.write(0x1A);
          //CellularSerial.write(0x0D);  // hex equivalent of Carraige return    
          //CellularSerial.write(0x0A);  // hex equivalent of newline
      CellularSerial.println(0x1a); 
    } 
    else CellularSerial.println(command);
    long int time = millis();   
    while( (time+timeout) > millis())
    {
      while(CellularSerial.available())
      {       
        char c = CellularSerial.read(); 
        response+=c;
      }  
    }    
    if(debug)
    {
      Serial.print(response);
    }    
    return response;
}

Anyone?

This is the serial monitor session can someone tell me why it's not sending the message out?

After 3s, test begin!!
AT+CMGF=1

OK
AT+CSTT="TM","","

OK
AT+CSTT?

+CSTT: "TM",  "", ""

OK

+CTZV:18/10/03,22:33:52,+01
AT+CPIN?

+CPIN:READY

OK

+CIEV: service,  1
+CIEV: roam, 1

+CREG: 5
AT+CNUM

+CNUM: "","+882360004xxxxxx",145

OK
AT+CMGF?

+CMGF: 1

OK
AT+CREG?

+CREG: 1,5

OK
AT+CMGS="+1xxxxxxxxxx"

> Sent from Arduino GSM
26

And this is an incoming message sent from my cellphone so the board can receive, just not send?

+CIEV: "MESSAGE",1

+CMT: "+1xxxxxxxxxx",,"2018/10/03,17:55AT+CSTT="TM","","

I’ve had a look at (or at least tried to understand :wink: ) the AT command manual for your device.

It appears that you need to store the message into memory before using AT+CMGS to send it out

An example in that manual uses the following format

COMMAND:
AT+CSMP=17,167,0,4
(8bit encode of message to store or send in text
mode)
AT+CMGS=”13560243602”,129

So try

sendData("AT+CSMP=17,167,0,4",1000,DEBUG);
sendData("hello from Arduino",1000,DEBUG);
sendData("AT+CMGS=\"+12563129195\",129",1000,DEBUG);

NOTE: I do not have this hardware to use, so this is conjecture only.
Good luck :slight_smile:

<> Changed “.129” to “,129” typo on my part :o

darrob,

Thank you for your reply!

I am trying your suggestion, I didn't see that in the manual.

I've been a programmer a long time but this is the first time I've had to deal with this kind of communication (AT+), and really have trouble reading the manual)

Here is the first result (applicable part only):

OK
AT+CSMP=17,167,0,4

OK
hello from Arduino

+CME ERROR:58
AT+CMGS="+123456789xx",129

> 26

Something wrong with the memory storage statement (ERROR:58), I'll try to figure it out and post my progress

Thanks again, your help is sincerely appreciated! Don

I’m just documenting where I’m at
I’ve cleaned up the code a bit, but nothing so far that would fix it :

#include <SoftwareSerial.h>
SoftwareSerial CellularSerial(7, 8);

#include<stdio.h>
#include<string.h>
#define DEBUG true

void setup()
{
  Serial.begin(9200);
  CellularSerial.begin(9200);
  delay(10000);
  int pon=3;
  int poff=9;
  int lowp=2;
  pinMode(pon, OUTPUT);
  pinMode(poff, OUTPUT);
  pinMode(lowp, OUTPUT);
  digitalWrite(poff, LOW);
  digitalWrite(lowp, HIGH);   
  digitalWrite(pon, HIGH);
  delay(3000); 
  digitalWrite(pon, LOW);
  sendData("AT ",1000,DEBUG);
  baudrate();
  delay(3000);
  sendData("AT+CMGF=1",1000,DEBUG);
  Serial.println("After 3s, test begin!!");
  Serial.println("Wait 5 seconds");
  delay(5000);
  sendSMS();
}

void loop()
{
    sendData("AT+CIEV?",1000,DEBUG);
  delay(5000);
}

void sendSMS()
{
  /*
   * Attemp to set the APN
   * AT+ CSTT=<apn>, <user id>, <password>
   */
  sendData("AT+CSTT=\"TM\",\"\",\"",1000,DEBUG);
  sendData("AT+CSTT?",1000,DEBUG);
    
  sendData("AT+CPIN?",1000,DEBUG);
  sendData("AT+CNUM",1000,DEBUG);
  sendData("AT+CMGF?",1000,DEBUG);
  sendData("AT+CREG?",1000,DEBUG);
  sendData("AT+CSMP=17,167,0,4",1000,DEBUG);//  last parameter ONLY ALLOWES 0=7bit, 4=8bit, 8=16bit
  sendData("D. CASTEEL sent this message from Arduino",1000,DEBUG);

  /*
   * See AT+CSMP above last parameter (mode) must match second parameter (mode) below
   * AT+CMGS=”13560243602” (7bit encode of message to store or send in text mode)
   * AT+CMGS=”13560243602”,129 (8bit encode of message to store or send in text mode)
   * AT+CMGS=”+13560243602”,145 (16bit encode of message to store or send in text mode)
   */
  sendData("AT+CMGS=\"+12563129195\",129",1000,DEBUG);

  /*
   * Since the method only accepts string input
   * the "0x1A" is just a flag string that the sendData method
   * recognizes and then writes the proper byte code
   */
  sendData("0x1A",1000,DEBUG);
  
  Serial.println("Wait 5 seconds");
  delay(5000);

}
void baudrate()
{
      int i=0;
      for(i=0;i<10;i++)
      {
           String msg = String("");
           msg=sendData("AT",2000,DEBUG);
           if( msg.indexOf("OK") >= 0 ){
              return;
           }
      }
}

String sendData(String command, const int timeout, boolean debug)
{
    String response = "";    
    if(command=="0x1A")
      {
        CellularSerial.println(0x1A); 
        CellularSerial.println(0x0D); 
        CellularSerial.println(0x0A); 
      } 
    else 
      {
        CellularSerial.println(command);
      }
    long int time = millis();   
    while( (time+timeout) > millis())
    {
      while(CellularSerial.available())
      {       
        char c = CellularSerial.read(); 
        response+=c;
      }  
    }    
    if(debug)
    {
      Serial.print(response);
    }    
    return response;
}

It looks like I may need to change the AT+CMGS= command to AT+CMSS to send from memory?

I will try it out later today:

  //sendData("AT+CMGS=\"+11234567890\",129",1000,DEBUG);

  sendData("AT+CMSS=1,\"+11234567890\",129",1000,DEBUG);

I’ve been doing a bit more reading on the, and found this document with examples from the AT command set.
Unfortunately, it’s in Chinese.
However, this was part way down.

发送短信

AT+CMGF=1 //文本方式发送
AT+CMGS=“xxxxxxxxxxx(电话号码)” //返回>,然后输入要发送的txt内容,发送数据,之后请取消”发送新行”选项,勾选"HEX(16进制发送)"选项,最后发送0x1a即可。

Translated, it comes out to this

send messages

AT+CMGF=1 //Text mode sending
AT+CMGS=“xxxxxxxxxxx(telephone number)” //Go back to >, then enter the txt content to be sent, send the data, then cancel the “send new line” option, check the “HEX (hexadecimal send)” option, and finally send 0x1a.

I think what it is essentially saying there is

send AT+CMFG=1

This will put the unit into text mode (not SMS, but processing text rather than binary data)

send AT+CMGS=“xxxxxxxxxxx”

The unit will respond with a > prompt. once that is received/detected then…
Send the actual text message (without CR/LF)
Send \0x1A.
effectively
*_ <em>*sendData("AT+CMGS=\"+12563129195\",129",1000,DEBUG); sendData("hello from Arduino\0x1A");*</em> _*
I’m not sure if you will have to explicitly wait for the > response between those two lines.
If the two together like that don’t work, try putting in some code to look for it.
Now, as to why your original code didn’t work (I think):
*_ <em>* sendData("AT+CMGS=\"+12563129195\"",1000,DEBUG); sendData("hello from Arduino",1000,DEBUG); sendData("0x1A",1000,DEBUG);*</em> _*
The docs say the there should not be a CR between the message and the
your sendData() uses CellularSerial.println() for all commands. This explicitly sends a CR at the end of each string sent out.
Again, this is all speculation on my part. Unfortunately I cannot verify anything that I’ve written down.
Anyhoo, hope it helps :slight_smile:

darrob,

Thanks for your continued help and encouragement!

I will try all of the above tonight when I get home and post the results.

Best Regards Don

Don’t forget to WAIT for the > prompt after sending the CMGS sentence.

Will this work, add the ctrl-z as a char to the end of the string?

 sendData("AT+CMGS=\"+12563129195\"",1000,DEBUG);
 sendData("hello from Arduino"+(char)26,1000,DEBUG);

Just. noticed... You need to complete the +CMGS sentence with a carriage return. And you seem to be ok - the 0x1A is already there (CTRL-Z) at the end of the message. BTW, nowadays you shouldn’t have to set the APN for text messaging.

ThresholdEngineering: Will this work, add the ctrl-z as a char to the end of the string?

 sendData("AT+CMGS=\"+12563129195\"",1000,DEBUG);
 sendData("hello from Arduino"+(char)26,1000,DEBUG);
sendData("hello from Arduino\0x1A",1000,DEBUG);

Thanks darrob,

Here's the current code, it's followed by the serial monitor output

  sendData("AT+CSTT=\"TM\",\"\",\"",1000,DEBUG);
  sendData("AT+CSTT?",1000,DEBUG);
    
  sendData("AT+CPIN?",1000,DEBUG);
  sendData("AT+CNUM",1000,DEBUG);
  sendData("AT+CMGF?",1000,DEBUG);
  sendData("AT+CREG?",1000,DEBUG);
  sendData("AT+CSMP=17,167,0,4",1000,DEBUG);

  sendData("AT+CMGS=\"+11234567890\"",1000,DEBUG);
  delay(2000);
  sendData("threshold sent this message from Arduino\x1A\x0D",1000,DEBUG);


  Serial.println("Wait 5 seconds");
  delay(5000);

Output:

Wait 5 seconds
AT+CSTT="TM","","

OK
AT+CSTT?

+CSTT: "TM",  "", ""

OK
AT+CPIN?

+CPIN:READY

OK
AT+CNUM

+CNUM: "","+882360004036935",145

OK
AT+CMGF?

+CMGF: 1

OK
AT+CREG?

+CREG: 1,5

OK
AT+CSMP=17,167,0,4

OK
AT+CMGS="+12563129195"

> threshold sent this message from Arduino

Wait 5 seconds

+CMS ERROR:500

Woo hoo. Progress.

you're adding a '\0x0D' to the last sendData() command. You shouldn't need to. sendData uses .println() to send stuff to your modem. .println() automatically adds a '\0x0D' for you.

I think you should change your code to

sendData("AT+CSTT=\"TM\",\"\",\"",1000,DEBUG);
sendData("AT+CSTT?",1000,DEBUG);
sendData("AT+CPIN?",1000,DEBUG);
sendData("AT+CNUM",1000,DEBUG);
sendData("AT+CMGF=1",1000,DEBUG);    
sendData("AT+CMGS=\"+11234567890\"",1000,DEBUG);
delay(1000);
sendData("threshold sent this message from Arduino\0x1A",1000,DEBUG);

Serial.println("Wait 5 seconds");
delay(5000);

I had a look to see what +CMS ERROR:500 means. Unfortunately it essentially says "DUH... Sometink went wrong. Dunno wot". There are three possibilities that I found.

  • No or weak network coverage - move modem somewhere with a better signal reception
  • Insufficient SIM card credit - charge SIM
  • International phone number required - send recipient's number to modem with country code

If you still get the same error after changing the code, try the last option (use a full telephone number)

Still struggling…

Below is the code, everything looks OK based on all of the suggestions above (I think?)

I’ve also removed the delays and added code to wait for responses specific to each command.

The only thing I could think of is the way I’m formatting the phone number, so in the loop section, I’m trying every combination I can think of.

It compiles and runs well and there are no errors except with invalid phonenumber strings (length)

I would paste the entire serial monitor results, but every time I try I only a few lines, I’m pasting what few lines I can below the code section

#include <SoftwareSerial.h>
SoftwareSerial CellularSerial(7, 8);

#include<stdio.h>
#include<string.h>
#define DEBUG true

String phonenumber = "5551231234";
void setup()
{
  Serial.begin(9200);
  CellularSerial.begin(9200);
  delay(10000);
  int pon=3;
  int poff=9;
  int lowp=2;
  pinMode(pon, OUTPUT);
  pinMode(poff, OUTPUT);
  pinMode(lowp, OUTPUT);
  digitalWrite(poff, LOW);
  digitalWrite(lowp, HIGH);   
  digitalWrite(pon, HIGH);
  delay(3000); 
  digitalWrite(pon, LOW);
  sendData("AT ",1000,DEBUG, "OK");
  baudrate();
  delay(3000);
  //sendData("AT+IPR=9600",5000,DEBUG,"OK");
  //sendData("AT+CMGF=1",20000,DEBUG, "+CIEV: service,  1");
  sendData("AT+CMGF=1",60000,DEBUG, "+CIEV: roam, 1");
  Serial.println("Test begin!!");
  flush();
  sendSMS("5551231234");
  flush();
  sendSMS("\"5551231234\""); 
  flush();
  sendSMS("15551231234"); 
  flush();
  sendSMS("\"15551231234\""); 
  flush();
  sendSMS("+5551231234"); 
  flush();
  sendSMS("\"+5551231234\""); 
  flush();
  sendSMS("+15551231234"); 
  flush();
  sendSMS("\"+15551231234\""); 
  flush();
  sendSMS("0115551231234"); 
  flush();
  sendSMS("\"0115551231234\""); 
  flush();
  sendSMS("+0115551231234"); 
  flush();
  sendSMS("\"+0115551231234\""); 
  flush();
  flush();
  flush();
  flush();

  Serial.println("All attempts completed: " + phonenumber);
}

void flush()
{
  String bufferString = "";
  
  Serial.println("Start Flush");
  while (Serial.available() > 0)
   {
     char k = Serial.read();
     bufferString += k;
     delay(1);
   }
  Serial.print(bufferString);
  Serial.println("EndFlush wait 15 seconds");
  delay(15000);
}

void loop()
{
}

void sendSMS(String phonenumber)
{
  Serial.println("Attempting phone number format: " + phonenumber);
  /*
   * Attemp to set the APN
   * AT+ CSTT=<apn>, <user id>, <password>
   */
  sendData("AT+CSTT=\"TM\",\"\",\"",1000,DEBUG, "OK");
  sendData("AT+CSTT?",1000,DEBUG, "+CSTT:");
    
  sendData("AT+CPIN?",1000,DEBUG, "+CPIN:READY");
  sendData("AT+CNUM",1000,DEBUG, "+CNUM:");
  sendData("AT+CMGF?",1000,DEBUG, "+CMGF:");
  sendData("AT+CREG?",1000,DEBUG, "+CREG:");
  //sendData("AT+CSMP=17,167,0,4",1000,DEBUG);//  last parameter ONLY ALLOWES 0=7bit, 4=8bit, 8=16bit

  /*
   * See AT+CSMP above last parameter (mode) must match second parameter (mode) below
   * AT+CMGS="13560243602" (7bit encode of message to store or send in text mode)
   * AT+CMGS="13560243602",129 (8bit encode of message to store or send in text mode)
   * AT+CMGS="+13560243602",145 (16bit encode of message to store or send in text mode)
   */
  sendData("AT+CMGS=" + phonenumber,1000,DEBUG, ">");
  delay(2000);
  sendData(phonenumber + ":  thresholdengineering sent this message from Arduino\x1A",1000,DEBUG, "+CMGS:");

  /*
   * Since the method only accepts string input
   * the "0x1A" is just a flag string that the sendData method
   * recognizes and then writes the proper byte code
   */
  //sendData("0x1A",1000,DEBUG);
}

void baudrate()
{
      int i=0;
      for(i=0;i<10;i++)
      {
           String msg = String("");
           msg=sendData("AT",2000,DEBUG, "OK");
           if( msg.indexOf("OK") >= 0 ){
              return;
           }
      }
}

String sendData(String command, const int timeout, boolean debug, String expected)
{
    String response = "";    
    if(command=="0x1A")
      {
        CellularSerial.println(0x1A); 
        CellularSerial.println(0x0D); 
        CellularSerial.println(0x0A); 
      } 
    else 
      {
        CellularSerial.println(command);
      }
    long int time = millis();   
    //s1.find(s2) != std::string::npos  //msg.indexOf("ok") >= 0
    while( (time+timeout) > millis() && !(response.indexOf(expected) >= 0))
    {
      while(CellularSerial.available())
      {       
        char c = CellularSerial.read(); 
        response+=c;
      }  
    }    
    if(debug)
    {
      Serial.print(response);
    }    
    return response;
}
t⸮⸮t⸮⸮f*⸮
FNf*E+⸮f*E⸮F⸮AT

OK
Test begin!!
Start Flush
EndFlush wait 15 seconds
Attempting phone number format: 2563129195
AT+CMGF=1

OK

+CTZV:18/10/05,19:41:55,+01

+CIEV: servicAT+CSTT="TM","","
AT+CSTT?

OK
AT+CPIN?

+CPIN:READY

OK
AT+CNUM

+CNUM: "","+882360004036935",145

Here's a full phone number test section

Attempting phone number format: "+0115551234567"

+CMS ERROR:500
AT+CSTT="TM","","

OK
AT+CSTT?

+CSTT: "TM",  "", ""

OK
AT+CPIN?

+CPIN:READY

OK
AT+CNUM

+CNUM: "","+882360004036935",145
OK
AT+CMGF?

+CMGF: 1

OK
AT+CREG?

+CREG: 1,5

OK
AT+CMGS="+0115551234567"

> "+0115551234567":  Threshold Engineering sent this message from Arduino
Start Flush
EndFlush wait 15 seconds
Start Flush
EndFlush wait 15 seconds
Start Flush
EndFlush wait 15 seconds
Start Flush
EndFlush wait 15 seconds
All attempts completed: 5551234567

I'm curious the "+CREG: 1,5" means I'm connected to the network and roaming, is this correct?

Could I need to set the frequency band of my board?

I'm also curious if the baudrate could be keeping me from transmitting, everything shows up correctly in the serial monitor but does that mean everything is working?

Does anyone know if there is a danger in using the AT&F reset command for the GSM board?