asbjorn
Published © LGPL

Boat Controller

Remotely control lights and heater with an Android app. Also includes a geo-fence alarm, and outside and inside temp/humidity sensors.

IntermediateFull instructions provided4,075
Boat Controller

Things used in this project

Hardware components

Arduino Mega 2560
Arduino Mega 2560
×1
Adafruit Fona 808 Shield - Mini Cellular GSM + GPS For Arduino
×1
Relay Shield for Particle Photon I²C 8-Channel SPDT 10-Amp
ControlEverything.com Relay Shield for Particle Photon I²C 8-Channel SPDT 10-Amp
×2
DHT11 Temperature & Humidity Sensor (4 pins)
DHT11 Temperature & Humidity Sensor (4 pins)
×1
Waterproof DS18B20 Digital temperature sensor + extras
×1
UBEC DC/DC Step-Down (Buck) Converter - 5V @ 3A output
×1
Adafruit Passive GPS Antenna uFL - 15mm x 15mm 1 dBi gain
×1
Adafruit Slim Sticker-type GSM/Cellular Quad-Band Antenna - 3dBi uFL
×1

Software apps and online services

MIT App Inventor
MIT App Inventor

Story

Read more

Code

BoatController

Arduino
This has been put together from several different sketches and I'm still working on it. So there may be some commenting that should not bee there. Also this is an work in progress and I know that some of the code will be changed...
#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_SleepyDog.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>


// LED & Buzzer pins
const int alarmpin = 7;
const int buzzerPin = 9;

// Geofence Alarm
int counter = 0;
bool alarm = false;

// Size of the geo fence (in meters)
float maxDistance;
bool geofenceAlarm = false;

// Latitude & longitude for position and distance measurement
float initialLatitude;
float initialLongitude;
float latitude, longitude, speed_kph, heading, altitude;
float alarmstatus(0);

// settings for voltmeter
float vPow = 4.6;
float r1 = 100000;
float r2 = 22000;


#define FONA_TX 11    //using the arduino mega with fona 808 gps shield i had to change original TX/RX to this, I`we soldiered connectorcables from original pins to these on phona shield.. 
#define FONA_RX 10    //-----""------
#define FONA_RST 4
#define FONA_RI 6

#define BUSYWAIT 5000  // milliseconds

int Relay13status = HIGH;
int Relay13active = HIGH;
int Relay13counter = LOW;


float intemperature(0);
float humidity(0);
unsigned long HeaterTurnedOffTime = 0; 
const long HeaterDelayTime = 2700000;
unsigned long BurnerTurnedOffTime = 0; 
const long BurnerDelayTime = 120000;
float termostatTemp(0);

const int numReadings = 10;

int readings[numReadings];      // the readings from the digital temp/humidity input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int averageTemp = 0;                // the averageTemp

int inputPin = A0;


// Temperature Sensor Data wire is plugged into port 21 on the Arduino Mega
#define ONE_WIRE_BUS 52


#define DHTPIN            53         // Pin which is connected to the DHT Temperature/Humidity sensor.
//the type of sensor in use:
#define DHTTYPE           DHT11     // DHT 11 


// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);


DHT_Unified dht(DHTPIN, DHTTYPE);

uint32_t delayMS;


const int Relay1Pin = 22;  // Deck Flood Light..        the pin that the Relay  1 is attached to
const int Relay2Pin = 23;  // Cockpit Light..           the pin that the Relay  2 is attached to
const int Relay3Pin = 24;  // Nav Lights by Sail..      the pin that the Relay  3 is attached to
const int Relay4Pin = 25;  // Nav Lights by Engine..    the pin that the Relay  4 is attached to (works always together with Relay 3, to isolate power for white lantern in mast) 
const int Relay5Pin = 26;  // Nav Lights when Moored..  the pin that the Relay  5 is attached to
const int Relay6Pin = 27;  // Aft Cabin Light..         the pin that the Relay  6 is attached to
const int Relay7Pin = 28;  // Main Cabin Light..        the pin that the Relay  7 is attached to
const int Relay8Pin = 29;  // Bathroom Light..          the pin that the Relay  8 is attached to
const int Relay9Pin = 30;  // Bow Cabin Light..         the pin that the Relay  9 is attached to
const int Relay10Pin = 31; // Function 1..              the pin that the Relay 10 is attached to
const int Relay11Pin = 32; // Function 2..              the pin that the Relay 11 is attached to
const int Relay12Pin = 33; // Function 3..              the pin that the Relay 12 is attached to
const int Relay13Pin = 34; // Function 4..              the pin that the Relay 13 is attached to
const int Relay14Pin = 35; // Function 5..              the pin that the Relay 14 is attached to
const int Relay15Pin = 36; // Function 6..              the pin that the Relay 15 is attached to
const int Relay16Pin = 37; // Function 7..              the pin that the Relay 16 is attached to





// this is a large buffer for replies
char replybuffer[255];

char maxDistancebuffer[30];

char sender[25];
char outmessage[250];


// or comment this out & use a hardware serial port like Serial1 (see below)
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);

Adafruit_FONA fona = Adafruit_FONA(FONA_RST);

uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);

boolean fonainit(void) {
  Serial.println(F("Initializing....(May take 3 seconds)"));




  // make it slow so its easy to read!
  fonaSS.begin(4800); // if you're using software serial
  //Serial1.begin(4800); // if you're using hardware serial

  // See if the FONA is responding
  if (! fona.begin(fonaSS)) {           // can also try fona.begin(Serial1) 
    Serial.println(F("Couldn't find FONA"));
    return false;
  }
  Serial.println(F("FONA is OK"));
  return true;
  
}

// Halt function called when an error occurs.  Will print an error and stop execution while
// doing a fast blink of the LED.  If the watchdog is enabled it will reset after 8 seconds.
void halt(const __FlashStringHelper *error) {
  Serial.println(error);
  while (1) {
    digitalWrite(alarmpin, LOW);
    delay(100);
    digitalWrite(alarmpin, HIGH);
    delay(100);
  }
}

void printFloat(float value, int places) {
  // this is used to cast digits 
  int digit;
  float tens = 0.1;
  int tenscount = 0;
  int i;
  float tempfloat = value;

    // make sure we round properly. this could use pow from <math.h>, but doesn't seem worth the import
  // if this rounding step isn't here, the value  54.321 prints as 54.3209

  // calculate rounding term d:   0.5/pow(10,places)  
  float d = 0.5;
  if (value < 0)
    d *= -1.0;
  // divide by ten for each decimal place
  for (i = 0; i < places; i++)
    d/= 10.0;    
  // this small addition, combined with truncation will round our values properly 
  tempfloat +=  d;

  // first get value tens to be the large power of ten less than value
  // tenscount isn't necessary but it would be useful if you wanted to know after this how many chars the number will take

  if (value < 0)
    tempfloat *= -1.0;
  while ((tens * 10.0) <= tempfloat) {
    tens *= 10.0;
    tenscount += 1;
  }


  // write out the negative if needed
  if (value < 0)
    Serial.print('-');

  if (tenscount == 0)
    Serial.print(0, DEC);

  for (i=0; i< tenscount; i++) {
    digit = (int) (tempfloat/tens);
    Serial.print(digit, DEC);
    tempfloat = tempfloat - ((float)digit * tens);
    tens /= 10.0;
  }

  // if no places after decimal, stop now and return
  if (places <= 0)
    return;

  // otherwise, write the point and continue on
  Serial.print('.');  

  // now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
  for (i = 0; i < places; i++) {
    tempfloat *= 10.0; 
    digit = (int) tempfloat;
    Serial.print(digit,DEC);  
    // once written, subtract off that digit
    tempfloat = tempfloat - (float) digit; 
  }
}

