Mosfet resta attivo

Buongiorno,
Scrivo per chiedere un parere a chi più esperto o chi magari si è già trovato in una situazione simile.

Ho un progetto cui attivo dei motori 12v con una scheda mosfet a 4 canali (immagine allegata).
Utilizzo arduino nano.
Il codice di comando è abbastanza facile:
Ad un if corrisponde l’attivazione del singolo canale che aziona il singolo mosfet e pilota il singolo motore.
Trascorso un tempo X, viene spento.
Il fatto strano è che una volta tanto decide di bloccarsi la disattivazione, ovvero impostando su LOW il pin di riferimento questo non funziona ed il motore continua a girare fintanto che non tolgo corrente.

Noto che il led presente sulla scheda resta illuminato, a significare che è presente un segnale sul pin stesso

Avete idee? Cosa posso controllare?

Schema delle connessioni?
Link diretto alla board Mosfet (per leggerne caratteristiche ed il datasheet)?
Codice Arduino?

I piedini che pilotano i mosfet sono impostati come uscita?
Pubblica il programma.

Link scheda: https://a.aliexpress.com/_EG4gZL3
Codice

#include <LiquidCrystal_I2C.h>
#include <Wire.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

#define pompa1 4
#define pompa2 5
#define pompa3 6
#define pompa4 7

#define segnale1 8
#define segnale2 9
#define segnale3 10
#define segnale4 12
#define segnale5 14

#define LED_PIN 11

bool lcd_attesa = true;
bool lcd_errore = false;
bool lcd_fine_prodotto1 = false;
bool lcd_fine_prodotto2 = false;
bool lcd_fine_prodotto3 = false;
bool lcd_fine_prodotto4 = false;
bool lcd_interrotta = false;
bool spegni = false;

bool consenso_prodotto1 = false;
bool consenso_prodotto2 = false;
bool consenso_prodotto4 = false;

bool conteggio_prodotto1 = false;
bool conteggio_prodotto2 = false;
bool conteggio_prodotto4 = false;
bool conteggio_prodotto3 = false;

bool avvio_programma = false;
bool interrotto_programma = false;

bool tempolow = true;
bool tempohigh = false;

unsigned long inizio_prodotto1 = 0;
unsigned long inizio_prodotto2 = 0;
unsigned long inizio_prodotto4 = 0;
unsigned long inizio_prodotto3 = 0;

unsigned long rimbalzo1 = 2000;
unsigned long rimbalzo = 200;
unsigned long premuto = 0;

unsigned long inizio_schermo = 0;
unsigned long fine_schermo = 1500;
unsigned long timer_acceso = 10;

int durata_prodotto1 = 0;  //variabile
int durata_prodotto2 = 0;  //60 grammi
int durata_prodotto4 = 0;  //30 grammi
int durata_prodotto3 = 0;  //50 grammi

int fine_prodotto1 = 0;
int fine_prodotto2 = 0;
int segnale = 0;

void setup() {
  Serial.begin(9600);
  pinMode(pompa1, OUTPUT);
  pinMode(pompa2, OUTPUT);
  pinMode(pompa3, OUTPUT);
  pinMode(pompa4, OUTPUT);

  digitalWrite(pompa4, LOW);
  digitalWrite(pompa1, LOW);
  digitalWrite(pompa3, LOW);
  digitalWrite(pompa2, LOW);

  pinMode(LED_PIN, OUTPUT);
  pinMode(13, OUTPUT);

  pinMode(segnale1, INPUT_PULLUP);
  pinMode(segnale2, INPUT_PULLUP);
  pinMode(segnale3, INPUT_PULLUP);
  pinMode(segnale4, INPUT_PULLUP);
  pinMode(segnale5, INPUT_PULLUP);

  lcd.init();
  lcd.backlight();
  analogWrite(LED_PIN, 40);
}

