/*
   Arduino controlador pajarera con control de luz ( via Mosfet de potencia), monitorizacion de
   Temperatura y Humedad (DHT22) y Calendario/reloj(RTC DS3231) con visualización en monitor TFT (ILI9341 2,8")
   ©ramoncho28
*/
#include "SPI.h"
#include <Adafruit_GFX.h>     // incluir Adafruit graphics Libreria
#include <Adafruit_ILI9341.h>  // incluir Adafruit ILI9341 TFT Libreria
#include "RTClib.h"           // incluir Adafruit RTC Libreria
#include <DHT.h>
#include <LibPrintf.h>

#define TFT_RST 8  // TFT RST pin a arduino pin 8
#define TFT_CS 9   // TFT CS  pin a arduino pin 9
#define TFT_DC 10  // TFT DC  pin a arduino pin 10
// initialize ILI9341 TFT Libreria
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
#define DHTPIN A2      // DHT22 data pin conectado a Arduino  pin A2
#define DHTTYPE DHT22  // DHT22 sensor
DHT dht22(DHTPIN, DHTTYPE);
// initialize RTC Libreria
//RTC_DS3231 rtc;
RTC_DS1307 rtc;
DateTime now;

// botons definition
#define boton1 3   // boton B1 conectado a Arduino pin 7
#define boton2 2   // boton B2 conectado a Arduino pin 6
#define deshumi 4  //Rele deshumidificador pin 4
int ledStart = 21;
int ledStop = 23;
int minutos, horas;
int Led = 6;         // salida PWM mosfet pin 6
const int Ldr = A0;  //Ldr a pin analogico 0
int VLdr;
const byte pinPowerDHT22 = 7;   //reset DHT 22 pin 7


void setup(void) {
  Serial.begin(9600);
  pinMode(boton1, INPUT_PULLUP);
  pinMode(boton2, INPUT_PULLUP);
  pinMode(Led, OUTPUT);
  pinMode(deshumi, OUTPUT);
  dht22.begin();
  digitalWrite(pinPowerDHT22, HIGH);
  rtc.begin();  // inicializar RTC chip
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);                         // llenar pantalla color negro
  tft.drawFastHLine(0, 64, tft.width(), ILI9341_BLUE);   // pintar linea horizontal azul en posicion (0, 44)
  tft.drawFastHLine(0, 102, tft.width(), ILI9341_BLUE);  // pintar linea horizontal azul en posicion (0, 102)

  tft.setTextWrap(false);                        // desactivar ajuste de texto
  tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);  //  color texto verde y fondo negro
  tft.setTextSize(3);                            // texto tamaño = 3
  tft.setCursor(15, 80);                         // mover cursor texto posicion (15, 27) pixel
  tft.print("TEMPERATURA:");
  tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);  //  color texto amarillo y fondo negro
  tft.setCursor(43, 80);                         // mover cursor texto posicion (15, 27) pixel
  tft.print("HUMEDAD:");
}

// funcion corta boton1 (B1) debounce
bool debounce() {
  byte count = 0;
  for (byte i = 0; i < 5; i++) {
    if (!digitalRead(boton1))
      count++;
    delay(10);
  }

  if (count > 2) return 1;
  else return 0;
}

void RTC_display() {
  char _buffer[11];
  char dow_matrix[7][10] = { "Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado" };
  byte x_pos[7] = { 29, 29, 23, 11, 17, 29, 17 };
  static byte previous_dow = 8;

  // print day of the week
  if (previous_dow != now.dayOfTheWeek()) {
    previous_dow = now.dayOfTheWeek();
    tft.fillRect(11, 55, 108, 14, ILI9341_BLACK);
    tft.setCursor(x_pos[previous_dow], 55);
    tft.setTextColor(ILI9341_CYAN, ILI9341_BLACK);  //  color texto cyan y fondo negro
    tft.print(dow_matrix[now.dayOfTheWeek()]);
  }

  // print date
  sprintf(_buffer, "%02u-%02u-%04u", (byte) now.day(), now.month(), now.year());
  Serial.print(_buffer); Serial.print(" ");
  tft.setCursor(4, 79);
  tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);  //  color texto amarillo y fondo negro
  tft.print(_buffer);
  // print time
  sprintf(_buffer, "%02u:%02u:%02u", (byte) now.hour(), (byte) now.minute(), (byte) now.second());
  Serial.println(_buffer);
  tft.setCursor(16, 136);
  tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);  //  color texto verde y fondo negro
  tft.print(_buffer);
}