// Calculate distance between two points
float distanceCoordinates(float flat1, float flon1, float flat2, float flon2) {

  // Variables
  float dist_calc=0;
  float dist_calc2=0;
  float diflat=0;
  float diflon=0;

  // Calculations
  diflat  = radians(flat2-flat1);
  flat1 = radians(flat1);
  flat2 = radians(flat2);
  diflon = radians((flon2)-(flon1));

  dist_calc = (sin(diflat/2.0)*sin(diflat/2.0));
  dist_calc2 = cos(flat1);
  dist_calc2*=cos(flat2);
  dist_calc2*=sin(diflon/2.0);
  dist_calc2*=sin(diflon/2.0);
  dist_calc +=dist_calc2;

  dist_calc=(2*atan2(sqrt(dist_calc),sqrt(1.0-dist_calc)));
  
  dist_calc*=6371000.0; //Converting to meters

  return dist_calc;
}


void setup() {
  while (!Serial);  // useful for Leonardo/Micro, remove in production!


  // initialize the pins as an output:
  pinMode(Relay1Pin, OUTPUT);
  pinMode(Relay2Pin, OUTPUT);
  pinMode(Relay3Pin, OUTPUT);
  pinMode(Relay4Pin, OUTPUT);
  pinMode(Relay5Pin, OUTPUT);
  pinMode(Relay6Pin, OUTPUT);
  pinMode(Relay7Pin, OUTPUT);
  pinMode(Relay8Pin, OUTPUT);
  pinMode(Relay9Pin, OUTPUT);
  pinMode(Relay10Pin, OUTPUT);
  pinMode(Relay11Pin, OUTPUT);
  pinMode(Relay12Pin, OUTPUT);
  pinMode(Relay13Pin, OUTPUT);
  pinMode(Relay14Pin, OUTPUT);
  pinMode(Relay15Pin, OUTPUT);
  pinMode(Relay16Pin, OUTPUT);

  // Set alarm components
  pinMode(alarmpin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  alarm = false;
  geofenceAlarm = false;




  // Set all pins High from the start, (Relays are active when pin is low, this to set all relays inactive).
  digitalWrite(Relay1Pin, HIGH);
  digitalWrite(Relay2Pin, HIGH);
  digitalWrite(Relay3Pin, HIGH);
  digitalWrite(Relay4Pin, HIGH);
  digitalWrite(Relay5Pin, HIGH);
  digitalWrite(Relay6Pin, HIGH);
  digitalWrite(Relay7Pin, HIGH);
  digitalWrite(Relay8Pin, HIGH);
  digitalWrite(Relay9Pin, HIGH);
  digitalWrite(Relay10Pin, HIGH);
  digitalWrite(Relay11Pin, HIGH);
  digitalWrite(Relay12Pin, HIGH);
  digitalWrite(Relay13Pin, HIGH);
  digitalWrite(Relay14Pin, HIGH);
  digitalWrite(Relay15Pin, HIGH);
  digitalWrite(Relay16Pin, HIGH);

    // Start up the library for Temperature Sensor
  sensors.begin();  

    // Start up the library for Temperature/Humidity Sensor

    dht.begin();

  
  Serial.begin(115200);
  Serial.println(F("FONA basic test"));

  while (! fonainit()) {
    delay(5000);
  }
  
  // Print SIM card IMEI number.
  char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
  uint8_t imeiLen = fona.getIMEI(imei);
  if (imeiLen > 0) {
    Serial.print("SIM card IMEI: "); Serial.println(imei);
  }
  
  pinMode(FONA_RI, INPUT);
  digitalWrite(FONA_RI, HIGH); // turn on pullup on RI
  // turn on RI pin change on incoming SMS!
  fona.sendCheckReply(F("AT+CFGRI=1"), F("OK"));


int8_t lastsmsnum = 0;


// Use the watchdog to simplify retry logic and make things more robust.
  // Enable this after FONA is intialized because FONA init takes about 8-9 seconds.
//  Watchdog.enable(8000);
 // Watchdog.reset();

  // Enable GPS.
  fona.enableGPS(true);

  // Wait a little bit to stabilize the connection.
 // Watchdog.reset();
 // delay(3000);

 if (maxDistance > 99)
{
  maxDistance = maxDistance;
}
else
{
  maxDistance = 100;
}



  // Initial GPS read
  bool gpsFix = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);
  initialLatitude = 60.352402;
  initialLongitude = 4.989827;

  alarmstatus = 0;


  // Init counter
  counter = millis();


  


  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
/*  Serial.println("------------------------------------");
  Serial.println("Temperature");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" *C");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" *C");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" *C");  
  Serial.println("------------------------------------");*/
  // Print humidity sensor details.
  dht.humidity().getSensor(&sensor);
 /* Serial.println("------------------------------------");
  Serial.println("Humidity");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println("%");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println("%");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println("%");  
  Serial.println("------------------------------------"); */
  // Set delay between sensor readings based on sensor details.
  delayMS = sensor.min_delay / 1000;

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}


void loop() {


 // Watchdog reset at start of loop--make sure everything below takes less than 8 seconds in normal operation!
  Watchdog.reset();

  // Grab a GPS reading.
  float latitude, longitude, speed_kph, heading, altitude;
  bool gpsFix = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);

  Serial.print("Latitude: ");
  printFloat(latitude, 6);
  Serial.println("");

  Serial.print("Longitude: ");
  printFloat(longitude, 6);
  Serial.println("");

  Serial.print("Initial latitude: ");
  printFloat(initialLatitude, 6);
  Serial.println("");

  Serial.print("Initial longitude: ");
  printFloat(initialLongitude, 6);
  Serial.println("");

  // Calculate distance between new & old coordinates
  float distance = distanceCoordinates(latitude, longitude, initialLatitude, initialLongitude);
  
  Serial.print("Distance: ");
  printFloat(distance, 6);
  Serial.println("");



  Serial.print("GeoFence distance: ");
  printFloat(maxDistance, 0);
  Serial.println("");

  //Temperature/Humiditysensor readings

  //delay(delayMS);
  // Get temperature event and print its value.
  sensors_event_t event;  
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println("Error reading temperature!");
  }
  else {
    Serial.print("Temperature: ");
    Serial.print(event.temperature);
    Serial.println(" *C");
    intemperature = event.temperature;

  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
  }
  else {
    Serial.print("Humidity: ");
    Serial.print(event.relative_humidity);
    Serial.println("%");
    humidity = event.relative_humidity;
  }