void loop() {
  if (digitalRead(segnale1) == LOW && (digitalRead(segnale2) == HIGH && digitalRead(segnale3) == HIGH && digitalRead(segnale4) == HIGH && digitalRead(segnale5) == HIGH)) {
    if (tempolow) {
      avvio_programma = true;
      premuto = millis();
      tempolow = false;
    }
    if (avvio_programma && ((millis() - premuto) > rimbalzo1)) {
      consenso_prodotto1 = true;
      durata_prodotto1 = 9500;
      durata_prodotto3 = 10000;
      tempohigh = true;
      segnale = 1;
      avvio_programma = false;
    }
    if (segnale == 1) prodotto1();
  } else if (digitalRead(segnale1) == LOW && (digitalRead(segnale2) == LOW || digitalRead(segnale3) == LOW || digitalRead(segnale4) == LOW || digitalRead(segnale5) == LOW)) {
    lcd_errore = true;
    errore();
  } else if ((digitalRead(segnale1) == HIGH && segnale == 1) && (conteggio_prodotto1 || conteggio_prodotto3)) {
    if (tempohigh) {
      interrotto_programma = true;
      premuto = millis();
      tempohigh = false;
    }
    if (interrotto_programma && ((millis() - premuto) > rimbalzo)) {
      lcd_interrotta = true;
      erogazione_interrotta();
      interrotto_programma = false;
    }
  }

  if (digitalRead(segnale2) == LOW && (digitalRead(segnale1) == HIGH && digitalRead(segnale3) == HIGH && digitalRead(segnale4) == HIGH && digitalRead(segnale5) == HIGH)) {
    if (tempolow) {
      avvio_programma = true;
      premuto = millis();
      tempolow = false;
    }
    if (avvio_programma && ((millis() - premuto) > rimbalzo1)) {
      consenso_prodotto1 = true;
      durata_prodotto1 = 6500;  //DOSAGGIO
      durata_prodotto3 = 10000;
      tempohigh = true;
      segnale = 2;
      avvio_programma = false;
    }
    if (segnale == 2) prodotto1();
  } else if (digitalRead(segnale2) == LOW && (digitalRead(segnale1) == LOW || digitalRead(segnale3) == LOW || digitalRead(segnale4) == LOW || digitalRead(segnale5) == LOW)) {
    lcd_errore = true;
    errore();
  } else if ((digitalRead(segnale2) == HIGH && segnale == 2) && (conteggio_prodotto1 || conteggio_prodotto3)) {
    if (tempohigh) {
      interrotto_programma = true;
      premuto = millis();
      tempohigh = false;
    }
    if (interrotto_programma && ((millis() - premuto) > rimbalzo)) {
      lcd_interrotta = true;
      erogazione_interrotta();
      interrotto_programma = false;
    }
  }

  if (digitalRead(segnale3) == LOW && (digitalRead(segnale1) == HIGH && digitalRead(segnale2) == HIGH && digitalRead(segnale4) == HIGH && digitalRead(segnale5) == HIGH)) {
    if (tempolow) {
      avvio_programma = true;
      premuto = millis();
      tempolow = false;
    }
    if (avvio_programma && ((millis() - premuto) > rimbalzo1)) {
      consenso_prodotto1 = true;
      durata_prodotto1 = 17000;  //DOSAGGIO
      durata_prodotto3 = 10000;
      tempohigh = true;
      segnale = 3;
      avvio_programma = false;
    }
    if (segnale == 3) prodotto1();
  } else if (digitalRead(segnale3) == LOW && (digitalRead(segnale1) == LOW || digitalRead(segnale2) == LOW || digitalRead(segnale4) == LOW || digitalRead(segnale5) == LOW)) {
    lcd_errore = true;
    errore();
  } else if ((digitalRead(segnale3) == HIGH && segnale == 3) && (conteggio_prodotto1 || conteggio_prodotto3)) {
    if (tempohigh) {
      interrotto_programma = true;
      premuto = millis();
      tempohigh = false;
    }
    if (interrotto_programma && ((millis() - premuto) > rimbalzo)) {
      lcd_interrotta = true;
      erogazione_interrotta();
      interrotto_programma = false;
    }
  }

  if (digitalRead(segnale4) == LOW && (digitalRead(segnale1) == HIGH && digitalRead(segnale2) == HIGH && digitalRead(segnale3) == HIGH && digitalRead(segnale5) == HIGH)) {
    if (tempolow) {
      avvio_programma = true;
      premuto = millis();
      tempolow = false;
    }
    if (avvio_programma && ((millis() - premuto) > rimbalzo1)) {
      consenso_prodotto2 = true;
      durata_prodotto2 = 9500;
      durata_prodotto3 = 8000;
      tempohigh = true;
      segnale = 4;
      avvio_programma = false;
    }
    if (segnale == 4) prodotto2();
  } else if (digitalRead(segnale4) == LOW && (digitalRead(segnale1) == LOW || digitalRead(segnale2) == LOW || digitalRead(segnale3) == LOW || digitalRead(segnale5) == LOW)) {
    lcd_errore = true;
    errore();
  } else if ((digitalRead(segnale4) == HIGH && segnale == 4) && (conteggio_prodotto2 || conteggio_prodotto3)) {
    if (tempohigh) {
      interrotto_programma = true;
      premuto = millis();
      tempohigh = false;
    }
    if (interrotto_programma && ((millis() - premuto) > rimbalzo)) {
      lcd_interrotta = true;
      erogazione_interrotta();
      interrotto_programma = false;
    }
  }

  if (digitalRead(segnale5) == LOW && (digitalRead(segnale1) == HIGH && digitalRead(segnale2) == HIGH && digitalRead(segnale3) == HIGH && digitalRead(segnale4) == HIGH)) {
    if (tempolow) {
      avvio_programma = true;
      premuto = millis();
      tempolow = false;
    }
    if (avvio_programma && ((millis() - premuto) > rimbalzo1)) {
      consenso_prodotto4 = true;
      durata_prodotto4 = 4000;
      tempohigh = true;
      segnale = 5;
      avvio_programma = false;
    }
    if (segnale == 5) prodotto4();
  } else if (digitalRead(segnale5) == LOW && (digitalRead(segnale1) == LOW || digitalRead(segnale2) == LOW || digitalRead(segnale3) == LOW || digitalRead(segnale4) == LOW)) {
    lcd_errore = true;
    errore();
  } else if ((digitalRead(segnale5) == HIGH && segnale == 5) && conteggio_prodotto4) {
    if (tempohigh) {
      interrotto_programma = true;
      premuto = millis();
      tempohigh = false;
    }
    if (interrotto_programma && ((millis() - premuto) > rimbalzo)) {
      lcd_interrotta = true;
      erogazione_interrotta();
      interrotto_programma = false;
    }
  }

  if ((digitalRead(segnale1) == HIGH && digitalRead(segnale2) == HIGH && digitalRead(segnale3) == HIGH && digitalRead(segnale4) == HIGH
       && digitalRead(segnale5) == HIGH && conteggio_prodotto4 == false && conteggio_prodotto3 == false && conteggio_prodotto2 == false && conteggio_prodotto1 == false)
      || (segnale == 0)) {
    attesa();
  }
}

