/*
=======================================================================================
Name ..........: Airbox ADUE
Description ...: Gestione airbox con arduino
Platform ......: Arduino
Board .........: Arduino mega 2560
Author ........: Mauro P.
=======================================================================================
Changelog =============================================================================
Legend: (+) NEW, (*) CHANGED, (!) FIXED
---------------------------------------------------------------------------------------
31/08/2022 : Mauro
+ V1.0.0
+ Prima versione
---------------------------------------------------------------------------------------
=======================================================================================
*/
/* --------------------------------------- NOTA ---------------------------------------
Per azzerare ore di funzionamento in collaudo, andare in pagina warning ore e mantenere premuto il
pulsante ENTER per 5 secondi
In pagina Lettura UV, tenere premuto ENTER per 5 secondi per accedere alla pagina impostazione
soglia bassa UV.
--------------------------------------------------------------------------------------- */
//#define DEBUG // Commentare per bloccare tutti i debug
//#define DEBUG_MOTOR_OFF // Commentare per abilitare il comando motore
//#define DEBUG_RAMPA_MOTORE // Commentare se scrittura velocità motore non serve
//#define DEBUG_ORE // Commentare se debug ore non serve
//#define DEBUG_ALLARME_PRESSIONE // Commentare se debug pressione non serve
//#define DEBUG_ALLARME_UV // Commentare se debug Uv non serve
const String strmenu = String("ADUE S.P.A V1.0.0");
#include "ezOutput.h"
#include "ezButton.h"
#include "ezLED.h"
#include "LiquidCrystal.h"
#include "Allarme.h"
#include "Neotimer.h"
#include "Analogiche.h"
#include "EEPROM.h"
#include "DebugUtils.h"
#include "Ramp.h" // v.0.6.0
///////////////////////////////////////////////////////////
///// COSTANTI
///////////////////////////////////////////////////////////
// INDIRIZZI EEPROM
const int MOTORE_INDIRIZZO_1 = 11;
const int MOTORE_INDIRIZZO_2 = 12;
const int HOUR_INDIRIZZO_1 = 21;
const int HOUR_INDIRIZZO_2 = 22;
const int SP_UV_INDIRIZZO_1 = 31;
const int SP_UV_INDIRIZZO_2 = 32;
// PIN INGRESSI DIGITALE
const int I2 = 2; // Abilitazione run da remoto
const int I3 = 3; // disponibile
const int I4 = 4; // disponibile
const int I5 = 5; // disponibile
const int I6 = 6; // disponibile
const int I7 = 7; // disponibile
// PIN USCITE RELE
const int RL22 = 22; // Lampade 1
const int RL24 = 24; // Lampade 2
const int RL26 = 26; // disponibile
const int RL28 = 28; // Warning lampade
const int RL30 = 30; // Running
const int RL32 = 32; // Allarme Airbox
// MOTORE
const int MOTORE = 8; // Pin Motore PWM
const byte VEL_MINIMA_MOTORE = 58; // su range 0 - 255
const byte VEL_MASSIMA_MOTORE = 116; // su range 0 - 255
const int RAMP_DURATION = 15000; // ms, rampa di 15 secondi all'avvio
// PRESSIONE
const int SOGLIA_BASSA_ALLARME_PRESSIONE = 30; // Pascal
const int SOGLIA_ALTA_ALLARME_PRESSIONE_FILTRO = 300; // Pascal
const int RITARDO_CONTROLLO_SOGLIA_PRESSIONE = 2000; // ms
// UV
// const int SOGLIA_BASSA_ALLARME_UV_DEFAULT = 30; // Uv index di default al primo avvio ( da controllare dove mettere)
const int SOGLIA_BASSA_ALLARME_UV_ISTERESI = 2; // Uv index
const int SOGLIA_MAX_ORE_LAVORO = 1000; // ore
const int RITARDO_CONTROLLO_SOGLIA_UV = 2000; // ms
// PAGINE
const int MIN_PAGE_MENU = 1; // prima pagina da visualizzare
const int MAX_PAGE_MENU = 5; // ultima pagina da visualizzare(senza warning di manutenzione)
const int MIN_PAGE_ALARM = 10; // prima pagina da visualizzare in caso di 3 allarmi
const int MAX_PAGE_ALARM = 13; // ultima pagina da visualizzare in caso di 3 allarmi
// PIN MODULO LAN
const int RESET_MODULO_LAN = 34; // uscita reset modulo LAN
const int RX_3 = 15; // ingresso seriale modulo LAN
const int TX_3 = 14; // uscita seriale modulo LAN
// ALTRI
const long INTERVALLO_DI_LAMPEGGIO = 1000; // intervallo in cui effettuare il lampeggio
const int NUM_ALARMS = 3; // numero elementi array totale di allarmi
// PIN LED
const int LED_ROSSO = 52; // presenza di un allarme qualsiasi(tranne warning di manutenzione)
const int LED_ARANCIONE = 50; // warning di manutenzione(superamento delle ore massime di lavoro)
const int LED_BLU = 53; // macchina in funzione e assenza di allarmi
const int LED_BIANCO = 51; // presenza di comunicazione ethernet
///////////////////////////////////////////////////////////
///// VARIABILI GLOBALI
///////////////////////////////////////////////////////////
int numero_allarme_pagina = 10; // variabile per scorrimento degli allarmi
int numero_pagina = 1; // variabile per il cambio delle pagine
int velocita_motore; // controllo velocità
int velocita_motore_salvata; // ultima velocità motore salvata in eprom letta all'avvio
int sp_soglia_bassa_uv; // soglia uv per allarme
bool cumulativo_allarmi; // stato cumulativo allarmi (true almeno un allarme)
int counter_allarmi = 0; // numero totale allarmi
String str_ore_lavoro; // stringa leggibile ore lavoro HH:MM:SS
unsigned int ore_di_lavoro; // ore di lavoro
bool primo_ciclo_done = false;
bool motor_started = false;
bool in_page_alarm = false;
bool puls_fulmine_premuto = false;
bool allarmi[NUM_ALARMS]; // array booleano degli allarmi
bool consenso = false; // tag per consensi
// PRESSIONE
int valore_pressione;
// UV
int valore_uv;
// EEPROM
byte high_byte_work_hours; // byte superiore della word del valore delle ore di lavoro
byte low_byte_work_hours; // byte inferiore della word del valore delle ore di lavoro
byte high_byte_speed; // byte superiore della word del valore della velocità motore
byte low_byte_speed; // byte inferiore della word del valore della velocità del motore
byte high_byte_sp_uv; // byte superiore della word del valore sp uv
byte low_byte_sp_uv; // byte inferiore della word del valore sp_uv
// LIQUID CRYSTAL
const int rs = 46, en = 44, d4 = 36, d5 = 42, d6 = 38, d7 = 40; // pin del display da collegare ad arduino
///////////////////////////////////////////////////////////
///// ISTANZE
///////////////////////////////////////////////////////////
// RAMPA MOTORE
ramp rampMotor(VEL_MINIMA_MOTORE); // Instanza rampa motore , partenza da velocità minima 0 - 255
// RELÈ
ezOutput rele_lampada1(RL22); // lampada 1
ezOutput rele_lampada2(RL24); // lampada 2
ezOutput rele_26(RL26); // disponibile
ezOutput rele_warning(RL28); // presenza di warning lampade
ezOutput rele_running(RL30); // Running a valle
ezOutput rele_alarm(RL32); // presenza di allarme a valle
// LIQUID CRYSTAL
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // connessione display
// PULSANTI
ezButton input_consenso_marcia(I2); // pulsante provvisorio per provare i consensi digitali
ezButton pulsante_destro(39); // pagina successiva
ezButton pulsante_sinistro(45); // pagina precedente
ezButton pulsante_incremento(41); // incremento
ezButton pulsante_decremento(43); // decremento
ezButton pulsante_enter(37); // Enter
ezButton pulsante_enter_PRESSIONE_LUNGA(37); // Enter
ezButton pulsante_fulmine(47); // pagina allarmi
// ALLARMI
Allarme allarme_bassa_portata(2, SOGLIA_BASSA_ALLARME_PRESSIONE, -1, RITARDO_CONTROLLO_SOGLIA_PRESSIONE); // allarme in caso di pressione troppo bassa (controllo su soglia negativa) -1 = non usato soglia
Allarme allarme_filtro(10, -1, SOGLIA_ALTA_ALLARME_PRESSIONE_FILTRO, RITARDO_CONTROLLO_SOGLIA_PRESSIONE); // allarme in caso di pressione troppo alta (controllo su soglia positiva) -1 = non usato soglia
Allarme allarme_uv(SOGLIA_BASSA_ALLARME_UV_ISTERESI, sp_soglia_bassa_uv, -1, RITARDO_CONTROLLO_SOGLIA_UV); // allarme in caso di livello di radiazione troppo basso -1 = non usato soglia
Allarme warning_ore_lavoro(1, -1, SOGLIA_MAX_ORE_LAVORO, 1000); // Allarme in caso di superamento delle ore massime di lavoro -1 = non usato soglia
// TIMERS
Neotimer mytimer_orelavoro(3600000); // intervallo di funzionamento per ore di lavoro (una ora = 3600000ms)
Neotimer mytimer_ledrosso(INTERVALLO_DI_LAMPEGGIO); // intervallo di funzionamento del timer, per led rosso lampeggio
Neotimer mytimer_ledarancione(INTERVALLO_DI_LAMPEGGIO); // intervallo di funzionamento del timer, per led arancione lampeggio
Neotimer mytimer_alarm_engine(INTERVALLO_DI_LAMPEGGIO); // intervallo funzionamento del timer, per scorrimento in caso di più allarmi(pagina allarme bassa portata)
Neotimer mytimer_alarm_filter(INTERVALLO_DI_LAMPEGGIO); // intervallo funzionamento del timer, per scorrimento in cao di più allarmi(pagina allarme filtro intasato)
Neotimer mytimer_alarm_uv(INTERVALLO_DI_LAMPEGGIO); // intervallo funzionamento del timer, per scorrimento in caso di più allarmi(pagina allarme radiazioni uv)
Neotimer mytimer_warning_hours_work(INTERVALLO_DI_LAMPEGGIO); // intervallo di funzionamento del timer, per scorrimento in vaso di più allarmi(pagina warning ore di lavoro)
Neotimer mytimer_consenso(4000); // intervallo avvio ritardato timer consenso
Neotimer tempo_attuale(); // istanza per il calcolo del tempo di lavoro
Neotimer reset_calcolo_tempo(); // istanza per il reset delle variabili per calcol tempo di lavoro
Neotimer mytimer_refreshPage(500); // istanza per refresh pagina 500 ms dove ho letture di valori
// LED
ezLED led_rosso(LED_ROSSO); // presenza di allarme qualsiasi
ezLED led_arancione(LED_ARANCIONE); // superamento ore di lavoro massime
ezLED led_blu(LED_BLU); // disponibile
ezLED led_bianco(LED_BIANCO); // Running
// ANALOGICHE
Analogiche lettura_pressione(A0, 0, 1023, -99, 1000); // Fondo scala pressione 0 - 1000 Pascal (0,5V a 4.5V) a zero legge 99
Analogiche lettura_radiazione_uv(A1, 0, 1023, 0, 1000); //#TODO|ADUE_MP-08/09/2022: fondo scala ???
Analogiche anl_velocita_motore(MOTORE, 0, 255, 0, 255); // uscita PWM
///////////////////////////////////////////////////////////
///// DICHIARAZIONI FUNZIONI
///////////////////////////////////////////////////////////
void home_page();
void pagina_controllo_velocita(); // Pagina menu
void pagina_controllo_pressione(); // Pagina menu
void pagina_sensore_uv(); // Pagina menu
void pagina_connessione_ethernet(); // Pagina menu
void pagina_sp_soglia_uv(); // Pagina menu Impostazioni
void pagina_lista_allarmi(); // Pagina menu
void pagina_richiesta_conferma_reset_warning(); // Pagina menu
void scorrimento_allarmi(); // switch-case per scorrimento allarmi
void scorrimento_pagine(); // switch-case per scorrimento pagine
void controllo_pagine(); // sequenza dei pulsanti
void allarme_low_flow(); // Pagina allarme
void allarme_radiazione_uv(); // Pagina allarme
void allarme_filtro_intasato(); // Pagina allarme
void warning_ore_di_lavoro(); // Pagina allarme
void salvataggio_velocita_motore_eeprom();
void salvataggio_ore_eeprom();
String millis_to_strTime(unsigned long currentMillis);
//##################################################################################################################################
///////////////////////////////////////////////////////////
///// MAIN SETUP
///////////////////////////////////////////////////////////
//##################################################################################################################################
void setup()
{
// SERIALE PER DEBUG
Serial.begin(115200);
// Serial3.begin(9600);//porta seriale per comunicazione ethernet tx3 e rx3
// MODULO LAN
pinMode(RESET_MODULO_LAN, OUTPUT); // uscita reset modulo LAN
pinMode(RX_3, INPUT); // ingresso seriale modulo LAN
pinMode(TX_3, OUTPUT); // uscita seriale modulo LAN
// SETTAGGIO TEMPO PER OGNI ISTANZA DEL TIMER
mytimer_orelavoro.set(3600000); // frequenza di salvataggio delle ore di lavoro
mytimer_ledarancione.set(1000); // frequenza di lampeggio del led arancione
mytimer_ledrosso.set(1000); // frequenza di lampeggio del led rosso
mytimer_alarm_engine.set(1000); // frequenza di lampeggio freccia segnalazione di più allarmi(pagina allarme bassa portata)
mytimer_alarm_filter.set(1000); // frequenza di lampeggio freccia segnalazione di più allarmi(pagina allarme filtro)
mytimer_alarm_uv.set(1000); // frequenza di lampeggio freccia segnalazione di più allarmi(pagina allarme uv)
mytimer_warning_hours_work.set(1000); // frequenza di lampeggio freccia segnalazione di più allarmi(pagina allarme warning)
// timer consenso start
mytimer_consenso.start(); // avvio ritardato timer per consenso
// LCD
lcd.begin(16, 2); // inizializzazione display lcd
// TEMPO DI ANTIRIMBALZO PULSANTI
pulsante_destro.setDebounceTime(30); // pagina successiva
pulsante_sinistro.setDebounceTime(30); // pagina precedente
pulsante_incremento.setDebounceTime(30); // incremento velocità motore e scorrimento in avanti degli allarmi
pulsante_decremento.setDebounceTime(30); // decremento velocità motore e scorrimento indietro degli allarmi
pulsante_enter.setDebounceTime(30); // visualizzazione menu, reset warning manutenzione e reset modulo lan
pulsante_enter_PRESSIONE_LUNGA.setDebounceTime(5000); // pulsante da premere 5 secondi in pagina allarmi ore per resettare orario funzionamento
pulsante_fulmine.setDebounceTime(30); // pagina lista allarmi,lista degli allarmi e reset in caso di warning manutenzione
// INGRESSI DIGITALI
pinMode(I3, INPUT); // disponibile
pinMode(I4, INPUT); // disponibile
pinMode(I5, INPUT); // disponibile
pinMode(I6, INPUT); // disponibile
pinMode(I7, INPUT); // disponibile
// STATO INIZIALE BASSO DEI CONTATTI RELè
rele_lampada1.low();
rele_lampada2.low();
rele_26.low();
rele_warning.low();
rele_running.low();
rele_alarm.low();
// LETTURA EEPROM VELOCITA MOTORE
byte low_byte_speed = EEPROM.read(MOTORE_INDIRIZZO_1); // lettura del byte di ordine inferiore(word) della singola cella (1 byte)
byte high_byte_speed = EEPROM.read(MOTORE_INDIRIZZO_2); // lettura del byte di ordine superiore(word) della singola cella (1 byte)
velocita_motore_salvata = word(high_byte_speed, low_byte_speed); // ricomposizione della word intera(2 byte) della velocità del motore
// LETTURA EEPROM ORE DI LAVORO
byte low_byte_work_hours = EEPROM.read(HOUR_INDIRIZZO_1); // lettura del byte di ordine inferiore(word) della singola cella (1 byte)
byte high_byte_work_hours = EEPROM.read(HOUR_INDIRIZZO_2); // lettura del byte di ordine superiore(word) della singola cella (1 byte)
ore_di_lavoro = word(high_byte_work_hours, low_byte_work_hours); // ricomposizione della word intera(2 byte) dell velocità del motore
// LETTURA EEPROM SOGLIA UV
byte low_byte_work_sp_uv = EEPROM.read(SP_UV_INDIRIZZO_1); // lettura del byte di ordine inferiore(word) della singola cella (1 byte)
byte high_byte_work_sp_uv = EEPROM.read(SP_UV_INDIRIZZO_2); // lettura del byte di ordine superiore(word) della singola cella (1 byte)
sp_soglia_bassa_uv = word(high_byte_work_sp_uv, low_byte_work_sp_uv); // ricomposizione della word intera(2 byte) sp soglia uv
}
//##################################################################################################################################
///////////////////////////////////////////////////////////
///// MAIN LOOP
///////////////////////////////////////////////////////////
//##################################################################################################################################
void loop()
{
// loop controllo marcia e relè lampade
// RELE LOOP
input_consenso_marcia.loop();
rele_lampada1.loop();
rele_lampada2.loop();
// LED LOOP
led_rosso.loop(); // Alarm
led_arancione.loop(); // warning
led_bianco.loop(); // Running
consenso = input_consenso_marcia.getState();
// tutte le volte che segnale alto , riparto con il timer
if (input_consenso_marcia.isPressed())
{
mytimer_consenso.start();
}
// ###################### CICLO PRINCIPALE CON CONDIZIONE INGRESSO #####################################
// chiusura temporizzata dei relè e inizio del programma dopo avvenuto consenso
if (consenso && mytimer_consenso.done())
{
// CHIAMATA IN LOOP DEI CONTATTI RELE
rele_warning.loop();
rele_running.loop();
rele_alarm.loop();
// Settaggi primo ciclo
if (!primo_ciclo_done)
{
DEBUG_PRINTLN("Primo ciclo");
lcd.clear();
mytimer_orelavoro.start();
// Setto nuova soglia allarme uv
allarme_uv.set_soglia_min(sp_soglia_bassa_uv); // Setto soglia variabile UV
// Controllo se velocità salvata < di vel min
if (velocita_motore_salvata < VEL_MINIMA_MOTORE){
velocita_motore_salvata = VEL_MINIMA_MOTORE;
}
}
// Gestione velocità motore | true=In marcia con rampa / false=stop
gestione_velocita_motore(true);
// Accensioni lampade
rele_lampada1.high();
rele_lampada2.high();
// relè running
rele_running.high();
// LED
led_bianco.turnON();
// Lettura analogiche
valore_pressione = lettura_pressione.read_analog();
valore_uv = lettura_radiazione_uv.read_analog();
// creo stringa ore lavoro leggibile
str_ore_lavoro = millis_to_strTime(mytimer_orelavoro.getEllapsed());
#ifdef DEBUG_ORE
DEBUG_PRINT("ORE LAVORO = ");
DEBUG_PRINT(ore_di_lavoro);
DEBUG_PRINT(" timer = ");
DEBUG_PRINT(mytimer_orelavoro.getEllapsed());
DEBUG_PRINT(" | ");
DEBUG_PRINTLN(str_ore_lavoro);
#endif
if (mytimer_orelavoro.repeat()) // ripetizione ogni ora
{
ore_di_lavoro++;
salvataggio_ore_eeprom();
}
// CHIAMATA IN LOOP PULSANTI
pulsante_destro.loop(); // pagina successiva
pulsante_sinistro.loop(); // pagina precedente
pulsante_incremento.loop(); // incremento velocità motore e scorrimento in avanti degli allarmi
pulsante_decremento.loop(); // decremento vellocità motore e scorrimento indietro delgi allarmi
pulsante_enter.loop(); // visualizzazione menu, reset warning manutenzione e reset modulo lan
pulsante_fulmine.loop(); // visuaizzazione pagina lista allarmi
pulsante_enter_PRESSIONE_LUNGA.loop(); // Reset conteggio ore per collaudo (5 sec)
// FUNZIONI PER SCORRIMENTO DI PAGINE (MENU E ALLARMI)
controllo_pagine(); // sequenza di funzionamento pulsanti
scorrimento_pagine(); // switch-case per scorrimento pagine menu
// CONTROLLO CUMULATIVO ALLARMI
allarmi[0] = allarme_bassa_portata.check_allarme_negativo(valore_pressione); // Allarme bassa portata
allarmi[1] = allarme_filtro.check_allarme_positivo(valore_pressione); // Allarme filtro pressione
allarmi[2] = allarme_uv.check_allarme_negativo(valore_uv); // Allarme radiazione uv
#ifdef DEBUG_ALLARME_PRESSIONE
DEBUG_PRINT("PRESSIONE = ");
DEBUG_PRINT(valore_pressione);
DEBUG_PRINT(" soglia min = ");
DEBUG_PRINT(SOGLIA_BASSA_ALLARME_PRESSIONE);
DEBUG_PRINT(" ALM MIN = ");
DEBUG_PRINT(allarmi[0]);
DEBUG_PRINT(" soglia max = ");
DEBUG_PRINT(SOGLIA_ALTA_ALLARME_PRESSIONE_FILTRO);
DEBUG_PRINT(" ALM MAX = ");
DEBUG_PRINTLN(allarmi[1]);
#endif
#ifdef DEBUG_ALLARME_UV
DEBUG_PRINT("UV = ");
DEBUG_PRINT(valore_uv);
DEBUG_PRINT(" soglia min = ");
DEBUG_PRINT(sp_soglia_bassa_uv);
DEBUG_PRINT(" ALM MIN = ");
DEBUG_PRINTLN(allarmi[2]);
#endif
///////////////////////////////////////////////////////////
///// CONTROLLO CUMULATIVO ALLARMI
///////////////////////////////////////////////////////////
cumulativo_allarmi = false;
for (int i; i < NUM_ALARMS; i++)
{
if (allarmi[i])
{
cumulativo_allarmi = true;
counter_allarmi++;
}
}
if (cumulativo_allarmi)
{
if (mytimer_ledrosso.repeat())
{ //
led_rosso.toggle(); // cambio stato led per lampeggio
}
rele_alarm.high(); // chiusura del contatto relè per allarmi a valle
}
else
{
led_rosso.turnOFF(); // led rosso spento
rele_alarm.low(); // apertura del contatto relè per allarmi a valle
}
///////////////////////////////////////////////////////////
///// // WARNING ORE DI LAVORO
///////////////////////////////////////////////////////////
if (warning_ore_lavoro.check_allarme_positivo(ore_di_lavoro))
{
if (mytimer_ledarancione.repeat())
{ //
led_arancione.toggle(); // cambio stato led per lampeggio
}
rele_warning.high(); // chiusura del contatto relè per allarmi a valle
}
else
{
led_arancione.turnOFF(); // led spento
rele_warning.low(); // apertura del contatto relè per allarmi a valle
}
// Settaggio primo ciclo terminato
primo_ciclo_done = true;
} // ###################### FINE CICLO PRINCIPALE CON CONDIZIONE INGRESSO #####################################
else
{ // ###################### CICLO PRINCIPALE SENZA CON CONDIZIONE INGRESSO #####################################
mytimer_orelavoro.stop();
// Gestione velocità motore | true=In marcia con rampa / false=stop
gestione_velocita_motore(false);
primo_ciclo_done = false;
rele_alarm.low();
rele_warning.low();
rele_lampada1.low();
rele_lampada2.low();
rele_running.low();
led_rosso.turnOFF();
led_arancione.turnOFF();
led_bianco.turnOFF();
lcd.setCursor(0, 0);
lcd.print("Waiting input signal");
lcd.setCursor(0, 1);
lcd.print(".... ");
}
} //--------------------------------- FINE DEL LOOP ----------------------------------------
// ______________________________________________________________________________________________________________________________________________________
// ______________________________________________________________________________________________________________________________________________________
// ______________________________________________________________________________________________________________________________________________________
//##################################################################################################################################
///////////////////////////////////////////////////////////
///// FUNZIONI
///////////////////////////////////////////////////////////
//##################################################################################################################################
///////////////////////////////////////////////////////////
///// FUNZIONE PER CONVERTIRE millisecondi IN FORMATO STR HH:MM:SS
///////////////////////////////////////////////////////////
String millis_to_strTime(unsigned long currentMillis)
{
unsigned long seconds = currentMillis / 1000;
unsigned long minutes = seconds / 60;
unsigned long hours = minutes / 60;
unsigned long days = hours / 24;
currentMillis %= 1000;
seconds %= 60;
minutes %= 60;
hours %= 24;
// String hrMinSec = (String(hours, DEC) + ":" + String(minutes, DEC) + ":" + String(seconds, DEC));
// Creo String con leading zero
String readableTime;
if (hours > 0)
{
readableTime += String(hours) + ":";
}
if (minutes < 10)
{
readableTime += "0";
}
readableTime += String(minutes) + ":";
if (seconds < 10)
{
readableTime += "0";
}
readableTime += String(seconds);
return readableTime;
}
///////////////////////////////////////////////////////////
///// FUNZIONE PER SCRIVERE VELOCITA' MOTORE SU USCITA
///////////////////////////////////////////////////////////
void gestione_velocita_motore(bool state)
{
// Se true in marcia , altrimenti uscita a 0
if (state)
{
// Settaggio rampa iniziale
if (!motor_started)
{
motor_started = true;
DEBUG_PRINT("Start = ");
DEBUG_PRINTLN(VEL_MINIMA_MOTORE);
DEBUG_PRINT("Target = ");
DEBUG_PRINTLN(velocita_motore_salvata);
rampMotor.go(velocita_motore_salvata, RAMP_DURATION);
}
// loop rampa
if (rampMotor.isRunning())
{ // test to see if ramp is running
velocita_motore = rampMotor.update();
}
// Forza velocità motore nei limiti
velocita_motore = constrain(velocita_motore, VEL_MINIMA_MOTORE, VEL_MASSIMA_MOTORE); // range velocità motore (mai sotto il 7%)
}
else
{
// azzero rampa a velocità minima motore
motor_started = false;
rampMotor.go(VEL_MINIMA_MOTORE, 0);
velocita_motore = 0;
}
#ifdef DEBUG_MOTOR_OFF
anl_velocita_motore.write_analog(0); // Motore fermo
#else
anl_velocita_motore.write_analog(velocita_motore); // velocità motore range 0 - 255
#endif
#ifdef DEBUG_RAMPA_MOTORE
DEBUG_PRINT(" VEL MOTORE = ");
DEBUG_PRINT(velocita_motore);
DEBUG_PRINT(" | RAMP RUNNING = ");
DEBUG_PRINTLN(rampMotor.isRunning());
#endif
}
///////////////////////////////////////////////////////////
///// // FUNZIONE PER SALVARE ORE LAVORO
///////////////////////////////////////////////////////////
void salvataggio_ore_eeprom()
{
// Salvo in eeprom
low_byte_work_hours = lowByte(ore_di_lavoro); // suddivisione in due byte di memoria del valore delle ore di lavoro
high_byte_work_hours = highByte(ore_di_lavoro);
EEPROM.update(HOUR_INDIRIZZO_1, low_byte_work_hours); // scrittura del byte di ordine inferiore(della word)contenuto nella cella di indirizzo 1
EEPROM.update(HOUR_INDIRIZZO_2, high_byte_work_hours); // scrittura del byte di ordine superiore(della word) contenuto nella cella di indirizzo 2
}
///////////////////////////////////////////////////////////
///// // FUNZIONE PER SALVARE LA VELOCITÀ DEL MOTORE SULLA EEPROM
///////////////////////////////////////////////////////////
void salvataggio_velocita_motore_eeprom()
{
high_byte_speed = highByte(velocita_motore); // suddivisione in due byte di memoria del valore della velocità del motore
low_byte_speed = lowByte(velocita_motore);
EEPROM.update(MOTORE_INDIRIZZO_1, low_byte_speed); // scrittura del byte di ordine inferiore(della word)contenuto nella cella di indirizzo 1
EEPROM.update(MOTORE_INDIRIZZO_2, high_byte_speed); // scrittura del byte di ordine superiore(della word) contenuto nella cella di indirizzo 2
}
///////////////////////////////////////////////////////////
///// // FUNZIONE PER SALVARE SP UV
///////////////////////////////////////////////////////////
void salvataggio_sp_uv_eeprom()
{
high_byte_sp_uv = highByte(sp_soglia_bassa_uv); // lettura del byte di ordine superiore(word) della singola cella (1 byte)
low_byte_sp_uv = lowByte(sp_soglia_bassa_uv); // lettura del byte di ordine inferiore(word) della singola cella (1 byte)
EEPROM.update(SP_UV_INDIRIZZO_1, high_byte_sp_uv); // scrittura del byte di ordine inferiore(della word)contenuto nella cella di indirizzo 1
EEPROM.update(SP_UV_INDIRIZZO_1, low_byte_sp_uv); // scrittura del byte di ordine superiore(della word) contenuto nella cella di indirizzo 2
}
///////////////////////////////////////////////////////////
///// // FUNZIONE PER SALVARE LA VELOCITÀ DEL MOTORE SULLA EEPROM
///////////////////////////////////////////////////////////
void controllo_pagine()
{
// se non sono nella pagina degli allarmi scorro le pagine del menu normale
if (!in_page_alarm)
{
if (pulsante_destro.isPressed() && (numero_pagina < MAX_PAGE_MENU))
{
lcd.clear();
numero_pagina++; // premendo il pulsante destro vado alla pagina successiva
}
if (pulsante_sinistro.isPressed() && (numero_pagina > MIN_PAGE_MENU))
{
lcd.clear();
numero_pagina--; // premendo il pulsante sinistro torno alla pagina precedente
}
}
// se sono nella pagina degli allarmi scorro le pagine degli allarmi
else
{
if (pulsante_destro.isPressed() && (numero_allarme_pagina < MAX_PAGE_ALARM))
{
lcd.clear();
numero_allarme_pagina++; // premendo il pulsante destro vado alla pagina successiva
}
if (pulsante_sinistro.isPressed() && (numero_allarme_pagina > MIN_PAGE_ALARM))
{
lcd.clear();
numero_allarme_pagina--; // premendo il pulsante sinistro torno alla pagina precedente
}
}
///////////////////////////////////////////////////////////
///// // PULSANTE FULMINE ALLARMI
///////////////////////////////////////////////////////////
if (pulsante_fulmine.isPressed() && !in_page_alarm)
{
lcd.clear();
in_page_alarm = true;
numero_pagina = 6; // premendo il pulsante fulmine(quando non ci sono allarmi) vado alla pagina di chiamata pagina allarmi
numero_allarme_pagina = 10; // riparto dalla prima pagina(allarmi) e vedo quali allarmi sono ok e quali non
}
else if (pulsante_fulmine.isPressed() && in_page_alarm)
{ // premendo il pulsante fulmine (quando c'è un allarme) torno nella pagina del menu
lcd.clear();
numero_pagina = 1;
in_page_alarm = false;
}
}
///////////////////////////////////////////////////////////
///// // CONTROLLO SCORRIMENTO PAGINE MENU
///////////////////////////////////////////////////////////
void scorrimento_pagine()
{
switch (numero_pagina)
{
case 1:
home_page();
break;
case 2:
pagina_controllo_velocita();
break;
case 3:
pagina_controllo_pressione();
break;
case 4:
pagina_sensore_uv();
break;
case 5:
pagina_connessione_ethernet();
break;
case 6:
// pagina_lista_allarmi();
scorrimento_allarmi();
break;
// ------------------- Pagina configurazioni settaggi collaudo --------------------------
case 9:
pagina_sp_soglia_uv();
break;
}
}
///////////////////////////////////////////////////////////
///// // CONTROLLO SCORRIMENTO PAGINE ALLARMI
///////////////////////////////////////////////////////////
void scorrimento_allarmi()
{
switch (numero_allarme_pagina)
{
case 10:
allarme_low_flow();
break;
case 11:
allarme_radiazione_uv();
break;
case 12:
allarme_filtro_intasato();
break;
case 13:
warning_ore_di_lavoro();
break;
}
}
///////////////////////////////////////////////////////////
///// HOME PAGE - PAGINA 1
///////////////////////////////////////////////////////////
void home_page()
{
lcd.setCursor(0, 0);
lcd.print(strmenu); // messaggio iniziale
lcd.setCursor(0, 1);
lcd.print("Push Enter to Menu"); // premere il tasto enter per andare al menu
if (pulsante_enter.isPressed())
{ // premendo il pulsante enter vado alla pagina di controllo velocità e visualizzazione delle ore di lavoro
lcd.clear();
numero_pagina = 2;
}
}
///////////////////////////////////////////////////////////
///// VELOCITA' MOTORE - PAGINA 2
///////////////////////////////////////////////////////////
void pagina_controllo_velocita()
{
float velocita_motore_in_percentuale = (velocita_motore * 100.0 / VEL_MASSIMA_MOTORE); // calcolo percentuale velocità motore
lcd.setCursor(3, 0);
lcd.print("Speed");
lcd.setCursor(9, 0);
lcd.print(velocita_motore_in_percentuale); // stampa velocità motore in percentuale
lcd.setCursor(15, 0);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("Hour:");
lcd.setCursor(5, 1);
if (mytimer_refreshPage.repeat())
{
lcd.print(" "); // pulisco vecchio valore
}
lcd.setCursor(5, 1);
lcd.print(ore_di_lavoro); // stampa il tempo di lavoro trascorso dall'accensione di Arduino
lcd.setCursor(11, 1);
lcd.print(str_ore_lavoro); // stampa minuti : sec rimasti del conteggio parziale
// Incremento - decremento velocità con pulsanti up / down
if (pulsante_incremento.isPressed())
{
velocita_motore++; // premendo il pulsante incremento aumento la velocità del motore
salvataggio_velocita_motore_eeprom(); // funzione per salvataggio velocità motore su eeprom
DEBUG_PRINTLN(velocita_motore);
// salvataggio velocità motore per rampa
velocita_motore_salvata = velocita_motore;
}
else if (pulsante_decremento.isPressed())
{
velocita_motore--; // premendo il pulsante decremento riduco la velocità del motore
salvataggio_velocita_motore_eeprom(); // funzione salvataggio velocità motore su eeprom
DEBUG_PRINTLN(velocita_motore);
// salvataggio velocità motore per rampa
velocita_motore_salvata = velocita_motore;
}
}
///////////////////////////////////////////////////////////
///// CONTROLLO PRESSIONE - PAGINA 3
///////////////////////////////////////////////////////////
void pagina_controllo_pressione()
{
if (mytimer_refreshPage.repeat())
{
lcd.setCursor(1, 0);
lcd.print("Pressure sensor");
lcd.setCursor(5, 1);
lcd.print("Pa = ");
lcd.setCursor(10, 1);
lcd.print(" "); // pulisco vecchio valore
lcd.setCursor(10, 1);
lcd.print(valore_pressione); // stampa il valore letto dal sensore di pressione
}
}
///////////////////////////////////////////////////////////
///// CONTROLLO UV - PAGINA 4
///////////////////////////////////////////////////////////
void pagina_sensore_uv()
{
if (mytimer_refreshPage.repeat())
{
lcd.setCursor(0, 0);
lcd.print("Value photodiode");
lcd.setCursor(4, 1);
lcd.print("UV = ");
lcd.setCursor(9, 1);
lcd.print(" "); // pulisco vecchio valore
lcd.setCursor(9, 1);
lcd.print(valore_uv); // stampa il valore letto dal sensore uv
lcd.print(" > ");
lcd.print(sp_soglia_bassa_uv); // soglia UV
}
if (pulsante_enter_PRESSIONE_LUNGA.isPressed()) // pulsante ritardato di 5 secondi per azzeramento ore in collaudo, anche se tempo non scaduto
{
lcd.clear();
numero_pagina = 9; // Pagina sp soglia UV
}
}
///////////////////////////////////////////////////////////
///// CONTROLLO ETHERNET - PAGINA 5
///////////////////////////////////////////////////////////
void pagina_connessione_ethernet()
{
//#TODO|ADUE_MP-31/08/2022: Da modificare per controllo ethernet
/* if (Serial3.available())
{
lcd.setCursor(3, 0);
lcd.print("Connection OK "); // messaggio in caso di collegamento ad una rete ethernet
digitalWrite(LED_BIANCO, HIGH); // led bianco acceso
RX_3 = Serial3.read(); // lettura a disposizione del PLC
}
else
{
lcd.setCursor(0, 0);
lcd.print("! Connection not ok"); // messaggio in caso di assenza di connessione ethernet
digitalWrite(LED_BIANCO, LOW); // led bianco spento
lcd.setCursor(0, 1);
lcd.print("Push E to reset LAN"); // messaggio per resettare il modulo LAN
if (pulsante_enter.isPressed())
{ // premendo il pulsante enter si resetta il modulo LAN
digitalWrite(RESET_MODULO_LAN, HIGH); // reset modulo LAN
}
} */
lcd.setCursor(0, 0);
lcd.print("ETHERNET NOT "); // messaggio in caso di assenza di connessione ethernet
lcd.setCursor(0, 1);
lcd.print("AVAILABLE "); // messaggio in caso di assenza di connessione ethernet
}
///////////////////////////////////////////////////////////
///// SP SOGLIA UV - PAGINA 9 (SOLO COLLAUDATORI)
///////////////////////////////////////////////////////////
void pagina_sp_soglia_uv()
{
lcd.setCursor(0, 0);
lcd.print("SP UV : ");
lcd.setCursor(8, 0);
lcd.print(" "); // pulisco vecchio valore
lcd.setCursor(8, 0);
lcd.print(sp_soglia_bassa_uv); // sp soglia bassa Uv introdotto in collaudo
lcd.setCursor(0, 1);
lcd.print("ENTER to save ");
// Incremento - decremento velocità con pulsanti up / down
if (pulsante_incremento.isPressed())
{
sp_soglia_bassa_uv++; // premendo il pulsante incremento
salvataggio_sp_uv_eeprom(); // funzione per salvataggio sp uv
allarme_uv.set_soglia_min(sp_soglia_bassa_uv); // Setto soglia variabile UV
DEBUG_PRINTLN(sp_soglia_bassa_uv);
}
else if (pulsante_decremento.isPressed())
{
sp_soglia_bassa_uv--; // premendo il pulsante decremento r
salvataggio_sp_uv_eeprom(); // funzione per salvataggio sp uv
allarme_uv.set_soglia_min(sp_soglia_bassa_uv); // Setto soglia variabile UV
DEBUG_PRINTLN(sp_soglia_bassa_uv);
}
if (pulsante_enter.isPressed()) // premendo il pulsante enter reset esco su pagina principale
{
lcd.clear();
numero_pagina = 4; // Ritorno a pagina UV
in_page_alarm = false;
}
}
//##################################################################################################################################
///////////////////////////////////////////////////////////
///// PAGINE ALLARMI
///////////////////////////////////////////////////////////
//##################################################################################################################################
///////////////////////////////////////////////////////////
///// ALLARME BASSA PORTATA - PAGINA 10
///////////////////////////////////////////////////////////
void allarme_low_flow()
{ // funzione per pagina allarme bassa portata
lcd.setCursor(0, 0);
if (allarme_bassa_portata.check_allarme_negativo(valore_pressione))
{
lcd.print("- Alarm low flow "); // messaggio in caso allarme bassa portata
}
else
{
lcd.print("- Flow OK "); // portata ok
}
if (counter_allarmi > 1)
{ // freccia in caso di più allarmi
lcd.setCursor(16, 1);
lcd.print("-->");
//}
}
}
///////////////////////////////////////////////////////////
///// ALLARME UV - PAGINA 11
///////////////////////////////////////////////////////////
void allarme_radiazione_uv()
{ // funzione per pagina allarme radiazione
lcd.setCursor(0, 0);
if (allarmi[2])
{
lcd.print("- Alarm lamps U.V. "); // messaggio in caso di allarme radiazioni uv
}
else
{
lcd.print("- Lamps OK "); // lampade ok
}
if (counter_allarmi > 1)
{ // freccia in caso di più allarmi
lcd.setCursor(16, 1);
lcd.print("-->");
}
}
///////////////////////////////////////////////////////////
///// ALLARME FILTRO - PAGINA ALLARME 12
///////////////////////////////////////////////////////////
void allarme_filtro_intasato()
{ // funzione per pagina allarme filtro intasato
lcd.setCursor(0, 0);
if (allarmi[1])
{
lcd.print("Alarm filter clogged"); // messaggio in caso di allarme filtro intasato
}
else
{
lcd.print("- Filter OK "); // filtro ok
}
if (counter_allarmi > 1)
{ // freccia in caso di più allarmi
lcd.setCursor(16, 1);
lcd.print("-->");
}
}
///////////////////////////////////////////////////////////
///// WARNING ORE LAVORO - PAGINA ALLARME 13
///////////////////////////////////////////////////////////
void warning_ore_di_lavoro()
{ // funzione per pagina allarme ore di lavoro
lcd.setCursor(0, 0);
if (warning_ore_lavoro.check_allarme_positivo(ore_di_lavoro))
{
lcd.print("Lamp Need maintenance");
lcd.setCursor(0, 1);
lcd.print("ENTER - reset hours? ");
if (pulsante_enter.isPressed()) // premendo il pulsante enter reset, torno a pagina 1
{
ore_di_lavoro = 0;
salvataggio_ore_eeprom();
lcd.clear();
numero_pagina = 1;
in_page_alarm = false;
}
}
else
{
lcd.print("- Work hours OK "); // ore di lavoro ok
lcd.setCursor(0, 1);
lcd.print("Hour:");
lcd.setCursor(5, 1);
if (mytimer_refreshPage.repeat())
{
lcd.print(" "); // pulisco vecchio valore
}
lcd.setCursor(5, 1);
lcd.print(ore_di_lavoro); // stampa il tempo di lavoro trascorso dall'accensione di Arduino
lcd.setCursor(11, 1);
lcd.print(str_ore_lavoro); // stampa minuti : sec rimasti del conteggio parziale
if (pulsante_enter_PRESSIONE_LUNGA.isPressed()) // pulsante ritardato di 3 secondi per azzeramento ore in collaudo, anche se tempo non scaduto
{
ore_di_lavoro = 0;
salvataggio_ore_eeprom();
lcd.clear();
numero_pagina = 1;
in_page_alarm = false;
}
}
if (counter_allarmi > 1)
{ // freccia in caso di più allarmi
lcd.setCursor(17, 1);
lcd.print("<--");
}
}