cambio stato out al cambio stato di un ingresso. Ripetere solo una volta

Probabilmente la birretta che ho bevuto (tra l'altro leggera) sta avendo effetti negativi su di me...

Una cosa semplicissima, se premo il pulsante (pulsante_campanello) deve attivare il relè del cicalino_campanello ma solo una volta (perché devo inviare solo una volta lo stato del relè).
Quando mollo il pulsante il relè si diseccita ed invia una sola volta il nuovo stato.

Con questo sketch se premo il pulsante attivo il relè ma continuo ad inviare lo stato (e a me non va bene).
Il pin del pulsante_campanello è settato INPUT_PULLUP

Dove sbaglio?

  lettura_pulsante_campanello = digitalRead(pulsante_campanello);
  if (lettura_pulsante_campanello != ultimaLettura_pulsante_campanello) {
    ultimoTempoDebounce_pulsante_campanello = millis();
  }

  if ((millis() - ultimoTempoDebounce_pulsante_campanello) > attesaDebounce) {
    if ((digitalRead(pulsante_campanello) == LOW) && (digitalRead(cicalino_campanello) == LOW)) {
      digitalWrite(cicalino_campanello, HIGH);
      stato_cicalino_campanello = HIGH;
      Serial.println("cicalino_campanello -->ON");
      Serial.print("stato rele campanello");
      Serial.println(cicalino_campanello);
      client.publish("board1/stat/cicalino_campanello", "ON");
      stato_pulsante_campanello = lettura_pulsante_campanello;
    } else {
      if ((digitalRead(pulsante_campanello) == HIGH) && (digitalRead(cicalino_campanello) == HIGH)) {
        digitalWrite(cicalino_campanello, LOW);
        stato_cicalino_campanello = LOW;
        Serial.println("cicalino_campanello -->OFF");
        Serial.print("stato rele campanello");
        Serial.println(cicalino_campanello);
        client.publish("board1/stat/cicalino_campanello", "OFF");
        stato_pulsante_campanello = lettura_pulsante_campanello;
      }
    }
  }

  ultimaLettura_pulsante_campanello = lettura_pulsante_campanello;

Ricapitolando: premo il pulsante, eccito il relè ed invio solo una volta lo stato relè; rilascio il pulsante, diseccito il relè ed invio solo una volta lo stato.
Sinceramente mi vergogno a chiedere aiuto per una banalità simile...

Se stato_attuale != stato_precedente, allora c'è stata una variazione, faccio quello che devo fare e mi segno quale è lo il nuovo stato_precedente, altrimenti ...
... ora divertiti a pensare come applicare questa cosa :wink:

Guglielmo

No, nemmeno così va....
Mi accende il led per 100 millisecondi (il debunce che ho impostato) e poi lo spegne.

  lettura_pulsante_campanello = digitalRead(pulsante_campanello);
  if (lettura_pulsante_campanello != ultimaLettura_pulsante_campanello) {
    ultimoTempoDebounce_pulsante_campanello = millis();
  }

  if ((millis() - ultimoTempoDebounce_pulsante_campanello) > attesaDebounce) {
    if (lettura_pulsante_campanello != stato_pulsante_campanello) {
      stato_cicalino_campanello = !stato_cicalino_campanello;
      digitalWrite(cicalino_campanello, stato_cicalino_campanello);
      if (stato_cicalino_campanello == 1) {
        client.publish("board1/stat/cicalino_campanello", "ON");
        Serial.println("cicalino campanello --> ON");
      } else {
        client.publish("board1/stat/cicalino_Campanello", "OFF");
        Serial.println("cicalino_campanello --> OFF");
      }
          }
    stato_pulsante_campanello = lettura_pulsante_campanello;
  }

  ultimaLettura_pulsante_campanello = lettura_pulsante_campanello;

Oramai sono cotto...

Primo, NON USARE I DEBOUNCE SOFTWARE, che ti complicano la vita e basta (e poi, vuoi mettere quanto e' piu elegante e sobrio usare una semplice rete RC ? ... :wink: ) ... secondo, usa una flag ed un paio di if (o un if-else if, fa lo stesso se la usi correttamente) ...

Poi, come gia suggerito da Guglielmo ... se stato pulsante e' cambiato E flag no, invia segnale e cambia stato a flag ... due di fila, uno per ogni valore (oops, cosi ti ho suggerito troppo :D)

Va beh, è un codice scritto da cane... probabilmente lo si può riscrivere con la metà del codice... però sembra funzionare così...

int pulsante_campanello = 14;
int cicalino_campanello = 15;
bool stato_cicalino_campanello = 0;
bool consenso_invio_dati_campanello = 0;
int controllo = 0;
int controllo2 = 0;

void setup() {
  pinMode(cicalino_campanello, OUTPUT);
  pinMode(pulsante_campanello, INPUT_PULLUP);
  Serial.begin(115200);

}

void loop() {
  if ((digitalRead(pulsante_campanello) == LOW) && (digitalRead(cicalino_campanello) == LOW)) {
    Serial.println("condizione avvenuta");
    digitalWrite(cicalino_campanello, HIGH);
    stato_cicalino_campanello = HIGH;
    consenso_invio_dati_campanello = 1;
    if (consenso_invio_dati_campanello == 1) {
      Serial.println("premuto pulsante campanello, sta suonando");
      controllo = controllo + 1;
      Serial.print("numero invio campanello");
      Serial.println(controllo);
      consenso_invio_dati_campanello = 0;
    }
  }
  if ((digitalRead(pulsante_campanello) == HIGH) && (digitalRead(cicalino_campanello) == HIGH)) {
    Serial.println("condizione2 avvenuta");
    digitalWrite(cicalino_campanello, LOW);
    stato_cicalino_campanello = LOW;
    consenso_invio_dati_campanello = 1;
    if (consenso_invio_dati_campanello == 1) {
      Serial.println("rilasciato pulsante campanello, non sta più suonando");
      controllo2 = controllo2 + 1;
      Serial.print("numero invio campanello");
      Serial.println(controllo);
      consenso_invio_dati_campanello = 0;
    }
  }
}

Come detto, a me interessa che invii via seriale (poi anche in mqtt) l'avvenuto cambio di stato del cicalino campanello (sia ON che OFF).

Può andare?
Sperimentando con un led sembra di si: metto a gnd il pin del pulsante e il led si accende ed invia il dato via seriale, quando rilascio il pin campanello il led si spegne e viene inviata comunicazione via seriale.

Ce l'ho fatta? Altrimenti mi bevo un'altra birretta e via :smiley:

EDIT:dimenticavo, la variabile stato_cicalino_campanello in questo sketch non serve a nulla, mi servirà poi in quello completo.

Se va é soluzione. Comunque qualche consiglio:

  1. usa variabili di tipo byte se esse devono contenere valori massimi minori di 255, e usa la parola const nella loro dichiarazione (tra tipo e nome) se esse non devono cambiare il loro valore (es. pin)
  2. per tutte le Serial.print/ln ("...") sostituiscile con delle Serial.print/ln (F("...")), così riduci l'uso di memoria
  3. negli if puoi togliere ==HIGH, in caso di boolean é sottinteso
  4. per alzare di 1 una variabile la via più breve é variabile++. MAI, MAI, MAI variabile=variabile++.

Se usi un led credo che non ti serva la variabile "consensoinvio...", se non usi un led credo il codice non vada come speri

Silente:
Se va é soluzione. Comunque qualche consiglio:

  1. usa variabili di tipo byte se esse devono contenere valori massimi minori di 255, e usa la parola const nella loro dichiarazione (tra tipo e nome) se esse non devono cambiare il loro valore (es. pin)
  2. per tutte le Serial.print/ln ("...") sostituiscile con delle Serial.print/ln (F("...")), così riduci l'uso di memoria
  3. negli if puoi togliere ==HIGH, in caso di boolean é sottinteso
  4. per alzare di 1 una variabile la via più breve é variabile++. MAI, MAI, MAI variabile=variabile++.

Se usi un led credo che non ti serva la variabile "consensoinvio...", se non usi un led credo il codice non vada come speri

Grazie per le preziose info a te, ma anche a Etem e Guglielmo!
Nello sketch postato all'inizio avevo continui invii seriali/mqtt che generavano un flooding e mi incasinavano tutto.
Cosa intendi quandi dici che se non uso il led il codice non funzionerà come spero?
Adesso sto utilizzando un led (ovviamente con resistore) per simulare il funzionamento. Poi ci sarà un piccolo relè che chiuderà il contatto del campanello alla pressione del pulsante.

Nel programma vedo che tu hai usato due macro blocchi, in entrambi controlli se pulsante e led hanno lo stesso stato (in uno alto e nell'altro basso), ma non controlli la variabile "consensoinvio...", variabile che ad un certo punto forzi a 1. Dopo quel punto c'è si una if (la variabile è a 1), ma essa è certamente vera, in quanto la hai appena messa a 1. A bloccarti la ripetizione, quindi, probabilmente è la lettura del pin del led, il cui stato cambia all'interno del blocco.
Es:

Il programma inizia con led spento e pulsante LOW
entra nel primo blocco
{
invia quello che deve
accende il led
mette a 1 la variabile
la variabile è a 1, entra nell'if di invio e invia quello che deve e la variabile torna a 0
}
ora il pulsante è LOW e il led è HIGH. Non entra più in nessun if

Il pulsante si alza. Ora led e pulsante sono su HIGH
Entra nel secondo blocco
{
fa quel che deve
spegne il led
mette a 1 la variabile
entra nell'if e invia. Mette a 0 la variabile
}
il pulsante è HIGH e il led LOW. Non entra in nessun if
Il gioco ricomincia

La vera memoria la hai nel led, non nella variabile. Per avere la memoria nella variabile dovresti fare che ognuno dei due controlli verifichi il pulsante e la variabile (in uno entrambi HIGH e nell'altro LOW), e nel suo corpo metta la variabile come va bene all'altro
Es.

pulsante LOW e variabile a 0
il primo controllo è soddisfatto
{
fa quello che deve, incluso inviare
mette la variabile a 1
}
il controllo non è più soddisfatto.
Neanche il secondo

il pulsante passa a HIGH
Il secondo controllo è soddisfatto
{
fa quello che deve, incluso inviare
mette la variabile a 0
}
nessun controllo è sddisfatto
il giro ricomincia

.
E dimenticavo
una boolean ==LOW è equivalente a ! una boolean. E le digitalRead sono contate boolean (diciamo)