30 Taster einlesen mit i2c oder shiftRegister?

Hallo,

also bevor Du, Skoby, hier Unsinn verbreitest muß ich mich doch nochmal melden. Leute, nehmt doch einfach mal die Bounce2 Lib zur Hand bevor ihr darüber schreibt.

Man kann und muß jeden Taster als eigenes Objekt erstellen und legt damit auch für jeden Taster seine eigene Entprellzeit fest. Kann man natürlich auch mit einer Variable für alle global festlegen.

Das ganze sieht dann ungefähr so aus. Mal paar Zeilen rauskopiert von meinem Sketch

 ....
Bounce debouncer1 = Bounce();  // Instantiate a Bounce object Nr.1 (1. Taster SDread)
Bounce debouncer2 = Bounce();  // Instantiate a Bounce object Nr.2 (2. Taster BTmodul)
Bounce debouncer3 = Bounce();  // Instantiate a Bounce object Nr.3 (3. Taster SD_write_protect)

 ....

// After setting up the button, setup debouncer
  debouncer1.attach(Taster_SDread);
  debouncer1.interval(30);    // Entprellzeit 30ms
  
  debouncer2.attach(Taster_BTmodul);
  debouncer2.interval(30);    // Entprellzeit 30ms
  
  debouncer3.attach(Taster_SD_access_protect);
  debouncer3.interval(30);    // Entprellzeit 30ms

Ihr könnt aber gern versuchen das anders und einfacher zu lösen. Nur guckt Euch bitte die Bsp. der Bounce2 vorher an, bevor ihr darüber schreibt. Bitte. Sonst endet das hier im Kaos.

Oder nimm einfach die ClickButton / OneButton Lib

Hallo,
ich wußte nicht, das es Unsinn ist, was ich geschrieben habe. Es lag mir auch
fern diesen zu verbreiten. Ich glaube, ich lasse das in Zukunft. Dann müssen
die "Profis" auch nicht jede Frage eines "Deppen" unzureichend beantworten.
Gruß und Spaß
Andreas

Kann man die debounce2 lib auch für Schieberegister oder IO Erweiterungen nehmen? Ich dachte, das geht nur für native Pins des Boards.

Doc_Arduino:
Man kann und muß jeden Taster als eigenes Objekt erstellen und legt damit auch für jeden Taster seine eigene Entprellzeit fest. Kann man natürlich auch mit einer Variable für alle global festlegen.

Man kann übrigens auch Arrays aus Objekten erstellen. Dann kann man über alle Objekte iterieren und muss nicht den Code für jedes einzeln schreiben.

ElEspanol:
Kann man die debounce2 lib auch für Schieberegister oder IO Erweiterungen nehmen? Ich dachte, das geht nur für native Pins des Boards.

Sehr richtig !

Warum erschlägt man das bei der Anzahl von Taster nicht [...] mit "Software".

Das ist mir allerdings tatsächlich unverständlich, darum gehts doch hier, oder? :wink:

Bevor man sich eine neue Bounce2A library schreibt, die z.B. das digitalRead nicht selbst macht, sondern sich sonstwo her holt, sollte man nochmal von vorne überlegen, was man tatsächlich braucht.

Egal ob i2c oder shiftIn, das ganze ist seriell und es geht um mechanische manuell betätigte Licht-Taster. Da kommt es doch wohl auf 50 msec nicht an. Individuelle debounce-Zeiten ... wenn es für ein mehrstimmiges keyboard wäre, könnte man das ja diskutieren ...

Was ist nun richtig. Nur native Ports oder auch I2C und Schieberegister?

Hallo,

entprellen muß man nur digitale Eingänge wo echte Taster o.ä. angeschlossen sind.

Digitale Signale von anderen digitalen Schaltungen muß man nicht entprellen.

Wobei Achtung. Hier geht es darum das echte Taster an Porterweiterungen angeschlossen sind. Wenn man die Eingänge der vorgelagerten Porterweiterung abfragt, wird das Kontaktprellen bis zum µC 1:1 durchgereicht. Also muß man wieder entprellen.
Bsp. man fragt die Porterweiterung in loop aller 1ms ab, oder noch schneller, was der µC gerade hergibt, und der Taster prellt 30ms nach, dann zählt man in der loop womöglich geschätze 20 Signaländerungen.
Kann man doch gedanklich nachvollziehen?

