#include <math.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EasyBuzzer.h>
Adafruit_SSD1306 display(128, 64, &Wire, -1); 

#define buzzer             11                  //Buzzer
#define ni                 A0                  //entrada nivel +
#define te                 A2                  //entrada termistor
#define vo                 A1                  //entrada voltimetro
#define Vref               4.97                //voltaje referencia vcc
#define ADC               1024                // Multiplo de entrada ADC
#define NUM_SAMPLES       5                  // NUMERO DE MUESTRAS TOMADAS Voltaje
#define THERMISTOR        10000                 // VALOR OHM DEL SENSOR 25 °C(992 spark)(2500 optra)
#define NUMSAMPLES        10                  // NUMERO DE MUESTRAS TOMADAS NTC
#define BCOEFFICIENT      3680                // beta coefficient 3000-4000 (3680 spark) 
#define SERIESRESISTOR    10000                 // resistor en serie 10k (1k para spark)
#define RV1               98700               //RV1=100000 ohms
#define RV2               9780                //RV2=10000 ohms
#define DEG2RAD 0.0174532925

unsigned char sample_count=0, m;
int samples[NUMSAMPLES], sum=0, Nivel1, temp;
float steinhart, p, p3, Volt, ba, Nivel;
unsigned long timer, timer2, timer3;
boolean indicador;

const unsigned char bat2 [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x01, 0xfc, 0x00, 0x0f, 0xff, 0x80, 0x0f, 
	0xff, 0x80, 0x0c, 0x01, 0x80, 0x0c, 0x01, 0x80, 0x0c, 0x01, 0x80, 0x0c, 0x11, 0x80, 0x0c, 0x11, 
	0x80, 0x0c, 0x21, 0x80, 0x0c, 0x61, 0x80, 0x0c, 0xe1, 0x80, 0x0c, 0xf9, 0x80, 0x0c, 0x31, 0x80, 
	0x0c, 0x31, 0x80, 0x0c, 0x61, 0x80, 0x0c, 0x41, 0x80, 0x0c, 0x41, 0x80, 0x0c, 0x01, 0x80, 0x0c, 
	0x01, 0x80, 0x0c, 0x01, 0x80, 0x0f, 0xff, 0x80, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00
};
const unsigned char advert [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x90, 0x00, 0x01, 0x98, 0x00, 0x03, 
	0x0c, 0x00, 0x02, 0x64, 0x00, 0x06, 0x66, 0x00, 0x04, 0x62, 0x00, 0x0c, 0x63, 0x00, 0x18, 0x61, 
	0x80, 0x18, 0x61, 0x80, 0x30, 0x60, 0xc0, 0x60, 0x00, 0x60, 0x60, 0x00, 0x60, 0xc0, 0x60, 0x30, 
	0xc0, 0x60, 0x30, 0xe0, 0x00, 0x70, 0x7f, 0xff, 0xe0, 0x00, 0x00, 0x00
};
void termistor()
{
  float Rth, average=0;  char i;                                                 
  for (i=0; i< NUMSAMPLES; i++) { samples[i] = analogRead(te); } 
  for (i=0; i< NUMSAMPLES; i++) { average += samples[i]; }
  average /= NUMSAMPLES;                                                        
  Rth = (ADC * float(THERMISTOR)/average)-float(THERMISTOR);      //Valor de Rth en funcion del conexionado de nuestro termistor
  steinhart = (1/((1/298.15)+(1/float(BCOEFFICIENT))*log(SERIESRESISTOR/Rth)))-273.15;                       //Aplicamos directamente Steinhart-hart para NTC                                           

  /* The easy circuit:
  *                  Analog pin A2
  *                         |
  *    GND |-----/\/\/\-----+-----/\/\/\-----| 5V
  *               ^                ^ 
  *           R termistor        10K resistor
  */
}
int fillArc2(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour)
{
 // x,y == coords of centre of arc
 // start_angle = 0 - 359
 // seg_count = number of 3 degree segments to draw (120 => 360 degree arc)
 // rx = x axis radius
 // yx = y axis radius
 // w  = width (thickness) of arc in pixels
 // colour = 8 bit colour value "WHITE"
  byte seg = 3; // Segments are 3 degrees wide = 120 segments for 360 degrees
  byte inc = 3; // Draw segments every 3 degrees, increase to 6 for segmented ring
    // Calculate first pair of coordinates for segment start
    float sx = cos((start_angle - 90) * DEG2RAD);
    float sy = sin((start_angle - 90) * DEG2RAD);
    uint16_t x0 = sx * (rx - w) + x;
    uint16_t y0 = sy * (ry - w) + y;
    uint16_t x1 = sx * rx + x;
    uint16_t y1 = sy * ry + y;
  // Draw colour blocks every inc degrees
  for (int i = start_angle; i < start_angle + seg * seg_count; i += inc) {
    // Calculate pair of coordinates for segment end
    float sx2 = cos((i + seg - 90) * DEG2RAD);
    float sy2 = sin((i + seg - 90) * DEG2RAD);
    int x2 = sx2 * (rx - w) + x;
    int y2 = sy2 * (ry - w) + y;
    int x3 = sx2 * rx + x;
    int y3 = sy2 * ry + y;
    display.fillTriangle(x0, y0, x1, y1, x2, y2, colour);
    display.fillTriangle(x1, y1, x2, y2, x3, y3, colour);
    // Copy segment end to sgement start for next segment
    x0 = x2;
    y0 = y2;
    x1 = x3;
    y1 = y3;
  }
}
void base(int volt)
{
  /* circuito divisor de voltaje:
  *                  Analog pin A1
  *                         |
  *    GND |-----/\/\/\-----+-----/\/\/\-----| 12V
  *               ^                ^ 
  *           1k termistor        10K resistor */

  Volt=constrain(Volt,10,14.7);     //centra solo un voltaje especifico
  ba=map(Volt,10,14,127,1);         //rango min y max de 10 a 14 voltios
  display.drawRect(0,60,128,4,1);   //barra exterior
  display.fillRect(ba,61,127,3,1);  //barra relleno
  display.drawBitmap(55,25,bat2,20,27,WHITE); // icono bateria
  display.setTextSize(1); display.setCursor(0,52);  display.print("100");
  display.setTextSize(1); display.setCursor(60,52);  display.print("50");
  display.setTextSize(1); display.setCursor(115,52);  display.print("10");
}

