//---------------------------------------------------------------------------
// https://www.plcforum.it/f/topic/308039-progetto-timer-10-ore-programmabile-con-commutatore-rotativo-e-display-sette-segmenti
//---------------------------------------------------------------------------
// inclusione librerie necessarie
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// definizione collegamenti e livelli hardware
#define PIN_SET 5 // collegamenti pulsanti
#define PIN_STASTO 4
#define PIN_RELE 2 // collegamento rele'
#define PRESSLVL 0 // livello letto a pulsanti premuti
#define ONLVL 1 // livello rele' acceso
// variabili globali
Adafruit_SSD1306 display(128, 64, &Wire, -1);
uint32_t now; // tempo sistema in millisecondi
bool onSet = 0; // 1 per 1 ciclo se click su set
bool onSetlpress = 0; // 1 per 1 ciclo se long press set
bool onStasto = 0; // 1 per 1 ciclo se press start/stop
bool blink_ena = 0; // 1 abilita lampeggio punti
bool q = 0; // stato rele', 1 = acceso
//---------------------------------------------------------------------------
// LIVELLO 2
//---------------------------------------------------------------------------
void stampa_punti(){
display.setCursor(55, 16);
display.print(":");
display.display();}
void cancella_punti(){
display.setCursor(55, 16);
display.print(" ");
display.display();}
void visu_time(uint8_t h, int8_t m){
display.setCursor(8, 16);
if (h < 10 ) display.print(" ");
display.print(h);
display.setCursor(78, 16);
if (m < 10 ) display.print("0");
display.print(m);
display.display();}
//---------------------------------------------------------------------------
// LIVELLO 1
//---------------------------------------------------------------------------
void lettura_ingressi(){
static uint32_t t = now; // temporizzazione 30 ms
static uint32_t tSet; // misura tempo puls.set
static uint8_t sSet = 0; // stato processo puls.set
static bool mStasto = 1; // flag riconosc.fronte
onSet = onSetlpress = onStasto = 0;
if (now-t < 30) return;
t = now;
bool inp = digitalRead(PIN_SET) == PRESSLVL;
if (0==sSet && inp){
tSet = now;
sSet = 1;}
else if (1==sSet && (now-tSet > 1000)){
onSetlpress = 1;
sSet = 2;}
else if (1==sSet && !inp){
onSet = 1;
sSet = 0;}
else if (2==sSet && !inp)
sSet = 0;
inp = digitalRead(PIN_STASTO) == PRESSLVL;
onStasto = inp && !mStasto;
mStasto = inp;}
void elabora(){
static uint8_t h = 0; // ore
static int8_t m = 0; // minuti
static uint8_t s = 0; // stato processo elabora
static uint32_t t; // temporizzazione 1 minuto
if (0==s && onSetlpress){
h = m = 0;
visu_time(h, m);}
else if (0==s && onSet){
h += h < 10;
visu_time(h, m);}
else if (0==s && onStasto && h>0){
t = now;
q = s = blink_ena = 1;}
else if (1==s && onStasto){
blink_ena = 0;
h = m = q = s = 0;
visu_time(h, m);}
else if (1==s && (now-t >= 60000)){
t += 60000;
m--;
if (0==h && 0==m)
q = s = blink_ena = 0;
else if (m < 0){
m = 59;
h--;}
visu_time(h, m);}}
void aggiorna_uscite(){
digitalWrite(PIN_RELE, q ? ONLVL : !ONLVL);}
void lampeggia(){
static uint8_t s = 0; // stato processo lampeggia
static bool sp; // stato punti
static uint32_t t; // temporizzazione 500 ms
if (0==s && blink_ena){
cancella_punti();
sp = 0;
s = 1;
t = now;}
else if (1==s && !blink_ena){
stampa_punti();
sp = 1;
s = 0;}
else if (1==s && (now-t >= 500)){
t += 500;
(sp ^= 1) ? stampa_punti() : cancella_punti();}}
//---------------------------------------------------------------------------
// LIVELLO 0
//---------------------------------------------------------------------------
void setup(){
pinMode(PIN_SET, INPUT_PULLUP);
pinMode(PIN_STASTO, INPUT_PULLUP);
pinMode(PIN_RELE, OUTPUT);
digitalWrite(PIN_RELE, !ONLVL);
display.begin(SSD1306_SWITCHCAPVCC, 0x3c);
display.clearDisplay();
display.setTextColor(1, 0);
display.setTextSize(4, 4);
visu_time(0, 0);
stampa_punti();}
void loop(){
now = millis();
lettura_ingressi();
elabora();
aggiorna_uscite();
lampeggia();}