Mit entsprechender Variablenübergabe sollte die Bounce2 Lib auch mit Porterweiterungen funktionieren. Mußt nur vorher, wenn Du zum Bsp. die Eingänge Byte weise eingelesen bekommst, dass Byte in Bits zerlegen.

Wegen Bounce2 Lib oder auch nicht. Hab mir das nochmal überlegt. Vielleicht kommt man besser weg, wenn man sich die Entprellroutine selbst schreibt mit der üblichen millis Methode und darin sämtliche Statusvariablen der Taster einspeichert und vergleicht. Wird zwar auch eine hohe Schreibaufwand, aber vielleicht mit weniger RAM Verbrauch. Das Grundgerüst würde die Bounce2 Lib einem abnehmen und "verstecken".

Das einzigste Problem was ich sehe, wenn man nur eine Entprellzeit für alle Taster verwendet und diese ist sehr hoch, dann kann es passieren, wenn mehrere Leute im Haus auf irgendwelche Taster drücken, nur auf den ersten Taster der gedrückt wurde reagiert wird. Dann muß man warten bis die Entprellzeit abgelaufen ist, bevor man einen anderen Taster drücken kann. Wenn man deswegen wiederum für jeden Taster eine eigene Entprellzeit verwenden möchte oder gar muß, dann kommt man vom Aufwand her mit der Bounce2 sicherlich besser und schneller zum Ziel.

weiter machen ... :wink:

d.h. also, wenn ich die Porterweiterung nur alle 50ms abfrage, kann ich mir das entprellen sparen, laufe aber Gefahr, dass ein kurz zuvor gedrückter Taster gerade prellt und mir 0 stat 1 liefert. Da ich den Taster aber in aller Pegel länger als 50ms gedrückt halte, kommt spätestens bei der nächsten Abfrage eine 1

Sehe ich das richtig?

Hallo,

könnte klappen. Schreib mal Deinen Code, dass er aller 50ms abfragt und zusätzlich für jeden Tastendruck eine LED umschaltet, Ein/AUS, und zusätzlich die Signaländerungen, dass ggf. vorhandene prellen, einfach hochzählt und Dir ausgibt. Dann wirste sehen was passiert und ob das so funktioniert. Dann veränderst Du die 50ms auf weniger oder mehr und guckst was dann passiert. Dann lernste das ganz schnell. :wink:

Ich mach eine Schleife "blink ohne delay" mit 50ms, ggf. weniger, mit include adafruit mcp23017 lib

darin
mcp.digitalRead(1);
if Taster gedrückt: digidalwrite(13, !digitalRead(13)); prellzaehler++

den prellzaehler auf serial ausgeben und vergleichen

Das ganze mit miesem taster, der übel prellt.

So?, dann werd ich das später mal testen

P.S.: Wenn ich dann länger als 50ms draufbleibe, wechselt doch die LED ständig den zustand, oder? Werde doch die kompliziertere Methode nehmen ..., sonst läuft ja auch der prellzaehler alle 50ms um eins hoch

Hallo,

zum sauberen "umschalten" mache ich das so. Wenn wirklich ein sauberes Signal ohne prellen rein kommt, dann schaltet die LED bei jedem Tastendruck genau einmal um. Mußte jetzt nur an Deine Pins und mcp Funktionen/Lib anpassen.

// Taster 1  
   if ( digitalRead(Taster1) == HIGH) {
      prellzaehler++;
      if ( ledState1 == LOW ) {
         ledState1 = HIGH;
       } else {
         ledState1 = LOW;
       }
     digitalWrite(led1, ledState1); 
   }

wenn ich die Porterweiterung nur alle 50ms abfrage, kann ich mir das entprellen sparen, laufe aber Gefahr, dass ein kurz zuvor gedrückter Taster gerade prellt und mir 0 stat 1 liefert. Da ich den Taster aber in aller Pegel länger als 50ms gedrückt halte, kommt spätestens bei der nächsten Abfrage eine 1
Sehe ich das richtig?

Ja, siehst du richtig.
Einmal Änderung erkennen reicht übrigens.

