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:

/*
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=\"+41787581181\"");
          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=\"+41787581181\"");
          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);
}