Taster entprellen ausreichend?

Hallo,

ist folgende Möglichkeit von mir ausreichend oder hat es irgendwo eine Schwäche, die ich gerade nicht sehe.

Hintergrund ist es, dass ich meine Equinox nur noch mit einem Attiny85 @8MHz betreibe.

				Program Memory Usage 	:	1104 bytes   13,5 % Full
				Data Memory Usage 		:	212 bytes   41,4 % Full

Jedoch noch keine großen Optimierung vorgenommen außer das alles selbst geschrieben wurde (mit Ausnahme eines kleinen Assemblerabschnitts).

Wie soll es funktionieren:
Alle 20ms wird der Taster abgefragt. Wenn diese aktiv ist, wird gezählt. Sobald dieser nicht mehr aktiv ist, wird die Anzahl an Impulsen ausgewertet.

Hat die Zahl einen bestimmten Wert nicht erreicht, so zählt es im Subprogrammen einen Hoch (bei Taster 2 runter). Ist der Wert jedoch erreicht, wird nur das Hauptprogramm hoch oder runter gezählt. Können hier irgendwelche Schwächen auftreten? Der ganze Code ist verzögerungsfrei aufgebaut. Lediglich beim Senden der RGB Arrays muss ich 50µS pausieren.

/*
ATtiny85_Equinox.c
Created: 31.07.2014 16:16:07
Author: sschultewolter

(PCINT5/!RESET/ADC0/dW)			PB5	1	| AT |	8	VCC
(PCINT3/XTAL1/CLKI/!OC1B/ADC3)	PB3	2	| TI |	7	PB2	(SCK/USCK/SCL/ADC/T0/INT0/PCINT2)
(PCINT4/XTAL2/CLKO/OC1B/ADC2)	PB4	3	| NY |	6	PB1	(MISO/DO/AIN1/OC0B/OC1A/PCINT1)
________________________________GND	4	| 85 |	5	PBO (MOSI/DI/SDA/AIN0/OC0A/!OC1A/AREF/PCINT0)

PB1 - WS2812B
PB3 - Button1
PB4 - Button2
*/

#include "main.h"

int main(void)
{
	time_init();
	//time_set(0, 15, 30);
	
	DDRB &= ~((1 << DDB3) | (1 << DDB4));	// PB3 + PB4 als Eingang
	PORTB |= ((1 << PB3) | (1 << PB4));		// PB3 + PB4 PullUp aktivieren
	
	while(1)
	{
		//>-- Zu Testzwecken mit != 0 initialisiert
		static int16_t mode1=10;
		static int16_t mode2=5;
		//<--
		
		{
			static int8_t ct_button1;
			static int8_t ct_button2;
			
			int8_t state_button1;
			static int8_t lastState_button1;
			
			int8_t state_button2;
			static int8_t lastState_button2;
			
			static int16_t lastChange;
			if(frequency_50 != lastChange)		// alle 20ms
			{
				lastChange = frequency_50;
				
				state_button1 = !(PINB & (1 << PINB3));
				state_button2 = !(PINB & (1 << PINB4));
				
				if(state_button1) ct_button1++;
				else if(!state_button1 && lastState_button1)
				{
					if(ct_button1 > 50) mode1++;
					else mode2++;
					ct_button1 = 0;
				}
				lastState_button1 = state_button1;
				
				if(state_button2) ct_button2++;
				else if(!state_button2 && lastState_button2)
				{
					if(ct_button2 > 50) mode1--;
					else mode2--;
					ct_button2 = 0;
				}
				lastState_button2 = state_button2;
				
				//--> Visuelles Debugging
				leds_clear();
				leds_rgb(leds_index(mode1), 255,0,0);
				leds_rgb(leds_index(mode2), 0,0,255);
				leds_on();
				//<--
			}
		}
	}
	
	return 0;
}

Hallo,

sobald der Taster gedrückt ist, werden Impulse an einem anderen Eingang gezählt?

Entprellen sollte ausreichen. Jedoch solltest Du den Taster hardwaremäßig entprellen, wenn Du Deine "aller 20ms Abfrage" einhalten möchtest. Sonst addiert sich die Abfragezeit um die Softwareentprellzeit auf. Zum Bsp. mit der Bounce2 Library. Kann man mit Schmitt-Trigger oder RS-Flip-Flop aufbauen.

Oder Du lässt Deine jetzige feste Zeit von 20ms weg und nutzt nur 20ms Entprellzeit. Allerdings reicht das für manche billigen Taster nicht aus. Mußte mal probieren.

Es ist generell die Frage, was ist besser Hardware oder Softwareentprellen.

Wie Doc_Arduino schon sagte, ein Monoflop IC ein Widerstand und ein Kondensator reichen aus.
Und wenn die Ressourcen eh nicht so üppig sind wäre dies wohl der bessere Weg ?

Hallo,

was besser ist, ob Software- oder Hardware Entprellung, kommt glaube ich immer auf den Anwendungsfall an. Im Normalfall sollte die Entprellung per Software ausreichend sein. Man ist damit auch flexibler. Alles was man programmieren kann und nicht in Hardware gießen muß bringt Gestaltungsfreiheit mit sich.

