//Milligan Engineering Low Voltage Disconnect Arduino Code
//Specify Libraries
#include <EEPROM.h> //This library is necesary for memory management
#include <LiquidCrystal_I2C.h> //This library is necesary for memory management
#include <Encoder.h> //This library is necessary for encoder functionality
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 20 chars and 4 line display
const int EEPROM_ADDR = 0; // EEPROM address to store the user input
const int MAX_INPUT_LENGTH = 32; // Maximum length of user input
char userInput[MAX_INPUT_LENGTH] = {0}; // Buffer to store user input
//Liquid crystal display related variables
int scrollPosition = 0; //First Line
bool selectPressed = false; // Select button latch
//Voltage Probe related variables
const float Resistor1 = 1.35e6; //ohms
const float Resistor2 = 750e3; //ohms
//Global Variables:
float NominalVoltage = 24;
bool EnableNominalVoltageInterface = true;
float ShutOffVoltage = 12;
bool EnableShutOffVoltageInterface = false;
float TurnBackOnVoltage = 10;
bool EnableTurnBackOnVoltageInterface = false;
bool Override = false;
unsigned long OverrideDelay = 20*60000; //milliseconds
bool EnableTimerOffsetBoolean = false;
unsigned long TimerOffset = 0*1000; //milliseconds
int TimeDelay = 30000; //Delay for turning back on or off
int LanguageSetting = 1;
bool EnableLanguageInterface = false;
int DeviceSetting = 3;
//Timer-related variables
unsigned long previousMillis = 0;
unsigned long RolloverTime = (pow(2,32)-1);// Set an interval in milliseconds to ensure that millis() rollover (happens once approximately every 50 days when millis() resets to zero) is never an issue for more than 10 minutes
//Get Pin Assignments:
int VoltageProbe= 7;
int lcdSDA= 27;
int lcdSCL= 19;
int EncoderCLK = 2;
int EncoderDT = 3;
int EncoderSW = 8;
int PushButton = 13;
int RelayOutput = 4;
int InputUp = 12;
int InputDown = 13;
int InputRight = 10;
int InputLeft = 5;
int InputSelect = 6;
//Encoder
int CLKNow;
int CLKPrevious;
int DTNow;
int DTPrevious;
//Initialize States
//All Possible Screens
void Screens(int scrollPosition)
{
switch(scrollPosition)
{
case 0:
{
lcd.setCursor(0,0);
lcd.print(">Batt. V ");
lcd.print(NominalVoltage,1);
lcd.setCursor(0,1);
lcd.print(" CutOff V ");
lcd.print(ShutOffVoltage,1);
lcd.setCursor(0,2);
lcd.print(" CutOn V ");
lcd.print(TurnBackOnVoltage,1);
lcd.setCursor(0,3);
lcd.print(" Override T: ");
lcd.print(OverrideDelay/60000);
lcd.print("min");
break;
}
case 1:
{
lcd.setCursor(0,0);
lcd.print(" Batt. V ");
lcd.print(NominalVoltage,1);
lcd.setCursor(0,1);
lcd.print(">CutOff V ");
lcd.print(ShutOffVoltage,1);
lcd.setCursor(0,2);
lcd.print(" CutOn V ");
lcd.print(TurnBackOnVoltage,1);
lcd.setCursor(0,3);
lcd.print(" Override T: ");
lcd.print(OverrideDelay/60000);
lcd.print("min");
break;
}
case 2:
{
lcd.setCursor(0,0);
lcd.print(" Batt. V ");
lcd.print(NominalVoltage,1);
lcd.setCursor(0,1);
lcd.print(" CutOff V ");
lcd.print(ShutOffVoltage,1);
lcd.setCursor(0,2);
lcd.print(">CutOn V ");
lcd.print(TurnBackOnVoltage,1);
lcd.setCursor(0,3);
lcd.print(" Override T: ");
lcd.print(OverrideDelay/60000);
lcd.print("min");
break;
}
case 3:
{
lcd.setCursor(0,0);
lcd.print(" Batt. V ");
lcd.print(NominalVoltage,1);
lcd.setCursor(0,1);
lcd.print(" CutOff V ");
lcd.print(ShutOffVoltage,1);
lcd.setCursor(0,2);
lcd.print(" CutOn V ");
lcd.print(TurnBackOnVoltage,1);
lcd.setCursor(0,3);
lcd.print(">Override T: ");
lcd.print(OverrideDelay/60000);
lcd.print("min");
break; //The reason I didn't just have cases to only change the position of the arrow is the screen will have to be cleared to get rid of the arrows or a space would be needed to overwrite this. It was just as easy to do this.
} //end of case 3
}
}
void Scroll()
{
Screens(scrollPosition);
} // end void Scroll()
/*
void Select()
{
int RIGHT_State = digitalRead(InputRight);
int LEFT_State = digitalRead(InputLeft);
//I think I should add a timer to get out of select state in case user leaves it, battery voltage would not be updated on LCD
if (scrollPosition == 1)
{
Screens(scrollPosition); // Keep updating the screen
if (RIGHT_State == HIGH)
{
ShutOffVoltage = ShutOffVoltage + 0.1;
} //end if(RIGHT_State == HIGH)
if (LEFT_State == HIGH)
{
ShutOffVoltage = ShutOffVoltage - 0.1;
} // end if(LEFT_State == HIGH)
} //end (if ScrollPosition==1)
else if (scrollPosition == 2)
{
Screens(scrollPosition);
if (RIGHT_State == HIGH)
{
TurnBackOnVoltage = TurnBackOnVoltage + 0.1;
} //if (RIGHT_State == HIGH)
if (LEFT_State == HIGH)
{
TurnBackOnVoltage = TurnBackOnVoltage - 0.1;
} //end of if(LEFT_State == HIGH)
} //end of else if (scrollPosition == 2)
else if (scrollPosition == 3)
{
Screens(scrollPosition);
if (RIGHT_State == HIGH)
{
OverrideDelay = OverrideDelay + (5*60000);
}
if (LEFT_State == HIGH && (OverrideDelay > 0))
{
OverrideDelay = OverrideDelay - (5*60000);
} //end of if (LEFT_State == HIGH)
}
*/
void setup()
{
// Initialize serial communication
lcd.init(); // initialize the lcd
lcd.backlight();
//Button Initialization
pinMode(InputUp, INPUT);
pinMode(InputDown, INPUT);
pinMode(InputLeft, INPUT);
pinMode(InputRight, INPUT);
pinMode(InputSelect, INPUT);
selectPressed = false;
Serial.begin(9600);
Serial.println("Basic Encoder Test:");
//Encoder Initialization - Ideally, the pins should be interrupt pins
pinMode(EncoderCLK, INPUT); //RotaryCLK //I added this
pinMode(EncoderDT, INPUT); //RotaryDT //I added this
pinMode(EncoderSW, INPUT_PULLUP); //Button
CLKPrevious = digitalRead(EncoderCLK);
DTPrevious = digitalRead(EncoderDT); //Must be in setup
} //End of void setup
void loop()
{
CLKNow = digitalRead(EncoderCLK);
DTNow = digitalRead(EncoderDT)
//User Input:
//EncoderScroll();
if (CLKNow != CLKPrevious && CLKNow == 1) //Change has been detected in encoder
{
// If the DT state is different than the CLK state then
// the encoder is rotating in A direction, so we increase
if (DTNow != CLKNow) // IF DT and CLK are different, turning clockwise (Scroll DOWN)
{
if (scrollPosition < 0) // we do not go below 0
{
scrollPosition++;
}
}
else //IF DT and CLK are the same, turning counter clockwise (Scroll UP)
{
if (scrollPosition < 3) // we do not go above 3
{
scrollPosition++;
}
else
{
scrollPosition = 0;
}
}
}
CLKPrevious = CLKNow; // Store last CLK state
Scroll();
Serial.print("Clk Now: ");
Serial.println(CLKNow);
Serial.print("\n");
Serial.print("DT Now: ");
Serial.println(DTNow);
Serial.print("\n");
Serial.print("Clk Prev: ");
Serial.println(CLKPrevious);
Serial.print("\n");
Serial.print("DT Prev: ");
Serial.println(DTPrevious);
Serial.print("\n");
}
/*
if (newPosition >&& scrollPosition < 3) {
scrollPosition++;
} else if (newPosition < oldPosition && scrollPosition > 0) {
scrollPosition--;
}
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
Serial.print("\n");
Serial.print("ScrollPosition: ");
Serial.println(scrollPosition);
Serial.print("\n");
}
*/
//End of Void Loop