Blog

Send sms from an A9G pudding dev board

Yet another article on sending sms!! This time with a A9G pudding dev board. I hope this will be the second in a series of articles on this module. My project is to make a GPS tracking system that can save the coordinates to an SD card and send them by SMS when requested.

This article starts where the previous one left off (
https://www.twiggotronix.com/en/a9g-pudding-grps-gps-and-microcontroller-all-in-one/) which explains how get set up and upload your first program.

I created a git repo with all the code for this article :
https://github.com/twiggotronix/a9g-pudding-sms

I admit having shamelessly copied the sms example and adapted it to my needs! This code will send an sms on startup to tell us that the module is ready, and then relay all messages recieved to a configured phone number.

Configuration

The only configuration needed is the phone number to send messages to. We simply need to copy and rename include/app_main_example.h to
include/app_main.h and edit the phone number (I haven’t tried other formats but it works well for me with the “+336xxxxx” format with the country code, 33 being France).

You should be able to compile and upload the code and get a message containing “Ready and able!”

.\build.bat app

Events

We can know what state the module is currently in by observing events. This way we can know when the module is registered on the network and ready to comunicate or when an error occures. For each event, the
EventDispatch function is called with an object that contains more information. For example, when the event’s id corresponds to the
API_EVENT_ID_NETWORK_REGISTER_SEARCHING constant, we know that the board is searching for a network. You can find the list of available event constants in /include/api_inc/api_event.h

void EventDispatch(API_Event_t* pEvent)
{
    
    switch(pEvent->id)
    {
        case API_EVENT_ID_NO_SIMCARD:
            Trace(10,"!!NO SIM CARD%d!!!!",pEvent->param1);
            break;
       ....
    }
}

Note: Just when I thought I had something stable and working, the module stoped comunicating… By adding a case uin the switch, I was able to determine that I was getting an error while registering on the network (
API_EVENT_ID_NETWORK_REGISTER_DENIED ). I’m not 100% sure why but I think it was to do with the antena thatgot disconnected, it started working again later, probably because I fiddled about with it in frustration!

Sending messages

I made the SendSMS function (I actually just extracted what I needed from the sms demo and adapted it) that takes a uint8_t message[] parameter and sends the content.

void SendSMS(uint8_t message[])
{
    uint8_t* unicode = NULL;
    uint32_t unicodeLen;
 
    Trace(1,"sms start send UTF-8 message");
 
    if(!SMS_LocalLanguage2Unicode(message,strlen(message),CHARSET_UTF_8,&unicode,&unicodeLen))
    {
        Trace(1,"local to unicode fail!");
        return;
    }
    if(!SMS_SendMessage(PHONE_NUMBER,unicode,unicodeLen,SIM0))
    {
        Trace(1,"sms send message fail");
    }
    OS_Free(unicode);
}

SendSMS("Ready and able!");

Receiving messages

When we receive a message, the API_EVENT_ID_SMS_RECEIVED event is fired, we can get the contents of the message in the pParam2
(pEvent->pParam2). In my code, the function messageRecieved extracts the content of the message and relays it to my phone by sms. You could get the phone number of the person that sent the message in the pParam1 attribute that contains the message headers, but I didn’t need to. I would love to know how you go about it though!

void messageRecieved(uint8_t* content)
{
    char buffer[200];
    snprintf(buffer, sizeof(buffer), "Message received : %s", content);
    Trace(1, buffer);
    SendSMS(buffer);
}

void EventDispatch(API_Event_t* pEvent)
{
    switch(pEvent->id)
    {
        case API_EVENT_ID_SMS_RECEIVED:
            Trace(2,"received message");
            uint8_t* content = pEvent->pParam2;

            Trace(2,"message header:%s",header);
            Trace(2,"message content length:%d",contentLength);
            messageRecieved(content);            
            break;
    }
}

A9G pudding – GRPS, GPS and microcontroller all in one!

Not only does it have a cool name, this little dev board has a ton of functions :

GPS, SMS, Calls, Internet, Flash card reader, loads of I/Os, and much more…

The module responds to AT commands just like the A6 and A7 chips but I focused on using the build-in micro controller in C!!! No need for a seperate arduino, lowering cost, size and power requirements.

Getting set up and running under windows takes a bit of work but once it’s done, it works great!

Wiring:

setup your FTDI programmer module like this:

FTDIA9G
RX HST_TX
TX HST_RX
GNDGND
VCCDon’t connect

The board will be powered by an external phone charger pluged into the micro usb port.

Toolchain

The toolchain contains all the tools you’ll need to compile and run your code on the chip. You can download it here :
 http://test.ai-thinker.com/csdk/CSDTK42.7z (the documentation is here : https://ai-thinker-open.github.io/GPRS_C_SDK_DOC/en/c-sdk/installation.html)

Open PowerShell in admin mode and go to the CSDTK directory (or CSDTK42 in my case), and execute the config_env_admin.bat script. It will add all the environment variables you’ll need:

./config_env_admin.bat 

SDK:

Download the SDK :https://github.com/Ai-Thinker-Open/GPRS_C_SDK/releases/tag/V2.112 (the file GPRS_C_SDK_V2112.7z)

Open PowerShell again in admin mode and cd to the
GPRS_C_SDK directory. You will find a demo directory containg loads of examples!

To test our setup, we’re going to compile the “first” example :

./build.bat demo first

If all goes well, you should see the compiled version in the hex/first directory.

Getting our code on to the chip :

In the CSDTK42\cooltools directory, the coolwatcher.exe tool will allow us to send code to our dev board. When coolwatcher starts up, select profil 8955 and specify the lastcomport field (my FTDI is on port COM4) :

The first thing to do is select the programmer in the
« Flash > Choose Flash Programmer… » menu and choose the
CSDTK42\cooltools\chipgen\Modem2G\toolpool\plugins\fastpf\flash_programmershost_8955_flsh_spi32m_ramrun.lod file

Then we need to choose the compiled project in
« Flash > Choose LOD file… » and select the largest if the files we generated earlier : GPRS_C_SDK\hex\trackerfirst_B2112_debug.lod

To start uploading the code to the module, go to
« Flash > Launch fastpf with current LOD file and flash programmer ».

If all goes well you should have something like this :

This step didn’t work on the first go for me, check the connections and especially that the GND pins are connected. If that doesn’t work, click on the
« Restart Chip » button in coolwatcher and try again…

Once the upload has completed, go to the « Plugins > Activate Tracer » menu to see the debug info. You should see the « Hello GRPS » trace :

Voilà! We have programmed our module! now all we need to do is dig deeper into the examples to start having fun! 🙂

Simple A6Smslib Librairy for sending sms with an A6 module

To simplify the code from my previous post “Send SMS with an ESP8266 and an A6 GSM module“, I created a small library to send SMS and get feedback on the state.

You can find it on github : https://github.com/davidtw/a6SmsLib

An example of code :

#include "A6SmsLib.h"

const String NUMBER = "00336XXXXXXXX";
const String MESSAGE = "whoop whoop!";

const int rx = D1;
const int tx = D2;
const int resetPin = D0;

A6SmsLib a6Sms(rx, tx, resetPin);

void statusUpdate(String state, String message)
{
  Serial.println("[statusUpdate] " + state + " : " + message);
}

void smsUpdate(String state, String message)
{
    Serial.println("[smsUpdate] " + state + " : " + message);
}

void setup()
{
    Serial.begin(9600);
    a6Sms.debug();
    a6Sms.begin();
    a6Sms.setStatusCallback(statusUpdate);
    a6Sms.setSmsCallback(smsUpdate);
    a6Sms.waitUntilReady();

    a6Sms.sms(NUMBER, MESSAGE);
}

void loop()
{
    a6Sms.loop();
}

Setup

In this example, i configured the pins according to my protoboard circuit (D1 pour RX, D2 pour TX et D0 pour le redémarrer le module)

const int rx = D1;
const int tx = D2;
const int resetPin = D0;

A6SmsLib a6Sms(rx, tx, resetPin);

Activate Debug mode

Call the debug method to allow debug messages to the serial output :

a6Sms.debug();

Callbacks

  • setStatusCallback specifies the function to be called when the module’s state updates
  • setSmsCallback specifies the function to be called when an sms has been sent, or attempted.

The loop

the loop function allows the library to update it’s internal states, it should be called on each loop.

Sending

Sending an sms is done with the sms function, you just need to give a number and a message to be sent.

Le tout assemblé et branché

Send SMS with an ESP8266 and an A6 GSM module

This article takes off from where I left off in the previous one (https://www.twiggotronix.com/en/send-sms-with-an-a6-gsm-module/), I recommend you read that one first.

In the previous article, we managed to send SMSs with an FTDI programmer board. This time we’re going to replace it with a microcontroller (ESP8266 in this case but it should work with just about any arduino).

What you’ll need:

More or less the same as for the previous article, plus a microcontroller. I used a WEMOS D1 mini :

Wemos D1 mini
Wemos D1 mini

I buy them straight from WEMOS Electronics, Delivery tends to be a bit long, but they’re cheap and really reliable.

Wiring

I made a bit of an effort this time 😉 and did the diagram out in fritzing :

Wiring diagram
Wiring diagram

I added a wire between D0 on the D1 and the RST pin on the A6 that will allow us to restart the module when we’re ready. Then I just added power and hooked up D1 and D2 respectiverly to UTX and URX on the GSM module.

At this point, I thought it would be a good idea to make things a bit more permanent and broke out a perfboard. This will make sure I don’t get errors due to wiring… You can however just leave everything on the breadboard.

Perfboard from above
Perfboard from above

Perfboard from bellow
Perfboard from bellow (sorry if my soldering job makes you nauseous…)

The assembled kit
The assembled kit

To the code!

Initialisation

Communication between our GSM module and our microcontroller is done using the standard softwareSerial librairy:

#include <SoftwareSerial.h>

#define RX_PIN D1 // Green wire
#define TX_PIN D2 // Orange wire
#define RESET_PIN D0 // Yellow wire

SoftwareSerial a6Serial(RX_PIN, TX_PIN);

void setup() {
    Serial.begin(9600);
    a6Serial.begin(115200); //The A6's defaul baudrate is 115200
    delay(500);
}
void loop() {}

Then we can restart our A6 module. This step is probably not necessary but allows us to keep track of the GSM module’s state.

void resetModule() {
    digitalWrite(RESET_PIN, HIGH);
    delay(200);
    digitalWrite(RESET_PIN, LOW); 
}

void setup() {
    Serial.begin(9600);
    a6Serial.begin(115200); //The A6's defaul baudrate is 115200
    delay(500);

    pinMode(RESET_PIN, OUTPUT);
    resetModule(); //restart the GSM module
}

To finish setting everything up, we need to wait for the module to connect to the GSM network, and then set SMS mode :

void waitUntilReady()
{
  Serial.println("Waiting for network");
  while(state == "initing" || state == "sms_mode") {  
    if (a6Serial.available()) {
      String recievedA6 = a6Serial.readString();
      Serial.println(recievedA6);
      if(state == "initing" && recievedA6.indexOf("+CREG: 5") >= 0) {
        Serial.println("Mode sms");
        state = "sms_mode";
        delay(2000);
        a6Serial.println("AT+CMGF=1");  
      } else if(state == "sms_mode" && recievedA6.indexOf("OK") >= 0) {
        state = "ready";
        Serial.println("Ready!");
      }
    }
    yield(); // hands controll back to the ESP8266 to avoid wifi connexion loss
  }
}

Send an SMS

As seen in the previous article, sending an SMS is done using AT commands:

followed by the the message and Ctrl-Z:

void sendSms(String number, String message) {
  if(state == "ready") {
    Serial.println("Sending \"" + message + "\" to " + number);
    a6Serial.print("AT+CMGS=\"");
    a6Serial.print(number);
    a6Serial.write(0x22);
    a6Serial.write(0x0D);  // Return carriage in hexadecimal
    a6Serial.write(0x0A);  // New line in hexadecimal
    delay(2000);
    a6Serial.print(message);
    delay(500);
    a6Serial.println(char(26));// Control-Z in hexadecimal
  }
}

Just for the example, I send an SMS using a custom sendSMS command to the ESP8266 over  Serial :

void loop() {
  if(Serial.available()) {
    String received = Serial.readString();
    received.trim();
    if(state == "ready") {
      if(received == "sendSms") {
        sendSms(PHONE_NUMBER, MESSAGE);
      }
    }
  }
  if (a6Serial.available()) {
      String recievedA6 = a6Serial.readString();
      Serial.println("[A6] " + recievedA6);
  }
}

The result is :

Result of sending an SMS
Result of sending an SMS

The full code

#include <Arduino.h>
#include <SoftwareSerial.h>

#define RX_PIN D1 // Green wire
#define TX_PIN D2 // Orange wire
#define RESET_PIN D0 // Yellow wire

#define PHONE_NUMBER "+336XXXXXXXXX" // Replace with your country code (+33 is for France) and phone number
#define MESSAGE "Whoop whoop"

SoftwareSerial a6Serial(RX_PIN, TX_PIN);
String state = "initing";

void resetModule() {
    digitalWrite(RESET_PIN, HIGH);
    delay(200);
    digitalWrite(RESET_PIN, LOW); 
}

void waitUntilReady()
{
  Serial.println("Waiting for network");
  while(state == "initing" || state == "sms_mode") {  
    if (a6Serial.available()) {
      String recievedA6 = a6Serial.readString();
      Serial.println(recievedA6);
      if(state == "initing" && recievedA6.indexOf("+CREG: 5") >= 0) {
        Serial.println("Sms mode");
        state = "sms_mode";
        delay(2000);
        a6Serial.println("AT+CMGF=1");  
      } else if(state == "sms_mode" && recievedA6.indexOf("OK") >= 0) {
        state = "ready";
        Serial.println("Ready!");
      }
    }
    yield(); // hands controll back to the ESP8266 to avoid wifi connexion loss
  }
}

void sendSms(String number, String message) {
  if(state == "ready") {
    Serial.println("Sending \"" + message + "\" to " + number);
    a6Serial.print("AT+CMGS=\"");
    a6Serial.print(number);
    a6Serial.write(0x22);
    a6Serial.write(0x0D);  // Return carriage in hexadecimal
    a6Serial.write(0x0A);  // New line in hexadecimal
    delay(2000);
    a6Serial.print(message);
    delay(500);
    a6Serial.println(char(26));// Control-Z in hexadecimal
  }
}

void setup() {
    Serial.begin(9600);
    a6Serial.begin(115200); //The A6's defaul baudrate is 115200
    delay(500);

    pinMode(RESET_PIN, OUTPUT);
    resetModule(); //restart the GSM module
    waitUntilReady(); //Wait for the GSM network
}

void loop() {
  if(Serial.available()) {
    String received = Serial.readString();
    received.trim();
    if(state == "ready") {
      if(received == "sendSms") {
        sendSms(PHONE_NUMBER, MESSAGE);
      }
    }
  }
  if (a6Serial.available()) {
      String recievedA6 = a6Serial.readString();
      Serial.println("[A6] " + recievedA6);
  }
}

Conclusion

We now have a small module that allows us to send SMSs! Now all we need to do is to turn it into an even more connected thing!

Send SMS with an A6 GSM module

AI Thinker, the makers of my favorite micro controller, the ESP8266 have done it again with the A6 GSM module allowing us to connect to the GSM network and send sms, connect to the internet and even make phone calls!

What you’ll need:

  • A6 GSM moduleAn A6 module (This is an A6 mini bought you can find on ebay, aliexpress ect.. for 5 to 10€)
  • Sim card A Sim card with a valid subscription. Remember to remove the pin before starting by inserting it into a phone and deactivating the pin number.
  • Breadbord and jumper wires A breadboard and some jumper wires.
  • FDTI programer module An FTDI programer (2 to 5€ on Ebay ou aliexpress)
  • micro USB breakout board A micro usb breakout board get power to it all easily
  • Power supply A relatively powerful wall wart (here I recycled a 5V/2A power supply from a raspberry pi I had laying around ). Sending sms takes quite a lot of power for sending.
  • CoolTerm A computer with Windows and CoolTerm

Wiring

A6 wiring diagram
Wiring scematic of the A6 module with an FTDI

As you can see, I used my awesome artistic skills to come up with this horrible diagram!!

We need to power the module with our phone charger, join the FTDI and A6 module neutrals and then connect the TX of the of the RX pin, of the A6 and vice versa.

The finished setup
The finished setup

To the code!

Once you have pluged the FTDI in, CoolTerm should find the COM port on it’s own. You can also find it in windows device manager :

Peripherals

In CoolTerm, set the baudrate to 115200 and click on Connect. It takes a few seconds but it should come up with something like this (if not, try unpluging and pluging the A6 module power back in again) :

Connecting to the GSM network

+CREG: 5 means the module was able to conect to the network and is ready to go!

If nothing comes up, check all the connections again, especially that the RX/TX pins.

Snding an SMS

To send an SMS, go to Connection -> Send String ou Ctrl-T. The AT command (for attention) followed by a new line will return the current state :

send AT commandAT serial response

 The module should answer “ok”, however in some cases I got CME 58 errors. I think it means that it temporarily lost the signal, just sending AT again should work.

Next, we need to set the module to SMS mode :

AT+CMGF=1

followed with a new line:

Setting SMS mode

And finaly, to send the message :

AT+CMGS="003361234567"

(replacing the phone number with your’s) It will ask you to enter your message :

Sending SMS

Wait a few seconds and you should have youself a new message on your phone!

Traps

I had a few problems due the poor quality of my chinese jumper wires… I was also using a faulty usb extender cable.

Here is a document that helped me with certain errors and AT commands : GSM Developer Guide – GSM AT Commands – Rev A

Conclusion

Once all the wiring was in done and checked and the module answers, you only need 3 lines to send an sms! In the next article, I’ll try and send one from an arduino/ESP8266 instead of the computer.