////////////////////////////////////////////////////////////////////////////////////////
//////////////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 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 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

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 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 ventola 0=automatico 1=manuale
uint32_t pwmFumiM;//per salvare il valore proveniente dal display ventola 0-100%
uint32_t ventOnOff;//per salvare il valore proveniente dal display ventola 0=spenta 1=accesa
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 resetAllarmi;//per salvare il valore proveniente dal display del tasto reset
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, 14, "home.onOff"); //PER LEGGERE LO STATO 1=ON 0=OFF
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, 2, "home.n0"); // STAMPO AL DISPLAY LA PERCENTUALE DELLA VELOCITA ASPIRATORE
NexNumber n1 = NexNumber(0, 5, "home.n1"); // STAMPO AL DISPLAY LA PERCENTUALE DELL` APERTURA BOCCHETTA ARIA INGRESSO
NexNumber n2 = NexNumber(0, 19, "home.n2"); // TEMPERATURA CAMERA
NexNumber n3 = NexNumber(0, 8, "home.n3"); // TEMPERATURA SONDA 2
NexNumber n4 = NexNumber(0, 11, "home.n4"); // TEMPERATURA SONDA 1
NexNumber n5 = NexNumber(0, 21, "home.n5"); // PERCENTUALE DI COTTURA SONDA 1 CALCOLATA IN BASE ALLA TEMPERATURA DI SET E QUELLA RILEVATA
NexNumber n6 = NexNumber(0, 23, "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, 13, "home.t12");  //PER STAMPARE LO STATO SUL DISPLAY LAVORO/ACCENSIONE/ECC....

NexRadio r1 = NexRadio(0, 26, "home.r1");//PER ACCENDER/SPEGNERE IL GIRARROSTO
NexRadio r2 = NexRadio(0, 30, "home.r2");//PER ACCENDER/SPEGNERE L`ASPIRATORE
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,
  &fan,
  &air,
  &n0,
  &n1,
  &n2,
  &n3,
  &n4,
  &n5,
  &n6,
  &n40,
  &n41,
  &n42,
  &t12,
  &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(aspiratore, OUTPUT);
  pinMode(girarrosto, OUTPUT);
  pinMode(buzzer, OUTPUT);


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

  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
  r30.getValue(&pwmM);//0=pwm automatico / 1=pwm manuale
  r2.getValue(&ventOnOff);//0=ventola on / 1=ventola off
  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 (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();
  }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                           ///buzzer per segnalare che le sonde hanno raggiunto la temperatura desiderata///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
   if(buzzerOff==true){
      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;
       }  
    if((millis() - OldStartBuzzerOn) > 50000 ){
      buzzerOff=false;
    }
  }else{
    OldStartBuzzer = millis();
  }
  //dbSerial.flush();//pulisci la seriale
}




//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                           //CICLO LAVORO//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void lavoro(){

  if(modalitaStandby==false){//se la barbecue non e in modalita` standby
      int outputServo=map(tempCamera,setCamera-50,setCamera,100, 0);//percentuale aspiratore
      int resultServo=constrain(outputServo, 0, 100);
      servo.write(resultServo);
      n1.setValue(resultServo);

      if(tempCamera<setCamera-10){
        pwmFumi = 60;
        t12.setText("LAVORO");
      }else if((tempCamera>=setCamera-10)&&(tempCamera<setCamera+1)){
        pwmFumi = 40;
        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
 }
      
      if (ventOnOff == 0) { //se l`aspiratore e` spento
        analogWrite(aspiratore,0); //SPENGO L'ASPIRATORE
        n0.setValue(0);
      } else if (ventOnOff == 1) { //se e` l`aspiratore e` acceso
        analogWrite(aspiratore, pwmFumi);
        n0.setValue(map(pwmFumi, 0, 230, 0, 100));
      }

}

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


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                           //SPEGNIMENTO//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void spegnimento() {
      t12.setText("SPENTO");
      fan.getValue(&pwmFumiM);//0-100
      r40.getValue(&servoM);//0=servoaria automatico / 1=servoaria 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));
      }

}
