//pins
#define BUZZER_PIN 23
#define RELAY_GRILL 22
#define RELAY_GENERALE 21
#define RELAY_TOP 19
#define RELAY_BOTTOM 18
#define RELAY_FRONT_RG 05
#define RELAY_FRONT 17
#define RELAY_LUCE 16
#define RELAY_RAFFREDDAMENTO 04
#define RELAY_MOT_VENT 15
#define BUTTON_TT 39
#define BUTTON_UP 34
#define BUTTON_DOWN 35
#define BUTTON_START 33
#define BUTTON_SELECT 32
#define TEMP_PIN 36
#define LED_PIN 02
const int rs = 13, en = 12, d4 = 14, d5 = 27, d6 = 26, d7 = 25;
#define Acceso HIGH
#define Spento LOW
#define TEMP_READ_DELAY 1000 //can only read digital temp sensor every ~750ms
//pid settings and gains
#define dPulseWidth 5000
#define dKp .065
#define dKi .00015
#define dKd .5
#include "pitches.h"
#include <LiquidCrystal.h>
#include <AutoPID.h>
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int iMaxTimeRelAct = 120000;
unsigned long lastTempUpdate, lastTempRelay; //tracks clock time of last temp update
uint32_t deltaTime;
const int numSamples = 50; // Numero di campioni da acquisire per ogni lettura
u_long sensorValue;
int averageValue;
double dTempCorr = 0;
double dTargetTemp = 0;
int cookingTime = 0;
int remainingTime = 0;
int sec = 0;
int iSuonaNTR = 0;
bool bCookingStarted = false, bCookingFinished = false;
bool bTempReached = false, bSuonaTR = false;
bool bRelayControl, bLastRelayStatus, bPrograming, bRelayStop, bHeating, bCooling;
bool bSetTT;
AutoPIDRelay myPIDR(&dTempCorr, &dTargetTemp, &bRelayControl, dPulseWidth, dKp, dKi, dKd);
struct Program {
int temperature;
int time;
String strProg;
};
Program programs[] = {
{ 175, 50, "Ventilato" }, // Programma 1: Ventilato
{ 200, 90, "Tradizionale" }, // Programma 2: Tradizionale/Sopra-Sotto
{ 220, 35, "Pane/Pizza" }, // Programma 3: Pane/Pizza/Sotto-Ventilato
{ 170, 60, "Pasticceria" }, // Programma 4: Pasticceria/Sopra-Sotto-Ventilato
{ 180, 45, "Sopra Sotto Ventilato" }, // Programma 5: Sopra Sotto Ventilato
{ 170, 45, "Grill Ventilato" }, // Programma 6: Grill Ventilato
{ 250, 10, "Grill" }, // Programma 7: Grill
{ 170, 60, "Sopra" }, // Programma 8: Sopra
{ 170, 60, "Sotto" }, // Programma 9: Sotto
};
int programIndex = 0;
int numPrograms = sizeof(programs) / sizeof(programs[0]);
/*/ notes in the melody:
int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};
*/
int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};
int note[] = { NOTE_A4, NOTE_A4, NOTE_A4, NOTE_F4, NOTE_C5, NOTE_A4, NOTE_F4, NOTE_C5, NOTE_A4,
NOTE_E5, NOTE_E5, NOTE_E5, NOTE_F5, NOTE_C5, NOTE_A4, NOTE_F4, NOTE_C5, NOTE_A4,
NOTE_A5, NOTE_A4, NOTE_A4, NOTE_A5, NOTE_GS5, NOTE_G5,
NOTE_DS5, NOTE_D5, NOTE_DS5, 0, NOTE_A4, NOTE_DS5, NOTE_D5, NOTE_CS5,
NOTE_C5, NOTE_B4, NOTE_C5, 0, NOTE_F4, NOTE_GS4, NOTE_F4, NOTE_A4,
NOTE_C5, NOTE_A4, NOTE_C5, NOTE_E5,
NOTE_A5, NOTE_A4, NOTE_A4, NOTE_A5, NOTE_GS5, NOTE_G5,
NOTE_DS5, NOTE_D5, NOTE_DS5, 0, NOTE_A4, NOTE_DS5, NOTE_D5, NOTE_CS5,
NOTE_C5, NOTE_B4, NOTE_C5, 0, NOTE_F4, NOTE_GS4, NOTE_F4, NOTE_A4,
NOTE_A4, NOTE_F4, NOTE_C5, NOTE_A4
}; //inserire la nota PAUSE per inserire una pausa nello spartito
int tempi[] = { 4, 4, 4, -8, 16, 4, -8, 16, 2, 4, 4, 4, -8, 16, 4, -8, 16, 2, 4, -8, 16, 4, -8, 16,
16, 16, 8, 8, 8, 4, -8, 16, 16, 16, 16, 8, 8, 4, -8, -16, 4, -8, 16, 2,
4, -8, 16, 4, -8, 16,
16, 16, 8, 8, 8, 4, -8, 16,
16, 16, 16, 8, 8, 4, -8, -16,
4, -8, 16, 2
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 8, 8, 4, 4, 4, 4, 4
};
int melody2[] = {
NOTE_AS7, NOTE_B7, NOTE_C8, 0, NOTE_C8, NOTE_B7, NOTE_AS7, 0
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations2[] = {
8, 8, 8, 8, 8, 8, 8, 8
};
// Variabili globali per tracciare lo stato della melodia
unsigned long previousMillis = 0, previousMillisT = 0; // Tempo dell'ultimo aggiornamento
int currentNote = 0; // Indice della nota corrente
bool notePlaying = false; // Stato della nota (se sta suonando o meno)
unsigned long noteDuration = 0; // Durata della nota corrente
bool melodyPlaying = true; // Indica se la melodia sta suonando
float alpha = 0.1; // Peso della lettura più recente
// Variables will change:
int ledState = HIGH; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = HIGH; // the previous reading from the input pin
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0, deltaT = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(RELAY_FRONT, OUTPUT);
pinMode(RELAY_GENERALE, OUTPUT);
pinMode(RELAY_TOP, OUTPUT);
pinMode(RELAY_GRILL, OUTPUT);
pinMode(RELAY_BOTTOM, OUTPUT);
pinMode(RELAY_FRONT_RG, OUTPUT);
pinMode(RELAY_LUCE, OUTPUT);
pinMode(RELAY_RAFFREDDAMENTO, OUTPUT);
pinMode(RELAY_MOT_VENT, OUTPUT);
digitalWrite(RELAY_FRONT, Spento);
digitalWrite(RELAY_GENERALE, Spento);
digitalWrite(RELAY_TOP, Spento);
digitalWrite(RELAY_GRILL, Spento);
digitalWrite(RELAY_BOTTOM, Spento);
digitalWrite(RELAY_FRONT_RG, Spento);
digitalWrite(RELAY_LUCE, Spento);
digitalWrite(RELAY_RAFFREDDAMENTO, Spento);
digitalWrite(RELAY_MOT_VENT, Spento);
pinMode(BUTTON_UP, INPUT);
pinMode(BUTTON_DOWN, INPUT);
pinMode(BUTTON_START, INPUT_PULLUP);
pinMode(BUTTON_SELECT, INPUT_PULLUP);
pinMode(BUTTON_TT, INPUT);
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32!");
//dTempCorr = getCurrentTemperature();
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Selez. programma");
//Suona(note, tempi);
// Chiamata alla funzione passando gli array e la loro dimensione
//Suona(note, tempi, sizeof(note) / sizeof(note[0]),120);
//Suona(melody2, noteDurations2, sizeof(melody2) / sizeof(melody2[0]));
//SuonaNB(melody, noteDurations, sizeof(melody) / sizeof(melody[0]), 240);
}
void SuonaNB(int Note[], int Tempi[], int NumNote, int Tempo) {
unsigned long currentMillis = millis();
int wholenote = (60000 * 4) / Tempo;
int divider = 0;
if (!notePlaying) {
if (currentNote < NumNote) {
divider = Tempi[currentNote];
//noteDuration = (wholenote) / divider;
//noteDuration = 1000 / durations[currentNote];
if (divider > 0) {
// regular note, just proceed
noteDuration = (wholenote) / divider;
} else if (divider < 0) {
// dotted notes are represented with negative durations!!
noteDuration = (wholenote) / abs(divider);
noteDuration *= 1.5; // increases the duration in half for dotted notes
}
if (Note[currentNote] != 0) {
tone(BUZZER_PIN, Note[currentNote], noteDuration * 0.8);
}
previousMillis = currentMillis;
notePlaying = true;
} else {
// Reset al termine della melodia
currentNote = 0;
melodyPlaying = false; // Ferma la riproduzione della melodia
}
} else {
// Controlla se la durata della nota è terminata
if (currentMillis - previousMillis >= noteDuration) {
// Ferma la nota
//noTone(BUZZER_PIN);
// Passa alla prossima nota
currentNote++;
notePlaying = false;
}
}
}
void loop() {
// put your main code here, to run repeatedly:
delay(10); // this speeds up the simulation
if (melodyPlaying) SuonaNB(note, tempi, sizeof(note) / sizeof(note[0]), 120);
//handleButtons('x');
if (Serial.available()) {
handleButtons(Serial.read());
}
updateTemperature();
//dTempCorr = getCurrentTemperature();
if (dTargetTemp > 0) {
myPIDR.run(); //call every loop, updates automatically at certain time interval
digitalWrite(LED_PIN, myPIDR.atSetPoint(2)); //light up LED when we're at setpoint +-2 degree
} else {
myPIDR.stop();
}
updateTemperatureControl();
updateCoolingControl();
updateGeneralRelay();
/*
*/
}
void handleButtons(char cmd) {
if (digitalRead(BUTTON_SELECT) == LOW || cmd == 'p') {
selectProgram(1);
delay(200);
}
//------ premendo il tasto START...--------------------------
int reading = digitalRead(BUTTON_START);
/*
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
deltaT = (millis() - lastDebounceTime);
if (deltaT > debounceDelay && deltaT < 300) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == LOW) {
if (bCookingFinished) selectProgram(1);
if (bCookingStarted) {
// se SONO in cottura la fermo
Serial.println("StopCooking");
stopCooking();
} else if (bTempReached) {
// se HO già raggiunto la temp target avvio la cottura
Serial.println("StartCooking");
startCooking();
} else {
// se sono qui NON ho iniziato la cottura e NON ho raggiunto la temp
// quindi attivo o disattivo il riscaldamento
Heating();
}
bPrograming = false;
}
}
} else if (deltaT > debounceDelay && deltaT > 300 && deltaT < 310) {
startCooking();
delay(100);
}
*/
if (digitalRead(BUTTON_START) == LOW || cmd == 's') {
if (bCookingFinished) selectProgram(1);
if (bCookingStarted) {
// se SONO in cottura la fermo
Serial.println("StopCooking");
stopCooking();
} else if (bTempReached) {
// se HO già raggiunto la temp target avvio la cottura
Serial.println("StartCooking");
startCooking();
} else {
// se sono qui NON ho iniziato la cottura e NON ho raggiunto la temp
// quindi attivo o disattivo il riscaldamento
Heating();
}
delay(200);
//bPrograming = false;
}
//-----------------------------------------------------------
if (digitalRead(BUTTON_UP) == LOW && !bSetTT || cmd == 'u') {
dTargetTemp += 5;
delay(200);
selectProgram(0);
}
if (digitalRead(BUTTON_DOWN) == LOW && !bSetTT || cmd == 'd' || cmd == 'h') {
dTargetTemp -= 5;
delay(200);
selectProgram(0);
}
//-----------------------------------------------------------
if (digitalRead(BUTTON_UP) == LOW && bSetTT || cmd == 'i') {
if (!bCookingStarted) {
cookingTime += 5;
} else {
remainingTime += 5;
}
delay(200);
selectProgram(0);
}
if (digitalRead(BUTTON_DOWN) == LOW && bSetTT || cmd == 'j') {
if (!bCookingStarted) {
cookingTime -= 5;
} else {
remainingTime -= 5;
}
delay(200);
selectProgram(0);
}
//-----------------------------------------------------------
if ((digitalRead(BUTTON_SELECT) == LOW && digitalRead(BUTTON_START) == LOW) || cmd == 'r') {
ESP.restart();
delay(200);
}
if (digitalRead(BUTTON_TT) == LOW || cmd == 'l') {
bSetTT = !bSetTT;
delay(200);
}
}
void updateTemperature() {
unsigned long currentMillis = millis();
double temp = 0.0;
// Controlla se è passato l'intervallo di tempo specificato (100 ms) dall'ultima lettura
if (currentMillis - previousMillisT >= 100) {
previousMillisT = currentMillis;
// Fai una nuova lettura dall'ingresso analogico
int currentReading = analogRead(TEMP_PIN);
// Calcola la media mobile esponenziale
sensorValue = alpha * currentReading + (1 - alpha) * sensorValue;
temp = map(sensorValue, 0, 3476, 0, 2700);
dTempCorr = temp / 10;
}
}
double getCurrentTemperature() {
double temp = 0.0;
sensorValue = 0;
for (int i = 0; i < numSamples; i++) {
sensorValue += analogRead(TEMP_PIN);
delay(1); // Intervallo tra i campioni
}
averageValue = sensorValue / numSamples;
temp = map(averageValue, 0, 3476, 0, 2700);
return temp / 10;
}
void updateTimer() {
//if (remainingTime >= 0) {
if (remainingTime > 0 && sec == 0) {
remainingTime--;
sec = 60;
} else {
sec--;
}
//}
if (remainingTime == 0 && sec == 0) {
stopCooking();
}
Serial.print("Tempo rimanente: ");
Serial.print(remainingTime);
Serial.print(":");
Serial.print(sec);
Serial.println(" min");
}
void updateTemperatureControl() {
if (!bTempReached && dTempCorr >= dTargetTemp && dTargetTemp > 0) {
//se la temp di dest non è ancora raggiunta e la temp corrente è >= a temp dest, e temp dest > 0, allora il forno è pronto
bTempReached = true;
bSuonaTR = true;
} else if (bTempReached && (dTempCorr - dTargetTemp) < -5) {
Serial.print("Suona3: ");
Serial.print(iSuonaNTR);
bSuonaTR = false;
iSuonaNTR = 0;
Serial.print(" - ");
Serial.println(iSuonaNTR);
//if ((dTempCorr - dTargetTemp) < -5) bTempReached = false;
} else if (!bSuonaTR && dTempCorr >= dTargetTemp && dTargetTemp > 0) {
bSuonaTR = true;
}
if ((millis() - lastTempUpdate) > TEMP_READ_DELAY) {
lastTempUpdate = millis();
// se è in corso la cottura aggiorno iltimer del tempo rimasto
if (bCookingStarted) {
updateTimer();
}
Serial.printf("bTempReached: %o - bCookingStarted: %o - bCookingFinished: %o - bHeating: %o - bCooling: %o - bPrograming: %o - programIndex: %i - RELAY_GENERALE: %o\n", bTempReached, bCookingStarted, bCookingFinished, bHeating, bCooling, bPrograming, programIndex, digitalRead(RELAY_GENERALE));
// se sto selezionando i programmi salto momentaneamente la parte seguente
if (!bPrograming) {
Serial.printf("TC: %1f - TT: %1f - RS: %o - PW: %f - GI: %1f - KP: %1f - KI: %1f - KD: %1f\n", dTempCorr, dTargetTemp, bRelayControl, myPIDR.getPulseValue(), myPIDR.getIntegral(), dKp, dKi, dKd);
Serial.printf("%1f %1f\n", dTempCorr, dTargetTemp);
displayTemperature();
if (bTempReached && bSuonaTR && !bCookingStarted && !bCookingFinished) {
//se ho raggiunto la temp target e non ho ancora avviato la cottura e non ho già finito la cottura avviso che il forno è pronto
Serial.println("Temperatura desiderata raggiunta!");
Serial.println();
lcd.setCursor(0, 0);
lcd.print("Forno pronto ");
lcd.print(dTargetTemp);
lcd.blink();
if (iSuonaNTR < 1 && bHeating) {
iSuonaNTR += 1;
//Suona(2);
}
} else if (bHeating && !bTempReached && dTempCorr < dTargetTemp && dTargetTemp > 0) {
// se sono in riscaldamento, la temp corr è ancora < temp dest e temp dest > 0 allor sto ancora riscaldando il forno
//Serial.println("Riscaldamento forno in corso...");
lcd.setCursor(0, 0);
lcd.print("Riscald.to>> ");
lcd.print(dTargetTemp);
} else {
}
} else {
//return; // se sono in programmazione esco qui
}
}
}
void updateCoolingControl() {
if (dTempCorr > 100 && !bCooling) {
digitalWrite(RELAY_FRONT, Acceso);
digitalWrite(RELAY_RAFFREDDAMENTO, Acceso);
bCooling = true;
} else if (dTempCorr < 70 && bCooling) {
digitalWrite(RELAY_RAFFREDDAMENTO, Spento);
if (!bHeating) digitalWrite(RELAY_FRONT, Spento);
bCooling = false;
}
}
void updateGeneralRelay() {
if (!bHeating) {
if (digitalRead(RELAY_GENERALE) == Acceso) {
Serial.println("Spegnere Forno");
digitalWrite(RELAY_GENERALE, Spento);
}
return;
}
deltaTime = (millis() - lastTempRelay);
if (bRelayControl && !bRelayStop) {
if (deltaTime > iMaxTimeRelAct) {
// Se raggiungo il tempo massimo di relay attivo = iMaxTimeRelAct spengo per un po' a prescindere dal PID
lastTempRelay = millis();
deltaTime = 0;
bRelayStop = 1;
Serial.print("Relay Stop: ");
Serial.println(bRelayStop);
digitalWrite(RELAY_GENERALE, Spento); // relay spento
} else {
digitalWrite(RELAY_GENERALE, !bRelayControl); // relay gestito dal PID/Acceso
bLastRelayStatus = bRelayControl;
}
} else if (bRelayStop) {
if (deltaTime > iMaxTimeRelAct / 10) {
lastTempRelay = millis();
deltaTime = 0;
bRelayStop = 0;
}
} else {
digitalWrite(RELAY_GENERALE, !bRelayControl); // relay gestito dal PID/spento
if (bLastRelayStatus) {
bLastRelayStatus = bRelayControl;
lastTempRelay = millis();
} else {
}
}
/*
if (bRelayControl && !bRelayStop) {
deltaTime = (millis() - lastTempRelay);
if (deltaTime > iMaxTimeRelAct) {
// Se raggiungo il tempo massimo di relay attivo = iMaxTimeRelAct spengo per un po' a prescindere dal PID
lastTempRelay = millis();
deltaTime = 0;
bRelayStop = 1;
Serial.print("Relay Stop: ");
Serial.println(bRelayStop);
digitalWrite(RELAY_GENERALE, !Spento); // relay spento
} else {
digitalWrite(RELAY_GENERALE, !bRelayControl); // relay gestito dal PID/Acceso
}
} else if (bRelayStop) {
deltaTime = (millis() - lastTempRelay);
if (deltaTime > iMaxTimeRelAct / 10) {
lastTempRelay = millis();
deltaTime = 0;
bRelayStop = 0;
// digitalWrite(RELAY_GENERALE, !bRelayControl); // in teoria questa riga non serve, se tolgo la condizione di stop il ralay verrà gestito dal PID
}
} else {
lastTempRelay = millis();
deltaTime = 0;
digitalWrite(RELAY_GENERALE, !bRelayControl); // relay gestito dal PID/spento
bRelayStop = bRelayControl;
}
*/
}
void Heating() {
// se non sono impostati temperatura e tempo di cottura non parto
if (dTargetTemp < 1 || cookingTime < 1) return;
// accendo o spengo il reiscaldamento
bHeating = !bHeating;
Serial.println("Heating = " + String(bHeating));
myPIDR.reset();
Serial.println("PID reset");
if (!bHeating) {
bPrograming = true;
selectProgram(0);
} else {
bCookingFinished = false; // se inizio un ciclo di riscaldamento il ciclo dicottura non puo esere finito, lo azzero
bPrograming = false;
digitalWrite(RELAY_FRONT, Acceso);
deltaTime = 0;
lastTempRelay = millis();
}
iSuonaNTR = 0;
}
void startCooking() {
// se non sono impostati temperatura e tempo di cottura non parto
if (dTargetTemp < 1 || cookingTime < 1) return;
remainingTime = cookingTime;
bCookingStarted = true;
bCookingFinished = false;
bHeating = true; // nel dubbio se avvio la cottura devo per forza avviare anche il riscaldamento altrimenti parte solo il timer
/*
{ 175, 90, "Ventilato" }, // 0 Programma 1: Ventilato
{ 200, 90, "Tradizionale" }, // 1 Programma 2: Tradizionale
{ 220, 35, "Pane/Pizza" }, // 2 Programma 3: Pane/Pizza
{ 170, 60, "Pasticceria" }, // 3 Programma 4: Pasticceria
{ 180, 45, "Sopra Sotto Ventilato" }, // 4 Programma 5: Sopra Sotto Ventilato
{ 170, 45, "Grill Ventilato" }, // 5 Programma 6: Grill Ventilato
{ 250, 10, "Grill" }, // 6 Programma 7: Grill
{ 170, 60, "Sopra" }, // 7 Programma 8: Sopra
{ 170, 60, "Sotto" }, // 8 Programma 9: Sotto
*/
digitalWrite(RELAY_FRONT, Acceso);
digitalWrite(RELAY_LUCE, Acceso);
Serial.println("Avvio della cottura:");
Serial.print("Programma: ");
Serial.println(programIndex + 1);
Serial.print("Temperatura: ");
Serial.print(dTargetTemp);
Serial.println(" °C");
Serial.print("Tempo di cottura: ");
Serial.print(cookingTime);
Serial.println(" min");
Serial.println();
}
void stopCooking() {
bCookingFinished = true;
bCookingStarted = false;
bHeating = false;
remainingTime = 0;
sec = 0;
iSuonaNTR = 0;
programIndex = (programIndex - 1) % numPrograms;
if (!bCooling) digitalWrite(RELAY_FRONT, Spento); // Spengo il relay solo se il raff è spento
digitalWrite(RELAY_GENERALE, Spento);
digitalWrite(RELAY_LUCE, Spento);
digitalWrite(RELAY_MOT_VENT, Spento);
digitalWrite(RELAY_TOP, Spento);
digitalWrite(RELAY_GRILL, Spento);
digitalWrite(RELAY_BOTTOM, Spento);
digitalWrite(RELAY_FRONT_RG, Spento);
/*
digitalWrite(RELAY_RAFFREDDAMENTO, Spento);
*/
Serial.println("Cottura terminata!");
Serial.println();
lcd.clear();
displayTemperature();
}
void selectProgram(int i) {
int t = 0;
if (i > 0) {
if (!bHeating) bPrograming = true; // entro in mod programmazione solo se non sto scaldando altrimenti campio prog e basta
bTempReached = false; // ad ogni selezione del programma la resetto così da poter eventualmente ricalcolare il tempo di riscaldamento
dTargetTemp = programs[programIndex].temperature;
cookingTime = programs[programIndex].time;
if (bCookingFinished) bCookingFinished = false;
digitalWrite(RELAY_TOP, programIndex == 1 || programIndex == 3 || programIndex == 4 || programIndex == 7 ? Acceso : Spento);
digitalWrite(RELAY_GRILL, programIndex == 5 || programIndex == 6 ? Acceso : Spento);
digitalWrite(RELAY_BOTTOM, programIndex == 1 || programIndex == 2 || programIndex == 3 || programIndex == 4 || programIndex == 8 ? Acceso : Spento);
digitalWrite(RELAY_FRONT_RG, programIndex == 0 ? Acceso : Spento);
digitalWrite(RELAY_MOT_VENT, programIndex == 0 || programIndex == 2 || programIndex == 3 || programIndex == 4 || programIndex == 5 ? Acceso : Spento);
} else {
t = -1;
}
/*
{ 175, 90, "Ventilato" }, // 0 Programma 1: Ventilato
{ 200, 90, "Tradizionale" }, // 1 Programma 2: Tradizionale
{ 220, 35, "Pane/Pizza" }, // 2 Programma 3: Pane/Pizza
{ 170, 60, "Pasticceria" }, // 3 Programma 4: Pasticceria
{ 180, 45, "Sopra Sotto Ventilato" }, // 4 Programma 5: Sopra Sotto Ventilato
{ 170, 45, "Grill Ventilato" }, // 5 Programma 6: Grill Ventilato
{ 250, 10, "Grill" }, // 6 Programma 7: Grill
{ 170, 60, "Sopra" }, // 7 Programma 8: Sopra
{ 170, 60, "Sotto" }, // 8 Programma 9: Sotto
1 RELAY_GENERALE 21
2 RELAY_TOP 19
3 RELAY_GRILL 18
4 RELAY_BOTTOM 05
5 RELAY_FRONT_RG 17
6 RELAY_LUCE 16
7 RELAY_RAFFREDDAMENTO 04
8 RELAY_MOT_VENT 15
*/
Serial.print("Programma selezionato: ");
Serial.print(programIndex + i);
Serial.println(" " + String(programs[programIndex + t].strProg));
Serial.print("Temperatura: ");
Serial.print(dTargetTemp);
Serial.println("°C");
Serial.print("Tempo di cottura: ");
Serial.print(cookingTime);
Serial.println(" min");
Serial.println();
lcd.setCursor(0, 0);
lcd.clear();
lcd.print("Pr. ");
lcd.print(programIndex + i);
lcd.print(" Temp. ");
lcd.print(String(dTargetTemp, 0));
lcd.setCursor(0, 1);
lcd.print("Cottura ");
lcd.print(cookingTime);
lcd.print(" Min");
programIndex = (programIndex + i) % numPrograms;
}
void displayTemperature() {
if (bCookingStarted) {
lcd.setCursor(0, 0);
lcd.print("Cooking ");
if (remainingTime > 0) {
lcd.print(String(remainingTime) + " Min");
} else {
lcd.print(String(sec) + " Sec");
}
lcd.setCursor(0, 1);
lcd.print("Temp. ");
lcd.print(String(dTempCorr, 1) + "/");
lcd.print(String(dTargetTemp, 0));
} else if (bCookingFinished) {
lcd.setCursor(0, 0);
lcd.print("Cooking Finished");
lcd.setCursor(0, 1);
lcd.print("T. corr. ");
lcd.print(String(dTempCorr, 1) + " C");
} else {
lcd.setCursor(0, 1);
lcd.print("T. corr. ");
lcd.print(String(dTempCorr, 1) + " C");
}
}
void Suona(int iMelody[], int TempiN[], int numNote, int Tempo) {
int wholenote = (60000 * 4) / Tempo;
int divider = 0, noteDuration = 0;
for (int thisNote = 0; thisNote < numNote; thisNote++) {
// calculates the duration of each note
divider = TempiN[thisNote];
if (divider > 0) {
// regular note, just proceed
noteDuration = (wholenote) / divider;
} else if (divider < 0) {
// dotted notes are represented with negative durations!!
noteDuration = (wholenote) / abs(divider);
noteDuration *= 1.5; // increases the duration in half for dotted notes
}
tone(BUZZER_PIN, iMelody[thisNote], noteDuration * 0.8);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
delay(noteDuration);
// stop the tone playing:
noTone(BUZZER_PIN);
}
}