void prodotto1() {
  if (consenso_prodotto1) {
    analogWrite(LED_PIN, 40);
    digitalWrite(pompa4, HIGH);
    inizio_prodotto1 = millis();
    digitalWrite(pompa2, HIGH);
    inizio_prodotto3 = millis();
    digitalWrite(13, HIGH);
    Serial.println("Erogo prodotto1");
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print("EROGAZIONE");
    lcd.setCursor(4, 1);
    lcd.print("PRODOTTI");
    conteggio_prodotto1 = true;
    conteggio_prodotto3 = true;
    consenso_prodotto1 = false;
  }
  if (conteggio_prodotto1 && (millis() - inizio_prodotto1 >= durata_prodotto1)) {  //conto il tempo trascorso, quindi blocco l'erogazione
    digitalWrite(pompa4, LOW);
    Serial.println("prodotto1 OK");
    lcd.setCursor(0, 0);
    lcd.print("prodotto1 OK    ");
    fine_prodotto1++;
    conteggio_prodotto1 = false;
  }
  if (conteggio_prodotto3 && (millis() - inizio_prodotto3 >= durata_prodotto3)) {  //conto il tempo trascorso
    digitalWrite(pompa2, LOW);
    Serial.println("prodotto3 OK");
    lcd.setCursor(0, 1);
    lcd.print("prodotto3 OK ");
    fine_prodotto1++;
    conteggio_prodotto3 = false;
  }
  if (fine_prodotto1 >= 2) {
    digitalWrite(13, LOW);
    digitalWrite(pompa2, LOW);
    digitalWrite(pompa4, LOW);
    lcd_fine_prodotto1 = true;
    if (lcd_fine_prodotto1) {
      Serial.println("PRODOTTI EROGATI");
      lcd.clear();
      lcd.setCursor(4, 0);
      lcd.print("PRODOTTI");
      lcd.setCursor(4, 1);
      lcd.print("EROGATI");
      lcd_fine_prodotto1 = false;
    }
    lcd_attesa = true;
    inizio_schermo = millis();
    segnale = 0;
    fine_prodotto1 = 0;
  }
}

