I sell on Tindie
Grand Prize Winner
(Dec 2012)
Second Prize Winner
(July 2012)

GPS/GSM Module. Software support

Module software support includes GSM module library and an example of its typical usage for ATMega microprocessor family written in C/C++. The logic of interaction with SIM900D modem is enclosed in SIM900Modem.c, SIM900Modem.h files and relies on enhanced version of HardwareSerial class originally designed for Arduino project. As SIM900Modem.c does not depend on AVR specific features it may be quite easy adopted for different microprocessor types. The library has the following low level functionality to control the modem:

  • switch it on and off,
  • send AT commands and analyse responses,
  • extract certain parts from modem’s replies and convert them into other representations and formats.

On top of this logic more meaningful commands are implemented such as:

  • getting manufacturer ID,
  • getting IMEI,
  • getting model ID,
  • texting,
  • waiting for GSM network registration,
  • getting network operation,
  • opening/closing GPRS content,
  • etc.

Also there are two sets of methods, for sending data via HTTP and TCP protocols.

The first set utilises HTTP related AT commands, it hides a lot of things from end user and therefore much simpler for use. However, it does not allow to define arbitrary HTTP header and as a consequence, there is no way to send MIME-encoded POST requests and therefore no way for sending binary data such as pictures. In addition, the the commands do not provide functionality to set HTTP parameters separately and it is entirely user application responsibility to do URL-encoding. There is also no way to get response HTTP header fields, they are hidden by the modem. Yet this is fairly simple way to make HTTP requests by means of dedicated HTTP AT commands, the commands provide the following functionality:

  • initialising HTTP request,
  • setting target URL request,
  • setting user data parameters and values,
  • choosing action (either GET or POST),
  • reading data,
  • terminating connection.

The second group of methods facilitates sending/receiving data over TCP/UDP protocols and HTTP request might be generated on top of TCP. This way is more complex, it requires more efforts on user application side and utilises more RAM for intermediate buffer. At the same time it gives you all flexibility you need without limitations in number of parameters and binary data length as requests are sent by chunks. The following functionality is provided:

  • starting IP connection,
  • getting assigned local IP address,
  • getting GPRS PDP status,
  • sending data,
  • getting HTTP response,
  • parsing HTTP server current timestamp (for RTC synch),
  • closing IP connection.

Let’s take a closer look at the list of commands starting from low-level layer:

  • uint8_t SIM900Modem::init() initialises modem and powers it up it it has not been switched on yet via PWRK line. If this method returns false then there is something wrong with either modem itself or its connection to your microcontroller. Check SIM900D voltage, normally it should have 3.7V on 38-39 pins; then check serial connection to your host board and finally make sure that host board can control PWRK and has serial port properly initialised,
  • uint8_t SIM900Modem::powerOff() switches the modem off by sending appropriate AT command. In case if the modem stopped responding (very rare situation but still possible) use the next command,
  • void SIM900Modem::forcedPowerOff()switches the modem off by controlling PWRK line, works even if the modem is unresponsive to AT commands,
  • uint8_t SIM900Modem::sendATCmdWaitResp(const char* cmd) sends AT command and waits for either OK or ERROR reply. If nothing has been received within MDM_TIMEOUT x 100 ms timeframe returns false. If OK has been received returns true. cmd param should not have AT prefix as it is appended automatically inside the method,
  • uint8_t SIM900Modem::sendATCmdWaitResp_p(const prog_char cmd[]) does the same as the method above but reads cmd from program memory,
  • uint8_t SIM900Modem::sendATCmdWaitResp(const char* cmd, const prog_char expectedResp[], uint8_t delayCntr) allows to wait for modem reply different from OK or ERROR. It also waits longer, for delayCntr x 100 ms in addition to standard MDM_TIMEOUT x 100 ms,
  • uint8_t SIM900Modem::sendATCmdWaitResp_p(const prog_char cmd[], const prog_char expectedResp[], uint8_t delayCntr) does the same as the method above but reads cmd from program memory,
  • uint8_t findSubstr(const ring_buffer* buf, uint16_t len, const prog_char expectedResp[], uint16_t* posFound) searches a specified string in receiving buffer without actual reading it, the number of bytes in buffer is defined by len value. If the method returns true then posFound contains an index of a first byte of the searched string. Note that this method does not allocate memory for posFound, it should be done by user code,
  • uint8_t SIM900Modem::extractReply(char* outBuf, uint16_t len, uint8_t line) extracts a line of characters from modem receiving buffer into provided buffer outBuf with maximum number of characters to be copied defined in len. The desired line number is line. The method returns number of characters copied and outBuf filled with copied characters in case of success.