Serial.println ("Current");   
Serial.println (millis());
Serial.println ("Previous");   
Serial.println (BurnerTurnedOffTime);
Serial.println ("Relay13active");
Serial.println (Relay13active);
Serial.println (termostatTemp);
Serial.println ("GeofenceAlarm");
Serial.println (alarmstatus);

       if ((Relay13status == HIGH) && (millis() - HeaterTurnedOffTime > HeaterDelayTime)) {
           digitalWrite(Relay13Pin, HIGH);
   }
      if ((Relay13active == LOW) && (Relay13counter == HIGH) && (millis() - BurnerTurnedOffTime > BurnerDelayTime)) {
           digitalWrite(Relay13Pin, HIGH);
           Relay13active = HIGH; 
           Relay13counter = LOW;

   }
//Termostat function for heater
         if ((Relay13status == LOW) && (averageTemp < termostatTemp)) {
            digitalWrite(Relay13Pin, LOW);
            Relay13active = LOW;
            Relay13counter = LOW;
       }       
        if ((Relay13active == LOW) && (Relay13counter == LOW) && (averageTemp > termostatTemp)) {
            BurnerTurnedOffTime = millis();      
            Relay13counter = HIGH;

      }

        total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = intemperature;
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the averageTemp:
  averageTemp = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(averageTemp);
  delay(1);        // delay in between reads for stability


//Voltmeter functions
float v = (analogRead(10) * vPow) / 1024.0;
float v2 = v / (r2 / (r1 + r2));

Serial.println("Volt:");
Serial.println(v2);

  // Set alarm on?
  
  if ((distance > maxDistance) && (geofenceAlarm == true)) {
    alarm = true;
    alarmstatus = 1;

    

        if (!fona.sendSMS(sender, outmessage)) {
          Serial.println(F("Alarm Failed"));
        } else {
          Serial.println(F("Alarm Sent!"));
        initialLatitude = latitude;
        initialLongitude = longitude;
        alarmstatus = 0;  
        }
        
  }

    else {
          alarm = false;
          alarmstatus = 0;  
    }
  
  // Handle alarm
  if (alarm == false) {
        alarmstatus = 0;

    if (millis() - counter > 5000) {
      digitalWrite(alarmpin, HIGH);

    }

     if (millis() - counter > 5100) {
      digitalWrite(alarmpin, LOW);
      counter = millis();
    }

    noTone(buzzerPin);
    
  } 
  else {
        
    if (millis() - counter > 100) {
      digitalWrite(alarmpin, HIGH);
  
    }

     if (millis() - counter > 200) {
      digitalWrite(alarmpin, LOW);
      counter = millis();
    }
  
    tone(buzzerPin, 1000);

  }
  

