Salve a tutti,
ho collegato un pluviometro a bascula ad un ESP32 (in PULLUP hardwere con R da 10K) al GPIO 13 e programmato sotto interrupt; come ci si aspetta da un contatto di quel tipo i rimbalzi che fa sono parecchi.... Per controllare ho comunque collegato un oscilloscopio, ecco i risultati (immagine1).
HO poi collegato in parallelo al contatto un condensatore ceramico da 100nF ed il risultato è questo (immagine2); il problema è che a livello di software non migliora nulla, anzi al contrario peggiora!!
Ho allegato anche una foto dello schema.
La cosa strana e' che i pluviometri usano dei reed, che di solito hanno meno rimbalzi dei comuni switch meccanici (non ne sono totalmente esenti, tranne i reed a contatto "bagnato" in mercurio che pero' sono difficili da trovare, ma dovrebbero essere comunque molto meno) ... per di piu se usando lo schema proposto da Guglielmo ti da lo stesso problema ... inizierei a sospettare di qualcos'altro ...
>alanmasutti: prova a scrivere proprio due righe di codice che fanno solo la gestione del interrupt e magari incrementano un contatore che visualizzi su monitor seriale ... se il problma non appare, allora sai che è da qualche altra parte nel programma, se appare ancora ... posta il piccolo codice di test che diamo un'occhiata ... :
gpb01: >alanmasutti: prova a scrivere proprio due righe di codice che fanno solo la gestione del interrupt e magari incrementano un contatore che visualizzi su monitor seriale ... se il problma non appare, allora sai che è da qualche altra parte nel programma, se appare ancora ... posta il piccolo codice di test che diamo un'occhiata ... :
Guglielmo
void setup() {
// put your setup code here, to run once:
initPluviometro();
Serial.begin(115200);
pinMode(0,INPUT);
}
volatile int cont1;
void IRAM_ATTR pluviometroISR1() {
noInterrupts();
cont1++;
interrupts();
}
void initPluviometro() {
pinMode(13, INPUT);
attachInterrupt(13, pluviometroISR1, FALLING);
interrupts();
}
void loop() {
Serial.println(cont1);
delay(500);
if(!digitalRead(0)){
cont1 =0;
}
}
I contatori arrivano anche ad 70 volte per cambio di stato...
Ciao,
Dalle ultime prove, risulta che con il condensatore fa ancora peggio.... il contatore senza condensatore non supera 10, con il condensatore arriva anche a 80 senza problemi....
non mi spiego il perché!...
Fare l'antirimbalzo con un condensatore e' un metodo che funziona solo se l'ingresso usato e' a trigger di schmitt e con una isteresi sufficente, altrimenti il condensatore peggiora la situazione.
E' comunque un metodo che presenta una scarsa ripetibilita' a causa della tolleranza dei componenti.
Ti propongo una soluzione software che pero', non avendo un ESP32, ho testato su di una UNO.
#define DEBOUNCE_TIME 50 // tempo di antirimbalzo in mS
#define WAIT_FOR_INTERRUPT 0
#define WAIT_FOR_DEBOUNCE 1
uint16_t Conta;
uint32_t StartDebounceTime;
uint8_t State;
volatile bool IntFlag = false;
//------------------------------------------------------------------------
void setup()
{
Serial.begin(115200);
Conta = 0;
State = WAIT_FOR_INTERRUPT;
pinMode(2,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), pluviometroISR1, FALLING);
interrupts();
}
//------------------------------------------------------------------------
void loop()
{
switch (State)
{
case WAIT_FOR_INTERRUPT: // stiamo aspettando un interrupt
if (IntFlag) // e' arrivato un interrupt
{
Conta++; // incrementa il contatore
Serial.println(Conta); // e stampalo
StartDebounceTime = millis(); // inizializza il tempo di antirimbalzo
IntFlag = false; // resetta il flag di interrupt
State = WAIT_FOR_DEBOUNCE; // cambia stato
}
break;
case WAIT_FOR_DEBOUNCE: // stiamo aspettando che scada il tempo di antirimbalzo
if( (millis() - StartDebounceTime) > DEBOUNCE_TIME)
{ // il tempo e' scaduto
EIFR = 0x01; // resetta eventuali interrupt pendenti
// perche' il core di Arduino non lo fa prima di abilitare un interrupt
// (secondo me e' un baco anche se c'e' chi sostiene che sia una scelta)
attachInterrupt(digitalPinToInterrupt(2), pluviometroISR1, FALLING); // riabilita l'interrupt
State = WAIT_FOR_INTERRUPT; // cambia stato
}
break;
}
// qui si fanno le altre cose che deve fare il programma
// ...
// ...
}
//------------------------------------------------------------------------
void pluviometroISR1() // servizio interrupt
{
detachInterrupt(digitalPinToInterrupt(2)); // disabilita l'interrupt
IntFlag = true; // setta il flag per il main
}
Purtroppo a causa di un baco del core di Arduino (o secondo alcuni di una scelta) quando si abilita un interrupt quelli eventualmente pendenti non vengono prima resettati e quindi bisogna farlo con un accesso diretto al registro di flag. Quindi se per caso fossi interessato ad implementare la mia soluzione devi cercare come si fa questo sull'ESP32.
Sulimarco:
Fare l'antirimbalzo con un condensatore e' un metodo che funziona solo se l'ingresso usato e' a trigger di schmitt e con una isteresi sufficente, altrimenti il condensatore peggiora la situazione.
Quello che non capisco è: come mai con il pulsante sul GPIO 0 (non credo abbia il Trigger di Schmitt) funziona senza alcun problema...?
... non so la ESP32, ma la MCU di Arduino i trigger sugli ingressi li ha ...
Sulimarco:
Fare l'antirimbalzo con un condensatore e' un metodo che funziona solo se l'ingresso usato e' a trigger di schmitt e con una isteresi sufficente, altrimenti il condensatore peggiora la situazione.
...
Beh, è abbastanza probabile ...
... se non hai un "trigger di schmitt" sull'ingresso, il condensatore tiene il pin in una situazione "indeterminata" più a lungo, tempo dato dalla curva di carica ... :
Se intendi i vecchi ingressi senza alcuna tolleranza sono daccordo anch'io ... ma ormai a parte le porte logiche elementari, credo non li trovi piu su alcuna MCU ... almeno, io ho sempre utilizzato i debounce RC un po dappertutto, e fin'ora problemi simili a quelli dell'OP non ne ho mai avuto nemmeno uno ...
Etemenanki:
Se intendi i vecchi ingressi senza alcuna tolleranza sono daccordo anch'io ...
... si, ovviamnete intendo ingressi senza alcuna soglia ... non ho idea di come siano i pin di ingresso degli ESP32, ma mi sembra strano che non abbiano un trigger in ingresso, anche perché, da datasheet:
VIH (High-level input voltage): da 0.75×VDD1 a VDD1+0.3 V
VIL (Low-level input voltage) : da –0.3 a 0.25×VDD1 V
VIH (High-level input voltage): da 0.75×VDD1 a VDD1+0.3 V
VIL (Low-level input voltage) : da -0.3 a 0.25×VDD1 V
Queste non sono le specifiche di un ingresso a trigger di schmitt.
Qui si dice che da un certo valore in su viene letto sicuramente un 1 e che da un certo valore in giu' viene letto sicuramente uno 0. Nella fascia intermedia non e' garantito un risultato noto.
Questo e' un ingresso normale.
Un ingresso a trigger di schmitt deve avere specificati: VT+ Positive-Going Threshold Voltage