Forum: Mikrocontroller und Digitale Elektronik Arduino - Stöungen am Digitalen Eingang


von Mark (Gast)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem:

- Taster (Eingang) mit Widerstand wie überall beschrieben verdrahtet
- am Ausgang ein Relais welches einen Rollo betätigt
- Programm zählt die Tastendrücke und schaltet das Relais

Das alles funktioniert seit einigen Tagen ohne Probleme und macht das 
was es soll. Heute ist mir aufgefallen, daß wenn ich meinen ERSA 
Lötkolben in die Steckdose stecke und wieder rausziehe, der Taster immer 
wieder sporadisch "betätigt" wird. Das ganze passiert mit dem Arduino 
UNO Board genauso wie mit einem Arduino auf einem Steckbrett.

Wie gesagt, das ganze funktioniert seit einigen Tagen Problemlos. Nur 
der Lötkolben verursacht anscheinend die Störungen. Keine Küchengeräte, 
Staubsauger etc. haben den Rollo bisher ausgelöst.

Ich habe die Schaltung auch schon soweit abgeändert und den internen 
Pullup Widerstand verwendet --> gleicher Effekt...

Hat jemand eine Idee?

Besten Dank
Mark

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:
> Hallo zusammen,
>
> ich habe folgendes Problem:
>
> - Taster (Eingang) mit Widerstand wie überall ...

wie überall?
Also bei uns hier im Forum wird das (so gut wie) nirgends beschrieben. 
Wir hängen die Taster einfach so an. Taster schaltet nach GND und mit 
internem Pullup und der PeDa Entprellung kommt da so schnell nichts 
durcheinander.


> Hat jemand eine Idee?

Nimm eine ordentliche Entprellung, die auch kleine Störungen 
ausfiltert.

von Benedikt K. (benek)


Lesenswert?

Ist der Taster denn entprellt?

MfG Benedikt

von Mark (Gast)


Lesenswert?

Hallo,

danke für die Antworten.

Das ist ja das seltsame. Egal ob ich den internen Pullup oder auch einen 
externen Widerstand verwende. Das Problem bleibt bestehen.
Zur Entprellung verwende ich die Bounce-Library welche auch 
funktioniert.
Wenn ich nur den Taster betätige funktioniert alles ganz wunderbar.

Nur beim Anstecken und Abziehen vom Lötkolben schaltet der Ausgang 
sporadisch...

Besten Dank
Mark

von Mark (Gast)


Lesenswert?

Mark schrieb:
> Hallo,
>
> danke für die Antworten.
>
> Das ist ja das seltsame. Egal ob ich den internen Pullup oder auch einen
> externen Widerstand verwende. Das Problem bleibt bestehen.
> Zur Entprellung verwende ich die Bounce-Library welche auch
> funktioniert.
> Wenn ich nur den Taster betätige funktioniert alles ganz wunderbar.
>
> Nur beim Anstecken und Abziehen vom Lötkolben schaltet der Ausgang
> sporadisch...
>
> Besten Dank
> Mark

Das gleiche passiert auch mit einem Bügeleisen. Nur nicht so oft...?

von Peter D. (peda)


Lesenswert?

Mark schrieb:
> Zur Entprellung verwende ich die Bounce-Library welche auch
> funktioniert.

Funktionieren bedeutet nicht, nur bei schönem Wetter. Da findest du 
haufenweise Libs.

Die Spreu vom Weizen trennt sich erst, wenn das Signal mit Störungen 
behaftet ist, also im Praxiseinsatz. Und da findest Du nur wenige Libs, 
die auch wirklich was taugen.

Da niemand weiß, welche Lib Du meinst, gib mal einen Link zum Quelltext 
der Lib. Erst dann kann man sagen, ob sie wirklich funktioniert.

von Mark (Gast)


Lesenswert?

Hallo,

fogendes verwende ich:

http://playground.arduino.cc/Code/Bounce

Für den Taster funktioniert diese Lib ganz gut. Ohne habe ich dauernd 
"prellende" Effekte.

Kann das überhaupt an dem Prellen vom Taster liegen? Beim Stecker 
rein-raus vom Lötkolben wird der Taster doch gar nicht betätigt... 
(sorry für die eventuell dumme Frage)

Gruß
Mark

von mikel (Gast)


Lesenswert?

Stammt der Lötkolben vielleicht aus Ex-Stasi-Beständen...? Dann würde 
mich in Sachen 'seltsame RF-Störungen' nix mehr wundern.. ;-)

von Mark (Gast)


Lesenswert?

Der Lötkolben bestimmt nicht aber beim Bügeleisen bin ich mir nicht so 
sicher... ;)

