[Risolto]Problema con interrupt PCF8574

Salve a tutti!
Premetto che ho già cercato sul forum ed ho trovato decine di discussioni riguardo questo argomento, ma nessuna mi è stata di aiuto…
Allora, oggi stavo facendo delle prove con il PCF8574, e sono riuscito senza problemi ad usarlo come expander sia per gli ingressi che per le uscite, quindi ho deciso di provare ad usare gli interrupt e dopo aver letto sul playground come funzionano ho realizzato il collegamento allegato e scritto questo codice:

#include<Wire.h>

#define PCF8574_address 0x38

volatile byte data;
volatile boolean interrupt_received = false;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  attachInterrupt(0, PCF8574_read, FALLING);
  PCF8574_write(B11111111);
}

void loop()
{
  if(interrupt_received)
  {
    Serial.println(data);
    delay(2000);
  }
  
  else
    Serial.println("Waiting for an interrupt...");
}

void PCF8574_write(byte state)
{
  Wire.beginTransmission(PCF8574_address);
  Wire.write(state);
  Wire.endTransmission();
}

void PCF8574_read()
{
  interrupt_received = true;
  Wire.requestFrom(PCF8574_address, 1);
  if(Wire.available())
  {
    data = Wire.read();
  }
}

Il problema è che quando apro il monitor seriale invece di apparire la scritta “Waiting for an interrupt…” non appare nulla oppure appare solo una parte della scritta ( tipo “Waiting” oppure “Waitinf for an”) e poi non succede nulla, neanche se pigio i pulsanti.

Qualcuno ha un’idea del perchè?

Grazie in anticipo!

Aggiungi nel setup, prima di attachInterrupt:

pinMode(2, INPUT_PULLUP);

L'interrupt deve essere breve. Io toglierei la lettura dal bus e la sposterei nel loop. Lascia solo il cambio di variabile all'interno dell'interrupt.

@PaoloP
Grazie mille per la risposta!
Ho modificato il codice come mi hai suggerito:

#include<Wire.h>

#define PCF8574_address 0x38

byte data;
volatile boolean interrupt_received = false;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, PCF8574_interrupt, FALLING);
  PCF8574_write(B11111111);
}

void loop()
{
  if(interrupt_received)
  {
    data = PCF8574_read();
    Serial.println(data, BIN);
    interrupt_received = false;
    delay(2000);
  }
  
  else
    Serial.println("Waiting for an interrupt...");
}

void PCF8574_write(byte state)
{
  Wire.beginTransmission(PCF8574_address);
  Wire.write(state);
  Wire.endTransmission();
}

byte PCF8574_read()
{
  Wire.requestFrom(PCF8574_address, 1);
  if(Wire.available())
  {
    data = Wire.read();
  }
  return data;
}

void PCF8574_interrupt()
{
  interrupt_received = true;
}

Scusate se modifico il post, ma mi sono reso conto che non funzionava solo perchè mi ero dimenticato di rimuovere “detachInterrupt(0);” , adesso funziona tutto.
Da seriale rilevo entrambe le variazioni di stato dei pulsanti, cioè quando premo e quando rilascio, ora devo trovare il modo di ignorare l’interrupt generato quando rilascio il tasto…

Pelodiulo:
Da seriale rilevo entrambe le variazioni di stato dei pulsanti, cioè quando premo e quando rilascio, ora devo trovare il modo di ignorare l’interrupt generato quando rilascio il tasto…

Direi con una variabile di stato true/false

Però è strano, FALLING non dovrebbe darti 2 volte interrupt (quello dovrebbe farlo CHANGE) ?!?

Si, ci avevo pensato anche io ad una variabile booleana, dopo faccio qualche prova e vi faccio sapere...

Comunque da quello che ho capito sul datasheet è normale ottenere due interruzioni, infatti la variabile int passa da un valore logico alto ad uno basso ogni volta che cambia il valore su un pin o più del PCF8574, quindi anche quando viene rilasciato il pulsante e quindi il bit corrispondente torna ad avere valore 1.

La differenza fra FALLING e CHANGE serve solo per cambiare il momento in cui si attiva l'interrupt, infatti con FALLING l'interrup viene attivato quando Arduino vede un fronte di discesa (transizione 1->0) della variabile int, mentre con CHANGE viene attivato ogni volta che Arduino vede un cambiamento di stato della variabile int , quindi sia quando si ha una transizione 1->0, sia quando si ha una transizione 0->1. Invece usando come parametro LOW l'interrupt viene attivato ciclicamente per tutto il tempo in cui la variabile int ha valore 0. Almeno così ho capito io, se così non fosse correggetemi!

Nel datasheet c'è scritto che attiva l'interrupt sia per il RISING che per il FALLING degli I/O del PCF. Mentre sul micro devi settare FALLING. Ovviamente per ogni pressione con rilascio avrai 2 impulsi. Devi leggere tu da codice lo stato dei pulsanti e intervenire secondo la tua logica: es. mantenimento di un pulsante premuto o singola pressione (con rilascio).

Pelodiulo:
La differenza fra FALLING e CHANGE serve solo per cambiare il momento in cui si attiva l’interrupt, infatti con FALLING l’interrup viene attivato quando Arduino vede un fronte di discesa (transizione 1->0) della variabile int, mentre con CHANGE viene attivato ogni volta che Arduino vede un cambiamento di stato della variabile int , quindi sia quando si ha una transizione 1->0, sia quando si ha una transizione 0->1. Invece usando come parametro LOW l’interrupt viene attivato ciclicamente per tutto il tempo in cui la variabile int ha valore 0. Almeno così ho capito io, se così non fosse correggetemi!

Questo è quello che ho capito anche io. Dal punto di vista Arduino.
Leggendo poi il datasheet del pcf, come avete detto, il chip genera comunque 2 int sia in falling che in rising. Quindi dal punto di vista Arduino vede comunque 2 int. E si, la boolean è l’unica strada.

io farei anche un debounce degli ingressi all'expander