general purpose GSM controller with SIM900 and Arduino


Arduino Uno and SIM900 EFcom shield.

3 Outputs and 2 Inputs can be written/read over a short-message (SMS).


some SMS commands are:
“#s” : get status as SMS reply
“#u” : get status over usb, serial monitor
“#[a,b,c][0,1]” : set output level
(eg. “#c1” sets output c to 1)

some usb, serial monitor commands are:
“h” : show help
“c” : check credit
“s” : start/shutdown SIM900 shield

The communication between Arduino and the SIM900 shield utilizes AT-Commands.

my source code is a modified version of the following websites:
elecfreaks
instructables
circuitstoday

source code:
[code language=”cpp”]
/*
Author: Dejan Lauber
Datum: 4.2017
File: sim900efcom_ATcomp.c
Version: V1

Funktion: 3 ausgänge per sms steuerbar; statusabfrage von 2 eingängen und temperatur
Pinbelegung:
(EFCOM LCD5110 Header)
1 3.3V
2 GND
3 13 output a (+onboard LED)
4 12 output b
5 11 output c
6 10 input A
7 9 input B
8 LCD_BL

*/

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3);
#define sim900start 6
#define sim900reset 5

String tx;
char rx, diding_stuff;
String srx;

void setup()
{
mySerial.begin(19200); // the GPRS baud rate
Serial.begin(19200); // the usb baud rate
pinMode(sim900start, OUTPUT);
pinMode(sim900reset, OUTPUT);
pinMode(9, INPUT_PULLUP); //B
pinMode(10, INPUT_PULLUP); //A
pinMode(11, OUTPUT); //c;(pwm)
pinMode(12, OUTPUT); //b;auto-on
pinMode(13, OUTPUT); //a;(led)

digitalWrite(12, HIGH); //b auto-on

delay(1000);
mySerial.println("AT");
delay(2000);
if(mySerial.available()){
Serial.println("\nSIM900 seems ready");
}
else{
Serial.println("\nstarting up 20s");
digitalWrite(sim900start, HIGH);
delay(3000);
digitalWrite(sim900start, LOW);
delay(20000);
Serial.println("\ntext mode activated");
mySerial.println("AT+CMGF=1");
delay(500);
Serial.println("\nsms forward activated");
mySerial.println("AT+CNMI=2,2,0,0,0");
delay(500);
}

}