A list of auxiliary methods is given below:

  • uint8_t SIM900Modem::getManufacturerID(char* buf, uint16_t len) gets modem’s manufacturer ID,
  • uint8_t SIM900Modem::getModelID(char* buf, uint16_t len) gets modem’s model ID,
  • uint8_t SIM900Modem::getTARevision(char* buf, uint16_t len) gets modem’s revision,
  • uint8_t SIM900Modem::getIMEI(char* buf, uint16_t len) gets modem’s IMEI number,
  • uint8_t SIM900Modem::getNetworkRegistration() returns true if modem has successfully registered in GSM network and false otherwise,
  • uint8_t SIM900Modem::waitForNetworkRegistration() waits until modem is registered in GSM network but no more than MDM_TIMEOUT x 3000 ms,
  • uint8_t SIM900Modem::getNetworkOperator(char* buf, uint16_t len) gets GSM operator name.

Methods for SMS functionality:

  • uint8_t SIM900Modem::setTxtSMSMsgFormat() hardcoded for setting txt message format, should be invoked every time modem is restarted before sending/reading SMS,
  • uint8_t SIM900Modem::setGSMCharSet() hardcoded for setting GSM charset, should be invoked every time modem is restarted before sending/reading SMS,
  • uint8_t SIM900Modem::sendSMS(char* destAddr, char* msg) sends a text message msg to a phone addressed by number destAddr, returns true in case of success.

A list of methods for making HTTP connections by means of embedded HTTP AT commands:

  • uint8_t SIM900Modem::openGPRSContext(char* buf) opens GPRS context, buf parameter contains APN string. APN is different for different mobile providers, for instance, APN value for Australian Vodafone is vfinternet.au. Returns true if GPRS context has been opened false otherwise,
  • uint8_t SIM900Modem::closeGPRSContext() closes opened GPRS context, returns true in case of success,
  • uint8_t SIM900Modem::httpInit() initisalises HTTP request,
  • uint8_t SIM900Modem::httpSetURL(char* buf) sets URL to connect to a remote HTTP resource,
  • uint8_t SIM900Modem::httpSetData(char* buf, uint16_t len, uint16_t timeout) sets HTTP user data, buf parameter contains a string of URL-encoded parameter-value pairs with len characters in the biuffer,
  • uint8_t SIM900Modem::httpAction(uint8_t isPostMethod, uint16_t* responseLen) does actual sending of HTTP request and reading of HTTP reply. isPostMethod set to true creates POST HTTP request and GET otherwise,
  • uint8_t SIM900Modem::httpRead(char* buf, uint16_t startIdx, uint16_t len) reads HTTP reply, this method is not implemented in Rev1.1 GPS/GSM AVR Library
  • uint8_t SIM900Modem::httpTerm() closes HTTP connection, should be invoked at the end of each HTTP request.

A list of methods for making HTTP connections over TCP AT commands (which is primarily used by the example):

  • uint8_t SIM900Modem::startSingleIPConnMode() issues AT+CIPMUX=0 command to handle only one TCP connection at a time, should be invoked before even opening GPRS connection,
  • uint8_t SIM900Modem::setGPRSPDPAPN(char* apn, char* username, char* pwd) sets APN value, username and password. If username and password are not required by your mobile operator these two parameters might be set to NULL,
  • uint8_t SIM900Modem::actGPRSPDPContext() opens GPRS context and returns true in case of success or false otherwise,
  • uint8_t SIM900Modem::deactGPRSPDPContext() closes opened GPRS context, returns true in case of success,
  • uint8_t SIM900Modem::getLocalIP(char* buf, uint16_t len) retrieves local IP address after successfully opened GPRS context and puts it into buf buffer with maximum length no longer than len,
  • uint8_t SIM900Modem::sendIPConn(char* buf, uint16_t len, uint16_t delayCntr) sends len bytes from buf to remote side and waits delayCntr x 100 ms in addition to standard MDM_TIMEOUT x 100 ms,
  • uint8_t SIM900Modem::sendAndCheckHTTPRespIPConn(char* buf, uint16_t len, uint16_t bufsize, uint16_t delayCntr, RtcTimeType* rtc) sends len bytes from buf to remote side, retrieves remote side response, puts it into buf with maximum length bufsize, searches for HTTP/1.1 200 OK or HTTP/1.0 200 OK in reply content and if found parses server current datatime in UTC format into provided RtcTimeType variable. This method should be used for sending the very last block of data of your HTTP request,
  • uint8_t SIM900Modem::closeIPConn() is currently not used as sometimes modem becomes unresponsive after it. Use uint8_t SIM900Modem::deactGPRSPDPContext() method, it automatically closes opened IP connection if it has not been closed already by remote side.

To be continued…


1. Magictale GPS/GSM Module AVR Lib Rev1.1