////////////////////////////////////////////////////////////////////////////////////////
//////////////Barbecue automatizzato pellet/cippato carbonella/legna////////////////////
///////////////////////////AdbProject BAGLIVO///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
#include <SPI.h>
#include "Nextion.h"
#include  <Servo.h>
#include <Thermistor.h>
#include <NTC_Thermistor.h>

///////////////////TEMPERATURA MAX6675////////////////////////////////
int SO = PA6;
int CS = PA4;
int SLK = PA5;
///////////////////TEMPERATURA-LIBRERIA-THERMISTOR///////////////////////////////////////
#define SONDA_1 PA1 //SONDA1
#define SONDA_2 PB0  //SONDA2

#define RESISTENZA_SONDA1 8000   //RESISTENZA PULL-UP
#define RESISTENZA_NTC1 100000 //RESISTENZA NTC
#define RESISTENZA_SONDA2 8000   //RESISTENZA PULL-UP
#define RESISTENZA_NTC2 100000 //RESISTENZA NTC
#define NOMINAL_TEMPERATURE 25     //TEMPERATURA NTC
#define B_VALUE 3950   //VALORE NTC
#define STM32_ANALOG_RESOLUTION 4095

Thermistor* thermistor1; //SONDA1
Thermistor* thermistor2; //SONDA2

int tempSonda1;
int percentualeSonda1 = 0;
int percentualeSonda2 = 0;
int tempSonda2;
int tempCamera;


/////////////////////////////////////////////////////////////////////////////////////////

#define coclea PB3              // imposto il pin PB6 per la coclea serbatoio 220v on/off
#define candela PB7             // imposto il pin PB7 per la candeletta accensione 220v on/off
#define aspiratore PB8              // imposto il pin PB8 per il pwm fumi 12v
#define girarrosto PB13              // imposto il pin PB12 per il girarrosto 220v on/off
#define buzzer PB11             // imposto il pin PB11 buzzer


Servo servo;
////////////////////////////////////////////////////////////////////////////////////////////////////////
int fiamma = 0;                  //per capire se la fiamma è presente
int pwmFumi = 0;                 //per la velocita dell`aspiratore
int termost = HIGH;             //allarme temperatura
boolean modalitaStandby=false;           //per capire se la barbecue e` false=lavoro true=standby

unsigned int setTcocleaOn;               //variabile per impostare il tempo on caduta pellet in base alla potenza impostata sul display
unsigned int setTcocleaOff;              //variabile per impostare il tempo off caduta pellet in base alla potenza impostata sul display


boolean allarmeOn = true;           //per capire se sono se e` in fase di accensione
unsigned long OldStartBuzzer = 0;
boolean buzzerOff=false;
unsigned long OldStartBuzzerOn = 0; 

boolean PrimoCicloON = true;           //per capire se sono se e` in fase di accensione
unsigned long OldStartAccenditore = 0;


boolean CocleaCicloON = true ;
unsigned long OldStartCoclea = 0;

boolean Spellet = true ;
unsigned long OldStartSpellet = 0;

boolean readSonde = true ;
unsigned long OldStartSonde = 0;

uint32_t Vstato = 0;//per salvare il valore proveniente dal display e capire se la barbecue e` 1=accesa o 0=spenta
uint32_t pellet_legna;//per salvare il valore proveniente dal display 0=pellet 1=legna
uint32_t pwmM;//per salvare il valore proveniente dal display aspiratore 0=automatico 1=manuale
uint32_t pwmFumiM;//per salvare il valore proveniente dal display aspiratore 0-100%
uint32_t servoM;//per salvare il valore proveniente dal display aspiratore 0=automatico 1=manuale
uint32_t servoariaM;//per salvare il valore proveniente dal display servoaria 0-170gradi
uint32_t girarrostoOnOff;//per salvare il valore proveniente dal display del radioButton girarrosto 0=spento 1=acceso
uint32_t setSonda1;//per salvare il valore di set proveniente dal display della sonda 1
uint32_t setSonda2;//per salvare il valore di set proveniente dal display della sonda 2
uint32_t onOffSonda1;//per salvare il valore proveniente dal display del radioButton della sonda 1 0=non usata 1=usata
uint32_t onOffSonda2;//per salvare il valore proveniente dal display del radioButton della sonda 2 0=non usata 1=usata
uint32_t setCamera;//per salvare il valore di set proveniente dal display della camera


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NexVariable onOff = NexVariable(0, 18, "home.onOff"); //PER LEGGERE LO STATO 1=ON 0=OFF
NexVariable peLe = NexVariable(0, 22, "home.peLe"); //PER CAPIRE SE E`IN FUNZIONE 0=PELLET 1=LEGNA
NexVariable fan = NexVariable(1, 9, "aspiratore.fan"); //PER SALVARE LA PERCENTUALE DELLA VELOCITA ASPIRATORE
NexVariable air = NexVariable(2, 9, "aria.air"); //PER SALVARE LA PERCENTUALE DI APERTURA SERVO ARIA