void loop()
{

if(Serial.available())
{
tx=Serial.readString();
//mySerial.print(tx);
//Serial.print(tx);
if(tx=="a"){
//Serial.println("\nreceived A");
mySerial.println("AT");
}
if(tx=="f"){
Serial.println("\nsms forward activated");
mySerial.println("AT+CNMI=2,2,0,0,0");
}
if(tx=="m"){
Serial.println("\ntext mode activated");
mySerial.println("AT+CMGF=1");
}
if(tx=="s"){
Serial.print("\nstarting up/down");
digitalWrite(sim900start, HIGH);
delay(3500);
digitalWrite(sim900start, LOW);
}
if(tx=="c"){
Serial.println("\nchecking credit");
mySerial.println("ATD*130#"); //swisscom 130;
}
if(tx=="h"){
Serial.println("\nvalid usb commands:");
Serial.println("s start/stop SIM900 (auto)");
Serial.println("m enable text mode (auto)");
Serial.println("f enable live sms forwarding (auto)");
Serial.println("a send ‘AT’ to SIM900 and show answer");
Serial.println("c check swisscom prepaid credit");
Serial.println("h show this help dialog");
Serial.println("\nvalid sms commands:");
Serial.println("#[a|b|c][1|0] set output a|b|c to 1|0");
Serial.println("#s request status report over sms");
Serial.println("#u request status report over usb");
}
}

if(mySerial.available()){
//Serial.print("\nrx:");
//Serial.print(mySerial.readString());
rx = mySerial.read();
srx = String(rx);
Serial.print(srx);
if(rx==’#’){
delay(10);
rx = mySerial.read();
srx = String(rx);
Serial.print(srx);
switch(rx){
case ‘a’:
delay(10);
rx = mySerial.read();
srx = String(rx);
Serial.print(srx);
switch(rx){
case ‘1’:
digitalWrite(13, HIGH);
break;
case ‘0’:
digitalWrite(13, LOW);
break;
}
break;
case ‘b’:
delay(10);
rx = mySerial.read();
srx = String(rx);
Serial.print(srx);
switch(rx){
case ‘1’:
digitalWrite(12, HIGH);
break;
case ‘0’:
digitalWrite(12, LOW);
break;
}
break;
case ‘c’:
delay(10);
rx = mySerial.read();
srx = String(rx);
Serial.print(rx);
switch(rx){
case ‘1’:
digitalWrite(11, HIGH);
break;
case ‘0’:
digitalWrite(11, LOW);
break;
}
break;
case ‘u’:
//usb status report requested
Serial.println("\nreceived status report request");
Serial.print("Output a: ");
Serial.println(digitalRead(13));
Serial.print("Output b: ");
Serial.println(digitalRead(12));
Serial.print("Output c: ");
Serial.println(digitalRead(11));
Serial.print("Input_pullup A: ");
Serial.println(digitalRead(10));
Serial.print("Input_pullup B: ");
Serial.println(digitalRead(9));
Serial.print("MCU Temperature: ");
Serial.print((unsigned int)round(GetTemp()));
Serial.write(‘°’);
Serial.println("C");

break;
case ‘s’:
//gsm status report requested
delay(500);
mySerial.println("AT+CMGF=1");
delay(500);
Serial.print(mySerial.readString());
mySerial.println("AT+CMGS=\"+411234567890\"");
delay(500);
Serial.print(mySerial.readString());
mySerial.print("Output a: ");
mySerial.println(digitalRead(13));
mySerial.print("Output b: ");
mySerial.println(digitalRead(12));
mySerial.print("Output c: ");
mySerial.println(digitalRead(11));
mySerial.print("Input_pullup A: ");
mySerial.println(digitalRead(10));
mySerial.print("Input_pullup B: ");
mySerial.println(digitalRead(9));
mySerial.print("MCU Temperature: ");
mySerial.print((unsigned int)round(GetTemp()));
mySerial.println("C");
delay(500);
Serial.print(mySerial.readString());
mySerial.write(26);
delay(500);
Serial.print(mySerial.readString());

break;
case ‘W’:
//gsm easter egg activated
//Serial.print("gogo");
delay(500);
mySerial.println("AT+CMGF=1");
delay(500);
Serial.print(mySerial.readString());
mySerial.println("AT+CMGS=\"+411234567890\"");
delay(500);
Serial.print(mySerial.readString());
mySerial.println("Triggering sequence activated!");
mySerial.println("Time left: T-00:9:56.32");
delay(500);
Serial.print(mySerial.readString());
mySerial.write(26);
delay(500);
Serial.print(mySerial.readString());
break;
}
diding_stuff=1;
}

}
else{
delay(1000);
if(!mySerial.available()){
if(diding_stuff==1){
mySerial.println("AT+CMGD=1,4");
diding_stuff=0;
}
}
}

}

double GetTemp(void)
{
unsigned int wADC;
double t;

// The internal temperature has to be used
// with the internal reference of 1.1V.
// Channel 8 can not be selected with
// the analogRead function yet.

// Set the internal reference and mux.
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
ADCSRA |= _BV(ADEN); // enable the ADC

delay(20); // wait for voltages to become stable.

ADCSRA |= _BV(ADSC); // Start the ADC

// Detect end-of-conversion
while (bit_is_set(ADCSRA,ADSC));

// Reading register "ADCW" takes care of how to read ADCL and ADCH.
wADC = ADCW;

// The offset of 324.31 / 1.22 could be wrong. It is just an indication
t = (wADC – 329 ) / 1.22;

// The returned temperature is in degrees Celsius.
return (t);
}
[/code]