von Peter D. (peda)


Lesenswert?

1
// Protected: debounces the pin
2
int Bounce::debounce() {
3
  
4
  uint8_t newState = digitalRead(pin);
5
  if (state != newState ) {
6
      if (millis() - previous_millis >= interval_millis) {
7
        previous_millis = millis();
8
        state = newState;
9
        return 1;
10
  }
11
  }
12
  
13
  return 0;
14
  
15
}

Da fehlt der else-Zweig.
Wenns nur ne Störung war, muß ja previous_millis wieder neu zählen.

von Peter D. (peda)


Lesenswert?

Dater Pennegger schrieb im Beitrag #3064468:
> ...jetzt nicht gleich pingelig werden.

Huch, da ist aber jemand eingeschnappt.
Sei doch froh, daß ich den Fehler gefunden hab.

von Karl H. (kbuchegg)


Lesenswert?

Pater Dennegger schrieb im Beitrag #3064489:
> Ich vermute den Fehler woanders. Aber danke...

Das kannst du schon vermuten.
Tatsache ist aber das diese debounce() Funktion Schrott ist.
Wenn die nicht in Zeitabständen kleiner als interval_millis aufgerufen 
wird, debounced sie nämlich gar nicht mehr.
Und wie Peter schon sagte: mit kurzen Störungen kommt sie auch nicht 
zurecht.

Kommt dann auch noch beides zusammen (Stichwort: Programm gespickt mit 
delays), dann kommen eben Spikes durch den Debouncer durch.

von Karl H. (kbuchegg)


Lesenswert?

Dater Pennegger schrieb im Beitrag #3064468:
> ...jetzt nicht gleich pingelig werden.
>
> Ich würde eher mal schauen, ob der Arduino einen Reset macht, wenn der
> Lötkolben angeschlossen wird.

Ich denke, das wär ihm schon aufgefallen, wenn sein Zähler jedesmal 
wieder bei 0 anfängt zu zählen, wenn er den Lötkolben ein/aussteckt.

So blind kann er gar nicht sein, dass er den Unterschied zwischen 'fängt 
wieder bei 0 an' und 'zählt manchmal unmitiviert' nicht bemerkt.

von Karl H. (kbuchegg)


Lesenswert?

Pater Dennegger schrieb im Beitrag #3064496:
> Es geht hier um Arduinos...was erwartet ihr?

Das sich wer aufrafft und den Arduino Systementwicklern eine Mail 
schreibt und ihnen sagt, dass ihre Debounde Funktion fehlerhaft ist. Von 
mir aus auch mit Hinweis auf dieses Forum, Dann erklären wir ihnen warum 
und was sie dagegen tun können.

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:

> Kann das überhaupt an dem Prellen vom Taster liegen? Beim Stecker
> rein-raus vom Lötkolben wird der Taster doch gar nicht betätigt...
> (sorry für die eventuell dumme Frage)

Dein Lötkolben verursacht irgendwas an der Versorgungsspannung, so dass 
am Eingang ganz kurze Spikes auftauchen.
Eine gute Debounce Library ignoriert derartige Spikes in der Annahme, 
dass ein reinkommender Puls der kürzer als x Millisekunden ist kein 
Tastendruck sein kann.
Deine Lib macht das nicht. Deine Lib akzeptiert jeden Pegelwechsel als 
Tastendruck, egal wie kurz und stellt sich danach für eine gewisse Zeit 
'taub'. Das reicht für Tasten, kann aber kurze Spikes nicht ausfiltern.

von Mark (Gast)


Lesenswert?

Hallo,

also sollte ich mal eine andere Bounce Lib verwenden?
Was wäre dafür dann die Empfehlung?

Reset macht der Arduino keinen beim Einstecken vom Lötkolben. Das war 
eine meiner ersten Vermutungen...

Delays verwende ich nur während der Rollomotor läuft. Sonst nicht...

Danke
Mark

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:
> Hallo,
>
> also sollte ich mal eine andere Bounce Lib verwenden?
> Was wäre dafür dann die Empfehlung?

Du kannst ja den Code mal ein kleines bischen erweitern (wie PeDa schon 
vorgeschlagen hat)
1
int Bounce::debounce() {
2
  
3
  uint8_t newState = digitalRead(pin);
4
  if (state != newState ) {
5
    if (millis() - previous_millis >= interval_millis) {
6
      previous_millis = millis();
7
      state = newState;
8
      return 1;
9
    }
10
  }
11
  else
12
    previous_millis = millis();
13
14
  return 0;
15
}