void setup() 
{
  pinMode(ni, INPUT); 
  pinMode(te, INPUT); pinMode(vo, INPUT);           // Configurados entradas analogicas
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.setTextSize(2); display.setCursor(30,25); display.print("HOLA!!"); 
  display.display();
  delay(2000); display.clearDisplay();
  EasyBuzzer.setPin(buzzer);                        //Selecciona el pin de salida
  EasyBuzzer.beep( 2000, 500, 500, 3, 1000, 5);     //Frecuencia en Hz, Duración beep ms                           
  EasyBuzzer.stopBeep();                            //Inicia buzzer en modo off
  timer = millis();  timer2 = millis();  timer3 = millis();
  
}

void loop() 
{
  if (millis() > timer) 
  {
    while (sample_count < NUM_SAMPLES){sum += analogRead(ni); sample_count++;}
    p =((float)sum / (float)NUM_SAMPLES * Vref)/ADC;          // Promedio de muestras tomadas 
    m = constrain(p, 0.44, 3.0)*10;                        //rango de voltaje y multiplica rango x10
    Nivel=map(m,4.4, 30, 1,100);
    Nivel1=map(Nivel,1,100,8,48);
    sample_count = 0; sum = 0;                           // Reestablece los contadores
    timer = millis() + 5000UL;                       // Refresco cada 5s
  }
 //****************************************************************************************///  
  if (millis() > timer2) 
  {
    while (sample_count < NUM_SAMPLES){sum += analogRead(vo); sample_count++;}
    p3 =((float)sum / (float)NUM_SAMPLES * Vref)/ADC;          // Promedio de muestras tomadas
    Volt = p3/((float)RV2/(RV1+RV2));                        // Lectura Voltaje final
    sample_count = 0; sum = 0;                           // Reestablece los contadores
   timer2 = millis() + 3000UL;                       // Refresco cada 3s
  }
 //****************************************************************************************
    if (millis() > timer3) 
{
  base(vo);
  termistor();

  fillArc2(25,25,200,Nivel,25,25,3,WHITE); // Nivel
 
  temp= map(steinhart,30,115,1,100);
  fillArc2(102,25,200,temp,25,25,3,WHITE); // Tempertura

  display.setTextSize(2); display.setCursor(9,20); display.print(Nivel1);  display.print("L");
  display.setTextSize(2); display.setCursor(85,20); display.print(steinhart,0);
  display.setTextSize(1); display.println("o"); //display.print((char)247); // degree symbol 
  if (indicador==true)  {display.drawBitmap(54,0,advert,20,20,WHITE);} 
  display.display();   // Actualiza la pantalla
   timer3 = millis() + 500UL;                       // Refresco cada 500ms
  display.clearDisplay();
  }
  //Condicionales para alarma buzzer e indicación !
  if (Volt<10.2 || Nivel1<=10) {EasyBuzzer.update(); indicador=true;}  
  if (Volt>10.3 || Nivel1>=11) {EasyBuzzer.stopBeep();}
  if (steinhart>95) {EasyBuzzer.update(); indicador=true; }  
  if (steinhart<94 && Nivel1>=10) {EasyBuzzer.stopBeep(); indicador=false;}
 
}