//   digitalWrite(LED, HIGH);
//   delay(100);
//   digitalWrite(LED, LOW);
       
  while (fona.getNetworkStatus() != 1) {
    Serial.println("Waiting for cell connection");
    delay(2000);
  }
  
  // this is a 'busy wait' loop, we check if the interrupt
  // pin went low, and after BUSYWAIT milliseconds break out to check
  // manually for SMS's and connection status
  // This would be a good place to 'sleep'
  for (uint16_t i=0; i<BUSYWAIT; i++) {
     if (! digitalRead(FONA_RI)) {
        // RI pin went low, SMS received?
        Serial.println(F("RI went low"));
        break;
     } 
     delay(1);
  }
  
  int8_t smsnum = fona.getNumSMS();
  if (smsnum < 0) {
    Serial.println(F("Could not read # SMS"));
    return;
  } else {
    Serial.print(smsnum); 
    Serial.println(F(" SMS's on SIM card!"));
  }
  
  if (smsnum == 0) return;


  


  // there's an SMS!
  uint8_t n = 1; 
  while (true) {
     uint16_t smslen;
     
     Serial.print(F("\n\rReading SMS #")); Serial.println(n);
     uint8_t len = fona.readSMS(n, replybuffer, 250, &smslen); // pass in buffer and max len!
     // if the length is zero, its a special case where the index number is higher
     // so increase the max we'll look at!
     if (len == 0) {
        Serial.println(F("[empty slot]"));
        n++;
        continue;
     }
     if (! fona.getSMSSender(n, sender, sizeof(sender))) {
       // failed to get the sender?
       sender[0] = 0;
     }

     
     Serial.print(F("***** SMS #")); Serial.print(n);
     Serial.print(" ("); Serial.print(len); Serial.println(F(") bytes *****"));
     Serial.println(replybuffer);
     Serial.print(F("From: ")); Serial.println(sender);
     Serial.println(F("*****"));

       String stringInSMS = (replybuffer);
  Serial.println(stringInSMS);


     
    if (stringInSMS.substring(0, 2) == "A1") {
       digitalWrite(Relay1Pin, LOW);      
       }
      
    if (stringInSMS.substring(0, 2) == "A0") {
       digitalWrite(Relay1Pin, HIGH); 
       }

     
    if (stringInSMS.substring(2, 4) == "B1") {
       digitalWrite(Relay2Pin, LOW); 
     }
     
    if (stringInSMS.substring(2, 4) == "B0") {
       digitalWrite(Relay2Pin, HIGH); 
     }     


    if (stringInSMS.substring(4, 6) == "C1") {
       digitalWrite(Relay3Pin, LOW); 
       digitalWrite(Relay4Pin, LOW); 

     }
     
    if (stringInSMS.substring(4, 6) == "C0") {
       digitalWrite(Relay3Pin, HIGH); 
       digitalWrite(Relay4Pin, HIGH); 
     }


    if (stringInSMS.substring(6, 8) == "D1") {
       digitalWrite(Relay5Pin, LOW);      
      
       }
      
    if (stringInSMS.substring(6, 8) == "D0") {
       digitalWrite(Relay5Pin, HIGH); 
       }

     
    if (stringInSMS.substring(8, 10) == "E1") {
       digitalWrite(Relay6Pin, LOW); 
     }
     
    if (stringInSMS.substring(8, 10) == "E0") {
       digitalWrite(Relay6Pin, HIGH); 
     }     


    if (stringInSMS.substring(10, 12) == "F1") {
       digitalWrite(Relay7Pin, LOW); 
     }
     
    if (stringInSMS.substring(10, 12) == "F0") {
       digitalWrite(Relay7Pin, HIGH); 
     }


    if (stringInSMS.substring(12, 14) == "G1") {
       digitalWrite(Relay8Pin, LOW);      
       }
      
    if (stringInSMS.substring(12, 14) == "G0") {
       digitalWrite(Relay8Pin, HIGH); 
       }

     
    if (stringInSMS.substring(14, 16) == "H1") {
       digitalWrite(Relay9Pin, LOW); 
     }
     
    if (stringInSMS.substring(14, 16) == "H0") {
       digitalWrite(Relay9Pin, HIGH); 
     }     


    if (stringInSMS.substring(16, 18) == "I1") {
       digitalWrite(Relay10Pin, LOW); 
     }
     
    if (stringInSMS.substring(16, 18) == "I0") {
       digitalWrite(Relay10Pin, HIGH); 
     }

        
    if (stringInSMS.substring(18, 20) == "J1") {     
       digitalWrite(Relay11Pin, LOW);
      }
     
    if (stringInSMS.substring(18, 20) == "J0") {
       digitalWrite(Relay11Pin, HIGH);       
      } 


     
    if (stringInSMS.substring(20, 22) == "K1") {
       digitalWrite(Relay12Pin, LOW); 
     }
     
    if (stringInSMS.substring(20, 22) == "K0") {
       digitalWrite(Relay12Pin, HIGH); 
     }     


    if (stringInSMS.substring(22, 24) == "L1") {       //A part of string that activates relay 10 & 11
       digitalWrite(Relay14Pin, LOW);
       Relay13status = LOW;                           //Sets the status for relay 10 to LOW 
      }
 

    if (stringInSMS.substring(22, 24) == "L0") {
       digitalWrite(Relay13Pin, HIGH); 
       Relay13status = HIGH;
       HeaterTurnedOffTime = millis();      
     }


    if (stringInSMS.substring(24, 26) == "M1") {
       digitalWrite(Relay15Pin, LOW); 
     }
     
    if (stringInSMS.substring(24, 26) == "M0") {
       digitalWrite(Relay15Pin, HIGH); 
     }


    if (stringInSMS.substring(26, 28) == "N1") {
       digitalWrite(Relay16Pin, LOW);      
       }
      
    if (stringInSMS.substring(26, 28) == "N0") {
       digitalWrite(Relay16Pin, HIGH); 
       }    


    if (stringInSMS.substring(30, 32) == "Q1") {
        geofenceAlarm = true;
     }
     
    if (stringInSMS.substring(30, 32) == "Q0") {
        geofenceAlarm = false;
     }

    if (stringInSMS.substring(32, 37) == "save1") {
       initialLatitude = latitude;
       initialLongitude = longitude;
     }

     termostatTemp = (stringInSMS.substring(37, 39).toFloat());

     maxDistance = (stringInSMS.substring(39).toFloat());

//String stringOutSMS = String(("A1"),(bitRead(PORTA,0)),("|"),("A2"),(bitRead(PORTA,1)),("|"));

  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  sensors.requestTemperatures(); // Send the command to get temperatures


        
    String string1 = ("A");                                   // Refers to Relay 1 
    String string2 = String(bitRead(PORTA,0));                // To check pinstatus HIGH or LOW (returns 1 or 0) 
    String string3 = ("|B");                                  // the | makes an marker for App to know where to split Serial info, then the B refers to Relay 2.
    String string4 = String(bitRead(PORTA,1));                // To check pinstatus HIGH or LOW (returns 1 or 0)
    String string5 = ("|C");                                  // And so on....
    String string6 = String(bitRead(PORTA,2));
    String string7 = ("|D");
    String string8 = String(bitRead(PORTA,4));
    String string9 = ("|E");
    String string10 = String(bitRead(PORTA,5));
    String string11 = ("|F");
    String string12 = String(bitRead(PORTA,6));
    String string13 = ("|G");
    String string14 = String(bitRead(PORTA,7));
    String string15 = ("|H");
    String string16 = String(bitRead(PORTC,7));
    String string17 = ("|I");
    String string18 = String(bitRead(PORTC,6));
    String string19 = ("|J");
    String string20 = String(bitRead(PORTC,5));
    String string21 = ("|K");
    String string22 = String(bitRead(PORTC,4));
    String string23 = ("|L");
    String string24 = String(bitRead(PORTC,2));
    String string25 = ("|M");
    String string26 = String(bitRead(PORTC,1));
    String string27 = ("|N");
    String string28 = String(bitRead(PORTC,0));
    String string29 = ("|O");
    String string30 = String(bitRead(PORTC,0));     // TO BE REMOVED!!!
    String string31 = ("|");
    String string32 = String(sensors.getTempCByIndex(0));       //To read outside temperature..
    String string33 = ("|");
    String string34 = String(latitude, 6); 
    String string35 = ("|");
    String string36 = String(longitude, 6); 
    String string37 = ("|");
    String string38 = String(initialLatitude, 6); 
    String string39 = ("|");
    String string40 = String(initialLongitude, 6); 
    String string41 = ("|");
    String string42 = String(alarmstatus, 0);
    String string43 = ("|");
    String string44 = String(averageTemp);       //To read innside temperature..
    String string45 = ("|");
    String string46 = String(humidity, 0);       //To read innside Humidity..
    String string47 = ("|");
    String string48 = String(v2, 2);       //To read battery voltage..
    String string49 = ("|");


        // Connect all the strings to one long string
    String stringout = string1 + string2 + string3 + string4 + string5 + string6 + string7 + string8 + string9 + string10 + string11 + string12 + string13 + string14 + string15 + string16 + string17 + string18 + string19 + string20 + string21 + string22 + string23 + string24 + string25 + string26 + string27 + string28 + string29 + string30 + string31 + string32 + string33 + string34 + string35 + string36 + string37 + string38 + string39 + string40 + string41 + string42 + string43 + string44 + string45 + string46 + string47 + string48 + string49;




    stringout.toCharArray(outmessage,249);
    
    Serial.println (outmessage);

      
            if (!fona.sendSMS(sender, outmessage)) {
          Serial.println(F("Failed"));
        } else {
          Serial.println(F("Sent!"));
        }
    
/*  

*/
      
     delay(3000);
     break;
  }  
  fona.deleteSMS(n);
 
  delay(1000); 


     }

BoatController

Arduino
To control lights & heat in my boat
/*  BoatController combined with Boatcontroller App for android lets me control most of the electronics on my boat. 

    App/code Functions:
              - Heater: 
                        On:
                        SMS activates Relay 1 (main power), thermostate functions in code will activate Relay 2 (burner).
                        Turns on/off my Eberspacher Airtronic Heater with termostat function.
                        Heater is controlled by to relays (Relay 1 & 2), one for main power and one to activate the burner. Heater original functions lets heaterfan blow for a while after you turned heater off, this to let heater cool down.
                        Code has an delay for main power Relay to maintain this cool down function. 
                        Termostat function lets you set an preffered temperature in app settings, and stops then burner when temperature is achieved. This has also an delayfunction to prevent burner to start and stop rapidly,
                        code is forcing burner to be active for at least 2 minutes before switching off.
                        
                        Off:
                        SMS deactivates Relay 2 (burner), delayfunction will deactivate Relay 1 (main power).
                        
             - NavigationLights By Sail:
                        On:
                        SMS activates Relay 3 & 4, app will also deactivate relays 5 & 6.
                        Navigation lights buttons on the controlpanel in my boat (Bavaria 32 Cruiser - 2013) has seperate buttons/actions for bow lanthern (combination red/green) and the stern lanthern (white). The connections from Relay to lantherns would "shortcut"
                        these two original outputs making them as one, so to be shure to keep original functions in boat I split this output into Relay 3 & 4.

                        Off:
                        SMS deactivates Relay 3 & 4.
                        
            - NavigationLights By Engine:
                        On:
                        SMS activates Relay 3, 4 & 5, will also deactivate relay 6.
                        The android App will activate the same relays used for NavigathionLights By Sail, but also Relay 5 wich is connected to MastHead Light (white).

                        Off:
                        SMS deactivates Relay 3 & 4.
                        
            - Navigation Lights when Moored:
                        On:
                        SMS activates Relay 6, will also deactivate relay 3, 4 & 5.
                        Relay 6 will be active, wich is connected to Top Lanthern (white).

                        Off:
                        SMS deactivates Relay 6.
                        
            - Deck Flow Light:
                        On:
                        SMS activates Relay 7.

                        Off:
                        SMS deactivates Relay 7.

            - Rest of functions ar also like Deck Flow Light just on/off.....
                        
    
    To build i used an Arduino Mega, Adafruit Fona 808 shield with battery,GSM and GPS antenna, a pair of 8 channels 5 Volt RelayCards, an Waterproof DS18B20 Digital temperature sensor, and an DHT 11 Analog Temperature/Humidity Sensor.
    
       
 */