Jetzt werden auch kurze Spikes ausgefiltert (btw. wie groß ist bei dir 
eigentlich die Intervallzeit eingestellt.)
Allerdings kannst du jetzt die Funktion duration nicht mehr benutzen. 
Ist aber, denke ich verschmerzbar.

> Delays verwende ich nur während der Rollomotor läuft. Sonst nicht...

Auch da solltest du sie nicht benutzen!
Delays sind oft das Problem, aber selten die Lösung. Und in deinem Fall, 
bei dem Zusammenspiel mit dieser Debounce Funktion, sind sie sogar ein 
großes Problem, weil sie die Unterdrückung von Spikes aushebeln. Diese 
Debounce Funktion MUSS in kurzen Zeitabständen aufgerufen werden, 
ansonsten kommt das ganze Zeitmanagement auf dem alles beruht 
durcheinander.

von Mark (Gast)


Lesenswert?

Hallo,

dann werde ich die Änderungen mal versuchsweise einbauen.

Gibt es von euch Experten eine Lib welche ihr empfehlen könnt?

Bei den Intervallen hatte ich auch rumprobiert. Von 10 bis 200 hat sich 
nichts dabei verbessert...

Gruß
Mark

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:

> Gibt es von euch Experten eine Lib welche ihr empfehlen könnt?

Die wenigsten hier benutzen irgendwelche Arduino Libs. Wir programmieren 
selber :-)

> Bei den Intervallen hatte ich auch rumprobiert. Von 10 bis 200 hat sich
> nichts dabei verbessert...

Das kann auch jetzt noch so sein, solange du deine delays in der loop() 
nicht los wirst. Immer drann denken: Das Ausfiltern der Spikes 
funktioniert nur dann, wenn du diese debounce Funktion oft genug 
aufrufst. Tust du das nicht, dann Bye-Bye-Ausfilterung / Welcome 
sporadische Zähler

von Mark (Gast)


Lesenswert?

Hallo,

aber ihr erfindet doch das Rad in Bezug auf das Bounce-Problem nicht 
jedesmal neu, oder? Könnte jemand von euch eine funktionierende Lib zur 
Verfügung stellen? Das wäre echt klasse...

In der Loop selbst befinden sich keine delay's. Erst dann wenn der 
Taster betätigt wurde...

Gruß
Mark

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:
> Hallo,
>
> aber ihr erfindet doch das Rad in Bezug auf das Bounce-Problem nicht
> jedesmal neu, oder? Könnte jemand von euch eine funktionierende Lib zur
> Verfügung stellen? Das wäre echt klasse...

Entprellung

> In der Loop selbst befinden sich keine delay's. Erst dann wenn der
> Taster betätigt wurde...

Ich feilsch jetzt aber nicht herum.
delay ist delay. Und der muss weg. Wozu brauchst du den delay überhaupt 
bei einer Rollladensteuerung?

von Mark (Gast)


Lesenswert?

Hallo,

vielen Dank erst mal.
Ich werde mir jetzt erst mal den Link zum Entprellen verinnerlichen.

Das mit den Delays während der Rollo läuft habe ich für mich als ganz 
gut befunden. So lange der Motor läuft reagiert das ganze auf keine 
weiteren (eventuell störende) Tastendrücke.

Vielleicht zum besseren Verständnist was ich damit bezwecken möchte:

Der Rollo wird normalerweise über einen Rolloschalter (nicht Taster) 
gesteuert. D.h. so lange der Schalter "umgelegt" ist läuft der Rollo in 
eine Richtung.

Ich möchte die Steuerung aber nun über einen einzigen Taster erledigen.
- einmal drücken --> Rollo zu
- zweimal --> Rollo viertel auf
- dreimal --> Rollo halb auf
- viermal --> Rollo dreiviertel auf
- fünfmal --> Rollo ganz auf

Dazu messe ich die Zeiten von z.B. Position 1 bis Positio 2 und lasse 
dann den Motor dementsprechend lange laufen. Gleichzeitig merke ich mir 
die aktuelle Postion damit ich die Richtung einstellen kann.

Die Anzahl der Tastendrücke werden innerhalb von zwei Sekunden gezählt.

Wie gesagt das Programm funktioniert so weit. Nur der "Lötkolben-Effekt" 
ist derzeit das Problem.

Gruß
Mark

von Karl H. (kbuchegg)


Lesenswert?

Mark schrieb:

> Dazu messe ich die Zeiten von z.B. Position 1 bis Positio 2 und lasse
> dann den Motor dementsprechend lange laufen. Gleichzeitig merke ich mir
> die aktuelle Postion damit ich die Richtung einstellen kann.
>
> Die Anzahl der Tastendrücke werden innerhalb von zwei Sekunden gezählt.
>

