In a recent Arduino embedded system I needed to manage an Arduino GSM Shield for some specific use cases. However, I couldn’t use the well-known GSM library due to memory capacity limitations since this library “eats” the Arduino board memory 🙂 I could use an Arduino board with more memory capacity but this was not the case for me. I wrote the library SimpleGSM, which is a simple GSM library for managing the Arduino GSM shield (maybe you can use the library with other GSM cards) and execute some basic operations. I wrote the library to have exactly the operations I wanted. The library uses internally a software serial for the communication.
So, below is the source code of the SimpleGSM library.
SimpleGsm.h
#ifndef _SimpleGsm_H
#define _SimpleGsm_H
#include "Arduino.h"
#include <SoftwareSerial.h>
class SimpleGsm : public SoftwareSerial
{
public:
SimpleGsm (const byte rxPin, const byte txPin, const byte powerPin);
bool begin (const long baudRate, const byte numberOfRetries);
bool disableEcho ();
bool setSmsTextMode ();
bool sendSms (const String phoneNumber, const String message);
bool missedCall (const String phoneNumber,
const unsigned long ringingDuration);
bool startCall (const String phoneNumber);
bool callIsDialing ();
bool callIsRinging ();
void waitOnCallDialing ();
void waitOnCallRinging (const unsigned long duration);
bool hangCall ();
private:
void restart ();
bool setEcho (const bool state);
bool setSmsMode (const byte mode);
void queryForCallStatus ();
bool responseIsReceived (char * const pattern, const long timeOut);
static char * const OK_RESPONSE_FORMAT;
byte _powerPin;
};
#endif /* _SimpleGsm_H */
SimpleGsm.cpp
#include "SimpleGsm.h"
char * const SimpleGsm::OK_RESPONSE_FORMAT = "\r\nOK\r\n";
SimpleGsm::SimpleGsm (const byte rxPin,
const byte txPin,
const byte powerPin) : SoftwareSerial (rxPin, txPin)
{
_powerPin = powerPin;
pinMode(_powerPin, OUTPUT);
}
void
SimpleGsm::restart ()
{
digitalWrite(_powerPin, HIGH);
delay(12000);
digitalWrite(_powerPin, LOW);
delay(1000);
}
bool
SimpleGsm::responseIsReceived (char * const pattern, const long timeOut)
{
this->setTimeout(timeOut);
return this->find(pattern);
}
bool
SimpleGsm::disableEcho ()
{
return this->setEcho (false);
}
bool
SimpleGsm::setSmsTextMode ()
{
return this->setSmsMode (1);
}
bool
SimpleGsm::setEcho (const bool state)
{
this->print(F("ATE"));
this->print(state);
this->print(F("\r"));
return this->responseIsReceived(OK_RESPONSE_FORMAT, 3000);
}
bool
SimpleGsm::setSmsMode (const byte mode)
{
this->print(F("AT+CMGF="));
this->print(mode);
this->print(F("\r"));
return this->responseIsReceived(OK_RESPONSE_FORMAT, 3000);
}
bool
SimpleGsm::begin (const long baudRate, const byte numberOfRetries)
{
SoftwareSerial::begin (baudRate);
for (byte i = 0; i < numberOfRetries; i++)
{
this->restart ();
delay(1000);
this->print(F("AT\r"));
if (this->responseIsReceived(OK_RESPONSE_FORMAT, 3000))
{
return true;
}
}
return false;
}
bool
SimpleGsm::sendSms (const String phoneNumber, const String message)
{
this->print(F("AT+CMGS=\""));
this->print(phoneNumber);
this->print(F("\"\r"));
if (!this->responseIsReceived("\r\n> ", 3000))
{
return false;
}
this->print(message);
this->write(0x1A);
return this->responseIsReceived(OK_RESPONSE_FORMAT, 10000);
}
bool
SimpleGsm::startCall (const String phoneNumber)
{
this->print(F("ATD"));
this->print(phoneNumber);
this->print(F(";\r"));
return this->responseIsReceived(OK_RESPONSE_FORMAT, 3000);
}
bool
SimpleGsm::callIsDialing()
{
this->queryForCallStatus();
return this->responseIsReceived("+CLCC: 1,0,2,0,0", 500);
}
bool
SimpleGsm::callIsRinging()
{
this->queryForCallStatus();
return this->responseIsReceived("+CLCC: 1,0,3,0,0", 500);
}
void
SimpleGsm::waitOnCallDialing()
{
while (this->callIsDialing()) ;
}
void
SimpleGsm::waitOnCallRinging(const unsigned long duration)
{
const unsigned long previousMillis = millis();
while ((unsigned long) (millis() - previousMillis) < duration)
{
if (!this->callIsRinging())
{
break;
}
}
}
bool
SimpleGsm::missedCall (const String phoneNumber,
const unsigned long ringingDuration)
{
if (this->startCall(phoneNumber))
{
this->waitOnCallDialing();
if (this->callIsRinging())
{
this->waitOnCallRinging(ringingDuration);
}
this->hangCall();
return true;
}
return false;
}
void
SimpleGsm::queryForCallStatus()
{
this->print(F("AT+CLCC\r"));
}
bool
SimpleGsm::hangCall ()
{
this->print(F("ATH\r"));
return this->responseIsReceived(OK_RESPONSE_FORMAT, 3000);
}
Happy Hacking!


