/* ********************************************************
Title: Remote Monitoring and Control using GSM-SMS
***********************************************************/
/* Leds For Status Checking */
const int ledOrange = 13; // Teensy 3.0 has LED on 13
/* States for each LED */
int ledOrangeState = LOW; // Orange indicates Board Running
int ledGreenState = LOW; // Green indicates Success
int ledRedState = LOW; // Red indicates Error
int ledBlueState = LOW; // Blue indicates Network Connected and SIM Present and Ready
/* Timers for each LED */
Metro ledOrangeBlink = Metro(1000); // Led Blink Event Timer
const int buzzerPin = 23;
/* Debouncer for Button 1 and 2*/
Bounce btn1 = Bounce(btn1Pin, 10); // 10 ms debounce
Bounce btn2 = Bounce(btn2Pin, 10); // 10 ms debounce
/** Temperature Variables **/
const int tempPin = A3; //17
Metro tempReadTimer = Metro(2000); // Temperature Read Event Timer
float tempSetPoint = 40.00; // 40.00 degrees celsius
/** Humidity Variables **/
const int humidityDataPin = 20;
const int humidityClkPin = 21;
Metro humidityReadTimer = Metro(2000); // Humidity Read Event Timer
SHT1x sht1x(humidityDataPin, humidityClkPin);
/** Temperature Control Variables **/
boolean running = true; // Initially Heater is Running
int relayState = HIGH; // Initially Relay is ON
const int relayPin = 19; // Relay is on pin 19
/** Serial Port Received Strings **/
String inputString = ""; // Incoming data from GSM
Metro commTimer = Metro(10000); // Red Led Blink Event Timer
boolean commError = false;
boolean simReady = false;
boolean netReady = false;
Metro statusTimer = Metro(10000); // Blue Led Event Timer
String mobileNo = "9036658002";
void sendMessage(String a,float b);
This function runs just once during the startup of the Board
1.The serialport buffer is reserved 100 bytes of memory
2.All Digital Pins are configured as INPUT/INPUT_PULLUP/OUTPUT
3.Serial Port to PC is initialized at 9600 baud rate
4.Serial Port to GSM Module is initialized at 9600 baud rate
5.ALL LEDS are on for about 10 seconds indicating the board is switched ON
6.Recieve Notification of GSM Modem is Set
inputString.reserve(100);
pinMode(btn1Pin, INPUT_PULLUP);
pinMode(btn2Pin, INPUT_PULLUP);
pinMode(buzzerPin, OUTPUT);
pinMode(ledOrange, OUTPUT); // initialize the digital pin as an output.
pinMode(ledGreen, OUTPUT); // initialize the digital pin as an output.
pinMode(ledRed, OUTPUT); // initialize the digital pin as an output.
pinMode(ledBlue, OUTPUT); // initialize the digital pin as an output.
pinMode(relayPin, OUTPUT); // initialize the digital pin as an output.
Serial.begin(9600); // Serial port to the computer
Serial2.begin(9600); // Serial port to GSM Module
blink(ledOrange, ledOrangeState);
blink(ledGreen, ledGreenState);
blink(ledRed, ledRedState);
blink(ledBlue, ledBlueState);
Serial2.println("ATE0"); //Switch off ECHO
Serial2.println("AT+CNMI=1,2,0,0,0");// Notify message directly
blink(ledGreen, ledGreenState);
blink(ledRed, ledRedState);
blink(ledRed, ledBlueState);
This function runs over and over again as long as the board has power
1.The GSM Modem is first Checked for proper connectivity
1.The Button is monitored for forced message sending and testing
3.Then the Temperature if read from LM35 and checked
4.Any serialport Event is monitored
5.To indicate Board is running properly the onBoard Orange Led is made to Blink
/* Blink onBoard Orange LED to indicate Power ON */
if (ledOrangeBlink.check() == 1)
blink(ledOrange, ledOrangeState);
digitalWrite(buzzerPin, HIGH);
digitalWrite(buzzerPin, LOW);
/* StartUp Sound Function */
/* Alarm Sound Function */
This checks whether the Button state is changed/updated and
gives whether the button is rising or falling
Falling: Button is pressed - Sends Message of Temperature
Rising: Button is released
if (btn1.fallingEdge()) {
Serial.println("btn1 fall");
sendMessage("Temperature: ", tempC);
Serial.println("btn1 rise");
This checks whether the Button state is changed/updated and
gives whether the button is rising or falling
Falling: Button is pressed - Sends Message of Humidity
Rising: Button is released
if (btn2.fallingEdge()) {
Serial.println("btn2 fall");
sendMessage("Humidity: ", humidityRH);
Serial.println("btn2 rise");
This Toggles the state of the LED
void blink(const int led,int &state){
digitalWrite(led, state);
if(commTimer.check() == 1){
if(!Serial2.available()){
digitalWrite(ledGreen, LOW);
digitalWrite(ledRed, HIGH);
Serial.println("commError");
digitalWrite(ledGreen, HIGH);
digitalWrite(ledRed, LOW);
Serial.println("comm Working");
/* SerialPort Monitoring Function
This checks any incoming data at serialport and then splits the String based on
the LineFeed Character '\n' and sends it to the parser function
[GSM Modem SIM300 sends "\r\n" Carraige Return(CR) and LineFeed(LF) in every response]
while (Serial2.available()) {
char inChar = (char)Serial2.read();
inputString += inChar; // add it to the inputString:
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
/** GSM Related Functions **/
/* Network Connection Function
This checks whether the SIM in GSM Module SIM300 is connected and
whether network is connected based on which blue LED is turned ON or OFF
if(statusTimer.check() == 1){
digitalWrite(ledBlue, HIGH);
digitalWrite(ledBlue, LOW);
Serial2.println("AT+CSMINS?");
Serial2.println("AT+CREG?");
void sendMessage(String text, float value = 0.0){
Serial2.println("AT+CMGF=1");
Serial2.println("AT+CMGS=\""+mobileNo+"\"");
sprintf(charBuf,"%f", value);
Serial2.print("\r\n\x1A"); //CR+LF+EOF
This checks any incoming String from serialport for necessary monitoring
the communication from GSM Module SIM300
Serial.println(inputString);
if(contains("+CREG: 0,0")){
Serial.println("No Network Connection");
else if(contains("+CREG: 0,1") || contains("+CREG: 0,2") || contains("+CREG: 0,3")){
Serial.println("Net Ready");
else if(contains("+CSMINS: 0,1")){//inputString.substring(0) == ){ //+CPIN: READY RDY +SCKS:0
Serial.println("SIM READY");
else if(contains("+CSQ:")){ //RF Signal Strength
Serial.println(inputString); // Turn Green Led ON
Serial.println(inputString); // Turn Green Led ON
digitalWrite(ledRed, LOW);
digitalWrite(ledGreen, HIGH);
else if(contains("Error")){
Serial.println(inputString); // Turn Red Led ON
digitalWrite(ledRed, HIGH);
digitalWrite(ledGreen, LOW);
if(contains("+CMS ERROR: 517")){ //SIM Wait
Serial.println("SIM NOT READY");
else if(contains("+CMS ERROR: 515")){ //Busy
Serial.println("Please Wait");
else if(contains("TEMP")){ //The String contains TEMP
Serial.println("TEMP Received");
digitalWrite(ledGreen, HIGH);
delay(500); // 515 error busy please wait
sendMessage("Temperature: ", tempC);
else if(contains("HUM")){ //The String contains HUM
Serial.println("HUM Received");
digitalWrite(ledGreen, HIGH);
delay(500); // 515 error busy please wait
sendMessage("Humidity: ", humidityRH);
else if(contains("MAN")){
Serial.println("MAN Received");
digitalWrite(ledGreen, HIGH);
sendMessage("Already in Manual Mode");
sendMessage("Manual Mode is Set");
else if(contains("AUTO")){
Serial.println("AUTO Received");
digitalWrite(ledGreen, HIGH);
sendMessage("Already in Automatic Mode");
sendMessage("Automatic Mode is Set");
else if(contains("MOB")){
Serial.println("MOB Received");
digitalWrite(ledGreen, HIGH);
newChar[i] = inputString[i+4];
Serial.println("New Mobile no:"+mobileNo);
delay(500); // 515 error busy please wait
sendMessage("New Mobile Number: "+mobileNo);
Serial.println("ON Received");
delay(500); // 515 error busy please wait
sendMessage("Bulb is on");
sendMessage("Please Change to manual mode");
else if(contains("OFF")){
Serial.println("OFF Received");
delay(500); // 515 error busy please wait
sendMessage("Bulb is off");
sendMessage("Please Change to manual mode");
else if(contains("SET")){
Serial.println("SET Received");
newChar[0] = inputString[4];
newChar[1] = inputString[5];
tempSetPoint = atof(newChar);// Converting tempSetPoint from message to float
Serial.println(tempSetPoint);
delay(500); // 515 error busy please wait
sendMessage("tempSetPoint: ", tempSetPoint);
inputString = ""; // clear the string:
/* This checks if a search string is present in the inputString */
int contains(String search) {
int max = inputString.length() - search.length();
int lgsearch = search.length();
for (int i = 0; i <= max; i++) {
if (inputString.substring(i, i + lgsearch) == search) return true;
/** Monitor and Control Related Functions **/
/* Temperature Monitoring Function
This checks the temperature every 2second
if (tempReadTimer.check() == 1){ // check if the metro has passed it's interval
Serial.print("Temperature: ");
/* Temperature Reading Function
Reads 8 samples from the ADC pin A4/18 and then takes average
Voltage is calculated by multiplying by 3.3v reference voltage and dividing by 1024 10-bit ADC value
Temperature is calculated by multiplying voltage with 100 as LM35 has 10mV/C ex: 28c is 280mV or 0.28V
for(int i = 0;i<=7;i++){ // gets 8 samples from adc
readValue += analogRead(tempPin);
voltage = (3.3 * readValue)/1024;
/* Temperature Automatic Control Function
Automatically controls the temperature based on tempSetPoint value
void tempAutomaticControl(){
if(tempC >= tempSetPoint){
if(running){ // This is to prevent the system from sending messages and alarm continously
Serial.print("Temperature >= ");
Serial.println(tempSetPoint);
sendMessage("Temperature: ", tempC);
else{ // If Temperature dips below tempSetPoint then return to normal operation
Serial.print("Temperature < ");
Serial.println(tempSetPoint);
/* Temperature Manual Control Function
Manually controls the temperature based on used Input ON/OFF
void tempManualControl(){
/* Humidity Monitoring Function
This checks the humidity every 2seconds and performs necessary controlling
if (humidityReadTimer.check() == 1){
humidityRH = sht1x.readHumidity();
Serial.print("Humidity: ");
Serial.print(humidityRH);
/* 2-Position Controller Mode
This Turns ON or OFF the Relay based on tempSetPoint */
digitalWrite(relayPin, relayState);
/** GPRS Related Functions **/
Serial2.println("AT+CGATT=1"); // - Attach to GPRS Service
Serial2.println("AT+CGDCONT=1,\"IP\",\"wap.cingular\""); //- Define PDP Context (cid, PDP type, APN)
Serial2.println("AT+CDNSCFG=\"208.67.222.222\",\"208.67.220.220\""); //- Configure Domain Name Server (primary DNS, secondary DNS)
Serial2.println("AT+CSTT=\"wap.cingular\",\"\",\"\"");//- Start Task & set APN, User ID, and password
Serial2.println("AT+CIICR"); //- Bring up wireless connection with GPRS - THIS MAY TAKE A WHILE
Serial2.println("AT+CIFSR"); // - Get Local IP address
Serial2.println("AT+CIPHEAD=1"); //- Tells module to add an 'IP Header' to receive data
Serial2.println("AT+CDNSORIP=1"); //- Indicates whether connection request will be IP address (0), or domain name (1)
Serial2.println("AT+CIPSTART=\"TCP\",\"www.google.com\",\"80\"");
//- Start up TCP connection (mode, IP address/name, port) CONNECT OK - Indicates you've connected to the server
//- IT MAY TAKE A WHILE FOR THIS TO BE RETURNED
Serial2.println("AT+CIPSEND"); //- Issue Send Command - wait for module to return'>'
Serial2.print("GET / HTTP/1.1\r\n\x1A"); //- Send data - this example is an HTTP request for the default page
Serial2.println("AT+CGATT?"); // +CGATT:1 Gprs is active, 0:de:active
Serial2.println("AT+CIPSTATUS"); // check GPRS Status STATE: CONNECT OK or IP STATUS
Serial2.println("AT+CGATT=0"); // close gprs
Serial2.println("AT+CIPSHUT"); // close gprs
Serial2.println("AT+CFUN=0,1"); // close gprs
Serial2.println("AT+CPOWD=1"); // close gprs
Serial2.println("AT+CIPSTART=\"TCP\",\"211.136.42.12\",\"2020\""); // OK,CONENECT OK
Serial2.println("AT+CIPSEND");
Serial2.print("This is my data\r\n\x1A"); // SEND OK
Serial2.print("AT+CIFSR");
Serial2.print("AT+CIPCSGP=1\"CMNET\""); // OK
Serial2.print("AT+CLPORT=\"TCP\",\"2020\""); //OK
Serial2.print("AT+CIPSERVER"); // SERVER OK
Serial2.print("AT+CIPCCON=2"); // OK
Serial2.print("AT+CIFSR"); // IP nl REMOTE IP: 10.112.255.207:2020 Then CIPSEND