Und wozu brauchst du da jetzt delays.

Der Arduino-Trick ist eigentlich immer der gleiche. Man merkt sich in 
einer Variablen den Wert von millis() zum jetzigen Zeitpunkt und 
vergleicht beim nächsten Aufruf von loop() ob diese Zeit schon 
abgelaufen ist. Bei dir kann man das abwandlen, dass wenn der Motor 
eingeschaltet wird, dann merkt man bzw. rechnet sich aus, wann er wieder 
abzuschalten ist, basierend auf dem Wert von millis(). Die erste Aktion 
in loop() besteht dann einfach darin diese Zeit zu prüfen (und 
nachzusehen ob der Motor gerade läuft) und wenn die Zeit drüber ist, 
dann wird abgeschaltet.
1
unsigned long stopMotorAt;
2
bool          motorRunning;
3
4
void loop()
5
{
6
  if( motorRunning && stopMotorAt < millis() )
7
  {
8
     Motor ausschalten
9
     motorRunning = false;
10
  }
11
12
13
  if( ....... irgendwas, was den Motor eine bestimmte Zeit lang laufen
14
      lassen soll )
15
  {
16
    stopMotorAt = millis() + 5000;   // Motor soll 5 Sekunden laufen
17
    motorRunning = true;
18
    Motor einschalten
19
  }
20
}

kein delay und trotzdem schaltet sich der Motor 5 Sekunden nachdem er 
gestartet wurde ab. Ja. Ist ein bischen aufwändiger als die banale

    einschalten
    warten
    ausschalten

Lösung, aber dafür funktioniert das auch immer und der µC kann auch noch 
andere Dinge tun (zb Tasten abfragen, zb Endschalter abfragen, zb den 
Motorstrom überwachen) anstatt einfach nur stupide im Schritt 'warten' 
mit den Däumchen zu drehen.

> Wie gesagt das Programm funktioniert so weit. Nur der "Lötkolben-Effekt"
> ist derzeit das Problem.

:-)
Also funktioniert es eben nicht.
'Funktioniert' bedeutet bei mir: unter allen Umständen. Einzig das 
Abschalten des Stroms könnte man vielleicht gerade noch geltend machen, 
warum ein µC nicht mehr seine Arbeit tut. :-)
Aber abgesehen davon, hat ein µC seine Aufgabe korrekt zu erfüllen.
Das bedeutet bei mir 'funktionier'.

von Warum (Gast)


Lesenswert?

reitet ihr so auf der Debounce- Geschichte rum? Ich würde erst mal bei 
der
Stromversorgung ansetzen: Netzfilter, Abblock- Cs, Drossel, Erdung/ 
Schirmung....?

von Mark (Gast)


Lesenswert?

Da ist natürlich was dran... ;)
Dies unterscheidet eben den Profi vom Anfänger...

Vielen Dank für die Hinweise.

Gruß
Mark

von Peter D. (peda)


Lesenswert?

Warum schrieb:
> Netzfilter, Abblock- Cs, Drossel, Erdung/
> Schirmung....?

Man kann sich dumm und dusslig filtern, ohne großen Effekt. MCs sind 
nunmal verdammt schnell, kein Vergleich zu früheren Relaissteuerungen.
20MHz filtert man nicht eben so einfach weg.

Ich hab auch ein älteres Gerät mit TTL-Steuerung, da ist schon die halbe 
Platine mit RC-Tiefpässen zugepflastert.
Sowas muß man sich heutzutage nicht mehr antun. Alles in Software kriegt 
man zum Nulltarif, also sollte man soviel wie möglich die Software 
erledigen lassen.
Jede Lötstelle, jedes Bauelement kostet aber und kann ausfallen. Eine 
SW-Lösung ist daher auch zuverlässiger.

SW läßt sich auch viel leichter testen, man läßt sie einfach im 
Simulator laufen und kann sich jeden Schritt ganz bequem angucken. Die 
Störungen emuliert man mittels Stimuli.

von Mark (Gast)


Lesenswert?

Hallo,

noch eine Frage:
peda schreibt von einem Simulator mit mit Einzelschritt. Wo finde ich da 
was brauchbares? Und das Stimuli gehört dann dazu?

Nochmals Vielen Dank
Mark

von Peter D. (peda)


Lesenswert?

Der Simulator ist z.B. im AVRStudio dabei. Dazu muß man das Programm 
auch mit dem AVRStudio compilieren.

Die Stimuli muß man selber schreiben.
Man kann aber auch den Pin als Ausgang setzen und dann im Programm auf 
verschiedene Werte setzen, z.b. aus einem Array.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.