void prodotto2() {
  if (consenso_prodotto2) {
    analogWrite(LED_PIN, 40);
    digitalWrite(pompa1, HIGH);
    inizio_prodotto2 = millis();
    digitalWrite(pompa2, HIGH);
    inizio_prodotto3 = millis();
    digitalWrite(13, HIGH);
    Serial.println("Erogo prodotto2");
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print("EROGAZIONE");
    lcd.setCursor(4, 1);
    lcd.print("PRODOTTI");
    conteggio_prodotto2 = true;
    conteggio_prodotto3 = true;
    consenso_prodotto2 = false;
  }
  if (conteggio_prodotto2 && (millis() - inizio_prodotto2 >= durata_prodotto2)) {  //conto il tempo trascorso, quindi blocco l'erogazione
    digitalWrite(pompa1, LOW);
    Serial.println("prodotto2 OK");
    lcd.setCursor(0, 0);
    lcd.print("prodotto2 OK    ");
    fine_prodotto2++;
    conteggio_prodotto2 = false;
  }
  if (conteggio_prodotto3 && (millis() - inizio_prodotto3 >= durata_prodotto3)) {  //conto il tempo trascorso
    digitalWrite(pompa2, LOW);
    Serial.println("prodotto3 OK");
    lcd.setCursor(0, 1);
    lcd.print("prodotto3 OK ");
    fine_prodotto2++;
    conteggio_prodotto3 = false;
  }
  if (fine_prodotto2 >= 2) {
    digitalWrite(13, LOW);
    digitalWrite(pompa2, LOW);
    digitalWrite(pompa1, LOW);
    lcd_fine_prodotto2 = true;
    if (lcd_fine_prodotto2) {
      Serial.println("PRODOTTI EROGATI");
      lcd.clear();
      lcd.setCursor(4, 0);
      lcd.print("PRODOTTI");
      lcd.setCursor(4, 1);
      lcd.print("EROGATI");
      lcd_fine_prodotto2 = false;
    }
    lcd_attesa = true;
    inizio_schermo = millis();
    segnale = 0;
    fine_prodotto2 = 0;
  }
}

void prodotto4() {
  if (consenso_prodotto4) {
    analogWrite(LED_PIN, 40);
    digitalWrite(pompa3, HIGH);
    inizio_prodotto4 = millis();
    digitalWrite(13, HIGH);
    Serial.println("Erogo prodotto4");
    lcd.clear();
    lcd.setCursor(5, 0);
    lcd.print("EROGO");
    lcd.setCursor(2, 1);
    lcd.print("prodotto4");
    conteggio_prodotto4 = true;
    consenso_prodotto4 = false;
  }
  if (conteggio_prodotto4 && (millis() - inizio_prodotto4 >= durata_prodotto4)) {  //conto il tempo trascorso
    digitalWrite(pompa3, LOW);
    digitalWrite(13, LOW);
    lcd_fine_prodotto4 = true;
    if (lcd_fine_prodotto4) {
      Serial.println("prodotto4 erogato");
      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print("prodotto4");
      lcd.setCursor(4, 1);
      lcd.print("EROGATO");
      lcd_fine_prodotto4 = false;
    }
    lcd_attesa = true;
    inizio_schermo = millis();
    segnale = 0;
    conteggio_prodotto4 = false;
  }
}