NexNumber n0 = NexNumber(0, 6, "home.n0"); // STAMPO AL DISPLAY LA PERCENTUALE DELLA VELOCITA ASPIRATORE
NexNumber n1 = NexNumber(0, 9, "home.n1"); // STAMPO AL DISPLAY LA PERCENTUALE DELL` APERTURA BOCCHETTA ARIA INGRESSO
NexNumber n2 = NexNumber(0, 25, "home.n2"); // TEMPERATURA CAMERA
NexNumber n3 = NexNumber(0, 12, "home.n3"); // TEMPERATURA SONDA 2
NexNumber n4 = NexNumber(0, 15, "home.n4"); // TEMPERATURA SONDA 1
NexNumber n5 = NexNumber(0, 27, "home.n5"); // PERCENTUALE DI COTTURA SONDA 1 CALCOLATA IN BASE ALLA TEMPERATURA DI SET E QUELLA RILEVATA
NexNumber n6 = NexNumber(0, 29, "home.n6"); // PERCENTUALE DI COTTURA SONDA 2 CALCOLATA IN BASE ALLA TEMPERATURA DI SET E QUELLA RILEVATA
NexNumber n40 = NexNumber(3, 3, "set.n40"); // TEMPERATURA SETTATA PER LA SONDA 1
NexNumber n41 = NexNumber(3, 8, "set.n41"); // TEMPERATURA SETTATA PER LA SONDA 2
NexNumber n42 = NexNumber(3, 13, "set.n42"); // TEMPERATURA SETTATA PER LA CAMERA

NexText t12 = NexText(0, 17, "home.t12");  //PER STAMPARE LO STATO SUL DISPLAY LAVORO/ACCENSIONE/ECC....

NexRadio r0 = NexRadio(0, 2, "home.r0");//PER SEGNALARE CHE LA COCLEA E` ACCESA
NexRadio r1 = NexRadio(0, 32, "home.r1");//PER ACCENDER/SPEGNERE IL GIRARROSTO
NexRadio r2 = NexRadio(0, 4, "home.r2");//PER SEGNALARE CHE LA CANDELETTA E` ACCESA
NexRadio r30 = NexRadio(1, 3, "aspiratore.r30");//PER azionare l`aspiratore manualmente
NexRadio r40 = NexRadio(2, 3, "aria.r40");//PER AZIONARE IL SERVOMOTORE ARIA INGRESSO MANUALMENTE
NexRadio r50 = NexRadio(3, 17, "set.r50");//PER capire se la sonda 1 e` in funzione
NexRadio r51 = NexRadio(3, 18, "set.r51");//PER capire se la sonda 2 e` in funzione

char buffer[100] = {0};

/////////////////////////////////////////////////////////////////////////////////////////

