/* KW5GP Station Monitor

  Displays Voltage, Current, Date and Time with threshold warnings

  Uses DS3231 Library from Rinkydinkelectronics.com

  Uses Adafruit_ST7735 and Adafruit+GFX libraries

*/
/***************************************************
  This is a library for the Adafruit 1.8" SPI display.

  This library works with the Adafruit 1.8" TFT Breakout w/SD card
  ----> http://www.adafruit.com/products/358
  The 1.8" TFT shield
  ----> https://www.adafruit.com/product/802
  The 1.44" TFT breakout
  ----> https://www.adafruit.com/product/2088
  as well as Adafruit raw 1.8" TFT display
  ----> http://www.adafruit.com/products/618

  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

#include <Adafruit_GFX.h>    // Core graphics library for the LCD display
#include <Adafruit_ST7735.h> // Hardware-specific library for the ST7735 LCD Display
#include <SPI.h>  //The SPI library needed for the LCD Display

#include <DS3231.h> // The library for the DS3231 Real Time Clock Module

// Define the LCD Pins
#define TFT_CS     10
#define TFT_RST    9
#define TFT_DC     8

// Option 1 (recommended): must use the hardware SPI pins
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

#define backlight 3 // Define the pin used for the backlight
#define voltage_pin A1  // Define the pin used to sense the DC voltage
#define current_pin A0  // Define the pin used to sense the Amperage

// Init the DS3231 RTC
DS3231 rtc(SDA, SCL);

// The Hall Effect Current Sense Module can sense positive and negative current. The actual
// Zero Current point is at approximately 2.5V or about 510 counts on the Arduino
//Analog to Digital Converter
int zero_point = 510; // Sets the zero current count of the A/D
int current_cal_max = 893;  // Sets the A/D maximum count for a 30A Hall Effect Sensor


float voltage, current; // variables for the voltage and current
float volt_drop = 0.75; // the voltage drop across the input voltage diode and circuit
int volt_cal = 2490;  // Calibration value for the voltage MAP statement

float current_high = 25; // Threshold for high current alert (turns current value on display red)
float voltage_low = 11.9; // Threshold value for low voltage (turns voltage value yellow)
float voltage_high = 14.0;  // Threshold value for high voltage (turns voltage value red)
float temperature;  // variable for the temperature reading from the DS3231 RTC module
String rtcdate, rtctime, rtcday, rtcmonth, rtcyear ;  // variables for the RTC date and time data

void setup()
{

  // Use this initializer if you're using a 1.8" TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab

  pinMode(backlight, OUTPUT); // Set up the backlight pin as output
  digitalWrite(backlight, HIGH);  // Turn on the backlight

  // Initialize the DS3231 RTC object
  rtc.begin();

  // The following lines can be uncommented to set the time
  //rtc.setDOW(SUNDAY);        // Set Day-of-Week to SUNDAY
  //rtc.setTime(8,40,0);     // Set the time to 12:45:00 (24hr format)
  //rtc.setDate(3,7,2016);   // Set the date to May 30 2016. Note: format is dd.mm.yyyy

  tft.fillScreen(ST7735_BLUE); // Clear the display
  tft.setRotation(1); // Set the screen rotation
  tft.setTextWrap(false); // Turn off text wrap
  tft.setTextSize(2); // Set Font Size
  tft.setTextColor(ST7735_GREEN); // Set the initial text color to green
  // Display the start-up splash screen
  tft.setCursor(50, 30);
  tft.print("KW5GP");
  tft.setCursor(37, 60);
  tft.print("Station");
  tft.setCursor(37, 80);
  tft.print("Monitor");
  delay (5000);

  tft.fillScreen(ST7735_BLUE); // Fill the screen with the background color to clear the LCD

}

void loop()
{

  tft.setTextSize(3); // Set the font size
  tft.setTextColor(ST7735_GREEN); // Set the text color to green
  tft.fillScreen(ST7735_BLUE);  // "clear" the LCD screen
  tft.setCursor(40, 5); // Set up the basic display template of data that never changes
  tft.print("KW5GP");

  do  // loop forever
  {

    tft.setTextSize(3); // set the font size
    tft.setCursor(30, 40);  // Set the LCD cursor to the current value display point

    readCurrent();  // Read the input voltage
    readVoltage();  // Read the input current
    
    tft.setTextColor(ST7735_GREEN, ST7735_BLUE);  // set the text color to green with blue background
    if (current >= current_high)  // change the text color to red if current is at or above high current threshold
    {
      tft.setTextColor(ST7735_RED, ST7735_BLUE);
    }
    tft.print(current, 1);  // display the current in format XX.X
    tft.print(" A  ");
    tft.setCursor(30, 70);
    tft.setTextColor(ST7735_GREEN, ST7735_BLUE);  // set the text color to green with blue background
    if (voltage <= voltage_low)  // change the text color to yellow if voltage is at or below low voltage threshold
    {
      tft.setTextColor(ST7735_YELLOW, ST7735_BLUE);
    }
    else
    {
      if (voltage >= voltage_high)
      {
        tft.setTextColor(ST7735_RED, ST7735_BLUE);  // change the text color to red if voltage is at or above high voltage threshold
      }
    }

    tft.print(voltage, 1);  // Display the voltage
    tft.print(" V  ");
    tft.setTextColor(ST7735_GREEN, ST7735_BLUE);  // set the text color to green with blue background
    tft.setTextSize(2);
    tft.setCursor(55, 100);
    temperature = rtc.getTemp();  // get and display the temperature
    temperature = (temperature * 1.8) + 32; // Convert from Celsius to Fahrenheit
    tft.print(temperature, 0);  // Display the temperature
    tft.print(" F ");
    tft.setTextSize(1); // Set the font size 
    tft.setCursor(0, 120);
    rtcdate = rtc.getDateStr(); // get and display the date and time
    rtcmonth = rtcdate.substring(3, 5);
    rtcday = rtcdate.substring(0, 2);
    rtcyear = rtcdate.substring(6, 10);
    rtctime = rtc.getTimeStr();
    rtctime = rtctime.substring(0, 5);
    tft.setCursor(0, 120);
    tft.print(" ");
    tft.print(rtc.getDOWStr()); //get and display the day of the week
    tft.print(" ");
    tft.print(rtcmonth);
    tft.print("/");
    tft.print(rtcday);
    tft.print("/");
    tft.print(rtcyear);
    tft.print(" ");
    tft.print(rtctime);

    delay(10000); // Wait 10 seconds before updating

  } while (true);

}

// Function to read the input voltage
void readVoltage()
{
  float count = analogRead(voltage_pin);  // read the voltage
  voltage = map(count, 0, 1023, 0, volt_cal); // Map the A/D count value to the actual voltage
  voltage = (voltage / 100) + volt_drop; // Convert the voltage to XX.X format and subtract the voltage drop across the input protection diode and circuit loss
}

// Function to read the Hall Effect Sensor current value
void readCurrent()
{
  int count = analogRead(current_pin);  // read the Current value
  
  // If the count is less than the zero point, set it to zero so we don't show negative current
  // The Hall Effect sensor can handle negative current values but we don't want to 
  // have this project display negative current
  if (count < zero_point)
  {
    count = zero_point;
  }
  // Map the Arduino Current sense A/D value from 0 to 30A
  // we use 300 instead of 30 because we want to see tenths of an Amp
  current = map(count, zero_point, current_cal_max, 0, 300);
  current = current / 10; // Divide the current by 10 to convert it to format XX.X
}