Wobei 10 ms zum Entprellen von Tastern meist auch schon reichen sollten,
aber kaum jemand einen großen Licht-Taster kürzer als 100 ms drückt und trotzdem erwartet, dass das zugehörige Relais schaltet.

Die Bounce2 Library will eine Pin-Nummer und macht damit digitalRead. Ist also so wie sie ist, hier unbrauchbar.

Du musst ntürlich erstmal eine Änderung erkennen...

const int led1=13;
const int Taster1 = 3;

void loop() {
static unsigned int Zaehler;
static bool ledState1;
static bool Taster1Zustand;
if (digitalRead(Taster1) != Taster1Zustand)
{ 
    delay(10); // Entprellen
    Serial.println(Zaehler++); // Zählt jeden Wechsel
    Taster1Zustand = ! Taster1Zustand;
    if (TasterZustand == HIGH)
        ledState1 = ! ledState1;  // Toggle mit jedem Drücken 
}
digitalWrite(led1, ledState1); 
}

Hallo,

a) das delay ist an der falschen Stelle
b) das delay muß raus, muß und sollte man mit millis() machen

Das gesamte einlesen der Eingänge bzw. des Ports soll aller 50ms oder Deiner 10ms erfolgen. Die Auswertung danach sofort.

Das ist nur ein Beispiel für einen einzelnen Taster. ( mit digitalRead )
Zum Testen des Entprellens per delay.

Wenn sonst nix in loop ist, kann das delay ruhig so bleiben, auch an der Stelle :wink:

Wenn man 30 Taster per shiftIn oder wire.read() ( I2C ) einliest, und evtl. noch mehr macht, sollte man dies schon nach der
blinkwithoutdelay-Methode machen, richtig:

static unsigned long lastRead;
if (millis() - lastRead >= 20)  // zum Entprellen nur alle 20 ms einlesen
{
    lastRead= millis();
    einlesen_und_auswerten(); // ohne delay hierdrin.
}

Also, folgendes Resultat:

Ich habe es mir einfacher gemacht, ganz einfacher Code.

long previousmillis;
int interval=25;

void setup() {
pinMode(13, OUTPUT);
}

void loop() {

unsigned long currentMillis = millis();

  if (currentMillis - previousmillis > interval)
    {
    digitalWrite(13,digitalRead(2)); 
    previousmillis=currentMillis;
    }
}

Dann Logiganalyzer an CH0 an Pin2 und CH1 Pin13

Es ist ganz klar zu erkennen, dass es so funktioniert. Das schalten des Ausgangs ist natürlich etwas verzögert, eben verursacht durch die nicht ständig laufende Abfrage.
Ganz praktisch, so ein 8€ Ding

Screenshot, man sieht es klar:

Hallo,

schön das es klappt. Du kannst ruhig die v1.1.24 beta verwenden und die Abtastfrequenz ganz hoch setzen. Vielleicht siehste dann noch etwas mehr prellen des Kontakts.

Ganz schön verwirrend auf den ersten Blick, Deine NOT Operationen, aber ich denke ich habs verstanden. Wird funktionieren. :wink:

Wie hast du das "Prellen" in Ch0 erzeugt ?
Sieht zumindest anders aus als ich erwartet hätte. ( Fehlt da ein Pulldown-Widerstand am Taster ?)

Mach mal:

pinmode(2, INPUT_PULLUP);

und dann den Taster nach GND. Spart den PullDown-Widerstand.

Das ist ein Logiganalyzer kein DSO. Zeigt also nur oV oder 5V an, nix dazwischen.

Pulldown auf Masse. Bin irgendwie kein Fan von invertieter Logik.

@Doc
Was meinst du mit NOT Operationen? Die Schlichtheit meines Sketches? 8)

Hallo,

ich weis das Du kein DSO hast, sondern die kleine schwarze Plasteschachtel vom Chinesen. Wenn der Taster nicht mehr prellt, kannst Du auch nichts mehr sehen das er prellt. Deswegen kann es keine Werte zwischen 0/1 geben, sondern nur diese beiden. Entweder oder. Das haut schon hin. Erhöhst Du Deine Abtastfrequenz kann er noch mehr detektieren. Stell mal 24MS/s ein.

Mit NOT Operationen meinte ich den Code von michael. Die Syntax "!" ist NOT, drehe das bool'sche Signal um.