NexTouch *nex_listen_list[] =
{ &onOff,
  &peLe,
  &fan,
  &air,
  &n0,
  &n1,
  &n2,
  &n3,
  &n4,
  &n5,
  &n6,
  &n40,
  &n41,
  &n42,
  &t12,
  &r0,
  &r1,
  &r2,
  &r30,
  &r40,
  &r50,
  &r51,
  NULL
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
 Serial.begin(9600);
  nexInit();
  servo.attach(PB1);

   thermistor1 = new NTC_Thermistor(
    SONDA_1,
    RESISTENZA_SONDA1,
    RESISTENZA_NTC1,
    NOMINAL_TEMPERATURE,
    B_VALUE,
    STM32_ANALOG_RESOLUTION // ADC 12BIT RISOLUZIONE 4095
  );

   thermistor2 = new NTC_Thermistor(
    SONDA_2,
    RESISTENZA_SONDA2,
    RESISTENZA_NTC2,
    NOMINAL_TEMPERATURE,
    B_VALUE,
    STM32_ANALOG_RESOLUTION // ADC 12BIT RISOLUZIONE 4095
  );


  pinMode(coclea, OUTPUT);
  pinMode(candela, OUTPUT);
  pinMode(aspiratore, OUTPUT);
  pinMode(girarrosto, OUTPUT);
  pinMode(buzzer, OUTPUT);


  ///////////////////////////////////////////////////

  digitalWrite(coclea, LOW);
  digitalWrite(candela, LOW);
  analogWrite(aspiratore,0);
  digitalWrite(girarrosto, LOW);
  digitalWrite(buzzer, LOW);


  delay(500);

}
/////////////////Libreria max 6675///////////////////////////////
double readCelsiusMax6675(void) {
  uint16_t v;
  pinMode(CS, OUTPUT);
  pinMode(SO, INPUT);
  pinMode(SLK, OUTPUT);
  
  digitalWrite(CS, LOW);
  delay(1);
  v = spiread();
  v <<= 8;
  v |= spiread();
  digitalWrite(CS, HIGH);
  if (v & 0x4) 
  {    
  return NAN; //SENSORE MAX6675 SCOLLEGATO   
  }
  v >>= 3;
  return v*0.25;
}

/*/double readFahrenheitMax6675(void) {
  return readCelsiusMax6675() * 9.0/5.0 + 32;
}*/