byte edit(byte parameter) {
  static byte i = 0, y_pos,
              x_pos[5] = { 4, 40, 100, 16, 52 };
  char text[3];
  sprintf(text, "%02u", parameter);

  if (i < 3) {
    tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);  //  color texto amarillo y fondo negro
    y_pos = 79;
  } else {
    tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);  //  color  texto erde y fondo negro
    y_pos = 136;
  }

  while (debounce());

  while (true) {
    while (!digitalRead(boton2)) {
      parameter++;
      if (i == 0 && parameter > 31)
        parameter = 1;
      if (i == 1 && parameter > 12)
        parameter = 1;
      if (i == 2 && parameter > 99)
        parameter = 0;
      if (i == 3 && parameter > 23)
        parameter = 0;
      if (i == 4 && parameter > 59)
        parameter = 0;

      sprintf(text, "%02u", parameter);
      tft.setCursor(x_pos[i], y_pos);
      tft.print(text);
      delay(200);  // wait 200ms
    }

    tft.fillRect(x_pos[i], y_pos, 22, 14, ILI9341_BLACK);
    unsigned long previous_m = millis();
    while ((millis() - previous_m < 250) && digitalRead(boton1) && digitalRead(boton2))
      ;
    tft.setCursor(x_pos[i], y_pos);
    tft.print(text);
    previous_m = millis();
    while ((millis() - previous_m < 250) && digitalRead(boton1) && digitalRead(boton2))
      ;

    if (!digitalRead(boton1)) {
      i = (i + 1) % 5;
      return parameter;
    }
  }
}
char _buffer[7];

void loop() {

  VLdr = analogRead(Ldr);
  int Humi = dht22.readHumidity() * 10;
  int Temp = dht22.readTemperature() * 10;
  if (isnan(Humi) || isnan(Temp)) {
    digitalWrite(pinPowerDHT22, LOW);
    delay(100);  // demosle unos instantes para que todo se estabilice.
    digitalWrite(pinPowerDHT22, HIGH);
  }
  tft.setTextColor(ILI9341_RED, ILI9341_BLACK);  //  color texto rojo y fondo negro
  if (Temp < 0)
    sprintf(_buffer, "-%02u.%1u", (abs(Temp) / 10) % 100, abs(Temp) % 10);
  else  // temperature >= 0
    sprintf(_buffer, " %02u.%1u", (Temp / 10) % 100, Temp % 10);
  tft.setCursor(26, 81);
  tft.print(_buffer);
  tft.drawCircle(161, 87, 4, ILI9341_RED);  // print degree symbol ( ° )
  tft.drawCircle(161, 87, 5, ILI9341_RED);
  tft.setCursor(170, 81);
  tft.print("C");

  // print humidity (in %)
  tft.setTextColor(ILI9341_CYAN, ILI9341_BLACK);  //  color texto cyan y fondo negro
  sprintf(_buffer, "%02u.%1u %%", (Humi / 10) % 100, Humi % 10);
  tft.setCursor(50, 171);
  tft.print(_buffer);


  if (!digitalRead(boton1))
    if (debounce()) {
      while (debounce());
      byte day = edit(now.day());
      byte month = edit(now.month());
      byte year = edit(now.year() - 2000);
      byte hour = edit(now.hour());
      byte minute = edit(now.minute());
      rtc.adjust(DateTime(2000 + year, month, day, hour, minute, 0));
      while (debounce());
    }

  now = rtc.now();
  minutos = now.minute();
  horas = now.hour();
  RTC_display();
  if (Humi > 60) {
    digitalWrite(deshumi, HIGH);
  }
  else if (Humi < 45) {
    digitalWrite(deshumi, LOW);
  }

  if (horas == ledStart) {
    if (minutos >= 0 && minutos <= 59) {
      LedStart();
    }

    if (VLdr > 550 && horas > ledStart && horas < ledStop - 1) {
      digitalWrite(Led, HIGH);
    }

    if (((VLdr < 450) && horas < ledStart) || horas > ledStop) {
      digitalWrite(Led, LOW);
    }

    if (horas == ledStop - 1) {
      if (minutos >= 0 && minutos <= 59) {
        LedStop();
      }
    }
  }
  delay(100);
}
void LedStart() {
  int fade = map(minutos, 0, 59, 1, 255);
  analogWrite(Led, fade);
}

void LedStop() {
  int fade = map(minutos, 0, 59, 255, 0);
  analogWrite(Led, fade);
}
// Fin
GND5VSDASCLSQWRTCDS1307+