Archiv verlassen und diese Seite im Standarddesign anzeigen : Taster mit Kondensator entprellen
hallo,
ich möchte versuchen, ein paar Taster mit Kondensatoren zu entprellen, und zwar "quick and dirty", ohne weitere Widerstände.
Bringt es was, wenn man 10-20nF Kerkos parallel zu den Minitastern steckt?
(Ich habe noch keine hier, würde sie mir aber dann entspr. bestellen)
ARetobor
14.05.2019, 21:23
Parallel ist nicht sehr sinnvoll.
siehe hier:
https://www.mikrocontroller.net/articles/Entprellung
Gruß
Parallel ist nicht sehr sinnvoll.
siehe hier:
https://www.mikrocontroller.net/articles/Entprellung
Gruß
hmmm - das steht aber nichts über 1 Kondensator alleine ohne Widerstände, und wenn nicht parallel, wie dann?
Meine Taster sind zu input_pullup (intern im Arduino) gegen GND verschaltet.
Allerdings liegt auch hier im Bild aus deinem Link der Kondensator parallel zum Taster, allerdings mit Widerstand, den ich ja nicht verwenden will, wie ich im TOP schrieb.
https://www.mikrocontroller.net/wikifiles/thumb/f/f8/RC_debouncer.png/300px-RC_debouncer.png
In Serie geht es aber doch ganz sicher nicht, also wie dann mit nur 1 Kondensator, ohne Widerstände?
ARetobor
15.05.2019, 10:38
Kondensator an UB+ und an Input-Pin (mit pullup)
Taster an Input-Pin und Masse
ok, danke, verstehe ich aber noch nicht ganz komplett...
Kondensator und Taster also gemeinsam am Input_Pullup-Pin des Arduino.
Anderer Taster-Anschluss an Masse.
Soweit klar.
Was ist UB+ für den anderen Kondensator-Anschluss? Das gleiche wie der Vc-Pin 3V3 (edit: bei 3V3 Arduinos) ?
@HaWe ohne den Widerstand wird das aber nichts!
Zum Verständniss: (tl;dr; zum oben geposteten Link)
Der Kondensator nach Ground wird von deinem Pullup geladen solange der Taster offen ist.
Wenn dein Taster jetzt beim drücken prellt, ist dein Kondensator quasi sofort leer und damit absolut wirkungsfrei!
Wenn du jetzt aber zwischen Taster und Kondensator noch einen Widerstand packst, wird der Kondensator über den Widerstand "definiert langsam" entladen und das prellende Signal wird gefiltert.
Das ist nichts weiter als ein Tiefpass und wenn du bei deinem RC Tiefpass entweder R oder C zu Null machst, ist auch die Filterwirkung Null!
Hier eine kleine anschauliche Simulation
http://tinyurl.com/yxpqf44v
ah, danke, jetzt verstehe ichs - schade....
ARetobor
15.05.2019, 10:54
an 3,3 Volt
an 3,3 Volt
danke!
aber Ceos schrieb ja, das brächte ja leider trotzdem nichts
ARetobor
15.05.2019, 11:39
Nun,
viele Parameter haben einen Einfluss, selbst ein dünnes Anschlusskabel wirkt als Widerstand.
Aber,
warum löst du dass ganze nicht mit der Software?
Gruß
Aber,
warum löst du dass ganze nicht mit der Software?
Ich will auf jeden Fall irgendwelche, auch minimalste delays vermeiden, und ich will es für eine Statemachine verwenden, die auch Doppelklicks etc. erkennt.
White_Fox
15.05.2019, 12:05
Außerdem machst du dir auch ohne Widerstand die Taster überraschend schnell kaputt. Auch wenn es nur ein kleiner Kondensator ist, so fließen trotzdem Impulsströme die zwar sehr kurz, aber immer noch erstaunlich hohe Spitzenwerte haben. Die Taster werden schließlich auch nur so billig wie möglich hergestellt.
Ich hab auf diese Weise mal einer alten Maus den Rest gegeben: Da sich das Prellen der Taster dort bereits durch ungewollten Doppelklick bemerkbar gemacht hat, hab ich die Kontakte irgendwann mit einem 1206-Kondensator (irgendwas im mittleren nF-Bereich) überbrückt. Das hat den Ärger ein Weilchen behoben, bis ich das Problem nach einigen Wochen umso heftiger wieder hatte.
die Taster sind ja an 10k pullups
@HaWe
Guckst Du mal hier: https://www.mikrocontroller.net/articles/Entprellung
Das ist auch eine Schaltung mit 20nF Kondensator und R beschrieben.
MfG
@HaWe
Guckst Du mal hier: https://www.mikrocontroller.net/articles/Entprellung
Das ist auch eine Schaltung mit 20nF Kondensator und R beschrieben.
MfG
ich wollte doch OHNE R!
Ist auch der gleiche Link wie schon oben von Aretobor
Achso, sorry! Hab ich nicht gesehen.
MfG
White_Fox
15.05.2019, 13:00
die Taster sind ja an 10k pullups
Schon, aber das nutzt dem Taster ja nichts.
wenn er gedrückt wird, wird der Strom doch sicher über den Innenwiderstand des GPIOs begrenzt, und wenn man wieder loslässt, dann über den Pullup, oder irre ich?
Dennoch löst das ja nicht das Entprellen nur mit Kondensator, ich sehe, dass das wohl nicht geht.
wenn er gedrückt wird, wird der Strom doch sicher über den Innenwiderstand des GPIOs begrenzt
Die Energie die im Kondensator gespeichert ist ballert aber ohne jegliches R komplett über den Tater auf GND und brät ihn auf dauer durch!
Holomino
15.05.2019, 13:44
Ich will auf jeden Fall irgendwelche, auch minimalste delays vermeiden, und ich will es für eine Statemachine verwenden, die auch Doppelklicks etc. erkennt.
Da beißt sich die Katze in den Schwanz: Ein RC-Glied als Entprellung ist praktisch ein Delay.
Wenn Du nur das delay() im Code vermeiden willst, hilft Dir üblicherweise ein Timer.
White_Fox
15.05.2019, 14:52
Ich will auf jeden Fall irgendwelche, auch minimalste delays vermeiden, und ich will es für eine Statemachine verwenden, die auch Doppelklicks etc. erkennt.
Mal was anderes: Delays wirst du nicht völlig ausmerzen können. Wenn die Delays aber so wichtig sind, warum dann nicht mit immerhin definierten Delays? Außerdem: mit Softwareentprellung hast du die Taster im Prinzip delayfrei, denn das Signal kann ja sofort verarbeitet werden. In der Regel sperrst du den Taster nur für eine kurze Zeit, d.h. der nachfolgende Tastendruck kann z.B. erst wieder in 50ms erfolgen. Oder früher, wenn sich eine Zeit lang nichts mehr am Pin getan hat, da gibt es unterschiedliche Strategien. Aber der erste Puls wird auf jeden Fall mitgenommen.
Wenn du jedoch deine Taster so schnell betätigst daß du keine 50ms zwischendurch warten kannst, dann wäre es vielleicht besser etwas anderes als Taster zu verwenden. Denn die werden das mechanisch nur kurz mitmachen.
Kannst du die Taster über das Arduinoframework überhaupt so schnell abfragen? Ich habe mir die Sprache nur sehr kurz angesehen, außerdem ging es um AD-Wandlung. Ich fand das allerdings sehr limitierend, da (in meinem Falle AD-Wandlung) lediglich der gewandelte Wert genutzt werden konnte. Informationen, die darüber hinausgingen (z.B. Samplerate) konnten weder bestimmt noch irgendwie ermittelt werden. Damit war das praktisch nicht nutzbar, weil vernünftige Signalverarbeitung schlicht unmöglich war.
Wenn ich Microcontroller programmiert habe, dann entweder in ADM oder C, und da gibt es nun viele Strategien, Tasterabfragen in das Programm einzubauen. Über Hardwareinterrupts bis Abfragen in verschiedenen Zeitintervallen ist da vieles machbar. Hast du eine Abschätzung, wie groß das Delay dazwischen ist und wie die Abfragen genau erfolgen, oder kannst du das tatsächlich selber definieren?
Klar kann man die Taster so schnell abfragen. ;)
Sprache ist wohl C++.
Ich hatte für die Rollosteuerung auch schon diese Microtaster softwaremäßig entprellt. Man kann das einstellen, wenn man will. Über die Zeit eben. Ich habe da nicht so viel Augenmerk drauf gelegt, Hauptsache, die Tasten waren irgendwie entprellt. Deshalb sind meine eingesetzten Zeiten nur geschätzt. Aber der Code ist bei mir im Blog, kann jeder anschauen.
MfG
Holomino
15.05.2019, 15:37
… dann entweder in ADM oder C,...
Der war jetzt intellektuell anspruchsvoll. Hat ne Minute gedauert, zu merken, dass das "s" neben dem "d" liegt.:mad:
Ich kann Taster bzw. digital Pins mit ca 400-500ns lesen und toggeln (je nach µC auch etwas schneller oder etwas langsamer), aber vor allem: ich möchte einfach vermeiden, dass rechenintensive Funktionen sowie UART, i2c und SPI - R/W durch delays bei Buttonabfragen ausgebremst werden. 1ms ist da schon 1ms zuviel.
Da wir hier im Arduino-Unterforum sind: C++11.
Holomino
15.05.2019, 16:22
Ich hab's jetzt nachgeschlagen, wie ich das mal gelöst habe.
//Timer keys polling
ISR(TIMER0_COMPA_vect)
{
static uint8_t keyPrescaler = 0;
static uint8_t oldKeys = 0;
keyPrescaler++;
if (keyPrescaler >= 20)
{
keyPrescaler = 0;
uint8_t newKeys = (PINC & 0xF0); //Keys port
uint8_t keysChanged = newKeys ^ oldKeys;
uint8_t newKeysSet = keysChanged & newKeys;
keysSet |= newKeysSet;
oldKeys = newKeys;
}
}
Ich polle da wohl alle 20ms im 1ms-Timer-Interrupt die entsprechenden vier Port-Pins in die "keysSet"-Variable...
// called from Main loop
void MaskProcessFromForeground()
{
//SET KEYPRESSED, MASKTIMER ELAPSED AND CHECK READ BUFFER CALLS FROM MAIN ROUTINE
CheckReadBufferTelegrams((FIFO_t*) ReadBuffer, Admin.TelegramReceived);
if(TimerPrescalerCounter == 0)
{
TimerPrescalerCounter = Admin.TimerPrescaler;
if (Admin.TimerElapsed != 0)
Admin.TimerElapsed();
}
if (Admin.KeyPressed != 0)
{
uint8_t keysSetCopy = keysSet;
for (int i = 0; i < 4; i++)
{
if (keysSetCopy & (0x80 >> i))
Admin.KeyPressed(i);
}
cli();
keysSet &= ~keysSetCopy; // reset handled keys
sei();
}
}
...und spreche die keyPressed-callbacks (können dann schon mal etwas länger dauern) aus der main-loop an.
Nicht verwirren lassen: "Admin" ist eine Struktur mit Funktionszeigern, die auf die Funktionen der aktuell geladenen Bildschirmmaske zeigen (die werden beim Umladen der Maske in die Admin-Struktur geschrieben).
Interrupts kann ich leider nicht verwenden, ich verwende digitalRead für beliebig viele Buttons in Instanzen eines Button-Objekts:
https://github.com/dsyleixa/Arduino/tree/master/ButtonClass
Abgefragt werden alle Button-Zustände mindestens 1x pro loop(), und wie lange eine Loop dauert, lässt sich nicht allgemein vorhersagen (u.U. nur 1ms oder sogar weniger, evtl aber auch länger).
In der Button Class sind derzeit auch noch delay(1) drin, aber auch die sollen noch raus.
10 oder 20ms warten bis entprellt ist, ist absolut nicht möglich.
Leider gibt es auch kein preemptives Multithreading für die ARMs (POSIX pthread oder std::thread), sonst könnte ich das in einen eigenen langsameren Thread "outsourcen".
Daher suchte ich eine simple Entprellung per Kondensator.
Naja, man kann auch Schleifen ohne delay()-Funktion bauen, einfach mit Zählern.
Der Taster wird gegen Masse geschaltet. Ein Kondensator kann keine 0V ausgeben. Er kann nur positive Ladung abgeben.
Musst Du die Logik der Taster umkehren, dann kannst Du Kondensatoren in der Größe 4700µF oder mehr nehmen, evtl etwas weniger, musst Du dann ausprobieren.
MfG
Naja, man kann auch Schleifen ohne delay()-Funktion bauen, einfach mit Zählern.
Der Taster wird gegen Masse geschaltet. Ein Kondensator kann keine 0V ausgeben. Er kann nur positive Ladung abgeben.
Musst Du die Logik der Taster umkehren, dann kannst Du Kondensatoren in der Größe 4700µF oder mehr nehmen, evtl etwas weniger, musst Du dann ausprobieren.
MfG
4700µF Elkos würden aber bei weitem den verfügbaren Platz überschreiten ;)
die Kerkos sollten dicht neben die Tasterbuttons gesteckt werden, quasi daneben "verschwinden".
Schleifen ohne delay nutze ich ja bereits, denn es sollen ja auch Doppelklicks und lange Drücke erfasst werden.
Guck dir mal dazu bitte den ButtonClass-Code genau an.
Trotzdem kommt es zum unerwünschten Erfassen von Prellen im Bereich z.B. von 1ms bis (geschätzt) 10ms, die dann unerwünschterweise wie Doppelclicks wirken.
Holomino
15.05.2019, 17:38
Wenn Du kein delay() verwendet wissen möchtest, warum verwendest Du dann den oben angegebenen Code?
https://github.com/dsyleixa/Arduino/blob/master/ButtonClass/ButtonClass.h
Zeile 146
Zeile 175
Wenn Du kein delay() verwendet wissen möchtest, warum verwendest Du dann den oben angegebenen Code?
https://github.com/dsyleixa/Arduino/blob/master/ButtonClass/ButtonClass.h
Zeile 146
Zeile 175
ich schrieb doch oben: die sollen auch noch weg.
In der Button Class sind derzeit auch noch delay(1) drin, aber auch die sollen noch raus.
Momentan verbessern sie das Prellen zwar schon (bei Prellen innerhalb der ersten 1ms), aber dennoch nicht gut genug für die ersten 20ms, und daher wollte ich alles rausschmeißen und per Kondensatoren entprellen (siehe TO Post).
Wenn du aber den ButtonClass Code derart verbessern kannst, dass er SOWOHL perfekt bis 20ms entprellt ALS AUCH gar keine delays mehr verwendet:
HER DAMIT! 8)
4700µF Elkos würden aber bei weitem den verfügbaren Platz überschreiten ;)
Das ist mir klar :) Aber anders .... ?
Das ist mir klar Aber anders .... ?
das wäre genau die Frage ... ;)
Nimm doch statt delay(x) -> delayMicroseconds(x).
Du könntest auch mit millis() oder micros() arbeiten, bekommst ja dann die vergangene Zeit. und kannst also die Schleife immer wieder verlassen, solang eine gewisse Mindestzeit nicht vergangen ist.
Eigentlich wartet man nur darauf, dass der Taster eine gewisse Zeit nicht gedrückt wurde, um sicher zu gehen, dass er nicht mehr gedrückt ist.
Registriert man während dieser Wartezeit, dass der doch wieder gedrückt wurde oder ist, setzt man den Zähler zurück und wartet weiter, bis er die gewünschte Zeit eben nicht mehr gedrückt ist.
Mit millis() oder micros() weisst Du, wieviel Zeit vergangen ist und kannst deinen Zähler entspr. anpassen, bis der irgendwann auf 0 ist; dann ist der Taster nicht mehr gedrückt.
MfG
Nimm doch statt delay(x) -> delayMicroseconds(x).
Du könntest auch mit millis() oder micros() arbeiten, bekommst ja dann die vergangene Zeit. und kannst also die Schleife immer wieder verlassen, solang eine gewisse Mindestzeit nicht vergangen ist.
Eigentlich wartet man nur darauf, dass der Taster eine gewisse Zeit nicht gedrückt wurde, um sicher zu gehen, dass er nicht mehr gedrückt ist.
Registriert man während dieser Wartezeit, dass der doch wieder gedrückt wurde oder ist, setzt man den Zähler zurück und wartet weiter, bis er die gewünschte Zeit eben nicht mehr gedrückt ist.
Mit millis() oder micros() weisst Du, wieviel Zeit vergangen ist und kannst deinen Zähler entspr. anpassen, bis der irgendwann auf 0 ist; dann ist der Taster nicht mehr gedrückt.
MfG
moppi,
es geht um 20ms, die man quasi nach dem 1. Drücken abfeiern muss -
- da ist es völlig wurscht, ob man die in microseconds oder milliseconds zählt.
Es darf aber ÜBERHAUPT KEINE WARTEZEIT geben!
Hast du dir mal die Mühe gemacht, den ButtonClass Code mit seiner State Machine anzusehen, für den die Entprellung gebraucht wird??
Du wartes da auf gar nichts. Ist ja nicht notwendig. millis() abfragen, vom Zähler abziehen -> Zähler = 0? Nein, zurück, weil Taste noch gedrückt (status mitgeben: bool return x). Ist doch 0? Ja, dann zurück, weil Taste nicht mehr gedrückt (status mitgeben). Die Zeit, die da verbraucht wird, ist halt die, für die paar Befehle. Aber kein Warten in dem Sinn, dass man da so und so viele Micros() oder Millis() in einer Schleife festhängt.
MfG
Du wartes da auf gar nichts. Ist ja nicht notwendig. millis() abfragen, vom Zähler abziehen -> Zähler = 0? Nein, zurück, weil Taste noch gedrückt (status mitgeben: bool return x). Ist doch 0? Ja, dann zurück, weil Taste nicht mehr gedrückt (status mitgeben). Die Zeit, die da verbraucht wird, ist halt die, für die paar Befehle. Aber kein Warten in dem Sinn, dass man da so und so viele Micros() oder Millis() in einer Schleife festhängt.
MfG
Das ist mir leider zu allgemein und zu unkonkret.
Aber wenn du wirklich die konkrete Lösung kennst, dann schreib hier mal hin, wie der Code für die ButtonClass geändert werden muss, damit man
a) zwar einen Doppelclick und auch einen langen Buttonpress erkennt, aber
b) schnelles Prellen bei einzelnen Buttonclicks herausgefiltert wird.
Link: https://github.com/dsyleixa/Arduino/blob/master/ButtonClass/ButtonClass.h
Nein, DIE konkrete Lösung für Dein Programm kenne ich nicht.
Was ich beschrieben habe ist eine allgemeiner Lösungsweg, den man gehen kann.
Ich denke aber, das Thema: Taster mit Kondensator entprellen (https://www.roboternetz.de/community/threads/73406-Taster-mit-Kondensator-entprellen/page4)
ist wohl hier jetzt nicht mehr zutreffend. Das per Software zu lösen, waren ja nur noch mal Hinweise von einigen hier.
Ich habe da mal reingeschaut, Dein Code sieht ziemlich lang aus, scheint mir zu lang, weiß ich aber nicht. Wäre mir zu viel Arbeit drin herum zu werkeln. Lieber gleich neu schreiben. Ich glaub so viel macht der ja nicht. Weiß noch nicht mal genau, was der Code genau tun soll und wozu. Deshalb würde ich vorschlagen, dass Du das selber änderst, Du weißt am besten, wie und was Dein Code macht. Das sollte am Schnellsten erledigt sein.
Aber da Du ja schon mit millis() arbeitest, an verschiedenen Stellen und dies Konzept die Entprellung nicht berücksichtigt, vielleicht denkt man es dann wirklich gleich noch mal neu und nimmt einen neuen Anlauf, mit neuem Code. Manchmal ist das so. Bevor man den alten Cde so lange verbiegt, bis nichts richtig funktioniert.
MfG
Nein, DIE konkrete Lösung für Dein Programm kenne ich nicht.
Was ich beschrieben habe ist eine allgemeiner Lösungsweg, den man gehen kann.
Ich denke aber, das Thema: Taster mit Kondensator entprellen (https://www.roboternetz.de/community/threads/73406-Taster-mit-Kondensator-entprellen/page4)
ist wohl hier jetzt nicht mehr zutreffend. Das per Software zu lösen, waren ja nur noch mal Hinweise von einigen hier.
Ich habe da mal reingeschaut, Dein Code sieht ziemlich lang aus, scheint mir zu lang, weiß ich aber nicht. Wäre mir zu viel Arbeit drin herum zu werkeln. Lieber gleich neu schreiben. Ich glaub so viel macht der ja nicht. Weiß noch nicht mal genau, was der Code genau tun soll und wozu. Deshalb würde ich vorschlagen, dass Du das selber änderst, Du weißt am besten, wie und was Dein Code macht. Das sollte am Schnellsten erledigt sein.
Aber da Du ja schon mit millis() arbeitest, an verschiedenen Stellen und dies Konzept die Entprellung nicht berücksichtigt, vielleicht denkt man es dann wirklich gleich noch mal neu und nimmt einen neuen Anlauf, mit neuem Code. Manchmal ist das so. Bevor man den alten Cde so lange verbiegt, bis nichts richtig funktioniert.
MfG
den allgemeinen Weg über Software kenne ich doch und verwende ihn auch!
Mir geht es um eine konkrete Lösung für meine ButtonClass, für die deine allgemeine Lösung nicht ohne weiteres anwendbar ist - daher hatte ich an die Kondensator-Methode gedacht.
Allgemeines Gerede wie "Weiß noch nicht mal genau, was der Code genau tun soll und wozu. Deshalb würde ich vorschlagen, dass Du das selber änderst, Du weißt am besten, wie und was Dein Code macht." ist auch nicht gerade besonders nützlich, das müsstest du sicher selbst einsehen. Umschreiben der schon jetzt sehr verzwickten State Machine ist ntl die letzte Option.
Also bitte immer konkret bleiben - aber du darfst mir natürlich auch gerne meinen Code umschreiben bzw. erweitern, wenn du es kannst! ;)
- - - Aktualisiert - - -
PS:
ich fang jetzt schon mal an, einen oder zwei zusätzliche States einzubauen...
White_Fox
15.05.2019, 21:40
Ich kann Taster bzw. digital Pins mit ca 400-500ns lesen und toggeln (je nach µC auch etwas schneller oder etwas langsamer), aber vor allem: ich möchte einfach vermeiden, dass rechenintensive Funktionen sowie UART, i2c und SPI - R/W durch delays bei Buttonabfragen ausgebremst werden. 1ms ist da schon 1ms zuviel.
Da wir hier im Arduino-Unterforum sind: C++11.
Busse wie UART, I²C und SPI sind vieles, aber ganz sicher nicht rechenintensiv. Das sind normalerweise weitgehend eigenständige Hardwareeinheiten, die von der ALU weitgehend unabhängig laufen. In deren Datenregister wird ein Byte reingeschoben-und je nach Konfiguration war es das entweder, oder die UART/SPI/... meldet sich mit einem Interrupt zurück, daß sie fertig ist. Die CPU-Last beschränkt sich auf das gelegentliche Schreiben/Lesen in ein Register. Manche Controller verfügen auch über eine Funktion, daß die Peripherie selbständig Teile des Speichers auslesen kann, da hat die CPU kaum noch etwas mit zu tun.
Mit dem Warten sieht es übrigens ähnlich aus: Du kannst stur Zeit vertrödeln, (z.B. einfach nur ein Register inkrementieren), aber du kannst auch einen Timer verwenden. Das ist ein simpler Zähler, der ebenso weitgehend unabhängig von der CPU inkrementiert wird. Je nach Funktion kann das Inkrementieren mit einem Vorteiler noch verlangsamt werden. Der Timer kann, je nach Ausstattung und Konfiguration, u.A. einen Interrupt geben wenn er einen bestimmten Wert erreicht hat oder überläuft. Wenn der Timer einfach nur läuft, kann die CPU während dessen irgendwas anderes machen. Und damit kannst du sehr wohl einen Taster 20ms sperren, ohne den Controller 20ms zu blockieren.
Das hat übrigens nichts mit Threads oder so zu tun. Sondern einfach nur damit, wie so ein Mikrocontroller funktioniert. Ich weiß natürlich nicht, wie speziell dein Code genau funktioniert und welchen der vielen Wege nach Rom dein Programm letztendlich geht. Es sind schließlich recht viele Wege...
mit UART lese ich laufend eingehende Bytes ein und kopiere sie in verschiedene Zwischenpuffer zur Weiterverarbeitung (strtok etc.), über i2c werden laufend verschiedenste Sensoren nacheinander ausgelesen und die Werte dann verrechnet, dann werden neue Werte gesammelt und über UART arrays wieder zurückgeschickt, über SPI wird das 480x320 TFT angesteuert, was schon recht lang dauert, dann seine touchscreen und touchbutton events erfasst und Hardwarepuffer beschrieben/gelöscht.
Das alles dauert schon seine Zeit.
Damit dann das Bild nicht ruckelt, weil zwischendurch ein paarmal auf ein ButtonUp oder ein Debounce gewartetet werden muss, muss man zumindest hier auf delays verzichten.
Außerdem sind nicht alle Pins, an denen ein Button angeschlossen sein kann, Interrupt-fähig, dann beträfen Interrupts ja auch nur einzelne Instanzen, solange sie aktuell existieren, und sie müssten auf nur 1 Zustand der Statemachine begrenzt werden (z.B. Level 3) und bei anderen Zuständen (1,2,4,5,6,...) zwingend inaktiv bleiben - aus meiner Sicht also nicht machbar.
Mit pthread auf dem Pi mache ich das anders:
1 langsamer low priority Thread für HDMI TFT Ausgabe, die nach und nach mit 20Hz alles ausgibt, bis es vollständig ist, dann auf 50ms (nonblocking) delay, und dann sofort wieder von vorn aktualisiert,
1 superschneller super-high-priority-Thread für Encoderpins alle 100µs auslesen,
1 schneller high-proiority für 115200 baud UART für Dashboard und remote control im handshake ohne delay,
1 mittelschneller medium priority für 400kHz i2c mit ein paar delays zwischen einzelnen Device r/w
1 sehr langsamer low priority zum Keyboard auslesen
1 medium priority für SD r/w
usw.
Delays in irgend einem Thread werden dabei automatisch als Rechenzeit den anderen Threads zur Verfügung gestellt.
Die Zeitscheiben verwaltet pthread optimal, und das klappt wunderbar, kein Thread behindert einen anderen oder bremst irgend etwas aus, auch nicht auf einem Single-Core Zero: GPIO-toggle ist fast genau so schnell wie wenn es ganz alleine läuft.
Hier beim Arduino aber muss ich alles in 1 Thread-Loop reinpressen, und viele langsame Vorgänge bremsen die schnellen unerträglich herunter.
Dennoch, ich bin schon weitergekommen mit meiner statemachine, auch wenn es langsam unübersichtlich wird ;)
PS,
Allerdings wäre auch für künftige andere Entprell-Probleme ein simpler Kondensator am Button einfacher gewesen - wenn es funktioniert hätte...
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.