byte spiread(void) { 
  int i;
  byte d = 0;

  for (i=7; i>=0; i--)
  {
    digitalWrite(SLK, LOW);
    delay(1);
    if (digitalRead(SO)) {
      d |= (1 << i);
    }
    digitalWrite(SLK, HIGH);
    delay(1);
  }

  return d;
}
/////////////////////////////////////////////////////////////////////////////////////////
void loop() {


  
  nexLoop(nex_listen_list);
  onOff.getValue(&Vstato);//vedo sul display se e`impostata la modalita 0=pellet 1=legna
  n42.getValue(&setCamera);//vedo sul display il set temperatura impostato per la camera
  
  ////////////////girarrosto////////////////////
  r1.getValue(&girarrostoOnOff);//vedo sul display se r1 0=spento 1=acceso
  if(girarrostoOnOff==0){
    digitalWrite(girarrosto,LOW);
  }else if(girarrostoOnOff==1){
    digitalWrite(girarrosto,HIGH);
  }

  /////////////////////////////////////////////CALCOLO PERCENTUALI COTTURA SONDE/////////////////////////////////////////////////////////////////////
  r50.getValue(&onOffSonda1);//vedo sul display il radioButton della sonda 1 0=non usata 1=usata
  r51.getValue(&onOffSonda2);//vedo sul display il radioButton della sonda 2 0=non usata 1=usata
  ///////////////////////////////////////////////////////////////////////////////////////
  if(onOffSonda1==1){
   n40.getValue(&setSonda1);//vedo sul display il set temperatura impostato per la sonda 1
   percentualeSonda1=(100/setSonda1)*tempSonda1;
   n5.setValue(percentualeSonda1);
   
  if(percentualeSonda1>=100){//se la cottura e` arrivata al 100%
    buzzerOff=true;
    r50.setValue(0);
  }
  }
  ///////////////////////////////////////////////////////////////////////////////////////
  if(onOffSonda2==1){
   n41.getValue(&setSonda2);//vedo sul display il set temperatura impostato per la sonda 2
   percentualeSonda2=(100/setSonda2)*tempSonda2;
   n6.setValue(percentualeSonda2);

  if(percentualeSonda2>=100){//se la cottura e` arrivata al 100%
    buzzerOff=true;
    r51.setValue(0);
  }
  }

  //////////////eseguo la lettura delle sonde ogni 5 secondi////////
     if (readSonde) {      
        OldStartSonde = millis();
        readSonde=false;
      }

     if((millis() - OldStartSonde) > 500 ){ 
     ////////////////temp sonda 1//////////////////
     tempSonda1 = thermistor1->readCelsius();
     n4.setValue(tempSonda1);

     ////////////////temp sonda 2//////////////////
     tempSonda2 = thermistor2->readCelsius();
     n3.setValue(tempSonda2);

     ////////////////temp camera//////////////////
     //tempCamera = readFahrenheitMax6675();
     tempCamera = readCelsiusMax6675();
     n2.setValue(tempCamera);
     
     readSonde=true;//RESETTO IL CONTEGGIO
  }

  if(Vstato== 1){
       lavoro();
  }else{
      spegnimento();  
  }
  

  //app();

  if (OldStartCoclea > millis()) { //se millis si resetta
    OldStartCoclea = millis();
  }

  if (OldStartAccenditore > millis()) { //se millis si resetta
    OldStartAccenditore = millis();
  }

  if (OldStartSpellet > millis()) { // se millis si resetta
    OldStartSpellet = millis();
  }
  if (OldStartBuzzer > millis()) { // se millis si resetta
    OldStartBuzzer = millis();
  }

  if (OldStartBuzzerOn > millis()) { // se millis si resetta
    OldStartBuzzerOn = millis();
  }

  if (OldStartSonde > millis()) { // se millis si resetta
    OldStartSonde = millis();
  }

  
   if(buzzerOff==true){
    buzzerAllarm();
    if((millis() - OldStartBuzzerOn) > 50000 ){
      buzzerOff=false;
    }
  }else{
    OldStartBuzzer = millis();
  }
  //dbSerial.flush();//pulisci la seriale
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                           ///buzzer per segnalare che le sonde hanno raggiunto la temperatura desiderata///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void buzzerAllarm(){
       if (allarmeOn) {      
        OldStartBuzzer = millis();
      }
      allarmeOn=false;

       if((millis() - OldStartBuzzer) > 1000 ){ 
         digitalWrite(buzzer, HIGH); //SPENGO IL BUZZER 
       }else{                                      
         digitalWrite(buzzer, LOW); //ACCENDO IL BUZZER 
        }
       if((millis() - OldStartBuzzer) > 2000){
         allarmeOn=true;
       }                                             
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                             //MODALITA barbecue ACCESA//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void lavoro() {
  
  peLe.getValue(&pellet_legna);//vedo sul display se e`impostata la modalita 0=pellet/cippato 1=legna/carbonella
  
  if (PrimoCicloON) { // se è la prima volta che entro nello stato ON
    OldStartAccenditore = millis();
    PrimoCicloON = false;
  }

  if(CocleaCicloON){ 
     OldStartCoclea = millis();   //Tiene in memoria l'ultima accensione 
     CocleaCicloON=false;
  }

  if (fiamma == 0) {//se ancora la fiamma non e` presente
    pwmFumi = 200;
    t12.setText("ACCENSIONE");
    accensione();//avvio il ciclo di accensione
    servo.write(100);//apro al massimo l`aria
    n1.setValue(100);
  } else { //se la temperatura ha superato i 45gradi vuol dire che la fiamma e` presente
    cicloLavoro();
  }

   analogWrite(aspiratore, pwmFumi);
   n0.setValue(map(pwmFumi,0,255,0, 100));//percentuale aspiratore

}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                           //CICLO LAVORO//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void cicloLavoro(){
  
  if(modalitaStandby==false){//se la barbecue non e in modalita` standby
      int outputServo=map(tempCamera,20,setCamera,100, 0);//percentuale aspiratore
      int resultServo=constrain(outputServo, 0, 100);
      servo.write(resultServo);
      n1.setValue(resultServo);
  if (pellet_legna == 0) { //se e` in modalita pellet
      int TcocleaOn=1000;
      int TcocleaOff=8000;

      
      if(tempCamera<setCamera-10){
        TcocleaOn=1000;
        TcocleaOff=8000;
        pwmFumi = 150;
        t12.setText("LAVORO");
      }else if((tempCamera>=setCamera-10)&&(tempCamera<setCamera+1)){
        TcocleaOn=1000;
        TcocleaOff=10000;
        pwmFumi = 100;
        t12.setText("LAVORO MODULA");
      }else if(tempCamera>=setCamera+2){
        modalitaStandby=true;
      }
      
       if((millis() - OldStartCoclea) < TcocleaOn ){ 
         digitalWrite(coclea, HIGH);
         r0.setValue(1);//coclea on
       }else{                                                 //MODALITA AUTOMATICA STATO LAVORO MODULA
         digitalWrite(coclea, LOW);
         r0.setValue(0);//coclea off
        }
       if((millis() - OldStartCoclea) > TcocleaOff){
         CocleaCicloON=true;
       } 
       
  }else if (pellet_legna == 1) { //se e` in modalita legna
      
      digitalWrite(coclea,LOW);
      r0.setValue(0);//coclea off
      
      if(tempCamera<setCamera-10){
        pwmFumi = 150;
        t12.setText("LAVORO");
      }else if((tempCamera>=setCamera-10)&&(tempCamera<setCamera+1)){
        pwmFumi = 100;
        t12.setText("LAVORO MODULA");
      }else if(tempCamera>=setCamera+2){
        modalitaStandby=true;
      }
  }
  
 }else{//altrimenti se il barbecue e` in modalita` standby 
  standby(); //eseguo il ciclo standby
 }


}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                           //modalita` standby//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void standby() {
  if(tempCamera>setCamera-4){
    digitalWrite(coclea, LOW);
    pwmFumi = 0;
    t12.setText("STANDBY");
    servo.write(0);
    n1.setValue(0);
  }else{
    modalitaStandby=false;//riporto il barbecue in modalita` lavoro
  }
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                           //SPEGNIMENTO//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void spegnimento() {
      Spellet = true;
      t12.setText("SPENTO");
      fiamma=0;
      r30.getValue(&pwmM);//0=pwm automatico / 1=pwm manuale
      fan.getValue(&pwmFumiM);//0-100
      r40.getValue(&servoM);//0=servoaria automatico / 1=aervoaria manuale
      air.getValue(&servoariaM);//0-170gradi
      if (servoM == 0) { //se e` in modalita automatica
        servo.write(0);// chiudo l`aria d`ingresso
        n1.setValue(0);
      } else if (servoM == 1) { //se e` in modalita manuale
        servo.write(servoariaM);//Imposto il valore d`apertura rilevato dal display
        n1.setValue(servoariaM);
      }
      if (pwmM == 0) { //se e` in modalita automatica
        analogWrite(aspiratore,0); //SPENGO L'ASPIRATORE
        n0.setValue(0);
      } else if (pwmM == 1) { //se e` in modalita manuale
        int pwmOut = map(pwmFumiM, 0, 100, 0, 200);
        analogWrite(aspiratore, pwmOut);
        n0.setValue(map(pwmOut, 0, 255, 0, 100));
      }
      digitalWrite(candela, LOW);
      r2.setValue(0); //candeletta spento
      digitalWrite(coclea, LOW);
      r0.setValue(0);//coclea serbatoio
      PrimoCicloON = true;
      CocleaCicloON = true;
  
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                         //ACCENSIONE//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void accensione() {
  ////////////procedo con la prima accensione/////////////////////////////////////////////////
  if ((millis() - OldStartAccenditore) < 900000) {  // se non sono trascorsi 15 minuti
    if (tempCamera < 45) {
      cocleePrimaAccensione();  
      digitalWrite(candela, HIGH);
      r2.setValue(1); //candeletta accesa
    } else if (tempCamera >= 48) {
      digitalWrite(candela, LOW);
      r2.setValue(0); //candeletta spenta
      fiamma=1;//segnalo che la fiamma e` presente
    }
  } else {
    digitalWrite(candela, LOW);
    r2.setValue(0); //candeletta spenta
      if (tempCamera >= 48) {
        fiamma=1;//segnalo che la fiamma e` presente
      }
  }




}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////eseguo il ciclo delle coclee per la prima accensione///////////////////////////////////////////////////

void cocleePrimaAccensione() {
  if (pellet_legna == 0) { //se e` in modalita pellet

    if ((millis() - OldStartCoclea) < 215000 ) {
      if ((millis() - OldStartCoclea) < 140000 ) {
        r0.setValue(1);//coclea serbatoio
        digitalWrite(coclea, HIGH); //coclea serbatoio
      } else {
        r0.setValue(0);//coclea serbatoio
        digitalWrite(coclea, LOW); //coclea serbatoio
      }
    } else {
      r0.setValue(0);//coclea serbatoio
      digitalWrite(coclea, LOW); //coclea serbatoio

    }
  }
}
