Ok, ho fatto qualche prova con un mio o-quasi. Che la R-pull sia di 1kΩ o di 1MΩ cambia nulla (almeno macroscopicamente). Ho qualche riserva sul campionamento analogico, nel senso che un ingresso digitale potrebbe interpretare diversamente (il mio o-quasi legge un ingresso digitale).
Un pulsantino simile a quello del primo post mi da dei rimbalzi (una volta su dieci, e solo in apertura) entro un millisecondo, il caso peggiore è stato un buco di 4ms. Resistenza da 10k e condensatore da 100nF (costante di tempo 1ms) sembra bastare, anche se per me la costante di tempo per sicurezza non dovrebbe mai scendere sotto i 10ms.



Diverso è il caso di "filo infilato nella breadboard", in questo caso si può arrivare a oltre 50ms di "grattamento" (anche se la "norma" è 5..10ms):

In questo caso può servire una costante di tempo molto più lunga, e si rischia lo stesso di vedere cose come questa, dove spariscono i picchi veloci ma può rimanere una componente a frequenza più bassa:

Ho l'impressione che un debounce software da 20..30ms (accettazione segnale se stabile per almeno 20..30ms) permetta di non salire troppo con la costante di tempo richiesta da un debounce hardware.
L' o-quasi (4000 campioni da 25µs bitmappati in 500byte):
#define RESOL 25
#define SAMPL 4000
#define LENDATA 500
uint32_t t; // tempo in microsec
byte in; // valore 0/1 letto da ingresso
uint16_t n;
byte d[LENDATA] = { 0 };
bool basso = true;
//_____________________________________________________________
void setup()
{
pinMode(2, INPUT);
pinMode(13, OUTPUT);
Serial.begin(38400);
}
//_____________________________________________________________
void loop()
{
in = (PIND >> 2) & 1;
if (basso and in) // fronte di salita
{
t = micros();
d[0] = 0b10000000;
n = 7;
while (n < SAMPL)
{
while (micros() - t < RESOL);
in = (PIND >> 2) & 1;
n++;
d[n >> 3] |= in << (n & 7); // bit da scrivere
t += RESOL;
}
for (n = 0; n<LENDATA; n++)
{
Serial.write(d[n]);
d[n] = 0;
}
basso = false;
}
else if (!basso and !in) // fronte di discesa
{
t = micros();
d[0] = 0b011111111;
n = 7;
while (n < SAMPL)
{
while (micros() - t < RESOL);
in = (PIND >> 2) & 1;
n++;
d[n >> 3] |= in << (n & 7); // bit da scrivere
t += RESOL;
}
for (n = 0; n<LENDATA; n++)
{
Serial.write(d[n]);
d[n] = 0;
}
basso = true;
}
}
//_____________________________________________________________
Il visualizzatore:
#! /usr/bin/env python3
import tkinter as tk
import serial
import time
##______________________________________________________________
PORTNAME = '/dev/ttyUSB0'
WID = 500 ## pixel larghezza grafico
RESOL = 25 ## 25 microsec.
SAMPLES = 250 ## campioni da visualizzare, max 4000
FOSCA = SAMPLES * (RESOL / 1000.) ## fondo scala in ms
##______________________________________________________________
def crea_assi(): ## assi in millisecondi
for n in 1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 100:
x = (WID - 1.) * n / FOSCA
canv1.create_line(x, 0, x, 300, fill='#a0a0a0')
##______________________________________________________________
def draw():
canv1.delete('all')
crea_assi()
coords = []
sx = (WID - 1.) / (SAMPLES - 1.) ## step asse X
n = 0
while (n < SAMPLES):
x = n * sx
y = (g.d[n >> 3] >> (n & 7)) & 1
coords.extend([x, 200 - 100*y])
n += 1
canv1.create_line(*coords, fill='red')
##______________________________________________________________
class g(object): ## dati di lavoro globali
fase = 0
t = 0
d = [0] * 500
n = 0
##______________________________________________________________
def recall(): ## funzione attivata ogni 5 ms
if (g.fase == 0): ## attesa silenzio seriale 0.5 sec
if (ser.inWaiting()):
while (ser.inWaiting()): ser.read(1)
g.t = time.time()
elif (time.time()-g.t > 0.5):
g.fase = 1;
g.n = 0
elif ((g.fase == 1) and ser.inWaiting()): ## attesa dati
g.t = time.time()
g.fase = 2
elif (g.fase == 2): ## ricezione dati con timeout 0.5 sec
while (ser.inWaiting()):
g.d[g.n] = ser.read(1)[0]
g.n += 1
if (g.n == 500):
draw()
g.fase = 0
if (time.time()-g.t > 0.5): g.fase = 0;
root.after(5, recall)
##______________________________________________________________
root = tk.Tk()
root.title('Bounce display - By C.Fin 2019')
root.resizable(False, False)
canv1 = tk.Canvas(root, width=WID, height=300,
background='#ffffff', highlightthickness=0)
canv1.pack(padx=16, pady=16)
crea_assi()
ser = serial.Serial(PORTNAME, 38400, 8, 'N', 1, timeout=0)
g.t = time.time()
root.after(5, recall)
root.mainloop()