#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_SleepyDog.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>


// LED & Buzzer pins, for the GeoFence alarm. 
const int alarmpin = 7;             
const int buzzerPin = 9;

// Geofence Alarm
int counter = 0;
bool alarm = false;

// Size of the geo fence (in meters)
float maxDistance;
bool geofenceAlarm = false;

// Latitude & longitude for position and distance measurement
float initialLatitude;
float initialLongitude;
float latitude, longitude, speed_kph, heading, altitude;
float alarmstatus(0);

// settings for voltmeter
float vPow = 4.6;
float r1 = 100000;
float r2 = 22000;


#define FONA_TX 11    //using the arduino mega with fona 808 gps shield i had to change original TX/RX to this, I`we soldiered connectorcables from original pins to these on phona shield.. 
#define FONA_RX 10    //-----""------
#define FONA_RST 4
#define FONA_RI 6

#define BUSYWAIT 5000  // milliseconds

int HeaterSignal = HIGH;
int HeaterBurnerActive = HIGH;
int BurnerDelayActivated = HIGH;


float intemperature(0);
float humidity(0);
unsigned long HeaterTurnedOffTime = 0; 
const long HeaterDelayTime = 2700000;
unsigned long BurnerTermostatTime = 0; 
const long BurnerDelayTime = 120000;
float termostatTemp(0);

const int numReadings = 10;

int readings[numReadings];      // the readings from the digital temp/humidity input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int averageTemp = 0;                // the averageTemp

int inputPin = A0;


// Temperature Sensor Data wire is plugged into port 52 on the Arduino Mega
#define ONE_WIRE_BUS 52


#define DHTPIN            53         // Pin which is connected to the DHT Temperature/Humidity sensor.
//the type of sensor in use:
#define DHTTYPE           DHT11     // DHT 11 


// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);


DHT_Unified dht(DHTPIN, DHTTYPE);

uint32_t delayMS;


const int HeaterMainPowerPin = 22;  // Main power heater..          the pin that the Relay  1 is attached to
const int HeaterBurnerPowerPin = 23;  // Burner power heater..      the pin that the Relay  2 is attached to
const int Relay3Pin = 24;  // Nav Lights by Sail (Bow lantern)..    the pin that the Relay  3 is attached to
const int Relay4Pin = 25;  // Nav Lights by Sail (stern lantern)..  the pin that the Relay  4 is attached to (works always together with Relay 3, to isolate power for white lantern in mast) 
const int Relay5Pin = 26;  // Nav Lights by Engine..                the pin that the Relay  5 is attached to
const int Relay6Pin = 27;  // Nav Lights when Moored..              the pin that the Relay  6 is attached to
const int Relay7Pin = 28;  // Deck Flow Light..                     the pin that the Relay  7 is attached to
const int Relay8Pin = 29;  // Deck Cockpit Light..                  the pin that the Relay  8 is attached to
const int Relay9Pin = 30;  // Aft Cabin Light..                     the pin that the Relay  9 is attached to
const int Relay10Pin = 31; // Main Cabin Light..                    the pin that the Relay 10 is attached to
const int Relay11Pin = 32; // Main Cabin Light Port..               the pin that the Relay 11 is attached to
const int Relay12Pin = 33; // Main Cabin Light Starboard..          the pin that the Relay 12 is attached to
const int Relay13Pin = 34; // Bathroom Light..                      the pin that the Relay 13 is attached to
const int Relay14Pin = 35; // Bow Cabin Light..                     the pin that the Relay 14 is attached to
const int Relay15Pin = 36; // Function 1..                          the pin that the Relay 15 is attached to
const int Relay16Pin = 37; // Function 2..                          the pin that the Relay 16 is attached to





// this is a large buffer for replies
char replybuffer[255];

char maxDistancebuffer[30];

char sender[25];
char outmessage[250];


// or comment this out & use a hardware serial port like Serial1 (see below)
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);

Adafruit_FONA fona = Adafruit_FONA(FONA_RST);

uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);

boolean fonainit(void) {
  Serial.println(F("Initializing....(May take 3 seconds)"));




  // make it slow so its easy to read!
  fonaSS.begin(4800); // if you're using software serial
  //Serial1.begin(4800); // if you're using hardware serial

  // See if the FONA is responding
  if (! fona.begin(fonaSS)) {           // can also try fona.begin(Serial1) 
    Serial.println(F("Couldn't find FONA"));
    return false;
  }
  Serial.println(F("FONA is OK"));
  return true;
  
}

// Halt function called when an error occurs.  Will print an error and stop execution while
// doing a fast blink of the LED.  If the watchdog is enabled it will reset after 8 seconds.
void halt(const __FlashStringHelper *error) {
  Serial.println(error);
  while (1) {
    digitalWrite(alarmpin, LOW);
    delay(100);
    digitalWrite(alarmpin, HIGH);
    delay(100);
  }
}

void printFloat(float value, int places) {
  // this is used to cast digits 
  int digit;
  float tens = 0.1;
  int tenscount = 0;
  int i;
  float tempfloat = value;

    // make sure we round properly. this could use pow from <math.h>, but doesn't seem worth the import
  // if this rounding step isn't here, the value  54.321 prints as 54.3209

  // calculate rounding term d:   0.5/pow(10,places)  
  float d = 0.5;
  if (value < 0)
    d *= -1.0;
  // divide by ten for each decimal place
  for (i = 0; i < places; i++)
    d/= 10.0;    
  // this small addition, combined with truncation will round our values properly 
  tempfloat +=  d;

  // first get value tens to be the large power of ten less than value
  // tenscount isn't necessary but it would be useful if you wanted to know after this how many chars the number will take

  if (value < 0)
    tempfloat *= -1.0;
  while ((tens * 10.0) <= tempfloat) {
    tens *= 10.0;
    tenscount += 1;
  }


  // write out the negative if needed
  if (value < 0)
    Serial.print('-');

  if (tenscount == 0)
    Serial.print(0, DEC);

  for (i=0; i< tenscount; i++) {
    digit = (int) (tempfloat/tens);
    Serial.print(digit, DEC);
    tempfloat = tempfloat - ((float)digit * tens);
    tens /= 10.0;
  }

  // if no places after decimal, stop now and return
  if (places <= 0)
    return;

  // otherwise, write the point and continue on
  Serial.print('.');  

  // now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
  for (i = 0; i < places; i++) {
    tempfloat *= 10.0; 
    digit = (int) tempfloat;
    Serial.print(digit,DEC);  
    // once written, subtract off that digit
    tempfloat = tempfloat - (float) digit; 
  }
}