Kommt es auf sehr kurze Reaktionszeiten an auf irgendein Ereignis wobei man keine paar ms warten kann (Verzögerung), dann muß man Hardwaremäßig entprellen. Und ggf. einen Interrupt verwenden. Die Programmdurchlaufzeit muß man dann auch beachten.

Das wären meine Gedanken zum Thema.

Impulse werde so nicht gezählt. Es geht nur drum, zu unterscheiden, ob ein langer oder ein kurzer Tastdruck erfolgt. Deshalb meine ich auch, dass das eigentliche entprellen nicht notwendig.
Ob ich nun alle 20ms oder höher Abfrage, ist egal.

Hallo,

okay, verstanden. Ich denke dennoch das Du entprellen mußt, also irgendeine Wartezeit mußte einbauen mit Softwarenentprellung. . Wenn Du den Taster drückst, prellt er, Du bekommst mehrere Impulse die Du noch nicht auswerten darfst. Wenn Du Hardwaremäßig entprellst, kannst Du sofort die Zeitnahme starten sobald sich das Eingangssignal ändert.

Du bekommst mehrere Impulse die Du noch nicht auswerten darfst

Warum nicht?
Im Allgemeinen:
Der erste Impuls kommt nur, wenn ein Taster tatsächlich gedrückt wurde, und man kann loslegen, wenn man will.
Musst nur ignorieren, was in den nächsten paar Millisekunden passiert.
Nach hundert millis kann der Taster immer noch gedrückt sein oder auch nicht.
Beim Loslassen wird der Taster wieder prellen und also wieder mehrfach kommen und gehen. Die erste Änderung von zu nach auf muss also auch eine Entprell-Verzögerung starten. ( Mit oder ohne Aktion )

Hier:
Wenn eh du nur alle 20 ms einmal abfragst, kannst du dir jedes zusätzliche Entprellen sparen, da bin ich deiner Meinung, Stefan.
Aber zwischen kurz und lang drücken kann man erst beim Loslassen, oder wenn nach ca. 20 Zyklen ( = 400 ms ) der Taster immer noch gedrückt ist, unterscheiden.

Hallo,

genau das meine ich ja. Wenn irgendein Impuls kommt, kann man noch nicht sagen ob der vom Taster kam oder sonst woher. Man muß also wieder warten, was die Entprellzeit ist. Dann wartet man sich tot. :wink:

Eigentlich kann er das mit dem aller 20ms abfragen oder so ganz weglassen und ständig abfragen sobald die loop an der Stelle vorbeikommt. Dann kann man die Bounce2 Library nehmen, setzt seine Entprellzeit und wertet dann noch zusätzlich die anliegende Signaldauer aus für sich.

hallo,
ich persönlich mache das mit dem Entprellen so:
ich schreibe alle Taster-Daten in einen 3er-FiFo-Buffer (könnte auch ein 5er sein) und werte immer nur den Median aus.
Dieser stabilisiert sich sehr schnell und die Spikes werden gekappt.
Interessiert dich diese Methode?

Ist es beim FIFI Buffer nicht so, dass hier lediglich der Variablenwert eingetragen wird, welcher zu erst kommt, denn man nach x ms erst wieder ausliest bzw. neubeschreibt. Ich halte mich gerade an die Peter Danneger Variante "Komfortroutine (C für AVR)" (Entprellung – Mikrocontroller.net)

ich schiebe quasi von unten die neuen Werte rein, die alten oben wieder raus.
Immer wenn ich einen Wert brauche, berechne ich dann zunächst den Median, und nur den werte ich aus.
Der Median ist der mittlere Wert (bei 3en also der 2.) des nach Größe sortierten (!) Arrays (bzw. seiner Kopie, der originale darf ntl nicht überschrieben werden!).

Die Schritte sind also folgende:

Sensor-Wert auslesen
Fifo-Werte alle 1 nach oben schieben (oberster fällt raus)
in Fifo an 1. Stelle neu einspeichern

das kann man sehr schnell und häufig machen, wenn man will, um den Puffer möglichst aktuell zu halten.

wird ein sensor-Wert gebraucht, dann:

Kopie des Fifo Arrays erstellen (memcpy)
Kopie nach Größe sortieren (bei 3 reicht bubblesort)
den mittleren Wert der Fifos zurückgeben => das ist der median.

Nur den median jetzt weiterverwenden!

Hast du sehr stark schwankende, prellende , verrauschte Werte, dann ist ein Fifo mit 5 Werten ideal (verwende ich manchmal für Sharp IR-Sensoren).

HTH!

Kann es sein, dass du das für Sensor (analog) verwendest? Finde, so wie die Funktion gerade beschrieben wurde, unnötig rechenlastig für einen TASTER der 1 oder 0 liefert.

nein, ich verwende sie auch für prellende Taster. Klappt wunderbar, und so viel Rechnerei bei Fifo(3) ist es nicht!
Aber ich will dich nicht überreden, war nur ein Vorschlag wegen guter Erfahrung.
Wenns dich interessiert, kannst du den Code haben, sag Bescheid.