void erogazione_interrotta() {
  digitalWrite(13, LOW);
  digitalWrite(pompa4, LOW);
  digitalWrite(pompa1, LOW);
  digitalWrite(pompa3, LOW);
  digitalWrite(pompa2, LOW);
  if (lcd_interrotta) {
    Serial.println("EROGAZIONE INTERROTTA");
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print("EROGAZIONE");
    lcd.setCursor(3, 1);
    lcd.print("INTERROTTA");
    lcd_interrotta = false;
  }
  conteggio_prodotto1 = false;
  conteggio_prodotto2 = false;
  conteggio_prodotto4 = false;
  conteggio_prodotto3 = false;
  tempolow = true;
  lcd_attesa = true;
  inizio_schermo = millis();
  segnale = 0;
}

void errore() {
  digitalWrite(pompa4, LOW);
  digitalWrite(pompa1, LOW);
  digitalWrite(pompa3, LOW);
  digitalWrite(pompa2, LOW);
  if (lcd_errore) {
    analogWrite(LED_PIN, 40);
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print("CONFLITTO");
    lcd.setCursor(4, 1);
    lcd.print("SEGNALI");
    lcd_errore = false;
  }
  lcd_attesa = true;
  inizio_schermo = millis();
}

void attesa() {
  digitalWrite(pompa4, LOW);
  digitalWrite(pompa1, LOW);
  digitalWrite(pompa3, LOW);
  digitalWrite(pompa2, LOW);
  if (lcd_attesa) {
    if ((millis() - inizio_schermo) > fine_schermo) {
      Serial.println("Attendo un segnale");
      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print("ATTENDO UN");
      lcd.setCursor(4, 1);
      lcd.print("SEGNALE");
      lcd_attesa = false;
      spegni = true;
    }
  }
  if (spegni) {
    if ((millis() - inizio_schermo > (timer_acceso * 1000))) {
      analogWrite(LED_PIN, 0);
      spegni = false;
    }
  }
  tempolow = true;
  lcd_errore = true;
}

Schema molto semplice
Pin 4, 5, 6 e 7 escono da arduino e vanno ad ogni ingresso della scheda assieme alla massa.
Massa comune per i 4 pin che chiude a gnd di arduino.
I “segnali” sono 5 rele con contatto pulito di una scheda di un macchinario alla quale mi sono interfacciato con arduino ed uso il PULLUP interno di arduino.

Se serve, disegno uno schema.

P.S. ho mentito sul “semplice if” hahahaha

Se stacchi il filo di pilotaggio del mosfet cosa succede?

Ciao, Ale.

Sì esatto, proverò.
Ci ho pensato mentre scrivevo lo schema di collegamento e mentre rileggevo le caratteristiche dei mosfet stessi.

Proverò prima a misurare quanti volt trovo sull’input e poi a staccare il collegamento da arduino.
Leggevo dal datasheet della scheda mosfet che lavora nel range di 3v-20v input.
Forse qualche tensione parassita mi lascia 3v vaganti e non si azzera.

Da capire però perché non sempre…

In uno stesso ciclo di programma non si devono mai leggere gli ingressi più di una volta, altrimenti se i segnali cambiano tra una lettura e l'altra, la logica delle condizioni if else viene stravolta.

1 Like

Quel programma è troppo complicato

Impossibile da seguire e da debuggare

Devi ripartire da capo, tenendoti leggero

1 Like

Hai il led acceso
Non c'è nulla di vagante
Io voto per programma sbagliato

Anche perché senza schema ...

Puoi chiarirmi meglio cosa intendi?
Ho 5 segnali e li leggo in cascata.

Se 1 è attivo e gli altri spenti, esegue una cosa fintanto che resta attivo.
Se durante questo tempo si dovesse disattivare, disattiva la relativa uscita.