// Calculate distance between two points
float distanceCoordinates(float flat1, float flon1, float flat2, float flon2) {

  // Variables
  float dist_calc=0;
  float dist_calc2=0;
  float diflat=0;
  float diflon=0;

  // Calculations
  diflat  = radians(flat2-flat1);
  flat1 = radians(flat1);
  flat2 = radians(flat2);
  diflon = radians((flon2)-(flon1));

  dist_calc = (sin(diflat/2.0)*sin(diflat/2.0));
  dist_calc2 = cos(flat1);
  dist_calc2*=cos(flat2);
  dist_calc2*=sin(diflon/2.0);
  dist_calc2*=sin(diflon/2.0);
  dist_calc +=dist_calc2;

  dist_calc=(2*atan2(sqrt(dist_calc),sqrt(1.0-dist_calc)));
  
  dist_calc*=6371000.0; //Converting to meters

  return dist_calc;
}


void setup() {
  while (!Serial);  // useful for Leonardo/Micro, remove in production!


  // initialize the pins as an output:
  pinMode(HeaterMainPowerPin, OUTPUT);
  pinMode(HeaterBurnerPowerPin, OUTPUT);
  pinMode(Relay3Pin, OUTPUT);
  pinMode(Relay4Pin, OUTPUT);
  pinMode(Relay5Pin, OUTPUT);
  pinMode(Relay6Pin, OUTPUT);
  pinMode(Relay7Pin, OUTPUT);
  pinMode(Relay8Pin, OUTPUT);
  pinMode(Relay9Pin, OUTPUT);
  pinMode(Relay10Pin, OUTPUT);
  pinMode(Relay11Pin, OUTPUT);
  pinMode(Relay12Pin, OUTPUT);
  pinMode(Relay13Pin, OUTPUT);
  pinMode(Relay14Pin, OUTPUT);
  pinMode(Relay15Pin, OUTPUT);
  pinMode(Relay16Pin, OUTPUT);

  // Set alarm components
  pinMode(alarmpin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  alarm = false;
  geofenceAlarm = false;




  // Set all pins High from the start, (Relays are active when pin is low, this to set all relays inactive).
  digitalWrite(HeaterMainPowerPin, HIGH);
  digitalWrite(HeaterBurnerPowerPin, HIGH);
  digitalWrite(Relay3Pin, HIGH);
  digitalWrite(Relay4Pin, HIGH);
  digitalWrite(Relay5Pin, HIGH);
  digitalWrite(Relay6Pin, HIGH);
  digitalWrite(Relay7Pin, HIGH);
  digitalWrite(Relay8Pin, HIGH);
  digitalWrite(Relay9Pin, HIGH);
  digitalWrite(Relay10Pin, HIGH);
  digitalWrite(Relay11Pin, HIGH);
  digitalWrite(Relay12Pin, HIGH);
  digitalWrite(Relay13Pin, HIGH);
  digitalWrite(Relay14Pin, HIGH);
  digitalWrite(Relay15Pin, HIGH);
  digitalWrite(Relay16Pin, HIGH);

    // Start up the library for Temperature Sensor
  sensors.begin();  

    // Start up the library for Temperature/Humidity Sensor

    dht.begin();

  
  Serial.begin(115200);
  Serial.println(F("FONA basic test"));

  while (! fonainit()) {
    delay(5000);
  }
  
  // Print SIM card IMEI number.
  char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
  uint8_t imeiLen = fona.getIMEI(imei);
  if (imeiLen > 0) {
    Serial.print("SIM card IMEI: "); Serial.println(imei);
  }
  
  pinMode(FONA_RI, INPUT);
  digitalWrite(FONA_RI, HIGH); // turn on pullup on RI
  // turn on RI pin change on incoming SMS!
  fona.sendCheckReply(F("AT+CFGRI=1"), F("OK"));


int8_t lastsmsnum = 0;


// Use the watchdog to simplify retry logic and make things more robust.
  // Enable this after FONA is intialized because FONA init takes about 8-9 seconds.
//  Watchdog.enable(8000);
 // Watchdog.reset();

  // Enable GPS.
  fona.enableGPS(true);

  // Wait a little bit to stabilize the connection.
 // Watchdog.reset();
 // delay(3000);

//Make Geofence Alarm distance to be 100 or more to ensure poor GPS accuracy wont set off alarm. 
 if (maxDistance > 99)
{
  maxDistance = maxDistance;
}
else
{
  maxDistance = 100;
}



  // Initial GPS read
  bool gpsFix = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);
  initialLatitude = 60.352402;
  initialLongitude = 4.989827;

  alarmstatus = 0;


  // Init counter
  counter = millis();


  


  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
/*  Serial.println("------------------------------------");
  Serial.println("Temperature");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" *C");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" *C");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" *C");  
  Serial.println("------------------------------------");*/
  // Print humidity sensor details.
  dht.humidity().getSensor(&sensor);
 /* Serial.println("------------------------------------");
  Serial.println("Humidity");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println("%");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println("%");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println("%");  
  Serial.println("------------------------------------"); */
  // Set delay between sensor readings based on sensor details.
  delayMS = sensor.min_delay / 1000;

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}


void loop() {


 // Watchdog reset at start of loop--make sure everything below takes less than 8 seconds in normal operation!
  Watchdog.reset();

  // Grab a GPS reading.
  float latitude, longitude, speed_kph, heading, altitude;
  bool gpsFix = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);

  Serial.print("Latitude: ");
  printFloat(latitude, 6);
  Serial.println("");

  Serial.print("Longitude: ");
  printFloat(longitude, 6);
  Serial.println("");

  Serial.print("Initial latitude: ");
  printFloat(initialLatitude, 6);
  Serial.println("");

  Serial.print("Initial longitude: ");
  printFloat(initialLongitude, 6);
  Serial.println("");

  // Calculate distance between new & old coordinates
  float distance = distanceCoordinates(latitude, longitude, initialLatitude, initialLongitude);
  
  Serial.print("Distance: ");
  printFloat(distance, 6);
  Serial.println("");



  Serial.print("GeoFence distance: ");
  printFloat(maxDistance, 0);
  Serial.println("");

  //Temperature/Humiditysensor readings

  //delay(delayMS);
  // Get temperature event and print its value.
  sensors_event_t event;  
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println("Error reading temperature!");
  }
  else {
    Serial.print("Temperature: ");
    Serial.print(event.temperature);
    Serial.println(" *C");
    intemperature = event.temperature;

  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
  }
  else {
    Serial.print("Humidity: ");
    Serial.print(event.relative_humidity);
    Serial.println("%");
    humidity = event.relative_humidity;
  }

Serial.println ("Current");   
Serial.println (millis());
Serial.println ("Previous");   
Serial.println (BurnerTermostatTime);
Serial.println ("HeaterBurnerActive");
Serial.println (HeaterBurnerActive);
Serial.println (termostatTemp);
Serial.println ("GeofenceAlarm");
Serial.println (alarmstatus);

