/*
TIMER BROMOGRAFO ARDUINO
Questo progetto è di libero utilizzo, basta che venga citato il programmatore.
Programmatore Firmware: Ciro Marciano
email: [email protected]
Youtube channel: https://www.youtube.com/channel/UCEIDN2qiYnW27W2UHuESFSg?view_as=subscriber
Facebook: https://www.facebook.com/ciro.marciano/
*/
#include "pitches.h"
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // imposta indirizzo logico LCD a 0x27 per display 16 caratteri e 2 linee
#define encoder0PinA 2
#define encoder0PinB 3
volatile int encoder0Pos = 0;
int contatoreFineTempo;
int lastButtonState = 0;
// ------------------------++++++++++++++++++++++ Sezione ENCODER
static int pinA = 2;
static int pinB = 3;
volatile byte aFlag = 0;
volatile byte bFlag = 0;
volatile byte reading = 0;
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
volatile long encoderValue2 = 0;
volatile long encoderValue3 = 0;
long lastencoderValue = 0;
long lastencoderValue2 = 0;
long lastencoderValue3 = 0;
int ore = 0;
int minuti = 0;
int secondi = 0;
//--------- timer variabili
int buzzer = 7; //PIEDINO DEL BUZZER
int rele = 6;
int secondiTotali = 0; //Tempo totale
int msg = 0;
int reset = 0;
int start = A6; //Pulsante Start
int empieza = 1024; //Variabile per memorizzare il pulsante start
// assegnazione ingressi per i due pulsanti start e encoder
int pushButton = 4;
int pushButtonSTART = 5;
///////////////////////Musichetta Polifonica///////////////////////////////////////
//Per impostarla togliere gli slash di commento e riportare i valori di default nella sezione tempo esaurito.
//inserie poi due slash sulle due righe successive nella sezione tono singolo.
//int melody[]={NOTE_G3, NOTE_C4, NOTE_E4, NOTE_G4, NOTE_C5, NOTE_E5, NOTE_G5, NOTE_E5, NOTE_GS3, NOTE_CS4, NOTE_F4, NOTE_GS4, NOTE_CS5, NOTE_F5, NOTE_GS5, NOTE_F5, NOTE_AS3, NOTE_DS4, NOTE_G4, NOTE_AS4, NOTE_DS5, NOTE_G5, NOTE_AS5, NOTE_AS5, NOTE_AS5, NOTE_AS5, NOTE_C6};
//int noteDurations[]={12, 12, 12, 12, 12, 12, 4, 4, 12, 12, 12, 12, 12, 12, 4, 4, 12, 12, 12, 12, 12, 12, 4, 12, 12, 12, 2};
////////////////////////////Tono singolo//////////////////////////////////////////
int melody[]={NOTE_G5};
int noteDurations[]={1};
/////////////////////////////////////////////////////////////////////////////////
int pushButtonSTARTstate = 0;
int timeHOLD;
int timeSEC = 0;
int HorMinSec = 0;
int step_funzione = 0;
// Grafica per clessidra e cursore
uint8_t testChar[8] = {0x1F, 0x17, 0x1B, 0x1D, 0x1D, 0x1B, 0x17, 0x1F,};
uint8_t testClessidra[8] = {0x1F, 0x11, 0x0A, 0x04, 0x04, 0x0E, 0x1F, 0x1F,};
/*
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
VOID SETUP VOID SETUP
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
*/
void setup() {
lcd.init();
lcd.backlight();
Serial.begin(9600);
Serial.begin(9600);
pinMode(pushButton, INPUT); // dichiara che il "pushButton" è un input:
pinMode(pushButtonSTART, INPUT);
pinMode(start, INPUT); //Pin Pulsante start --> Ingresso
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
digitalWrite(encoder0PinB, HIGH);
digitalWrite(encoder0PinA, HIGH);
int pushButtonSTARTstate = HIGH; // RESISTENZA PULL UP DEL PULSANTE START
attachInterrupt(0,PinA, RISING);
attachInterrupt(1,PinB, RISING);
// CARICAMENTO dei valori temporali (ore, minuti, secondi)
lastencoderValue3 = EEPROM.read(1);
encoderValue3 = EEPROM.read(1);
lastencoderValue2 = EEPROM.read(2);
encoderValue2 = EEPROM.read(2);
lastencoderValue = EEPROM.read(3);
encoderValue = EEPROM.read(3);
// portare i resitori interni a pull up
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
pinMode(pushButtonSTART, INPUT_PULLUP);
pinMode(pushButtonSTARTstate, INPUT_PULLUP);
pinMode(pushButton, INPUT_PULLUP);
digitalWrite(pushButton, HIGH); // forza il pin a livello alto sfruttando la resistenza di pull-up interna ad arduino
digitalWrite(rele,HIGH);
pinMode(buzzer, OUTPUT);
pinMode(rele, OUTPUT);
// presentazione iniziale
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" UVC Sterilizer ");
lcd.setCursor(0, 1);
lcd.print(" Virus Cleaner ");
delay(4000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Vers. Firmware ");
lcd.setCursor(0, 1);
lcd.print(" 1.4 ");
delay(3000);
lcd.clear();
msg = 0;
empieza = 1024;
// CREAZIONE DEI DUE CARATTERI CUSTOM
lcd.createChar(0, testChar); // Invia il carattere personalizzato a lcd
lcd.createChar(1, testClessidra); // Invia il carattere personalizzato a lcd
}
/*
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
VOID loop VOID loop
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
*/
void loop() {
lcd.setCursor(0, 1);
lcd.print((char)1); // STAMPA LA CLESSIDRA
if(lastEncoded != encoder0Pos) {
if (HorMinSec == 2)encoderValue3 = encoder0Pos;
if (HorMinSec == 1)encoderValue2 = encoder0Pos;
if (HorMinSec == 0)encoderValue = encoder0Pos;
}
// Caricamento ultimo tempo utilizzato
ore = lastencoderValue;
minuti = lastencoderValue2;
secondi = lastencoderValue3;
switch (step_funzione) {
case 0: // STATO INIZIALE
INIZIO();
break;
case 1: // VAI ALLA FUNZIONE: EDIT TEMPO
EDIT_TEMPO();
break;
case 2: // VAI ALLA FUNZIONE: CONTO ALLA ROVESCIA
COUNT_DOWN();
break;
case 3: // VAI ALLA FUNZIONE: TEMPO SCADUTO
TEMPO_SCADUTO();
break;
}
}
//---------------------- ---------------------- ---------------------- ----------------------
//---------------------- FUNZIONE: INIZIO ---------------------- ----------------------------
//---------------------- ---------------------- ---------------------- ----------------------
void INIZIO() {
lcd.setCursor(0, 0);
lcd.print(" PREMI START ");
lcd.setCursor(0, 1);
lcd.setCursor(4, 1);
if (ore < 10) lcd.print("0"); // SE LE ORE SONO MENO DI 10, SCRIVI LO ZERO A SINISTRA.
lcd.print(ore); // STAMPA LE ORE
lcd.print(":"); // STAMPA I DUE PUNTI
if (minuti < 10) lcd.print("0"); // SE I MINUTI SONO MENO DI 10, SCRIVI LO ZERO A SINISTRA.
lcd.print(minuti); // STAMPA I MINUTI
lcd.print(":"); // STAMPA I DUE PUNTI
if (secondi < 10) lcd.print("0"); // SE I SECONDI SONO MENO DI 10, SCRIVI LO ZERO A SINISTRA.
lcd.print(secondi); // STAMPA I SECONDI
// VAI A SETTA TEMPO - - - - - - - - - - - - - - - - - - -
int buttonState = digitalRead(pushButton); //// PER ACCEDERE AL MENU EDITOR CON IL MANTENIMENTO DEL PULSANTE ENCODER
if (buttonState == LOW) {
delay (1000);
Serial.println(timeSEC);
timeSEC++;
}
else {
timeSEC = 0; // AZZERAMENTO VARIABILE SEI SECONDI
}
delay(100);
if (timeSEC >= 2) { // VAI A EDITOR
lcd.clear();
timeSEC = 0;
step_funzione = 1;
}
//// ALLA PRESSIONE DEL PULSANTE START, VAI ALLA FUNZIONE: COUNT DOWN
int pushButtonSTARTstate = digitalRead(pushButtonSTART);
if (pushButtonSTARTstate == LOW) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Partenza tempo");
lcd.clear();
timeSEC = 0;
secondiTotali = secondi + (minuti * 60) + (ore * 60 * 60); //Converte il tempo scelto in secondi!!
digitalWrite (rele, LOW);
step_funzione = 2;
}
}
//---------------------- ---------------------- ---------------------- ----------------------
//---------------------- FUNZIONE: EDIT TEMPO ---------------------- ------------------------
//---------------------- ---------------------- ---------------------- ----------------------
void EDIT_TEMPO() {
if (timeSEC >= 2) {
lcd.clear();
timeSEC = 0;
HorMinSec = 0;
step_funzione = 0;
}
if (HorMinSec > 2) { HorMinSec = 0; } //// AZZERA LA VARIABILE PER LO STEP ORA MINUTI SECONDI.
lcd.setCursor(0, 1);
lcd.print("h");
lcd.setCursor(1, 1);
if (encoderValue < 10) lcd.print("0");
if (encoderValue < 0) {
encoderValue = 0;
encoder0Pos = 0;
}
// FAI IN MODO CHE L' ENCODER NON SUPERI I 59
if (encoderValue > 59) {
encoderValue = 59;
encoder0Pos = 59;
}
lcd.print(encoderValue, DEC);
lcd.print(":");
// -------------------------------------------------------------
lcd.setCursor(4, 1);
lcd.print("m");
if (encoderValue2 < 10) lcd.print("0");
if (encoderValue2 < 0) {
encoderValue2 = 0;
encoder0Pos = 0;
}
if (encoderValue2 > 59) {
encoderValue2 = 59;
encoder0Pos = 59;
}
lcd.print(encoderValue2, DEC);
lcd.print(":");
// -------------------------------------------------------------
lcd.setCursor(8, 1);
lcd.print("s");
if (encoderValue3 < 10) lcd.print("0");
if (encoderValue3 < 0) {
encoderValue3 = 0;
encoder0Pos = 0;
}
if (encoderValue3 > 59) {
encoderValue3 = 59;
encoder0Pos = 59;
}
lcd.print(encoderValue3, DEC);
lcd.print(" ");
// VISUALIZZA LO STATO SE STIAMO SETTANDO LE ORE, I MINUTI OPPURE I SECONDI
switch (HorMinSec) {
case 0: // ore
lcd.setCursor(0, 0);
lcd.print("Set ora");
lcd.setCursor(0, 1);
lcd.print((char)0);
break;
case 1: // minuti
lcd.setCursor(0, 0);
lcd.print("Set minuti");
lcd.setCursor(4, 1);
lcd.print((char)0);
break;
case 2: // secondi
lcd.setCursor(0, 0);
lcd.print("Set secondi");
lcd.setCursor(8, 1);
lcd.print((char)0);
break;
case 3: // funzione eccitazione / diseccitazione
// lcd.setCursor(0, 0);
// lcd.print("Set funzione");
// lcd.setCursor(8, 1);
// lcd.print((char)0);
break;
}
// PASSA DA ORE A MINUTI A SECONDI QUANDO SI PREME IL PULSANTE DELL' ENCODER
int buttonState = digitalRead(pushButton);
if (buttonState != lastButtonState)
if (buttonState == LOW)
{ HorMinSec++;
if(HorMinSec > 2){HorMinSec=0;}
switch(HorMinSec) {
case 0:
encoder0Pos = encoderValue;
break;
case 1:
encoder0Pos = encoderValue2;
break;
case 2:
encoder0Pos = encoderValue3;
break;
}
lcd.clear();
}
delay(100);
lastButtonState = buttonState;
// ESCI DALLA FUNZIONE EDITOR TEMPI PER ANDARE AD INIZIO CON IL TEMPO AGGIORNATO ALL' EDITOR
int pushButtonSTARTstate = digitalRead(pushButtonSTART);
if (pushButtonSTARTstate == LOW)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Partenza tempo");
lcd.clear();
timeSEC = 0;
lastencoderValue3 = encoderValue3;
lastencoderValue2 = encoderValue2;
lastencoderValue = encoderValue;
EEPROM.write(1, lastencoderValue3); // salvataggio su slot il valore
EEPROM.write(2, lastencoderValue2); // salvataggio su slot il valore
EEPROM.write(3, lastencoderValue); // salvataggio su slot il valore
delay(500);
step_funzione = 0;
}
}
//---------------------- ---------------------- ---------------------- ----------------------
//---------------------- CONTO ALLA ROVESCIA ---------------------- ----------------------
//---------------------- ---------------------- ---------------------- ----------------------
void COUNT_DOWN() {
// PARTENZA CONTEGGIO SE LA VARIABILE secondiTotali è maggiore di 0
while (secondiTotali > 0)
{
// RESET FORZATO SE MANTENIAMO PREMUTO IL TASTO START PER 3 SECONDI E RITORNA AD INIZIO
int pushButtonSTARTstate = digitalRead(pushButtonSTART); //// START START START START START
if (pushButtonSTARTstate == LOW) {
timeSEC++;
}
//----------------------------------
if (timeSEC >= 3) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Reset Forzato ");
lcd.setCursor(0, 1);
lcd.print("xxxxxxxxxxxxxxxx");
lcd.setCursor(1, 1);
lcd.print("xxxxxxxxxxxxxxxx");
digitalWrite (rele, HIGH); // SPEGNE IL RELE'
delay(2000);
lcd.clear();
timeSEC = 0;
step_funzione = 0;
break;
}
lcd.setCursor(0, 0);
lcd.print(" Tempo residuo: ");
delay (1000); // DELAY PER CONTARE STEP DI UN SECONDO...NON TOCCARE
secondiTotali--;
ore = ((secondiTotali / 60) / 60); // converte i secondi totali in ore
minuti = (secondiTotali / 60) % 60; // converte i secondi totali in minuti
secondi = secondiTotali % 60; // converte i secondi totali in secondi
lcd.setCursor(0, 0);
lcd.print(" Tempo residuo: ");
lcd.setCursor(4, 1);
if (ore < 10) lcd.print("0");
lcd.print(ore);
lcd.print(":");
if (minuti < 10) lcd.print("0");
lcd.print(minuti);
lcd.print(":");
if (secondi < 10) lcd.print("0");
lcd.print(secondi);
// VAI A FUNZIONE FINE TEMPO quando i secondi totali raggiungono il valore =0
if (secondiTotali == 0)
{
step_funzione = 3; // VAI ALL' ULTIMO STADIO...TEMPO CHE RAGGIUNGE LO ZERO
digitalWrite (rele, HIGH); // SPEGNE IL RELE'
break;
}
}
}
//---------------------- ---------------------- ---------------------- ----------------------
//---------------------- TEMPO ESAURITO ---------------------- ------------------
//---------------------- ---------------------- ---------------------- ----------------------
void TEMPO_SCADUTO() {
// AZZERA ALLA PRESSIONE DEL TASTO START E VAI AD INIZIO PRIMA DEL TEMPO DI 10 SECONDI
lcd.setCursor(0, 0);
lcd.print("Sterilizzazione");
lcd.setCursor(0, 1);
lcd.print(" Completata! ");
for (int thisNote=0; thisNote <1; thisNote++){ // default 27 (impostare per musica polifonica)
int noteDuration=1000 / noteDurations [thisNote]; //default 1640 (impostare per musica polifonica)
tone(buzzer, melody[thisNote],noteDuration);
int pauseBetweenNotes = noteDuration*0.800; //default 1.244 (impostare per musica polifonica)
delay(pauseBetweenNotes);
noTone(buzzer);
}
delay(500);
lcd.setCursor(0, 1);
lcd.print("Start=Ripristina");
contatoreFineTempo++;
delay(3000);
lcd.clear();
// VAI A INIZIO LIVELLO QUANDO IL TEMPO DI 10 SECONDI E' SCADUTO
if (contatoreFineTempo >= 3) {
contatoreFineTempo = 0;
timeSEC = 0;
step_funzione = 0;
}
int pushButtonSTARTstate = digitalRead(pushButtonSTART);
if (pushButtonSTARTstate == LOW)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Ripristino ");
delay(1000);
lcd.clear();
timeSEC = 0;
step_funzione = 0;
}
}
// Interrupt encoder lettura
void PinA(){
cli(); //ferma gli interrupt prima di leggere i valori dei pin
reading = PIND & 0xC; // leggere tutti gli otto valori pin, quindi rimuove tutti i valori tranne pinA e pinB
if(reading == B00001100 && aFlag) { //controlla che entrambi i pin siano in posizione di fermo (HIGH) e che ci aspettiamo un fermo sul fronte di salita di questo pin
encoder0Pos --; //decrementa il conteggio della posizione dell'encoder
bFlag = 0; //resetta i flag per il turno successivo
aFlag = 0; //resetta i flag per il turno successivo
}
else if (reading == B00000100) bFlag = 1; //segnale che ci aspettiamo che il pinB segnali il passaggio al fermo dalla rotazione libera
sei(); //riavvio interrupt
}
void PinB(){
cli(); //ferma gli interrupt prima di leggere i valori dei pin
reading = PIND & 0xC; //leggere tutti gli otto valori pin, quindi rimuove tutti i valori tranne pinA e pinB
if (reading == B00001100 && bFlag) { //controlla che entrambi i pin siano in posizione di fermo (HIGH) e che ci aspettiamo un fermo sul fronte di salita di questo pin
encoder0Pos ++; //incrementa il conteggio della posizione dell'encoder
bFlag = 0; //resetta i flag per il turno successivo
aFlag = 0; //resetta i flag per il turno successivo
}
else if (reading == B00001000) aFlag = 1; //segnale che ci aspettiamo che il pinA segnali il passaggio al fermo dalla rotazione libera
sei(); //riavvia interrupts
}