Datalogger di pressione

Iniziamo da qualche nota "stilistica" che però non è solo estetica, ma un modo "standard" di programmare e quindi rendere il listato più semplice da interpretare.

  1. le costanti, per convenzione, è opportuno impostarle sempre tutte in maiuscolo, per distinguerle "ad occhio" dalle variabili.
    Quindi non "#define S_Start 0" ma "#define S_START 0"
  2. quando un valore è rappresentato da una delle costanti, usare SEMPRE la costante. Quindi non "case 0:" ma "case S_START:"
  3. Cerca di mantenere il loop() più "sintetico" possibile. Se hai porzioni di codice relativamente lunghe, meglio inserirle in una funzione (assegnandole tra l'altro un noe che ne rappresenti lo scopo) e richiamare semplicemente la funzione stessa. Quindi niente tutta quella roba con "voltage0 = readChannel(..." che dopo averle inglobate in funzioni "LeggiCanali()" e "ScriviDati()" avrai il loop ben più semplice:
...
    case S_SAVE:
      LeggiCanali();
      ScriviDati();
...eccetera...

Passiamo poi a note più specifiche sul codice:
a) Le variabili modificate dalle routine ISR devono essere globali e dichiarate "volatile", qui non vedo questo; eviterei di modificare direttamente la variabile "stato" ma comunque anche se potrebbe anche andare così, per maggiore genericità userei la variabile bool "evento" (o come vuoi chiamarla, che so, "isAlarm");
b) Lo stato S_START si intende quello in cui fai eventualmente "altro", intanto che attendi il momento di attivare l'allarme, ma tu devi cambiare stato solo quando devi iniziare (ad es. in base alla pressione di un pulsante per fare start/stop dell'acquisizione? Un orario specifico o untervallo?) per cui quando si verifica la condizione (vedi il mio esempio) fai il reset della variabile "evento" usata dall'ISR che indica se si è verificato l'evento ossia l'allarme da interrupt, quindi fai l'attachInterrupt() e solo allora devi cambiare stato, passando a quello di attesa dell'interrupt ossia "S_WAIT"
c) Nello stato S_WAIT devi restare solo per il tempo necessario, quindi il mio "case S_WAIT" potrebbe addirittura restare invariato;
d) Nello stato S_EXEC fai tutto quello che devi fare quando si è verificato l'allarme (il mio "FaiQualcosaltro()") ossia letture dei dati e scrittura su SD, quindi torni a S_START per un nuovo ciclo. Oppure se non hai da fare altro mentre aspetti, potrebbe essere tutto nello S_WAIT (ecco perché in questo caso specifico potrebbe bastare 2 stati) e tornare a S_START;
e) Nel codice attivi il relè nel "case 0" (ossia "case S_START"...) ma non lo disattivi mai?