#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define SD_CS 5
#define SD_MOSI 23
#define SD_MISO 19
#define SD_SCK 18
#define I2C_SDA 21
#define I2C_SCL 22
#define LED_GREEN 12
#define LED_RED 13
#define BUZZER 25
#define BUTTON 4
LiquidCrystal_I2C lcd(0x27, 16, 2);
enum StatoSistema { STATO_ATTESA, STATO_RILEVAZIONE, STATO_VISUALIZZA, STATO_BLOCCATO };
StatoSistema statoAttuale = STATO_ATTESA;
enum ProtocolloCAN { PROTO_SCONOSCIUTO, PROTO_J1939_250K };
ProtocolloCAN protocolloRilevato = PROTO_SCONOSCIUTO;
struct DatiMacchina { uint16_t giri = 0; float oreTotali = 0; float voltaggio = 24.5; uint8_t temperatura = 85; } dati;
int schermata = 0;
unsigned long ultimoDisplay = 0, t_rip = 0, t_dati = 0;
bool pulsantePremuto = false, sdPronta = false;
void setup() {
pinMode(LED_GREEN, OUTPUT); pinMode(LED_RED, OUTPUT); pinMode(BUZZER, OUTPUT); pinMode(BUTTON, INPUT_PULLUP);
digitalWrite(LED_RED, HIGH); Wire.begin(I2C_SDA, I2C_SCL);
lcd.init(); lcd.backlight();
lcd.setCursor(0,0); lcd.print("Ciao Davide! ");
lcd.setCursor(0,1); lcd.print("Avvio Sistema...");
tone(BUZZER, 1800, 100); delay(200); tone(BUZZER, 1800, 100); delay(3000);
lcd.clear(); lcd.print("Verifica SD... ");
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS); delay(1000);
sdPronta = SD.begin(SD_CS); lcd.setCursor(0,1);
if(sdPronta) lcd.print("SD: OK "); else lcd.print("SD: NON TROVATA ");
delay(3000); lcd.clear(); lcd.print("SISTEMA PRONTO ");
lcd.setCursor(0,1); lcd.print("Attesa Quadro..."); delay(3000);
}
void loop() {
unsigned long ora = millis();
if (statoAttuale == STATO_BLOCCATO) {
digitalWrite(LED_RED, HIGH); digitalWrite(LED_GREEN, LOW);
lcd.setCursor(0,0); lcd.print("CAN NON TROVATA ");
lcd.setCursor(0,1); lcd.print("RIPROVO... ");
if (ora - t_rip > 10000) statoAttuale = STATO_ATTESA;
}
if (statoAttuale == STATO_ATTESA && dati.voltaggio > 10) {
statoAttuale = STATO_RILEVAZIONE;
lcd.clear(); lcd.print("TENSIONE RILEV.:");
lcd.setCursor(0,1); lcd.print(dati.voltaggio > 20 ? "SISTEMA 24V OK " : "SISTEMA 12V OK ");
tone(BUZZER, 2000, 200); delay(3000);
lcd.clear(); lcd.print("RICERCA CAN... "); delay(2000);
lcd.setCursor(0,1); lcd.print("Test: 250K (J) "); delay(2500);
protocolloRilevato = PROTO_J1939_250K; // Test
if (protocolloRilevato == PROTO_SCONOSCIUTO) { statoAttuale = STATO_BLOCCATO; t_rip = ora; }
else {
lcd.clear(); lcd.print("PROTOCOLLO OK! "); lcd.setCursor(0,1); lcd.print("J1939 RILEVATO ");
tone(BUZZER, 2000, 200); delay(250); tone(BUZZER, 2500, 400); delay(3000);
statoAttuale = STATO_VISUALIZZA; lcd.clear();
}
}
if (statoAttuale == STATO_VISUALIZZA) {
digitalWrite(LED_GREEN, HIGH); digitalWrite(LED_RED, LOW);
if (ora - t_dati > 1000) { dati.giri = 720+random(0,300); dati.oreTotali+=0.01; t_dati=ora; }
if (digitalRead(BUTTON) == LOW && !pulsantePremuto) {
pulsantePremuto = true; schermata = (schermata + 1) % 4; tone(BUZZER, 2500, 50); lcd.clear();
}
if (digitalRead(BUTTON) == HIGH) pulsantePremuto = false;
if (ora - ultimoDisplay >= 400) {
lcd.setCursor(0,0);
if (schermata == 0) { lcd.print("Giri: "); lcd.print(dati.giri); lcd.print(" rpm "); lcd.setCursor(0,1); lcd.print("Temp: "); lcd.print(dati.temperatura); lcd.print(" C "); }
else if (schermata == 1) { lcd.print("Batt: "); lcd.print(dati.voltaggio, 1); lcd.print(" V "); lcd.setCursor(0,1); lcd.print("Ore: "); lcd.print(dati.oreTotali, 1); lcd.print(" h "); }
else if (schermata == 2) { lcd.print("MANUTENZIONE tra"); lcd.setCursor(0,1); int d = 250 - (int)dati.oreTotali; lcd.print(d < 0 ? 0 : d); lcd.print(" ore "); }
else { lcd.print("SD STATUS: "); lcd.setCursor(0,1); lcd.print(sdPronta ? "LOG ATTIVO (OK) " : "SD ASSENTE "); }
ultimoDisplay = ora;
}
}
delay(10);
}