/*  Heater Delay settings description:
    When SMS is recieved with messaage to activate heater, HeaterBurnerPowerPin is set to LOW & "HeaterSignal" is set to LOW (My Relaycards used is kind of backwards where LOW = Relay Active so to keep this part of code easyer to understand "HeaterSignal" LOW also = Active).

    HeaterSignal = Tells if recieved message has activated heater or not.
    HeaterTurnedOffTime = the milliscounters reading at the time heater is turned off.
    HeaterDelayTime = The settings (in millis) for how long mainpower should be active to let heater cool down.
    HeaterBurnerActive = Tells that burner has been activated.
    BurnerTermostatTime = the milliscounters reading at the time the termostatsettings switches burner off.
    BurnerDelayTime = Defined at top of scetch to be 120 000 millis/2 minutes.
    BurnerDelayActivated = Tells if the delayfunction has been activated.
    
     
*/
       if ((HeaterSignal == HIGH)  && (millis() - HeaterTurnedOffTime > HeaterDelayTime)) {                                           // if you hawe turnd heater off & the HeaterDelayTime has passed 
         digitalWrite(HeaterMainPowerPin, HIGH);                                                                                      // HeaterMainPowerPin (mainpower to heater) will be switched off. This function lets the heater keep blowing to cool down.
   }

   //Termostat functions for heater


      if ((HeaterBurnerActive == LOW) && (BurnerDelayActivated == LOW) && (millis() - BurnerTermostatTime > BurnerDelayTime)) {       // If burner has been activated & BurnerDelay has been activated & delaytime has been reached 
           digitalWrite(HeaterBurnerPowerPin, HIGH);                                                                                  // this turns off the burner
           HeaterBurnerActive = HIGH;                                                                                                 // burner is no longer active
         BurnerDelayActivated = HIGH;                                                                                                 // burner delay is no longer active

   }

         if ((HeaterSignal == LOW) && (averageTemp < termostatTemp)) {                                                                // If you have turned heater on, and average temperature is lower than selected termostat temperature
            digitalWrite(HeaterBurnerPowerPin, LOW);                                                                                  // Burner gets activated, (Main power already got activated when SMS was recieved).
            HeaterBurnerActive = LOW;                                                                                                 // Tells that burner has been activated.
            BurnerDelayActivated = HIGH;                                                                                               // Tells that the burner delay has not been activated.
       }       
       
        if ((HeaterBurnerActive == LOW) && (BurnerDelayActivated == HIGH) && (averageTemp > termostatTemp)) {                          // If the burner has been activated & the burner delay function has not & selected termostat temperature has been reached 
            BurnerTermostatTime = millis();                                                                                           // this saves the millis counter time when selected temperature was reached.
            BurnerDelayActivated = LOW;                                                                                                // this tells that burnerdelay has been activated (secures that the burner is active for at least 2 minutes at time)

      }

        total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = intemperature;
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the averageTemp:
  averageTemp = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(averageTemp);
  delay(1);        // delay in between reads for stability


//Voltmeter functions
float v = (analogRead(10) * vPow) / 1024.0;
float v2 = v / (r2 / (r1 + r2));

Serial.println("Volt:");
Serial.println(v2);

  // Set alarm on?
  
  if ((distance > maxDistance) && (geofenceAlarm == true)) {
    alarm = true;
    alarmstatus = 1;

    

        if (!fona.sendSMS(sender, outmessage)) {
          Serial.println(F("Alarm Failed"));
        } else {
          Serial.println(F("Alarm Sent!"));
        initialLatitude = latitude;
        initialLongitude = longitude;
        alarmstatus = 0;  
        }
        
  }

    else {
          alarm = false;
          alarmstatus = 0;  
    }
  
  // Handle alarm
  if (alarm == false) {
        alarmstatus = 0;

    if (millis() - counter > 5000) {
      digitalWrite(alarmpin, HIGH);

    }

     if (millis() - counter > 5100) {
      digitalWrite(alarmpin, LOW);
      counter = millis();
    }

    noTone(buzzerPin);
    
  } 
  else {
        
    if (millis() - counter > 100) {
      digitalWrite(alarmpin, HIGH);
  
    }

     if (millis() - counter > 200) {
      digitalWrite(alarmpin, LOW);
      counter = millis();
    }
  
    tone(buzzerPin, 1000);

  }
  

