//Libraries
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <SoftwareSerial.h>
//Constants for Temperature Sensors
#define DHTPIN1 11 // what pin Sensor 1 is connected to
#define DHTPIN2 12 // what pin Sensor 2 is connected to
#define DHTTYPE DHT22 // Selecting DHT 22 as the sensor type
//Constants for Waveshare Module
#define GSM_TX_PIN 26 // Arduino Tx to Waveshare Rx
#define GSM_RX_PIN 24 // Arduino Rx to Waveshare Tx
#define GSM_POWERKEY_PIN 22 // Pin to power on the Waveshare GSM Module
#define PULSE_DURATION 100 // Duration of the power pulse in milliseconds
// Initialize DHT Sensor 1 & 2
DHT dht_1(DHTPIN1, DHTTYPE);
DHT dht_2(DHTPIN2, DHTTYPE);
// Initialize SoftwareSerial
SoftwareSerial gsmSerial(GSM_RX_PIN, GSM_TX_PIN);
// Initialize LCD Dislay
LiquidCrystal_I2C lcd(0x27, 20, 4);
//==========Creating Battery Percentage Graphic==========
//btyes for empty battery cells
byte batt_back_empty[] = { B01111, B10000, B10000, B10000, B10000, B10000, B10000, B01111 };
byte batt_body_empty[] = { B11111, B00000, B00000, B00000, B00000, B00000, B00000, B11111 };
byte batt_head_empty[] = { B11110, B00010, B00011, B00001, B00001, B00011, B00010, B11110 };
//bytes for filled battery cells
byte batt_back_full[] = { B01111, B10000, B10111, B10111, B10111, B10111, B10000, B01111 };
byte batt_body_full[] = { B11111, B00000, B11111, B11111, B11111, B11111, B00000, B11111 };
byte batt_head_full[] = { B11110, B00010, B11011, B11101, B11101, B11011, B00010, B11110 };
//=======================================================
//----------Variables-----------------------------------------------------------------------
//Variables for Predetermined Parameters
float LowOpTemp = 15.0;
float HighOpTemp = 85.0;
float CritLowTemp = 0.0;
float CritHighTemp = 100.0;
float HumOp = 100.0;
//Variables for Compared Temp & Humidity Values
float LowTemp, HighTemp, hum;
//Variables for LCD Top Row Display
int heating, cooling, critheating, critcooling, humremover;
//Variables for BatteryRunTime
const int Day_to_Min = 2;
int DayCount, BRTVar, BAOnOff;
float MinVal, TimeSet, TimeSet_Day, Time_Left, Time_Left_Til_Loop;
boolean DayOnOff;
//Variables for setting values in battery parameter function
boolean no_load = true;
boolean offset_skipper = false;
//Variables for Remote Control of Device***************************************************************************
// Variable for user's phone number
String phoneNumber = "+18143892833"; // IMPORTANT: This is the phone number that the GSM will send messages to.
// Edit this number if you wish to change it. Ex. "+1XXXXXXXXXX".
String recentSMS; // Global variable to store the most recent read SMS message
String lastMessage = ""; // Variable to store the last SMS message (clears out within function)
volatile bool menuChoice = false; // Flag to indicate new SMS
//*****************************************************************************************************************
//------------------------------------------------------------------------------------------
//`````Setting Pins```````````````````````````````````````````````
//Seting pins for Heater Plate and Case Fan Transistors
const int HPTPIN = 10;
const int CFTPIN = 9;
//Setting pin for solenoid relay
const int RelayPIN = 8;
//Setting pins for input buttons (2 == GND) (Wired as Keypad)
const int LeftButton = 5;
const int RightButton = 4;
const int EnterButton = 3;
//````````````````````````````````````````````````````````````````
// Variable for choosing what menu funtion the user is on
int MenuVar;
//~~~~~~~~~~~~~~~~~~~~~~~~LOCAL CONTROL FUNCTIONS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void startUp() {
/* This Function is Used to Initially Set O/P Pins for Heating and Cooling Transistors and Run Time Relay */
digitalWrite(HPTPIN, LOW); // Set voltage of pin 8 to 0V
digitalWrite(CFTPIN, LOW); // Set voltage of pin 9 to 0V
digitalWrite(RelayPIN, HIGH); // Set voltage of pin 10 to 5V
// These eight lines are used to display startup message on LCD
lcd.setCursor(0, 0);
lcd.print(" Portable Power ");
lcd.setCursor(0, 1);
lcd.print(" Station ");
lcd.setCursor(0, 2);
lcd.print(" Sr Design Project ");
lcd.setCursor(0, 3);
lcd.print(" Penn State Behrend ");
// Send 'AT' to GSM to confirm it is turned on
Serial.println("Sending AT command...");
gsmSerial.println("AT");
delay(1000);
// While loop to make sure that the GSM is on before continuing
unsigned long startTime = millis(); // Record the start time
while (!gsmSerial.find("OK")) { // Check if the module is ready
gsmSerial.println("AT");
// Check if too much time has passed since starting
if (millis() - startTime >= 15000) {
Serial.println("No Response, resending pulse and AT command...");
digitalWrite(GSM_POWERKEY_PIN, HIGH);
delay(PULSE_DURATION);
digitalWrite(GSM_POWERKEY_PIN, LOW);
startTime = millis(); // Reset the start time
}
delay(100); // Delay before retrying
}
// Confirming communication was established
Serial.println("Waveshare module is ready!");
// Clear Interrupt Flag
EIFR = 0x02;
// Attach interrupt to trigger on receiving SMS
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING);
delay(1500);
}
void setup() {
//This is the setup code, which is only ran once during the initial powering of the Arduino
Serial.begin(115200);
// Start serial communication with GSM module
gsmSerial.begin(9600);
//Start & Initialize Sensor 1 & 2
dht_1.begin();
dht_2.begin();
//Setting pins to O/P Heater Plate and Case Fan Transistors
pinMode(HPTPIN, OUTPUT);
pinMode(CFTPIN, OUTPUT);
// Setting Pin for turning on GSM Module to O/P
pinMode(GSM_POWERKEY_PIN, OUTPUT);
// Power on the Waveshare module by providing a pulse
digitalWrite(GSM_POWERKEY_PIN, HIGH);
delay(PULSE_DURATION);
digitalWrite(GSM_POWERKEY_PIN, LOW); // Set the pin back to low
//Setting pins to I/P for input buttons (INPUT_PULLUP means that the code will be looking for LOW on these pins)
pinMode(LeftButton, INPUT_PULLUP);
pinMode(RightButton, INPUT_PULLUP);
pinMode(EnterButton, INPUT_PULLUP);
pinMode(2, OUTPUT);
//Setting pin for O/P for solenoid relay
pinMode(RelayPIN, OUTPUT);
//initialize LCD & turn on backlight
lcd.init();
lcd.backlight();
startUp();
}
void checkTime() {
/* This function is for checking if power tranmission should be allowed, along with counting how long
the power transmission should be active for*/
float SysMin;
if (BAOnOff == 1) { // This if statement covers all of this code to make sure that battery run time is activated
if (DayOnOff) { // This if statement checks if the time duration should loop over multiple days
SysMin = (float)millis();
SysMin = (SysMin / 60000);
if (SysMin >= TimeSet_Day) { // If statement for if the system run time is longer than the set time for a day
DayCount--;
if (DayCount == 0) { // If statement to false-ify the DayOnOff boolean when the days should no longer loop
DayOnOff = false;
} else { // This else statement is if DayCount > 1. It sets the new time for a day to loop and sets the run time duration again
Serial.println("Went in Here");
SysMin = (float)millis();
SysMin = (SysMin / 60000);
TimeSet_Day = SysMin + Day_to_Min;
TimeSet = SysMin + MinVal;
}
}
else { // This code runs if SysMin < TimeSet_Day and lets the system see if power tranmsission is allowed.
SysMin = (float)millis();
SysMin = (SysMin / 60000);
if ((critcooling == 0) && (critheating == 0)) { // If the critical systems are off, then the relay's state can be changed.
if (TimeSet >= SysMin) { // If there is time still remaining, power transmission is allowed
digitalWrite(RelayPIN, HIGH); // Set voltage of pin 10 to 5V
Serial.println(SysMin);
} else if (TimeSet < SysMin) { // If there is no time left, then power tranmission is blocked
digitalWrite(RelayPIN, LOW); // Set voltage of pin 10 to 0V
}
}
}
}
else { // This code runs if DayOnOff has not been activated (i.e., the duration only happens once)
SysMin = (float)millis();
SysMin = (SysMin / 60000);
if ((critcooling == 0) && (critheating == 0)) { // If the critical systems are off, then the relay's state can be changed.
if (TimeSet >= SysMin) { // If there is time still remaining, power transmission is allowed
digitalWrite(RelayPIN, HIGH); // Set voltage of pin 10 to 5V
Serial.println(SysMin);
} else if (TimeSet < SysMin) { // If there is no time left, then power tranmission is blocked
digitalWrite(RelayPIN, LOW); // Set voltage of pin 10 to 0V
}
}
}
}
}
void BRTActivator() {
/* This Function is Used to Turn On and Off the Functionality of a Power Delay*/
if (BAOnOff == 0) { // If statement checking state of Battery Activation On/Off Value (Off State)
BAOnOff = 1; // Flips the state of the Battery Activation On/Off Value
lcd.setCursor(0, 1); // These Six lines are used to show Function is Activated
lcd.print(" Battery Run Time ");
lcd.setCursor(0, 2);
lcd.print(" Activated! ");
lcd.setCursor(0, 3);
lcd.print("You Can Now Set Time");
delay(1000);
return;
} else if (BAOnOff == 1) { // If statement checking state of Battery Activation On/Off Value (Off State)
BAOnOff = 0; // Flips the state of the Battery Activation On/Off Value
lcd.setCursor(0, 1); // These Six lines are used to show Function is Deactivated
lcd.print(" Battery Run Time ");
lcd.setCursor(0, 2);
lcd.print(" Deactivated! ");
lcd.setCursor(0, 3);
lcd.print(" ");
digitalWrite(RelayPIN, HIGH); // Set voltage of pin 10 to 5V
delay(1000);
return;
}
}
void BRTTimeSetter() {
//Local variables for finding the hour value and the system's time in minutes
float HrVal, SysMin;
int DayVal = 0;
MinVal = 0;
HrVal = 0;
lcd.setCursor(0, 1);
lcd.print("Use < > to set value");
lcd.setCursor(0, 2);
lcd.print("Use * to confirm ");
if (BAOnOff == !0) {
BRTVar = 1;
while (BRTVar == 1) {
// This first while loop is for setting the minute value between 0 and 60
lcd.setCursor(0, 3);
lcd.print(String("Minutes?: ") + String((int)MinVal) + String(" ")); // Display minute value on LCD
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(250);
if (MinVal < 1) {
} else {
MinVal--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(250);
if (MinVal > 59) {
} else {
MinVal++;
}
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(250);
BRTVar = 2;
}
}
while (BRTVar == 2) {
// This second while loop is for setting the hour value between 0 and 24 hours
lcd.setCursor(0, 3);
lcd.print(String("Hours?: ") + String((int)HrVal) + String(" ")); // Display hour value on LCD
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(250);
if (HrVal < 1) {
} else {
HrVal--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(250);
if (HrVal > 23) {
} else {
HrVal++;
}
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(250);
BRTVar = 3;
}
}
// If the user did not enter a time value (as in 0's for minutes and hours), then the code will tell the user that
// they entered an invalid time, and will return to the main menu
if ((MinVal == 0) && (HrVal == 0)) {
lcd.setCursor(0, 1);
lcd.print("Invalid Selection! ");
lcd.setCursor(0, 2);
lcd.print("Min & Hr Values Cant");
lcd.setCursor(0, 3);
lcd.print("Be Zero! Restarting.");
BRTVar = 0;
return;
}
// This clears the lcd lines so there is no leftover text for upcoming messages
else {
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(" ");
}
while (BRTVar == 3) {
// This third while loop is for the user to confirm they entered the correct time into the system
lcd.setCursor(0, 1);
lcd.print(String((int)HrVal) + String(" Hr(s) ")); // Display hour value on LCD
lcd.setCursor(0, 2);
lcd.print(String((int)MinVal) + String(" Min(s) ")); // Display minute value on LCD
lcd.setCursor(0, 3);
lcd.print("Yes?( * ) Back?( < )"); // Display Request for User Input on LCD
if (digitalRead(EnterButton) == LOW) { // If statement to move onto next while loop
BRTVar = 4;
lcd.setCursor(0, 1); // These six lines are used to show user the duration was accepted
lcd.print(" Duration ");
lcd.setCursor(0, 2);
lcd.print(" Accepted! ");
lcd.setCursor(0, 3);
lcd.print(" ");
delay(500);
}
if (digitalRead(LeftButton) == LOW) { // If statement to cancel the entered time values
lcd.setCursor(0, 1); // These six lines are used to show user they cancelled the set time
lcd.print(" Time Cancelled! ");
lcd.setCursor(0, 2);
lcd.print("Now Returning to the");
lcd.setCursor(0, 3);
lcd.print(" Main Menu ");
delay(500);
BRTVar = 0;
return; // Used to leave function (since code got stuck in here before)
}
}
while (BRTVar == 4) {
// This fourth while loop is used to see if the user will have the duration repeat over multiple days
lcd.setCursor(0, 1);
lcd.print("Should this repeat ");
lcd.setCursor(0, 2);
lcd.print("over multiple days? ");
lcd.setCursor(0, 3);
lcd.print("No?( < ) Yes?( * )");
if (digitalRead(LeftButton) == LOW) { // If statement to exit the function
DayOnOff = false;
MinVal = (HrVal / 60) + MinVal;
SysMin = (float)millis();
SysMin = (SysMin / 60000);
TimeSet = MinVal + SysMin;
DayCount = 0;
lcd.setCursor(0, 1);
lcd.print(" Only For 1 Day ");
lcd.setCursor(0, 2);
lcd.print("Now Returning to the");
lcd.setCursor(0, 3);
lcd.print(" Main Menu ");
delay(500);
return;
}
if (digitalRead(EnterButton) == LOW) { // If statement to move to next while loop
BRTVar = 5;
}
}
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("Use < > to set value");
lcd.setCursor(0, 2);
lcd.print("Use * to confirm ");
while (BRTVar == 5) {
// This fifth while loop is for the user to enter the amount of days that they would like the duration to loop for
lcd.setCursor(0, 3);
lcd.print(String("Days?: ") + String((int)DayVal) + String(" "));
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
Serial.println("Left Was Pressed");
delay(250);
if (DayVal < 1) {
} else {
DayVal--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
Serial.println("Right Was Pressed");
delay(250);
if (DayVal > 10) {
} else {
DayVal++;
}
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(250);
BRTVar = 6;
}
}
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(" ");
while (BRTVar == 6) {
// This sixth loop is for the user to confirm the total time (in minutes) and the total days the duration will loop for
MinVal = (HrVal / 60) + MinVal;
lcd.setCursor(0, 1);
lcd.print(String((int)MinVal) + String(" Min(s) ")); // Display hour value on LCD
lcd.setCursor(0, 2);
lcd.print(String((int)DayVal) + String(" Day(s) ")); // Display minute value on LCD
lcd.setCursor(0, 3);
lcd.print("Yes?( * ) Back?( < )");
if (digitalRead(EnterButton) == LOW) { // If statement to accept the time duration and day loop value
lcd.setCursor(0, 1); // These six lines are used to show user the duration was accepted
lcd.print(" Duration and Days ");
lcd.setCursor(0, 2);
lcd.print(" Accepted! ");
lcd.setCursor(0, 3);
lcd.print(" Returning to Menu! ");
delay(750);
DayOnOff = true;
MinVal = (HrVal / 60) + MinVal;
SysMin = (float)millis();
SysMin = (SysMin / 60000);
TimeSet = MinVal + SysMin;
DayCount = (int)DayVal;
DayVal = DayVal * Day_to_Min;
TimeSet_Day = Day_to_Min + SysMin;
BRTVar = 0;
return;
}
if (digitalRead(LeftButton) == LOW) { // If statement to cancel the user's time values and day loop value
DayOnOff = false;
lcd.setCursor(0, 1); // These six lines are used to show user they cancelled the set time
lcd.print(" Time Cancelled! ");
lcd.setCursor(0, 2);
lcd.print("Now Returning to the");
lcd.setCursor(0, 3);
lcd.print(" Main Menu ");
delay(500);
BRTVar = 0;
return; // Used to leave function (since code got stuck in here before)
}
}
} else { // This statement runs if BAOnOff is 0 (meaning that the user did not activate the battery run time function)
lcd.setCursor(0, 1); // These Six lines are used to show Function Cant Be Ran
lcd.print("Battery Run Time ");
lcd.setCursor(0, 2);
lcd.print("Is Off! Returning ");
lcd.setCursor(0, 3);
lcd.print("to Main Menu ");
delay(1000);
return;
}
}
void collectTemp() {
float temp1, temp2;
/* This Function is Used to Collect the Temperature Values */
//Read data, convert, & store to temp variables
temp1 = (dht_1.readTemperature() * (9.0 / 5.0)) + 32;
temp2 = (dht_2.readTemperature() * (9.0 / 5.0)) + 32;
//Store Highest and Lowest Temp Values
if (temp1 > temp2) {
HighTemp = temp1;
LowTemp = temp2;
} else {
HighTemp = temp2;
LowTemp = temp1;
}
}
void collectHumidity() {
float hum1, hum2;
/* This Function is Used to Collect the Temperature Values */
//Read data & store to hum
hum1 = dht_1.readHumidity();
hum2 = dht_2.readHumidity();
//Store Highest Humidity Value
if (hum1 > hum2) {
hum = hum1;
} else {
hum = hum2;
}
}
void TempnHumViewer() {
/* This function allows the user to see the temperature and humidity values updating in real time */
while (true) {
// This checks if the battery activation function is on.
if (BAOnOff == 1) {
checkTime();
}
collectTemp();
collectHumidity();
lcd.setCursor(0, 1); // These six lines are used to display Temp & Humidity on LCD
lcd.print(String("Low Temp = ") + String(LowTemp) + String(" F "));
lcd.setCursor(0, 2);
lcd.print(String("High Temp = ") + String(HighTemp) + String(" F "));
lcd.setCursor(0, 3);
lcd.print(String("Humidity = ") + String(hum) + String("% "));
if (digitalRead(EnterButton) == LOW) {
delay(200);
return;
}
}
}
void TimeLeft() {
float SysMin;
int DayCount_Viewer;
lcd.clear();
// This while loop makes sure that the user is stuck in here until pressing a button
while (true) {
SysMin = (float)millis();
SysMin = (SysMin / 60000);
// This checks if the battery activation function is on. If not, return to the main menu
if (BAOnOff == 1) {
checkTime();
}
else {
lcd.setCursor(0, 1);
lcd.print(" No Time Set! ");
lcd.setCursor(0, 2);
lcd.print(" Returning to Menu! ");
delay(750);
return;
}
// DayCount's indexing for showing the user the time is off by 1 (based on understanding)
DayCount_Viewer = DayCount - 1;
if (DayCount_Viewer < 0) { // This is to make sure that a negative value will be displayed
DayCount_Viewer = 0;
}
// Calculating the time left for the duration, along with the time left until next day loop
Time_Left = TimeSet - SysMin;
Time_Left_Til_Loop = TimeSet_Day - SysMin;
Time_Left_Til_Loop = Time_Left_Til_Loop / 60;
// The if statements are used to cover the edge cases that can appear
if ((Time_Left > 0) && (Time_Left_Til_Loop > 0)) {
lcd.setCursor(0, 0);
lcd.print(String(DayCount_Viewer) + String(" Days Left "));
lcd.setCursor(0, 1);
lcd.print(String(Time_Left) + String("Mins Left "));
lcd.setCursor(0, 2);
lcd.print(String(Time_Left_Til_Loop) + String("Hrs til next Day"));
lcd.setCursor(0, 3);
lcd.print(" Use * to Exit ");
} else if ((Time_Left > 0) && (Time_Left_Til_Loop < 0)) {
lcd.setCursor(0, 0);
lcd.print(String(DayCount_Viewer) + String(" Days Left "));
lcd.setCursor(0, 1);
lcd.print(String(Time_Left) + String("Mins Left "));
lcd.setCursor(0, 2);
lcd.print(String("0.00") + String("Hrs til next Day"));
lcd.setCursor(0, 3);
lcd.print(" Use * to Exit ");
} else if ((Time_Left < 0) && (Time_Left_Til_Loop > 0)) {
lcd.setCursor(0, 0);
lcd.print(String(DayCount_Viewer) + String(" Days Left "));
lcd.setCursor(0, 1);
lcd.print(String("0.00") + String("Mins Left "));
lcd.setCursor(0, 2);
lcd.print(String(Time_Left_Til_Loop) + String("Hrs til next Day"));
lcd.setCursor(0, 3);
lcd.print(" Use * to Exit ");
} else {
lcd.setCursor(0, 0);
lcd.print(String(DayCount_Viewer) + String(" Days Left "));
lcd.setCursor(0, 1);
lcd.print(String("0.00") + String("Mins Left "));
lcd.setCursor(0, 2);
lcd.print(String("0.00") + String("Hrs til next Day"));
lcd.setCursor(0, 3);
lcd.print(" Use * to Exit ");
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(250);
return;
}
}
}
void BattParamViewer() {
lcd.clear();
int c = 0;
//Creating LCD Characters-------------------
//Empty Battery Cells-------------
lcd.createChar(0, batt_back_empty);
lcd.createChar(1, batt_body_empty);
lcd.createChar(2, batt_head_empty);
//Full Battery Cells--------------
lcd.createChar(3, batt_back_full);
lcd.createChar(4, batt_body_full);
lcd.createChar(5, batt_head_full);
//------------------------------------------
lcd.setCursor(0, 1);
lcd.print("Currently Measuring");
lcd.setCursor(0, 2);
lcd.print(" Battery Parameters ");
while (true) {
// This checks if the battery activation function is on.
if (BAOnOff == 1) {
checkTime();
}
//Variables for collecting battery parameters
int R1 = 470; // Resistor 1 is 470 k ohms
int R2 = 160; // Resistor 2 is 160 k ohms
int input_V_value, output_V_value = 0; // analog pin being used: A0, A1 for output voltage (not in use)
double vin = 0.0, vin_tot = 0.0, percent_vin = 0.0; // Input voltage variables
double vout = 0.0, vout_tot = 0.0, percent_vout = 0.0; //Output voltage variables
double vin_2 = 0.0, vin_2_tot = 0.0, percent_vin_2 = 0.0; //Input voltage (second instance) variables
double v_nl = 0.0, percent_nl = 0.0; // No load input voltage variables
double v_avg = 0.0, percent_vavg = 0.0; // Average voltage variables
int percent_vin_int, percent_vin_2_int, percent_vout_int, percent_nl_int, percent_avg_int, percent_offset;
const double v_max = 14.6; // 14.6V maximum measured
const double v_min = 11; // 11 V minimum measured
//These if statements are for exiting this function at any time
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
//------Getting Values for No Load Parameters------
if (no_load) {
float wait = millis() + 5000;
while (wait > millis()) {
//These if statements are for exiting this function at any time
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
}
input_V_value = analogRead(A0); // collects input voltage value as analog value
v_nl = input_V_value * (5.0 / 1023.0); // converts analog value (0-1023) to voltage (0-5V)
v_nl = (v_nl * (R1 + R2)) / R2; // converts V_divider to V_source (0-5V to actual voltage value)
percent_nl = ((v_nl - v_min) / (v_max - v_min)) * 100.0; // measures the battery percentage based off of voltage range
percent_nl_int = (int)percent_nl; // finds the integer value of the percent
}
//------Getting Values for Input / Output Voltage Parameters------
for (int i = 0; i < 100; i++) { // This for loop makes sure that a random voltage spike does not matter
input_V_value = analogRead(A0); // collects input voltage value as analog value
output_V_value = analogRead(A1); // collects output voltage value as analog value
vin = input_V_value * (5.0 / 1023.0); // converts input analog value (0-1023) to voltage (0-5V)
Serial.println(String(vin) + String("Vin before V divider"));
vout = output_V_value * (5.0 / 1023.0); // converts output analog value (0-1023) to voltage (0-5V)
vin = (vin * (R1 + R2)) / R2; // converts V_divider to V_source (0-5V to actual voltage value)
vout = (vout * (R1 + R2)) / R2; // converts V_divider to V_source (0-5V to actual voltage value)
vin_tot = vin_tot + vin; // Storing measured value into a total value to be averaged after the loop
vout_tot = vout_tot + vout; // Storing measured value into a total value to be averaged after the loop
//These if statements are for exiting this function at any time
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
// This checks if the battery activation function is on.
if (BAOnOff == 1) {
checkTime();
}
}
vin = vin_tot / 100; // Getting the average input voltage
Serial.println(String(vin) + String(" Input Voltage"));
vout = vout_tot / 100; // Getting the average output voltage
percent_vin = ((vin - v_min) / (v_max - v_min)) * 100.0; // calculates the battery percentage based off of voltage range
percent_vin_int = (int)percent_vin; // finds the integer value of the percent
//------Finding Appropriate Value to display on LCD screen------
double v_diff = v_nl - vin;
v_diff = abs(v_diff);
// This if statement is for if a connected load lowers the voltage at the analog pin by more than 0.1 V
if (v_diff >= 0.1) { /*(v_diff > 0.1)*/
no_load = false;
//---Getting values for another instance of voltage parameters---
for (int i = 0; i < 100; i++) {
input_V_value = analogRead(A0); // collects input voltage value as analog value (2nd instance)
vin_2 = input_V_value * (5.0 / 1023.0); // converts input analog value (0-1023) to voltage (0-5V)
vin_2 = (vin_2 * (R1 + R2)) / R2; // converts V_divider to V_source (0-5V to actual voltage value)
vin_2_tot = vin_2_tot + vin; // Storing measured value into a total value to be averaged after the loop
//These if statements are for exiting this function at any time
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
// This checks if the battery activation function is on.
if (BAOnOff == 1) {
checkTime();
}
}
vin_2 = vin_2 / 100; // Getting the average input voltage (2nd instance)
percent_vin_2 = ((vin_2 - v_min) / (v_max - v_min)) * 100.0; // calculates the battery percentage based off of voltage range
percent_vin_2_int = (int)percent_vin_2; // finds the integer value of the percent
// If, Else statement to see which voltage value is lower, taking the lower as the true value (underestimation)
if (vin > vin_2) {
v_avg = vin_2;
percent_vavg = percent_vin_2;
}
else {
v_avg = vin;
percent_vavg = percent_vin;
}
percent_avg_int = (int)percent_vavg;
// If, Else statement to see if there should be an added-on offset for the displaying of the battery percentage
if (offset_skipper) {
}
else {
percent_offset = percent_nl_int - percent_avg_int;
offset_skipper = true;
}
}
// This else statement is for if a connected load does not lower the voltage at the analog pin
else {
no_load = false;
percent_offset = 0;
v_avg = vin;
percent_vavg = percent_vin_int;
}
if (c == 0) { // This is so the screen will clear the initial message, but not continuously
lcd.clear();
c++;
}
lcd.setCursor(0, 0);
double percent = percent_vavg + percent_offset;
// If statement to show that voltage cannot be negative
if (v_avg <= 0.0) {
v_avg = 0.0;
}
lcd.print(String("Voltage: ") + String(v_avg) + String("V "));
lcd.setCursor(0, 1);
// If statement to show that the percentage cannot be negative
if (percent <= 0.0) {
percent = 0.0;
}
lcd.print(String((int)(percent / 10) * 10) + String("% Battery Left "));
lcd.setCursor(0, 2);
//The following If statements are used to create the battery percentage graphic
if (percent >= 100) { //If the percentage is greater than 100%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(4);
lcd.setCursor(3, 2); lcd.write(4);
lcd.setCursor(4, 2); lcd.write(4);
lcd.setCursor(5, 2); lcd.write(4);
lcd.setCursor(6, 2); lcd.write(4);
lcd.setCursor(7, 2); lcd.write(4);
lcd.setCursor(8, 2); lcd.write(4);
lcd.setCursor(9, 2); lcd.write(5);
}
else if (percent > 90) { //If the percentage is greater than 90%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(4);
lcd.setCursor(3, 2); lcd.write(4);
lcd.setCursor(4, 2); lcd.write(4);
lcd.setCursor(5, 2); lcd.write(4);
lcd.setCursor(6, 2); lcd.write(4);
lcd.setCursor(7, 2); lcd.write(4);
lcd.setCursor(8, 2); lcd.write(4);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 80) { //If the percentage is greater than 80%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(4);
lcd.setCursor(3, 2); lcd.write(4);
lcd.setCursor(4, 2); lcd.write(4);
lcd.setCursor(5, 2); lcd.write(4);
lcd.setCursor(6, 2); lcd.write(4);
lcd.setCursor(7, 2); lcd.write(4);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 70) { //If the percentage is greater than 70%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(4);
lcd.setCursor(3, 2); lcd.write(4);
lcd.setCursor(4, 2); lcd.write(4);
lcd.setCursor(5, 2); lcd.write(4);
lcd.setCursor(6, 2); lcd.write(4);
lcd.setCursor(7, 2); lcd.write(1);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 60) { //If the percentage is greater than 60%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(4);
lcd.setCursor(3, 2); lcd.write(4);
lcd.setCursor(4, 2); lcd.write(4);
lcd.setCursor(5, 2); lcd.write(4);
lcd.setCursor(6, 2); lcd.write(1);
lcd.setCursor(7, 2); lcd.write(1);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 50) { //If the percentage is greater than 50%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(4);
lcd.setCursor(3, 2); lcd.write(4);
lcd.setCursor(4, 2); lcd.write(4);
lcd.setCursor(5, 2); lcd.write(1);
lcd.setCursor(6, 2); lcd.write(1);
lcd.setCursor(7, 2); lcd.write(1);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 40) { //If the percentage is greater than 40%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(4);
lcd.setCursor(3, 2); lcd.write(4);
lcd.setCursor(4, 2); lcd.write(1);
lcd.setCursor(5, 2); lcd.write(1);
lcd.setCursor(6, 2); lcd.write(1);
lcd.setCursor(7, 2); lcd.write(1);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 30) { //If the percentage is greater than 30%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(4);
lcd.setCursor(3, 2); lcd.write(1);
lcd.setCursor(4, 2); lcd.write(1);
lcd.setCursor(5, 2); lcd.write(1);
lcd.setCursor(6, 2); lcd.write(1);
lcd.setCursor(7, 2); lcd.write(1);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 20) { //If the percentage is greater than 20%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(4);
lcd.setCursor(2, 2); lcd.write(1);
lcd.setCursor(3, 2); lcd.write(1);
lcd.setCursor(4, 2); lcd.write(1);
lcd.setCursor(5, 2); lcd.write(1);
lcd.setCursor(6, 2); lcd.write(1);
lcd.setCursor(7, 2); lcd.write(1);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 10) { //If the percentage is greater than 10%
lcd.setCursor(0, 2); lcd.write(3);
lcd.setCursor(1, 2); lcd.write(1);
lcd.setCursor(2, 2); lcd.write(1);
lcd.setCursor(3, 2); lcd.write(1);
lcd.setCursor(4, 2); lcd.write(1);
lcd.setCursor(5, 2); lcd.write(1);
lcd.setCursor(6, 2); lcd.write(1);
lcd.setCursor(7, 2); lcd.write(1);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
else if (percent > 0) { //If the percentage is greater than 0%
lcd.setCursor(0, 2); lcd.write(0);
lcd.setCursor(1, 2); lcd.write(1);
lcd.setCursor(2, 2); lcd.write(1);
lcd.setCursor(3, 2); lcd.write(1);
lcd.setCursor(4, 2); lcd.write(1);
lcd.setCursor(5, 2); lcd.write(1);
lcd.setCursor(6, 2); lcd.write(1);
lcd.setCursor(7, 2); lcd.write(1);
lcd.setCursor(8, 2); lcd.write(1);
lcd.setCursor(9, 2); lcd.write(2);
}
lcd.setCursor(0, 3);
lcd.print("Use * < > to EXIT");
//These if statements are for exiting this function at any time
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
return;
}
}
}
void MenuChooser() {
//Variable for knowing what Menu is currently shown
int leave;
/* This Function's purpose is to let the User choose a Menu Option*/
leave = 500; // Sets 'leave a while loop' value to 500
while (leave > 0) { // While loop lets LCD update to a certain Menu Choice based on User Input
leave--; // Decreases 'leave a while loop' value. The while loop will end after 500 cycles of waiting for user input / confirmation
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar > 0) {
MenuVar--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar < 3) {
MenuVar++;
}
}
while (MenuVar == 1) { // while loop for confirmation on Battery Run Time Activator Function
collectTemp();
lcd.setCursor(0, 1); // These six lines are used to display confirmation message on LCD
lcd.print("Battery Run Time: ");
lcd.setCursor(0, 2);
lcd.print("Press * To Activate ");
lcd.setCursor(0, 3);
lcd.print(" ");
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar > 0) {
MenuVar--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar < 3) {
MenuVar++;
}
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
BRTActivator();
delay(200);
MenuVar = 0; // Reset MenuVar variable to go back to original message in MenuChooser
}
}
while (MenuVar == 2) { // while loop for confirmation on Battery Run Time Duration Function
lcd.setCursor(0, 1); // These six lines are used to display precursor message on LCD
lcd.print("Battery Run Time: ");
lcd.setCursor(0, 2);
lcd.print("Press * To Set The ");
lcd.setCursor(0, 3);
lcd.print("Time Duration ");
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar > 0) {
MenuVar--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar < 4) {
MenuVar++;
}
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
BRTTimeSetter();
MenuVar = 0; // Reset MenuVar variable to go back to original message in MenuChooser
}
}
while (MenuVar == 3) { // while loop for confirmation on Battery Parameter Collection Function
lcd.setCursor(0, 1); // These six lines are used to display precursor message on LCD
lcd.print("See Battery Voltage ");
lcd.setCursor(0, 2);
lcd.print("and Battery Percent ");
lcd.setCursor(0, 3);
lcd.print(" Press * to View ");
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar > 0) {
MenuVar--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar < 4) {
MenuVar++;
}
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
BattParamViewer(); // Run Battery Parameter Viewer
MenuVar = 0; // Reset MenuVar variable to go back to original message in MenuChooser
}
}
while (MenuVar == 4) { // while loop for confirmation on Internal Temperatures
lcd.setCursor(0, 1); // These six lines are used to display precursor message on LCD
lcd.print("View Remaining Time ");
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(" Press * to View ");
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar > 0) {
MenuVar--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar < 5) {
MenuVar++;
}
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
TimeLeft(); // Run View Remaining Time Function
MenuVar = 0; // Reset MenuVar variable to go back to original message in MenuChooser
}
}
while (MenuVar == 5) { // while loop for confirmation on Internal Temperatures
lcd.setCursor(0, 1); // These six lines are used to display precursor message on LCD
lcd.print("See Temperature and ");
lcd.setCursor(0, 2);
lcd.print(" Hummidity Values ");
lcd.setCursor(0, 3);
lcd.print(" Press * to View ");
if (digitalRead(LeftButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar > 0) {
MenuVar--;
}
}
if (digitalRead(RightButton) == LOW) { // This if statement is used to collect a user input
delay(200);
if (MenuVar < 5) {
MenuVar++;
}
}
if (digitalRead(EnterButton) == LOW) { // This if statement is used to collect a user input
delay(200);
TempnHumViewer(); // Run Temperature and Humidity Viewer
MenuVar = 0; // Reset MenuVar variable to go back to original message in MenuChooser
}
}
}
}
void MenuLCD() {
lcd.setCursor(0, 0); // The following if statements (24 Lines) are used to show Temperature Regulation Status on LCD
if (critcooling == 1) {
lcd.print("Temp Too High! No ");
lcd.setCursor(0, 1);
lcd.print("Power Output Allowed");
lcd.setCursor(0, 0);
} else if (critheating == 1) {
lcd.print("Temp Too Low! No ");
lcd.setCursor(0, 1);
lcd.print("Power Output Allowed");
lcd.setCursor(0, 0);
} else if (cooling == 1) {
lcd.print("Running: Cooling Sys");
} else if (heating == 1) {
lcd.print("Running: Heating Sys");
} else if (humremover == 1) {
lcd.print("Running: Hum Remover");
} else {
lcd.print(" Normal Operation ");
}
if ((critcooling == 1) || (critheating == 1)) {
lcd.setCursor(0, 2); // These Four lines are used to tell User they cannot choose a menu option
lcd.print("Cannot Use Functions");
lcd.setCursor(0, 3);
lcd.print("During Critical Temp");
} else if (MenuVar <= 0) {
lcd.setCursor(0, 1); // These Six lines are used to introduce User to choosing a menu option
lcd.print("Use < > to Choose");
lcd.setCursor(0, 2);
lcd.print("A Function. ");
lcd.setCursor(0, 3);
lcd.print(" ");
MenuChooser(); // Run Menu Chooser Function
} else {
MenuChooser(); // Run Menu Chooser Function
}
}
void critCoolSys() {
digitalWrite(HPTPIN, LOW); // Set voltage of pin 8 to 0V
digitalWrite(CFTPIN, HIGH); // Set voltage of pin 9 to 5V
digitalWrite(RelayPIN, LOW); // Set voltage of pin 10 to 0V
while (HighTemp > CritHighTemp) { // While loop to see if temperature is deeper in operating range than edge value
collectTemp(); // Collect most recent temp value
critcooling = 1; // Sets variable used for display on LCD (chosen in MenuLCD Function)
MenuLCD(); // Runs Menu LCD Function
}
digitalWrite(HPTPIN, LOW); // Set voltage of pin 8 to 0V
digitalWrite(CFTPIN, LOW); // Set voltage of pin 9 to 0V
if (BAOnOff == 1) {
//BattRunTimeCheck(); // Run Battery Run Time Check Function
} else {
digitalWrite(RelayPIN, HIGH); // Set voltage of pin 10 to 5V
}
critcooling = 0; // Sets variable used for display on LCD (chosen in MenuLCD Function)
}
void critHeatSys() {
digitalWrite(HPTPIN, HIGH); // Set voltage of pin 8 to 5V
digitalWrite(CFTPIN, HIGH); // Set voltage of pin 9 to 5V
digitalWrite(RelayPIN, LOW); // Set voltage of pin 10 to 0V
while (LowTemp < CritLowTemp) { // While loop to see if temperature is deeper in operating range than edge value
collectTemp(); // Collect most recent temp value
critheating = 1; // Sets variable used for display on LCD (chosen in MenuLCD Function)
MenuLCD(); // Runs Menu LCD Function
}
digitalWrite(HPTPIN, LOW); // Set voltage of pin 8 to 0V
digitalWrite(CFTPIN, LOW); // Set voltage of pin 9 to 0V
if (BAOnOff == 1) {
//BattRunTimeCheck(); // Run Battery Run Time Check Function
} else {
digitalWrite(RelayPIN, HIGH); // Set voltage of pin 10 to 5V
}
critheating = 0; // Sets variable used for display on LCD (chosen in MenuLCD Function)
}
void coolSys() {
digitalWrite(HPTPIN, LOW); // Set voltage of pin 8 to 0V
digitalWrite(CFTPIN, HIGH); // Set voltage of pin 9 to 5V
while (HighTemp > (HighOpTemp - 10)) { // While loop to see if temperature is deeper in operating range than edge value
collectTemp(); // Collect most recent temp value
cooling = 1; // Sets variable used for display on LCD (chosen in MenuLCD Function)
MenuLCD(); // Runs Menu LCD Function
}
digitalWrite(HPTPIN, LOW); // Set voltage of pin 8 to 0V
digitalWrite(CFTPIN, LOW); // Set voltage of pin 9 to 0V
cooling = 0; // Sets variable used for display on LCD (chosen in MenuLCD Function)
}
void heatSys() {
digitalWrite(HPTPIN, HIGH); // Set voltage of pin 8 to 5V
digitalWrite(CFTPIN, HIGH); // Set voltage of pin 9 to 5V
while (LowTemp < (LowOpTemp + 10)) { // While loop to see if temperature is deeper in operating range than edge value
collectTemp(); // Collect most recent temp value
heating = 1; // Sets variable used for display on LCD (chosen in MenuLCD Function)
MenuLCD(); // Runs Menu LCD Function
}
digitalWrite(HPTPIN, LOW); // Set voltage of pin 8 to 0V
digitalWrite(CFTPIN, LOW); // Set voltage of pin 9 to 0V
heating = 0; // Sets variable used for display on LCD (chosen in MenuLCD Function)
}
void humRemove() {
digitalWrite(HPTPIN, HIGH); // Set voltage of pin 8 to 5V
digitalWrite(CFTPIN, HIGH); // Set voltage of pin 9 to 5V
while (hum > (HumOp - 20)) { // While loop to see if humidity is deeper in operating range than edge value
collectHumidity(); // Collect most recent humidity value
humremover = 1; // Sets variable used for display on LCD (chosen in MenuLCD Function)
MenuLCD(); // Runs Menu LCD Function
}
digitalWrite(HPTPIN, LOW); // Set voltage of pin 8 to 0V
digitalWrite(CFTPIN, LOW); // Set voltage of pin 9 to 0V
humremover = 0; // Sets variable used for display on LCD (chosen in MenuLCD Function)
}
void checkTempValues() {
/* This Function is used to see if the temperature regulation functions should be active */
//If Temp Lower than Critical Low Temp, Run Critical Heating System Function
if (LowTemp < CritLowTemp) {
critHeatSys();
}
//If Temp Higher than Critical High Temp, Run Critical Cooling System Function
else if (HighTemp > CritHighTemp) {
critCoolSys();
}
//If Temp Lower than Operating Temp, Run Heating System Function
else if (LowTemp < LowOpTemp) {
heatSys();
}
//If Temp Higher than Operating Temp, Run Cooling System Function
else if (HighTemp > HighOpTemp) {
coolSys();
}
}
void checkHumidValue() {
//If Humidity Higher than Operating Range, Run Humidity Remover Function
if (hum > HumOp) {
humRemove();
}
}
void loop() {
// This is to set pin 2 to LOW, so that pins 3,4,5 are used based on seeing a GND (0 V)
digitalWrite(2, LOW);
// This is used to collect the temperature of the device
collectTemp();
// This is used to collect the humidity of the device
collectHumidity();
// This is used to compare the temperature values against the predetermined parameters
checkTempValues();
// This is used to compare the humidity value against the predetermined parameter
checkHumidValue();
// This is used to display the top row of the LCD display
MenuLCD();
// This If statement will turn off the relay if any critical temperature regulation system is active
if ((critcooling == 1) || (critheating == 1)) {
digitalWrite(RelayPIN, LOW); // Set voltage of pin 10 to 0V // Blocks Power Transmission
}
// If statements for if the Battery Duration has surpassed the set time, and Temperature Regulation is not blocking power transmission
else {
checkTime();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//**************************REMOTE CONTROL FUNCTIONS**************************************************
void intiateSendingMessage() {
//*****Remote Control***** Function to set up a message being sent to the user's cellphone
gsmSerial.print("AT+CMGS=\""); // Set AT command for sending SMS message
gsmSerial.print(phoneNumber); // Send GSM user's phone number
gsmSerial.println("\"");
}
void readSMS() {
// Function for reading the input from the SMS message
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
gsmSerial.println("AT+CMGR=0"); // Read the first SMS in memory
delay(500);
// While Loop for collecting ONLY the message, not the rest of the message's contents
while (gsmSerial.available()) {
lastMessage = gsmSerial.readStringUntil('"');
lastMessage.remove(lastMessage.length() - 8, 8);
lastMessage.remove(0, 2);
recentSMS = lastMessage; // Update the most recent read SMS message
lastMessage = "";
}
// Clear out all of the messages from the GSM's message storage
gsmSerial.println("AT+CMGD=1,4") while (gsmSerial.available()) {}
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
if (!menuChoice)
processSMS(); // Call process SMS function to choose a menu function
}
void processSMS() {
menuChoice = true;
// Extract the menu option sent in the SMS
int option = recentSMS.toInt();
// Process the menu option
switch (option) {
case 1:
toggleBatteryRunTime();
menuChoice = false;
break;
case 2:
setRunTimeDuration();
menuChoice = false;
break;
case 3:
seeBatteryPercentage();
menuChoice = false;
break;
case 4:
viewRemainingTime();
menuChoice = false;
break;
case 5:
viewTempRegStatus();
menuChoice = false;
break;
default:
// Handle invalid menu option
sendInvalidMessage();
menuChoice = false;
break;
}
}
void toggleBatteryRunTime() {
Serial.println("Toggle Battery Run Time");
//*****Remote Control***** Function to toggle battery run time
if (BAOnOff == 0) { // If statement checking state of Battery Activation On/Off Value (Off-to-On)
BAOnOff = 1; // Flips the state of the Battery Activation On/Off Value
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Battery Run Time Activated!"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending message of returning to menu selection
intiateSendingMessage();
gsmSerial.print("Returning to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
return;
} else if (BAOnOff == 1) { // If statement checking state of Battery Activation On/Off Value (On-to-Off)
BAOnOff = 0; // Flips the state of the Battery Activation On/Off Value
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Battery Run Time Deactivated!"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
digitalWrite(RelayPIN, HIGH); // Set voltage of pin 10 to 5V
// Sending message of returning to menu selection
intiateSendingMessage();
gsmSerial.print("Returning to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
return;
}
}
void setRunTimeDuration() {
Serial.println("Set Run Time Duration");
// Function to set run time duration
//Local variables for finding the hour value and the system's time in minutes
float HrVal, SysMin;
int DayVal = 0;
MinVal = 0;
HrVal = 0;
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
// Sending message about how many minutes the device should run for
intiateSendingMessage();
gsmSerial.print("How many minutes (0-60)? "); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
while (!gsmSerial.available()) {
if (BAOnOff == 1) {
checkTime();
}
} // Stay here until the user sends another SMS message
int message = recentSMS.toInt();
if ((message < 0) || (message > 60)) {
// Sending Invalid Selection Message
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
// Sending Invalid Message
intiateSendingMessage();
gsmSerial.print("Invalid Minute Selection! Back to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
return;
}
MinVal = message;
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
// Sending message about how many hours the device should run for
intiateSendingMessage();
gsmSerial.print("How many hours (0-24)? "); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
while (!gsmSerial.available()) {
if (BAOnOff == 1) {
checkTime();
}
} // Stay here until the user sends another SMS message
int message = recentSMS.toInt();
if ((message < 0) || (message > 24)) {
// Sending Invalid Selection Message
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
// Sending Invalid Message
intiateSendingMessage();
gsmSerial.print("Invalid Hour Selection! Back to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
return;
}
HrVal = message;
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
// Sending message about how many days the battery system should cycle the power duration for
intiateSendingMessage();
gsmSerial.print("How many days (0-7) should this duration cycle for? "); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
while (!gsmSerial.available()) {
if (BAOnOff == 1) {
checkTime();
}
} // Stay here until the user sends another SMS message
int message = recentSMS.toInt();
if ((message < 0) || (message > 7)) {
// Sending Invalid Selection Message
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Invalid Day Selection! Back to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
return;
}
DayVal = message;
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
// Sending that time was accepted
intiateSendingMessage();
gsmSerial.print("Time Accepted! Returning to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
DayOnOff = true;
MinVal = (HrVal / 60) + MinVal;
SysMin = (float)millis();
SysMin = (SysMin / 60000);
TimeSet = MinVal + SysMin;
DayCount = (int)DayVal;
DayVal = DayVal * Day_to_Min;
TimeSet_Day = Day_to_Min + SysMin;
}
void seeBatteryPercentage() {
Serial.println("See Battery Percentage");
//*****Remote Control***** Function to see battery percentage
if (BAOnOff == 1) {
checkTime();
}
// Variables for collecting battery parameters
int R1 = 470; // Resistor 1 is 470 k ohms
int R2 = 160; // Resistor 2 is 160 k ohms
int input_V_value, output_V_value = 0; // analog pin being used: A0, A1 for output voltage (not in use)
double vin = 0.0, vin_tot = 0.0, percent_vin = 0.0; // Input voltage variables
double vout = 0.0, vout_tot = 0.0, percent_vout = 0.0; // Output voltage variables
double vin_2 = 0.0, vin_2_tot = 0.0, percent_vin_2 = 0.0; // Input voltage (second instance) variables
double v_nl = 0.0, percent_nl = 0.0; // No load input voltage variables
double v_avg = 0.0, percent_vavg = 0.0; // Average voltage variables
int percent_vin_int, percent_vin_2_int, percent_vout_int, percent_nl_int, percent_avg_int, percent_offset;
const double v_max = 14.6; // 14.6V maximum measured
const double v_min = 11; // 11 V minimum measured
//------Getting No Load Values------
input_V_value = analogRead(A0); // collects input voltage value as analog value
v_nl = input_V_value * (5.0 / 1023.0); // converts analog value (0-1023) to voltage (0-5V)
v_nl = (v_nl * (R1 + R2)) / R2; // converts V_divider to V_source (0-5V to actual voltage value)
percent_nl = ((v_nl - v_min) / (v_max - v_min)) * 100.0; // measures the battery percentage based off of voltage range
percent_nl_int = (int)percent_nl; // finds the integer value of the percent
//------Getting Values for Input / Output Voltage Parameters------
for (int i = 0; i < 100; i++) { // This for loop makes sure that a random voltage spike does not matter
input_V_value = analogRead(A0); // collects input voltage value as analog value
output_V_value = analogRead(A1); // collects output voltage value as analog value
vin = input_V_value * (5.0 / 1023.0); // converts input analog value (0-1023) to voltage (0-5V)
Serial.println(String(vin) + String("Vin before V divider"));
vout = output_V_value * (5.0 / 1023.0); // converts output analog value (0-1023) to voltage (0-5V)
vin = (vin * (R1 + R2)) / R2; // converts V_divider to V_source (0-5V to actual voltage value)
vout = (vout * (R1 + R2)) / R2; // converts V_divider to V_source (0-5V to actual voltage value)
vin_tot = vin_tot + vin; // Storing measured value into a total value to be averaged after the loop
vout_tot = vout_tot + vout; // Storing measured value into a total value to be averaged after the loop
if (BAOnOff == 1) {
checkTime();
}
}
vin = vin_tot / 100; // Getting the average input voltage
vout = vout_tot / 100; // Getting the average output voltage
percent_vin = ((vin - v_min) / (v_max - v_min)) * 100.0; // calculates the battery percentage based off of voltage range
percent_vin_int = (int)percent_vin; // finds the integer value of the percent
//------Finding Appropriate Value to Send to User------
double v_diff = v_nl - vin;
v_diff = abs(v_diff);
// This if statement is for if a connected load lowers the voltage at the analog pin by more than 0.1 V
if (v_diff >= 0.1) { /*(v_diff > 0.1)*/
no_load = false;
//---Getting values for another instance of voltage parameters---
for (int i = 0; i < 100; i++) {
input_V_value = analogRead(A0); // collects input voltage value as analog value (2nd instance)
vin_2 = input_V_value * (5.0 / 1023.0); // converts input analog value (0-1023) to voltage (0-5V)
vin_2 = (vin_2 * (R1 + R2)) / R2; // converts V_divider to V_source (0-5V to actual voltage value)
vin_2_tot = vin_2_tot + vin; // Storing measured value into a total value to be averaged after the loop
if (BAOnOff == 1) {
checkTime();
}
}
vin_2 = vin_2 / 100; // Getting the average input voltage (2nd instance)
percent_vin_2 = ((vin_2 - v_min) / (v_max - v_min)) * 100.0; // calculates the battery percentage based off of voltage range
percent_vin_2_int = (int)percent_vin_2; // finds the integer value of the percent
// If, Else statement to see which voltage value is lower, taking the lower as the true value (underestimation)
if (vin > vin_2) {
v_avg = vin_2;
percent_vavg = percent_vin_2;
} else {
v_avg = vin;
percent_vavg = percent_vin;
}
percent_avg_int = (int)percent_vavg;
// If, Else statement to see if there should be an added-on offset for the displaying of the battery percentage
if (offset_skipper) {
} else {
percent_offset = percent_nl_int - percent_avg_int;
offset_skipper = true;
}
}
// This else statement is for if a connected load does not lower the voltage at the analog pin
else {
no_load = false;
percent_offset = 0;
v_avg = vin;
percent_vavg = percent_vin_int;
}
double percent = percent_vavg + percent_offset;
// If statement to show that voltage cannot be negative
if (v_avg <= 0.0) {
v_avg = 0.0;
}
// If statement to show that percentage cannot be negative
if (percent <= 0.0) {
percent = 0.0;
}
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
// Sending Battery Parameters
intiateSendingMessage();
gsmSerial.print(String("Voltage = ") + String(v_avg) + String("V\n") + String((int)(percent / 10) * 10) + String("% Battery Left")); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending that the user is returning to the menu
intiateSendingMessage();
gsmSerial.print("Returning to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
}
void viewRemainingTime() {
Serial.println("View Remaining Time");
//*****Remote Control***** Function to view remaining time left
float SysMin;
int DayCount_Viewer;
SysMin = (float)millis();
SysMin = (SysMin / 60000);
// This checks if the battery activation function is on. If not, return to the main menu
if (BAOnOff == 1) {
checkTime();
} else {
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("No Time Set! Back to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
return;
}
// DayCount's indexing for showing the user the time is off by 1 (based on understanding)
DayCount_Viewer = DayCount - 1;
// Calculating the time left for the duration, along with the time left until next day loop
Time_Left = TimeSet - SysMin;
Time_Left_Til_Loop = TimeSet_Day - SysMin;
Time_Left_Til_Loop = Time_Left_Til_Loop / 60;
if (DayCount_Viewer < 0) { // This is to make sure that a negative value will be displayed
DayCount_Viewer = 0;
}
if (Time_Left <= 0) {
Time_Left = 0;
}
if (Time_Left_Til_Loop <= 0) {
Time_Left_Til_Loop = 0;
}
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print(String(DayCount_Viewer) + String(" Day Cycles Left\n") + String(Time_Left) + String(" Minutes Left\n") + String(Time_Left_Til_Loop) + String(" Hours until next day loop")); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending user back to menu selection
intiateSendingMessage();
gsmSerial.print("Returning To Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
}
void viewTempRegStatus() {
Serial.println("View Temp Reg Status");
// Function to view temperature regulation status
if (critcooling == 1) {
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Running Critical Heating System!\nBattery is at dangerously low temperatures!\nNo Power Output Allowed!"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
} else if (critheating == 1) {
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Running Critical Cooling System!\nBattery is at dangerously high temperatures!\nNo Power Output Allowed!"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
} else if (cooling == 1) {
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Running Cooling System"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
} else if (heating == 1) {
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Running Heating System"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
} else if (humremover == 1) {
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Running Humidity Removal System"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
} else {
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print("Normal Operation"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
}
detachInterrupt(digitalPinToInterrupt(GSM_RX_PIN)); // Detaching interrupt so the reading process does not reactivate the interrupt during Tx/Rx of information
intiateSendingMessage();
gsmSerial.print(String("Low Temp = ") + String(LowTemp) + String(" F\nHigh Temp = ") + String(HighTemp) + String(" F\nHumidity = ") + String(hum) + String("%")); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending message of returning to menu selection
intiateSendingMessage();
gsmSerial.print("Returning to Menu Selection"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
// Sending Menu Options Again
intiateSendingMessage();
gsmSerial.print("Menu Options\n1: Toggle Battery Run Time\n2: Set Run Time Duration\n3. See Battery Percentage\n4. View Remaining Time\n5. View Temp Reg Status"); // Message being sent to the user's cellphone
gsmSerial.println((char)26); // End AT command with Ctrl+Z
delay(1000);
EIFR = 0x02; // Clear interrupt flag
attachInterrupt(digitalPinToInterrupt(GSM_RX_PIN), readSMS, FALLING); // Reattaching the interrupt
}
void sendInvalidMessage() {
Serial.println("Invalid Message!");
//*****Remote Control***** Function to send invalid message to user
intiateSendingMessage();
gsmSerial.print("Invalid Message Sent! "); // Message being sent to the user's cellphone
gsmSerial.print("The only valid inputs are: numbers, Y, N");
gsmSerial.println((char)26); // End AT command with Ctrl+Z
}
//****************************************************************************************************