// Método de ecualización de la curva del termistor NTC: Stein-Hart
// Resistencia nominal del sensor a 20°C: 20Kohm

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Definir el tamaño de la pantalla OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

// Crear una instancia de la pantalla OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

const int analogPin = A0;      // Pin analógico al que está conectado el termistor
const int beta = 3950;         // Parámetro beta del termistor
const int seriesResistor = 9900; // Valor del resistor en serie (10k ohmios)
const int nominalResistance = 20000; // Resistencia nominal a 20°C (20k ohmios)
const int nominalTemperature = 20;   // Temperatura nominal (20°C)
const float referenceTemperature = 74.0; // Temperatura de referencia en grados Celsius
const int outputPin = 13;      // Pin digital para la salida (por ejemplo, LED)
const int inputPinup = 6;      // Pin digital para entrada de pulso incremento
const int inputPindown = 7;      // Pin digital para entrada de pulso decremento
volatile bool flag1 = false; // Bandera para el pin incremento, para indicar la detección del flanco
volatile bool flag2 = false; // Bandera para el pin decremento, para indicar la detección del flanco


void setup() {
  // Inicializar comunicación serial
  Serial.begin(9600);
    // Inicializar la pantalla OLED
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Dirección I2C para SSD1306
    Serial.println(F("No se encontró un display OLED SSD1306"));
    for(;;);
  }

  // Limpiar la pantalla
  display.clearDisplay();
  display.display();

  // Establecer tamaño del texto
  display.setTextSize(1);
  // Establecer color del texto
  display.setTextColor(SSD1306_WHITE);

  // Configurar el pin de salida como salida
  pinMode(outputPin, OUTPUT);
  // Configurar el pines de entrada como entradas
  pinMode(inputPinup, INPUT);     // Configurar el pin de entrada
  pinMode(inputPindown, INPUT);   // Configurar el pin de entrada
  attachInterrupt(digitalPinToInterrupt(inputPinup), risingEdgeISR1, RISING); // Configurar la interrupción para detectar el flanco ascendente
  attachInterrupt(digitalPinToInterrupt(inputPindown), risingEdgeISR2, RISING);
  // fin setup
}

  // Detección de flanco ascendente entradas digitales pulsadores
void flags() {
  if (flag1) {
    Serial.println("Flanco ascendente detectado en inputPinup!");
    flag1 = false; // Reiniciar la bandera del primer pin
  }
  if (flag2) {
    Serial.println("Flanco ascendente detectado en inputPindown!");
    flag2 = false; // Reiniciar la bandera del segundo pin
  }
}

void risingEdgeISR1() {
  flag1 = true; // Establecer la bandera cuando se detecta un flanco ascendente en inputPinup
}

void risingEdgeISR2() {
  flag2 = true; // Establecer la bandera cuando se detecta un flanco ascendente en inputPindown

}

/**
attachInterrupt(digitalPinToInterrupt(inputPin), risingEdgeISR, RISING) configura una interrupción para detectar el flanco ascendente en el inputPin.

risingEdgeISR es una función de interrupción que se ejecuta cuando se detecta el flanco ascendente y establece la variable flag en true.

En el loop, se verifica el estado de flag y, si es true, se imprime un mensaje indicando que se detectó un flanco ascendente y se reinicia la bandera.
**/

void loop() { //Funcion de lectura, calculo y presentación de temperatura
  int analogValue = analogRead(analogPin); // Leer el valor analógico del termistor
  float resistance = seriesResistor * (1023.0 / analogValue - 1); // Calcular resistencia del termistor

  // Calcular la temperatura en grados Celsius
  float steinhart;
  steinhart = resistance / nominalResistance;      // (R/R0)
  steinhart = log(steinhart);                      // ln(R/R0)
  steinhart /= beta;                               // 1/B * ln(R/R0)
  steinhart += 1.0 / (nominalTemperature + 273.15); // + (1/T0)
  steinhart = 1.0 / steinhart;                     // Invertir
  steinhart -= 273.15;                             // Convertir a Celsius

  // Mostrar la temperatura en el monitor serial
  Serial.print("Temperatura: ");
  Serial.print(steinhart);
  Serial.println(" °C");
  Serial.print("Analog: ");
  Serial.println(analogValue);
  Serial.print("Resistencia: ");
  Serial.println(resistance);

  // Limpiar la pantalla
  display.clearDisplay();

  // Mostrar la temperatura en el display OLED
  display.setCursor(0, 0);
  display.println("Temperatura: ");
  display.println(" ");
  display.print(steinhart);
  display.println(" " + String(char(248)) + "C");

  // Actualizar la pantalla OLED
  display.display();

  // Comparar la temperatura medida con la referencia
  if (steinhart > referenceTemperature) {
    digitalWrite(outputPin, HIGH); // Activar la salida digital
  } else {
    digitalWrite(outputPin, LOW); // Desactivar la salida digital
  }

  // Esperar 1 segundo antes de la siguiente lectura
  delay(2000);
}