Non capisco cosa ha di sbagliato o quantomeno non so cosa intendi per “leggere più di una volta”

Capisco sia difficile da leggere, io stesso mi meraviglio di quanto sia venuto lungo però, una volta letto tutto, sembra a me essere snello abbastanza da avere solo il necessario.
(Tralascia i vari serial print usati come debug per capire se entrasse in tutte le fasi correttamente).

Alla fine, riassunto, legge lo stato dei 5 segnali.
Se uno si attiva, procede ad “erogare”. (Pompa 12v)
Trascorso un timer, disattiva la pompa.
Se si interrompe il segnale durante l’erogazione, blocca quest’ultima.

Nulla in più

Non è vero

C'è molto di più del necessario

Il fatto che tu non te ne renda conto è molto significativo

Inoltre non ti sei accorto che c'è anche molto di "meno"

A partire da tre semplici numeri

5 pulsanti
4 pompe
3 sole funzioni di erogazione

Ripeto

Riparti da capo

Non sono nemmeno facilmente comprensibili le variabili...
lcd_attesa: forse significa scrive_attesa?
interrotto_programma? Il programma è stato interrotto?
inizio_prodotto? Inizio_erogazione?
inizio_schermo???
Ah, sono UL... Sono letture di millis()? Allora metti a tutti una t_ all'inizio, così si capisce!
t_inizio_erogazione1
durata_prodotto1: durata_erogazione1?
Se inizio_prodotto è UL, perché fine_prodotto è int???...

uint32_t t_inizio_erogazione1;
uint32_t t_fine_erogazione1;

Al posto degli antirimbalzo, poi, metti semplicemente 100...220nF in parallelo ai pulsanti!

Anch'io credo proprio che, adesso che ti sei chiarito bene che cosa deve fare, dovresti riscriverlo con una macchina a stati finiti con uno switch/case.

segnale1, segnale2, ecc. leggili solo una volta all'inizio del loop:
bool segnale1 = digitalRead (PIN_SEGNALE1);
bool segnale2 = digitalRead (PIN_SEGNALE2);
...
e poi usa una struttura ad albero:

#define PIN_SEGNALE1 8
#define PIN_SEGNALE2 9
--- --- ---
loop:
if (segnale1)
  if (segnale2)...
  else ...
else...

5 segnali.
I primi 3 hanno tempi differenti di erogazione ma attivano sempre le stesse 2 delle 4 pompe.
Gli altri 2 segnali attivano ognuno la propria pompa.

Puoi consigliarmi dove guardare per togliere il “di più”?

In macchina a Stati ho scritto tutta la parte del menu, che gestisco con un encoder per modificare le varie variabili quali tempi di erogazione, tempo in cui lo schermo resta acceso, luminosità ecc, in quel caso ne ho ben 23 di “casi”.

Qui invece mi sembrava molto più facile verificare quelle poche condizioni e buttare tutto il codice giù a giro continuo.

Poi:
Lcd attesa è il flag per scrivere attesa su lcd
Interrotto programma è il flag per l’antirimbalzo
Inizio prodotto e inizio erogazione sono ul esatto per gestirmi millis

Ok quindi mi leggo una volta lo stato del segnale, lo salvo in una variabile e proseguo.

Potresti farmi giusto un esempio con la prima porzione?

Tralasciando un attimo la complessità del codice scritto/troppo confusionario, riuscite a trovare cose c’è che non va in questa porzione di codice?
(Ho tolto la parte riguardante la scrittura su lcd per semplificare la lettura)

Sia su seriale che su lcd:
la parte “prodotto1 ok” viene scritta;
la parte “prodotto3 ok” viene scritta;
la parte “prodotti erogati” viene scritta.

Quindi significa che la variabile fine_prodotto1 è stata correttamente innalzata a 2 dai precedenti passaggi e dunque dovrebbe aver svolto anche le righe “pompa4, LOW” e “pompa2, LOW” invece queste sono ancora HIGH.
Perché secondo voi?

Scusa ma:
Non c'è peggior sordo di chi non vuol capire