//   digitalWrite(LED, HIGH);
//   delay(100);
//   digitalWrite(LED, LOW);
       
  while (fona.getNetworkStatus() != 1) {
    Serial.println("Waiting for cell connection");
    delay(2000);
  }
  
  // this is a 'busy wait' loop, we check if the interrupt
  // pin went low, and after BUSYWAIT milliseconds break out to check
  // manually for SMS's and connection status
  // This would be a good place to 'sleep'
  for (uint16_t i=0; i<BUSYWAIT; i++) {
     if (! digitalRead(FONA_RI)) {
        // RI pin went low, SMS received?
        Serial.println(F("RI went low"));
        break;
     } 
     delay(1);
  }
  
  int8_t smsnum = fona.getNumSMS();
  if (smsnum < 0) {
    Serial.println(F("Could not read # SMS"));
    return;
  } else {
    Serial.print(smsnum); 
    Serial.println(F(" SMS's on SIM card!"));
  }
  
  if (smsnum == 0) return;


  


  // there's an SMS!
  uint8_t n = 1; 
  while (true) {
     uint16_t smslen;
     
     Serial.print(F("\n\rReading SMS #")); Serial.println(n);
     uint8_t len = fona.readSMS(n, replybuffer, 250, &smslen); // pass in buffer and max len!
     // if the length is zero, its a special case where the index number is higher
     // so increase the max we'll look at!
     if (len == 0) {
        Serial.println(F("[empty slot]"));
        n++;
        continue;
     }
     if (! fona.getSMSSender(n, sender, sizeof(sender))) {
       // failed to get the sender?
       sender[0] = 0;
     }

     
     Serial.print(F("***** SMS #")); Serial.print(n);
     Serial.print(" ("); Serial.print(len); Serial.println(F(") bytes *****"));
     Serial.println(replybuffer);
     Serial.print(F("From: ")); Serial.println(sender);
     Serial.println(F("*****"));

       String stringInSMS = (replybuffer);
  Serial.println(stringInSMS);

// Recieving message, Remember due to how Relaycard is made i had to use pinout LOW for relay active and High for Relay off.
     
    if (stringInSMS.substring(0, 2) == "A1") {
       digitalWrite(HeaterMainPowerPin, LOW);                               // Heater gets main power, burner will only get activated if temperature is lower than selected thermostat settings
       HeaterSignal = LOW;                                                  // tells other parts of scetch that heater is activated
       }
    if (stringInSMS.substring(0, 2) == "A0") {
       digitalWrite(HeaterBurnerPowerPin, HIGH);
       HeaterSignal = HIGH;
       HeaterTurnedOffTime = millis();  
       }


       
    if (stringInSMS.substring(2, 4) == "B1") {
       digitalWrite(Relay3Pin, LOW); 
       digitalWrite(Relay4Pin, LOW); 
     }    
    if (stringInSMS.substring(2, 4) == "B0") {
       digitalWrite(Relay3Pin, HIGH); 
       digitalWrite(Relay4Pin, HIGH); 
     } 


     
    if (stringInSMS.substring(4, 6) == "C1") {
       digitalWrite(Relay5Pin, LOW); 
     }
    if (stringInSMS.substring(4, 6) == "C0") {
       digitalWrite(Relay5Pin, HIGH); 
     }



    if (stringInSMS.substring(6, 8) == "D1") {
       digitalWrite(Relay6Pin, LOW);      
       }
    if (stringInSMS.substring(6, 8) == "D0") {
       digitalWrite(Relay6Pin, HIGH); 
       }


     
    if (stringInSMS.substring(8, 10) == "E1") {
       digitalWrite(Relay7Pin, LOW); 
     }
    if (stringInSMS.substring(8, 10) == "E0") {
       digitalWrite(Relay7Pin, HIGH); 
     }     



    if (stringInSMS.substring(10, 12) == "F1") {
       digitalWrite(Relay8Pin, LOW); 
     }
    if (stringInSMS.substring(10, 12) == "F0") {
       digitalWrite(Relay8Pin, HIGH); 
     }



    if (stringInSMS.substring(12, 14) == "G1") {
       digitalWrite(Relay9Pin, LOW);      
       }
    if (stringInSMS.substring(12, 14) == "G0") {
       digitalWrite(Relay9Pin, HIGH); 
       }


     
    if (stringInSMS.substring(14, 16) == "H1") {
       digitalWrite(Relay10Pin, LOW); 
     }
    if (stringInSMS.substring(14, 16) == "H0") {
       digitalWrite(Relay10Pin, HIGH); 
     }     


    if (stringInSMS.substring(16, 18) == "I1") {
       digitalWrite(Relay11Pin, LOW); 
     }     
    if (stringInSMS.substring(16, 18) == "I0") {
       digitalWrite(Relay11Pin, HIGH); 
     }


        
    if (stringInSMS.substring(18, 20) == "J1") {     
       digitalWrite(Relay12Pin, LOW);
      }
     
    if (stringInSMS.substring(18, 20) == "J0") {
       digitalWrite(Relay12Pin, HIGH);       
      } 


     
    if (stringInSMS.substring(20, 22) == "K1") {
       digitalWrite(Relay13Pin, LOW); 
     }
     
    if (stringInSMS.substring(20, 22) == "K0") {
       digitalWrite(Relay13Pin, HIGH); 
     }     


    if (stringInSMS.substring(22, 24) == "L1") { 
       digitalWrite(Relay14Pin, LOW);
      }
    if (stringInSMS.substring(22, 24) == "L0") {
       digitalWrite(Relay14Pin, HIGH);      
     }



    if (stringInSMS.substring(24, 26) == "M1") {
       digitalWrite(Relay15Pin, LOW); 
     }
    if (stringInSMS.substring(24, 26) == "M0") {
       digitalWrite(Relay15Pin, HIGH); 
     }



    if (stringInSMS.substring(26, 28) == "N1") {
       digitalWrite(Relay16Pin, LOW);      
       }
    if (stringInSMS.substring(26, 28) == "N0") {
       digitalWrite(Relay16Pin, HIGH); 
       }    


    if (stringInSMS.substring(28, 30) == "Q1") {
        geofenceAlarm = true;
     }
     
    if (stringInSMS.substring(28, 30) == "Q0") {
        geofenceAlarm = false;
     }

    if (stringInSMS.substring(30, 32) == "S1") {
       initialLatitude = latitude;
       initialLongitude = longitude;
     }

     termostatTemp = (stringInSMS.substring(32, 34).toFloat());

     maxDistance = (stringInSMS.substring(34).toFloat());

//String stringOutSMS = String(("A1"),(bitRead(PORTA,0)),("|"),("A2"),(bitRead(PORTA,1)),("|"));

  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  sensors.requestTemperatures(); // Send the command to get temperatures


        
    String string1 = ("A");                                   // Refers to Relay 1 
    String string2 = String(bitRead(PORTA,0));                // To check pinstatus HIGH or LOW (returns 1 or 0) 
    String string3 = ("|B");                                  // the | makes an marker for App to know where to split Serial info, then the B refers to Relay 2.
    String string4 = String(bitRead(PORTA,1));                // To check pinstatus HIGH or LOW (returns 1 or 0)
    String string5 = ("|C");                                  // And so on....
    String string6 = String(bitRead(PORTA,2));
    String string7 = ("|D");
    String string8 = String(bitRead(PORTA,4));
    String string9 = ("|E");
    String string10 = String(bitRead(PORTA,5));
    String string11 = ("|F");
    String string12 = String(bitRead(PORTA,6));
    String string13 = ("|G");
    String string14 = String(bitRead(PORTA,7));
    String string15 = ("|H");
    String string16 = String(bitRead(PORTC,7));
    String string17 = ("|I");
    String string18 = String(bitRead(PORTC,6));
    String string19 = ("|J");
    String string20 = String(bitRead(PORTC,5));
    String string21 = ("|K");
    String string22 = String(bitRead(PORTC,4));
    String string23 = ("|L");
    String string24 = String(bitRead(PORTC,3));   // pin 34
    String string25 = ("|M");
    String string26 = String(bitRead(PORTC,2));
    String string27 = ("|N");
    String string28 = String(bitRead(PORTC,1));
    String string29 = ("|O");
    String string30 = String(bitRead(PORTC,0));     // TO BE REMOVED!!!
    String string31 = ("|");
    String string32 = String(sensors.getTempCByIndex(0));       //To read outside temperature..
    String string33 = ("|");
    String string34 = String(latitude, 6); 
    String string35 = ("|");
    String string36 = String(longitude, 6); 
    String string37 = ("|");
    String string38 = String(initialLatitude, 6); 
    String string39 = ("|");
    String string40 = String(initialLongitude, 6); 
    String string41 = ("|");
    String string42 = String(alarmstatus, 0);
    String string43 = ("|");
    String string44 = String(averageTemp);       //To read innside temperature..
    String string45 = ("|");
    String string46 = String(humidity, 0);       //To read innside Humidity..
    String string47 = ("|");
    String string48 = String(v2, 2);       //To read battery voltage..
    String string49 = ("|");


        // Connect all the strings to one long string
    String stringout = string1 + string2 + string3 + string4 + string5 + string6 + string7 + string8 + string9 + string10 + string11 + string12 + string13 + string14 + string15 + string16 + string17 + string18 + string19 + string20 + string21 + string22 + string23 + string24 + string25 + string26 + string27 + string28 + string29 + string30 + string31 + string32 + string33 + string34 + string35 + string36 + string37 + string38 + string39 + string40 + string41 + string42 + string43 + string44 + string45 + string46 + string47 + string48 + string49;




    stringout.toCharArray(outmessage,249);
    
    Serial.println (outmessage);

      
            if (!fona.sendSMS(sender, outmessage)) {
          Serial.println(F("Failed"));
        } else {
          Serial.println(F("Sent!"));
        }
    
/*  

*/
      
     delay(3000);
     break;
  }  
  fona.deleteSMS(n);
 
  delay(1000); 


     }

Credits

asbjorn

asbjorn

1 project • 7 followers

Comments