Quel programma è nato male
Lo devi riscrivere

La domanda giusta sarebbe stata:

Quali idee potrebbero aiutarmi a scrivere un programma più semplice?

Però questo richiede che si sappiano prima tutte la prescrizioni del programma

Quindi comincia col metterle, se vuoi veramente il mio aiuto

Ok, riproviamo.

Ho cinque segnali con input pull Up interno.
I primi tre segnali comandano sempre le prime due pompe ma con tempi diversi di durata mentre gli altri due segnali attivano rispettivamente le altre due pompe rimanenti con tempi fissi.
Quindi devo verificare che, nel momento in cui solo un segnale è attivo e gli altri sono spenti, eseguo un passaggio (ovvero avviare la/le pompa/pompe) mentre se il segnale iniziale è attivo e si attiva un altro segnale, questi vanno in errore con lo blocco delle pompe e, ancora, se mentre il segnale iniziale è attivo, e l’erogazione non è ancora terminata, questo si dovesse interrompere, blocco tutto.
Starebbe a significare che la macchina è stata spenta o comunque quella fase è stata abortita.

Nulla di complicato, per questo pensavo di aver scritto solo il minimo indispensabile.
Probabile che tutte quelle letture dei segnali mandino in confusione qualcosa.

Ora riesci a darmi qualche dritta?

Limitandomi a quella funzione, direi che il codice sembra funzionare correttamente (anche se non hai citato se compare anche "Erogo prodotto1", suppongo di si, esatto?).
Quindi se quella scheda attiva il Mosfet se l'ingresso è HIGH e lo disattiva su LOW, non sembra un problema di codice ma più di hardware ossia o il cablaggio o la board Mosfet (di cui comunque non vedo schemi o datasheet in quella pagina...).

Ad esempio sulla board vedo che ci sono led sia per IN sia per OUT: i led IN riflettono correttamente lo stato in base al risultato di quella funzone (es. se scrive "Erogo prodotto1" deve essere acceso IN1 fino a che non compare "Erogo prodotto2" per cui IN1 si spegne e IN2 si accende)?

Altrimenti penso sia necessario che tu ci faccia vedere il cablaggio (se non hai uno schema possono forse andare bene una o due foto, purché nitide e con collegamenti comprensibili), ma la prima cosa che mi viene in mente è se i GND degli ingressi della board siano collegati tutti tra loro e in caso contrario se tu abbia collegato il GND di Arduino a tutti i GND della board.

Nei software "sequenziali" scritti in questo modo è facile perdersi perché quello che è "logica" viene mescolato con ciò che invece è altro come ad esempio le informazioni mostrate su display, la gestione dei tempi etc etc.

Il mio consiglio è quello di strutturare il software in modo più leggibile. Nel loop() dovresti lasciare poche chiamate "funzionali" che vanno poi sviluppate in classi o funzioni specifiche.
Più o meno come hai fatto con il display, ma in modo più spinto.

Il codice del debounce ad esempio, crea confusione. Riscrivi la gestione dei pulsanti usando una funzione o meglio ancora una classe cosi da ripulire tutto il resto (ci sono anche ottime librerie già pronte all'uso se vuoi semplificarti la vita).

La gestione della macchina a stati finiti è tipicamente più chiara e leggibile quando viene usato uno switch/case, soprattutto se usi delle funzioni per eseguire "cose" in ciascun stato.
La combinazione dei pulsanti determina lo stato della macchina ed in funzione dello stato attivo richiami la funzione relativa.

Gli stati devono essere esplicitati in modo chiaro e completo.
Ad esempio nel tuo caso avrai qualcosa tipo ATTESA_SELEZIONE, EROGAZIONE1, ATTESA_EROGAZIONE1, EROGAZIONE2, ATTESA_EROGAZIONE2, EROGAZIONE3, ATTESA_EROGAZIONE3, ERRORE.

Gli stati ATTESA_EROGAZIONEX potrebbero essere anche condensati in un unico stato dalla durata variabile (che viene quindi determinata dallo stato degli ingressi).