Forum: Mikrocontroller und Digitale Elektronik Entprellen von Schalter mit Interrupt und PinChange


von Stefan S. (kami)


Lesenswert?

Hi Leute,

ich habe hier folgendes Problem ich habe unter Arduino einen Attiny84 so 
programmiert, das er über einen simplen Schalter einen Interrupt 
auslöst.

Der Schalter wird nun geschlossen und geöffnet. Ich frage nur auf 
PinChange ab. Also beim Betätigen des Schalter wird der Interrupt 
gestartet.

Nun möchte ich gerne jeweils eine Ausgabe durch den Controller bekommen 
für folgende 2 Tätigkeiten:

1. Der Schalter wird geöffnet und wieder geschlossen.
2. Der Schalter wird nur geöffnet und bleibt offen stehen.

Problem dabei ist nun das der Schalter auch klappern kann, als relativ 
schnell auf und zu springen kann. Das soll durch den Controller nicht 
ausgewertet werden.

Ich habe dafür bisher folgenden Code unter  Arduino geschrieben:

ISR (PCINT0_vect) {
volatile unsigned long now;
  now = millis();
  if (now < inttime) { return;}

  inttime = now + 2000;
  flag=1;


}

void setup()   {
      setPrescaler(0); // div 1, i.e. speed up to 8 MHz


      delay(500);

      ADCSRA &= ~ bit(ADEN); // disable the ADC
      bitSet(PRR, PRADC); // power down the ADC
      PRR = bit(PRTIM1) | bit(PRUSI) | bit(PRADC); // only keep timer 0 
going

      pinMode(DIO1, INPUT);       //set the pin to input
      digitalWrite(DIO1, HIGH); //use the internal pullup resistor
      PCMSK0 |= (1<<PCINT2); //  tell pin change mask to listen to 
(DIO1)
      GIMSK  |= (1<<PCIE0); // enable PCINT interrupt in the general 
interrupt mask

      sei();



}


Der Rest des Codes ist unerheblich.

Wer hat da eine gute Idee wie man das Entprellen vernünftig wegbekommt?

Vielen Dank.

Gruß kami

von Peter II (Gast)


Lesenswert?

Stefan S. schrieb:
> Wer hat da eine gute Idee wie man das Entprellen vernünftig wegbekommt?

schon mal die suche verwendet?

https://www.mikrocontroller.net/articles/Entprellung

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Tasten an nen Interrupt zu hängen sollt man grundsätzlich lassen.
Beim prellen im kHz Bereich kanns vorkommen, dass der AVR dann nurnoch 
ISRs abhandelt.
Wenn die Taste unbedingt am Interrupt hängen muss, dann hau ne 
Hardwareentprellung davor.
LInk haste schon.

von Thomas E. (thomase)


Lesenswert?

Stefan S. schrieb:
> Der Rest des Codes ist unerheblich.
Wenn du Hilfe haben willst, poste deinen ganzen Code. Denn 
erfahrungsgemäß liegt der Fehler fast immer dort, wo er garaniert nicht 
liegt.

mfg.

von Wolfgang (Gast)


Lesenswert?

Stefan S. schrieb:
> Problem dabei ist nun das der Schalter auch klappern kann, als relativ
> schnell auf und zu springen kann. Das soll durch den Controller nicht
> ausgewertet werden.

Das "Klappern" spielt überhautp keine Rolle, solange die Zeiten für 
"relativ schnell" kürzer ist als "geöffnet und wieder geschlossen". Nach 
dem Erkennen der Flanke von "geöffnet" wartest du die maximal erlaubte 
Zeit für "geöffnet und wieder geschlossen" und guckst dann den 
Schalterzustand noch einmal an. Erst dann kannst du irgendetwas 
auswerten. Bis zum Ablauf von max_"geöffnet und wieder geschlossen" geht 
den µC überhaupt nichts an, was am Schalter passiert. Interrupt ist 
daher nicht unbedingt das das Mittel der Wahl. Man könnte ihn einfach 
abdrehen, solange die Zeit nicht abgelaufen ist oder - besser - den 
Schalter per Timer pollen.

von Karl H. (kbuchegg)


Lesenswert?

Stefan S. schrieb:

> Nun möchte ich gerne jeweils eine Ausgabe durch den Controller bekommen
> für folgende 2 Tätigkeiten:
>
> 1. Der Schalter wird geöffnet und wieder geschlossen.
> 2. Der Schalter wird nur geöffnet und bleibt offen stehen.

Eher eine ungewöhnliche Aufgabenstellung.
Denn wenn man genau darüber nachdenkt, dann kann man den Schalter nur 
ein einziges mal öffnen. Denn irgendwann muss er wieder geschlossen 
werden. Und wenn es 2 Stunden später ist.


Es gibt grundsätzlich 2 Ansätze
* entweder man unterscheidet zwischen
    # Schalter ist geöffnet
    # Schalter ist geschlossen
  dann hat man damit 2 Programmzustände verknüpft, die je nachdem ob
  der Schalter geöffnet oder geschlossen ist, ausgewählt werden.
  Beispiele:
     Schalter - LED      ist der Schalter geschlossen, leuchtet die LED
     Schalter - Motor    ist der Schalter geschlossen, läuft der Motor

* oder aber man betrachtet den kompletten Zyklus
   Schalter geschlossen, gedrückt, wieder geöffnet
  als eine einzige Aktion - einen Tastendruck.
  Dann hat man die Möglichkeit mit jedem Tastendruck (also einmal
  auf die Taste latschen und wieder loslassen) eine Aktion auszulösen.
  Was immer auch diese Aktion ist.
  Beispiele:
    Schalter - LED     mit jedem Tastendruck wechselt die LED in
                       den jeweils anderen Zustand.
                       Tastendruck - ein, Tastendruck - aus
                       Wieviele LED Zustände es gibt, ist per Def.
                       nicht vorgeschrieben, da können auch noch
                       mehrere sein, zb diverse Blinkstufen.
    Schalter - Motor   selbes Spiel. Durch Betätigen der Taste
                       startet der Motor, und der Motor läuft
                       weiter, selbst wenn die Taste losgelassen wird.
                       Der nächste Tastendruck könnte zb den Motor
                       wieder stoppen oder die Drehrichtung umdrehen
                       etc.


Das sind also 2 ganz verschiedene Dinge.
In dem einen Fall geht es darum, ob die Taste gedrückt IST oder ob sie 
nicht gedrückt IST.
Im anderen Fall geht es darum, dass die Taste gedrückt WIRD (und auch 
wieder losgelassen WIRD). In diesem Modus kann man sich dann noch 
Zusatzdinge einbauen, wie zb ein Autorepeat oder die Unterscheidung 
zwischen langen und kurzen Tastendrücken (ich bin sicher du findest 
dafür in deiner Umgebung selbst Beispiele).

Aber zwischen den beiden Dingen zu mischen ..... dürfte ersten 
programmtechnisch Ärger bringen (sieht man ja schon bei dir - was 
bedeutet das 'bleibt offen'? Gilt das auch wenn der Schalter erst nach 2 
Stunden wieder geschlossen wird? Eigentlich ist das dann ja ein 'wird 
geöffnet und dann wieder geschlossen' laut deiner Definition. Du hast ja 
nix von Zeiten dazwischen gesagt) ...
und zweitens liefert das meistens seltsame Bedienkonzepte, die man zwar 
selber (als Programmierer bzw. derjenige der das realisiert) unheimlich 
logisch findet, die aber jeden anderen in den Wahnsinn treiben. Und auch 
dafür gibt es auch bei kommerziellen Produkten genügend Beispiele.

von Peter D. (peda)


Lesenswert?

Dein Post erweckt den Eindruck, es habe sich nie jemand zuvor mit dem 
Prellen beschäftigt und daher mußt Du es selber lösen.

Warum benutzt Du nicht erstmal Google oder schaust einfach im 
Arduino-Manual nach?


Peter

von Stefan S. (kami)


Lesenswert?

Hi,

also ich habe mir da ja schon ein paar Beispiele rausgesucht. Aber 
irgendwie gehen die Meinung auseinander. Ich bin auch nicht der große 
Hardware- oder Softwareentwickler sondern mache das nur als Hobby. Also 
was habe ich mit dem ATTINY84 zu hause gemacht:

Mein Briefkasten wird die Klappe über einen einfachen Kontakt von zwei 
Kupferplatten überwacht. Der µC wird in einen Sleepmodus gesetzt, um die 
Batterie zu schonen. Mit meinem "gefährlichen Halbwissen" :) habe ich 
nun folgendes zusammengestellt. Klappe des Briefkasten geht auf, µC wird 
durch PinChange aufgeweckt und sendet per Funk an meine Basis eine 
Nachricht, das der Briefkasten geöffnet wurde. Nach einiger Zeit fällt 
der µC wieder in den Schlaf. Das klappt soweit auch super aber ich habe 
2 Probleme die sich gegenseitig als Problematisch zur Zeit darstellen.

1. Meine Nachbarn hauen ihre Klappe zu doll zu und Meine klappert nur 
leicht.
2. Der Zeitungsbote haut ne ZEitung rein und die Klappe bleibt auf.

Also nun muss würde ich natürlich am liebsten per Software da alles 
lösen, da die Hardware eigentlich funktioniert.

Hier mal mein Quellcode :
1
#include <JeeLib.h>
2
#include <avr/sleep.h>
3
#include <avr/interrupt.h>  
4
5
#define myNodeID 8
6
#define DIO1 10  // d10 
7
#define DIO2 14  // d10 
8
#define LOGGERNUM   134
9
#define Serial  1   // set to 1 to also report readings on the // Serial port
10
#define DEBUG   1   // set to 1 to display each loop() run and PIR trigger
11
#define TEST_LIMIT   10 
12
13
#define RETRY_PERIOD    10  // how soon to retry if ACK didn't come in
14
#define RETRY_LIMIT     5   // maximum number of times to retry
15
#define ACK_TIME        80  // number of milliseconds to wait for an ack
16
17
// set the sync mode to 2 if the fuses are still the Arduino default // mode 3 (full powerdown) can only be used with 258 CK startup fuses 
18
//#define RADIO_SYNC_MODE 2
19
20
volatile static int flag=0;
21
static byte testval = 1;
22
23
volatile unsigned long inttime,inttime2 ; // stored time of last interrupt
24
 
25
typedef struct {
26
    unsigned int device;
27
    unsigned int error;
28
    unsigned int lobat;
29
    unsigned int status1;
30
} msgstruct;
31
32
static void setPrescaler (uint8_t mode) {
33
    cli();
34
    CLKPR = bit(CLKPCE);
35
    CLKPR = mode;
36
    sei();
37
}
38
39
 
40
static byte waitForAck() {
41
    MilliTimer ackTimer;
42
    while (!ackTimer.poll(ACK_TIME)) {
43
        if (rf12_recvDone() && rf12_crc == 0 &&
44
                // see http://talk.jeelabs.net/topic/811#post-4712
45
                rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | myNodeID))
46
            return 1;
47
48
    }
49
    return 0;
50
}
51
 
52
ISR(WDT_vect) { Sleepy::watchdogEvent(); }
53
54
55
ISR (PCINT0_vect) { 
56
volatile unsigned long now;
57
  now = millis();
58
  if (now < inttime) { return;} 
59
 
60
  inttime = now + 2000;
61
  flag=1;
62
    
63
     
64
}
65
ISR (PCINT1_vect) { 
66
volatile unsigned long now;
67
  now = millis();
68
  if (now < inttime2) {  return;} 
69
 
70
  inttime2 = now + 2000;
71
  flag=3;
72
    
73
     
74
}
75
76
void setup()   {
77
      setPrescaler(0); // div 1, i.e. speed up to 8 MHz
78
      
79
      // Serial.begin(38400);
80
      rf12_initialize(8, RF12_868MHZ, 212);
81
      rf12_control(0xC647);
82
      rf12_control(0xC040);
83
    
84
      msgstruct msgfile;
85
      msgfile.device = LOGGERNUM;
86
      msgfile.error = 20;
87
      msgfile.lobat = rf12_lowbat();
88
      msgfile.status1 = testval;
89
      
90
      for (byte i = 0; i < TEST_LIMIT; ++i) {
91
       
92
      for (byte d = 0; d < RETRY_LIMIT; ++d) {
93
94
       rf12_sleep(-1);
95
        while (!rf12_canSend())
96
            rf12_recvDone();
97
        rf12_sendStart(RF12_HDR_ACK, &msgfile, sizeof msgfile);
98
99
        byte acked = waitForAck();
100
        rf12_sleep(0);
101
102
        if (acked) {
103
         
104
        // Serial.print("ack1 \n");
105
             d = RETRY_LIMIT;
106
            
107
        }
108
        else {
109
          // Serial.print(d);
110
        // Serial.print("no ack1 \n");
111
             Sleepy::loseSomeTime(RETRY_PERIOD * 100);
112
        } 
113
      
114
      }
115
      
116
      }
117
    
118
      if (testval == 1)  testval=0; else testval=1;
119
    
120
      msgfile.status1 = testval;
121
      delay(500);
122
       
123
      ADCSRA &= ~ bit(ADEN); // disable the ADC
124
      bitSet(PRR, PRADC); // power down the ADC
125
      PRR = bit(PRTIM1) | bit(PRUSI) | bit(PRADC); // only keep timer 0 going
126
       
127
      pinMode(DIO1, INPUT);       //set the pin to input
128
      digitalWrite(DIO1, HIGH); //use the internal pullup resistor
129
      PCMSK0 |= (1<<PCINT2); //  tell pin change mask to listen to (DIO1)
130
      GIMSK  |= (1<<PCIE0); // enable PCINT interrupt in the general interrupt mask
131
      pinMode(DIO2, INPUT);       //set the pin to input
132
      //digitalWrite(DIO2, HIGH); //use the internal pullup resistor
133
      PCMSK1 |= (1<<PCINT8); //  tell pin change mask to listen to (DIO1)
134
      GIMSK  |= (1<<PCIE1); // enable PCINT interrupt in the general interrupt mask
135
      sei(); 
136
137
138
 
139
}
140
 
141
void loop() {
142
  
143
    delay(500); 
144
    
145
    if (flag==1)
146
    {
147
    flag=2;
148
     
149
    domessage();
150
  
151
    }
152
    if (flag==3)
153
    {
154
    flag=2;
155
     
156
    domessage2();
157
  
158
    } 
159
    delay(500);
160
   
161
    if (rf12_easyPoll() == 0 && flag==0) {
162
        // Serial.println("sleep");
163
     
164
        sleepNow();
165
    }
166
 
167
}
168
 
169
void sleepNow()      
170
{
171
172
    rf12_sleep(0); 
173
    set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
174
    sleep_enable();        
175
    sleep_mode(); 
176
    sleep_disable(); 
177
 
178
}
179
 
180
 
181
void domessage()
182
{
183
  
184
   if (testval==1) testval=0; else testval=1;
185
  
186
    msgstruct msgfile;
187
    msgfile.device = LOGGERNUM;
188
    msgfile.error = 34;
189
    msgfile.lobat = rf12_lowbat();
190
    msgfile.status1 = testval;
191
192
    bitClear(PRR, PRUSI); // enable USI h/w   // Is this needed?
193
    
194
      for (byte i = 0; i < RETRY_LIMIT; ++i) {
195
   
196
        rf12_sleep(-1);
197
198
        while (!rf12_canSend())
199
            rf12_recvDone();
200
        rf12_sendStart(RF12_HDR_ACK, &msgfile, sizeof msgfile);
201
202
        byte acked = waitForAck();
203
        rf12_sleep(0);
204
 
205
        if (acked) {
206
         
207
        // Serial.print("ack2 \n");
208
             i = RETRY_LIMIT;           
209
        }
210
        else {
211
        // Serial.print("no ack2 \n");
212
             Sleepy::loseSomeTime(RETRY_PERIOD * 100);
213
        } 
214
      }
215
      bitSet(PRR, PRUSI); // disable USI h/w    // Is this needed?
216
      flag=0; 
217
}
218
void domessage2()
219
{
220
  
221
   if (testval==1) testval=0; else testval=1;
222
  
223
    msgstruct msgfile;
224
    msgfile.device = LOGGERNUM;
225
    msgfile.error = 36;
226
    msgfile.lobat = rf12_lowbat();
227
    msgfile.status1 = testval;
228
229
    bitClear(PRR, PRUSI); // enable USI h/w   // Is this needed?
230
    
231
      for (byte i = 0; i < RETRY_LIMIT; ++i) {
232
   
233
        rf12_sleep(-1);
234
235
        while (!rf12_canSend())
236
            rf12_recvDone();
237
        rf12_sendStart(RF12_HDR_ACK, &msgfile, sizeof msgfile);
238
239
        byte acked = waitForAck();
240
        rf12_sleep(0);
241
 
242
        if (acked) {
243
         
244
        // Serial.print("ack2 \n");
245
             i = RETRY_LIMIT;           
246
        }
247
        else {
248
        // Serial.print("no ack2 \n");
249
             Sleepy::loseSomeTime(RETRY_PERIOD * 100);
250
        } 
251
      }
252
      bitSet(PRR, PRUSI); // disable USI h/w    // Is this needed?
253
      flag=0; 
254
}

Vielen Dank aber auch schon mal für die ganzen tollen Tipps.

Gruß kami

von Peter D. (peda)


Lesenswert?

Sleep + Entprellung:

Beitrag "Re: AVR Sleep Mode / Knight Rider"


Peter

von Karl H. (kbuchegg)


Lesenswert?

Stefan S. schrieb:

> also ich habe mir da ja schon ein paar Beispiele rausgesucht. Aber
> irgendwie gehen die Meinung auseinander.

Eigentlich nicht.
Beim Thema 'Tasten entprellen' sind sich alle eigentlich ziemlich einig. 
'Externer Interrupt' ist genau die Methode, die einen nicht weiter 
bringt.

> Mein Briefkasten wird die Klappe über einen einfachen Kontakt von zwei
> Kupferplatten überwacht. Der µC wird in einen Sleepmodus gesetzt, um die
> Batterie zu schonen. Mit meinem "gefährlichen Halbwissen" :) habe ich
> nun folgendes zusammengestellt. Klappe des Briefkasten geht auf, µC wird
> durch PinChange aufgeweckt und sendet per Funk an meine Basis eine
> Nachricht, das der Briefkasten geöffnet wurde. Nach einiger Zeit fällt
> der µC wieder in den Schlaf. Das klappt soweit auch super aber ich habe
> 2 Probleme die sich gegenseitig als Problematisch zur Zeit darstellen.
>
> 1. Meine Nachbarn hauen ihre Klappe zu doll zu und Meine klappert nur
> leicht.
> 2. Der Zeitungsbote haut ne ZEitung rein und die Klappe bleibt auf.


Also alles nicht zeitkritisch.
Wenn dein µC alle 1 Sekunde mal aufwacht, einen kurzen Blick auf den 
Kontakt wirft und danach weiter schläft, ist der Batterieverbauch immer 
noch minimal.

>
> Also nun muss würde ich natürlich am liebsten per Software da alles
> lösen, da die Hardware eigentlich funktioniert.

Spricht ja auch nichts dagegen.

Las den Sleep Mode erst mal links liegen. Den baut man zum Schluss ein.
In einem Timer Interrupt überprüfst du alle, sagen wir mal halbe Sekunde 
ob der Kasten offen oder geschlossen ist. Mit einem Zähler der bei 
geöffnet angetroffenem Kasten um 1 hochgezählt wird, kannst du 
feststellen ob der Kasten geöffnet wurde und wenn ja, wie lange. Alles 
unter, Hausnummer, 1 Sekunde kannst du getrost ignorieren. So schnell 
kann keiner einen Brief und/oder Zeitung in den Kasten legen.

Hier geht es ja nicht darum, dass du 'zeitnah' das Öffnen feststellst. 
Wenn deine Kontrollampe erst 3 Sekunden angeht, nachdem der Briefträger 
am Kasten war, dann ist das auch kein Beinbruch.

von Mobilist (Gast)


Lesenswert?

Stefan S. schrieb:
> Hier mal mein Quellcode :

Wofür gibt es eigentlich die Option "Dateianhang"?

von Thomas E. (thomase)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wenn dein µC alle 1 Sekunde mal aufwacht, einen kurzen Blick auf den
> Kontakt wirft und danach weiter schläft, ist der Batterieverbauch immer
> noch minimal.
Aber nicht optimal. Das macht der Knightrider doch viel besser.

mfg.

von Interrupter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Beim Thema 'Tasten entprellen' sind sich alle eigentlich ziemlich einig.
> 'Externer Interrupt' ist genau die Methode, die einen nicht weiter
> bringt.

Es ist natürlich auch eine Methode, zu behaupten, dass es andere 
Meinungen gar nicht gibt. So etwas würde sich in einer meinungsoffenen 
und toleranten Gesellschaft oder Gruppierung selbst disqualifizieren, 
aber diese Grundlage ist hier ja nicht gegeben.
Ist Starrsinn und Ignoranz eigentlich Vorraussetzung, um hier Moderator 
zu werden?

von Karl H. (kbuchegg)


Lesenswert?

Interrupter schrieb:

> Ist Starrsinn und Ignoranz eigentlich Vorraussetzung, um hier Moderator
> zu werden?

Ach komm, bitte.

Die Diskussion gibt es alle 2 Wochen. Und immer wieder endet sie auf die 
gleiche Art und Weise. Noch nie wurde eine Tastenabfrage präsentiert, 
die auf externen Interrupts basiert und die besser funktioniert bzw. 
einfacher ist, als die Methode "Timer-Interrupt Pollen".
Die einzige Ausnahme besteht darin, wenn die Taste den µC aus dem Sleep 
holen muss. Und selbst dann ist es einfacher, wenn der Timer nach dem 
Aufwecken das weitere Pollen erledigt, bis sich der µC wieder schlafen 
legt.

Siehe die 'Knightrider Lösung', auf die PeDa dankenswerterweise verlinkt 
hat.

Das alles wurde schon x-mal bis zum Erbrechen durchgekaut. Und zwar 
schon seit Jahren. Die einzig ignoranten sind diejenigen, die immer 
wieder den externen Interrupt bei Tastenabfragen ins Spiel bringen und 
dann mittels diverser wait oder delay Mechanismen in der ISR 
irgendwelche Entprellungen vornehmen wollen.

Aber du kannst gerne mal deine auf externem Interrupt basierende Methode 
präsentieren. Dann vergleichen wir mal mit der PeDa Lösung und werden 
schon sehen, was da jetzt simpler in Bezug auf Rechenzeitverbrauch, 
Zuverlässigkeit und Universalität ist.
Und nein: "Ich versteh die PeDa Lösung nicht" ist kein zugelassenes 
Argument. Dann lern eben programmieren bzw. polier deine 
Analysefähigkeiten auf.

von Fabian O. (xfr)


Lesenswert?

In diesem Fall finde ich den externen Interrupt gar keine so schlechte 
Lösung. Ich würde ihn folgendermaßen benutzen:
1
ISR() // Auslösen bei Wechsel von geschlossen nach offen
2
{
3
  counter = 100;
4
}
5
6
loop()
7
{
8
  if (counter > 0) {
9
    if (schalter_offen()) {
10
      counter--;
11
      if (counter == 0) {
12
        // Schalter war eine Sekunde lang offen
13
        sende_nachricht();
14
      } else {
15
         delay_ms(10);
16
      }
17
    } else {
18
      // Schalter wurde zu früh wieder geschlossen
19
      counter = 0;
20
    }
21
  }
22
  if (counter == 0) {
23
    sleep();
24
  }
25
}

Der Mikrocontroller befindet sich also die meiste Zeit im Schlafmodus 
und wacht erst beim externen Interrupt auf. Dann muss 100 Mal 
hintereinander im Abstand von 10 ms der Schalter offen sein, damit es 
als Briefkasten geöffnet erkannt wird. Andernfalls geht es wieder zurück 
in den Sleepmodus. Statt delay_ms() kann man natürlich auch einen Timer 
benutzen, aber wenn der Mikrocontroller sonst nichts machen muss, ist es 
so imo auch OK.

Edit: Man müsste allerdings noch den Zugriff auf die Variable counter 
synchronisieren, sonst kann es zu Race-Conditions kommen.

von Thomas E. (thomase)


Lesenswert?

Interrupter schrieb:
> So etwas würde sich in einer meinungsoffenen
> und toleranten Gesellschaft oder Gruppierung selbst disqualifizieren,
> aber diese Grundlage ist hier ja nicht gegeben.
Du solltest dich den Leuten anschliessen, die LEDs ohne Vorwiederstand 
verbauen. Da wirst du nicht von den verbohrten Dogmatikern mit ihrer 
jahrzehntelangen Erfahrung und ihrer ewigen sich darauf gründenden 
Besserwisserei bevormundet.

mfg.

PS: Das "ie" war jetzt Absicht, das gehört bei denen ja irgendwie dazu. 
Schliesslich läst man sich ja auch vom Duden nichts sagen.

von Karl H. (kbuchegg)


Lesenswert?

Thomas Eckmann schrieb:
> Interrupter schrieb:
>> So etwas würde sich in einer meinungsoffenen
>> und toleranten Gesellschaft oder Gruppierung selbst disqualifizieren,
>> aber diese Grundlage ist hier ja nicht gegeben.
> Du solltest dich den Leuten anschliessen, die LEDs ohne Vorwiederstand
> verbauen. Da wirst du nicht von den verbohrten Dogmatikern mit ihrer
> jahrzehntelangen Erfahrung und ihrer ewigen sich darauf gründenden
> Besserwisserei bevormundet.
>
> mfg.
>
> PS: Das "ie" war jetzt Absicht, das gehört bei denen ja irgendwie dazu.
> Schliesslich läst man sich ja auch vom Duden nichts sagen.

Keinen Vorwiederstand zu verbauen ist sozusagen Standart.

von Falk B. (falk)


Lesenswert?

@  Fabian O. (xfr)

>In diesem Fall finde ich den externen Interrupt gar keine so schlechte
>Lösung.

"Finden" kann man viel. NACHWEISEN ist was anderes.

> Ich würde ihn folgendermaßen benutzen:

Igitt!!!! DELAY!!!!


>in den Sleepmodus. Statt delay_ms() kann man natürlich auch einen Timer
>benutzen,

Also DOCH Timer! Warum dann nicht gleich richtig?

> aber wenn der Mikrocontroller sonst nichts machen muss, ist es
>so imo auch OK.

So lernt man es nie. Beschäftige dich mal mit den Themen 
statemachine und Multitasking.

>Edit: Man müsste allerdings noch den Zugriff auf die Variable counter
>synchronisieren, sonst kann es zu Race-Conditions kommen.

Müsst, sollte, könnte. Jaja, alles sehr solide. . .

von m.n. (Gast)


Angehängte Dateien:

Lesenswert?

Bevor hier die Messer gezückt werden, meine 'timerfreie' 
Tasterentprellung aus dem letzten Jahrhundert: 
http://www.mino-elektronik.de/power_at90s/powerat90s.htm
Aktuell habe ich eine abgemagerte C-Version für den ATtiny13 angehängt, 
die einfacher nachzuvollziehen ist.

von Interrupter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Noch nie wurde eine Tastenabfrage präsentiert,
> die auf externen Interrupts basiert und die besser funktioniert bzw.
> einfacher ist, als die Methode "Timer-Interrupt Pollen".

Was "besser funktionieren" bedeutet, hängt wohl vom Einzelfall ab. Wenn 
eine Anforderung in maximaler Stromersparnis liegt, ist der power-down 
Mode die beste Wahl, aber der erlaubt nun mal kein Timer-gesteuertes 
Aufwachen.
Dazu kommt, dass die Danneger-Routine die Tastatureingabe unnötig 
verzögert. Wenn die erste Flanke auftritt, wurde die Taste gedrückt, und 
da muss nicht mehr gewartet werden, bis sie fertig geprellt hat, um dann 
die Tastatureingabe zu verarbeiten. Das kann parallel geschehen.

Ich hatte jedenfalls vor etwa 1 Monat eine entsprechende Methode 
implementiert, ausführlich getestet, gut dokumentiert, und mit 
Quelltexten unter Beitrag "Re: AVR Einstieg / Probleme mit Programm Interrupt" 
hier vorgestellt.
Die einzige Reaktion darauf kam von "STK500-Besitzer", der auf meine 
Argumente gar nicht einging, sondern mein Posting schlicht "Geschwafel" 
nannte, ohne es, wie er selbst zugab, ganz gelesen zu haben.
Im weiteren Verlauf des Threads ging es wieder darum, dass es schlecht 
ist, innerhalb einer ISR zu warten, was ganz meiner Meinung entspricht, 
aber wiederum, ohne auf meinen Code einzugehen, der eben nicht in der 
ISR wartet.
Da wurde mir klar, dass es egal ist, ob mein Code funktioniert und 
Vorteile gegenüber der Dannegger Methode hat und dass es keinen 
interessiert, ob er verständlich ist. Hier geht es nur darum, mit den 
Wölfen zu heulen, und wer da nicht mit heult, der hat schlechte Karten.
Ich werde hier jetzt keinen weiteren sinnlosen Versuch unternehmen, über 
meinen Code auf technischer Ebene zu diskutieren, denn es würde als 
Antwort (falls überhaupt) nur wieder das Dannegger Unser gebetet.
Meine Konsequenz war, hier erst mal Tschüss zu sagen, und erst mal 
(fast) nur lesend teilzunehmen. Als dann dieser Thread kam, konnte ich 
mich leider nicht zurückhalten. Ich hoffe, das gelingt mir nun besser!

> Das alles wurde schon x-mal bis zum Erbrechen durchgekaut. Und zwar
> schon seit Jahren. Die einzig ignoranten sind diejenigen, die immer
> wieder den externen Interrupt bei Tastenabfragen ins Spiel bringen und
> dann mittels diverser wait oder delay Mechanismen in der ISR
> irgendwelche Entprellungen vornehmen wollen.

Danke für das "und". Schade, dass in diesem großen Misthaufen ernsthafte 
Lösungen untergehen und nicht beachtet werden.

> Aber du kannst gerne mal deine auf externem Interrupt basierende Methode
> präsentieren. Dann vergleichen wir mal mit der PeDa Lösung und werden
> schon sehen, was da jetzt simpler in Bezug auf Rechenzeitverbrauch,
> Zuverlässigkeit und Universalität ist.

Als ich das gelesen hatte, musste ich lachen. Du warst auch in besagtem 
Thread, also kennst Du meine Methode längst! Da bist Du nicht darauf 
eingegangen und eine andere Version habe ich nicht.

von STK500-Besitzer (Gast)


Lesenswert?

[OT]
Interrupter schrieb:
> Die einzige Reaktion darauf kam von "STK500-Besitzer", der auf meine
> Argumente gar nicht einging, sondern mein Posting schlicht "Geschwafel"
> nannte, ohne es, wie er selbst zugab, ganz gelesen zu haben.
> Im weiteren Verlauf des Threads ging es wieder darum, dass es schlecht
> ist, innerhalb einer ISR zu warten, was ganz meiner Meinung entspricht,
> aber wiederum, ohne auf meinen Code einzugehen, der eben nicht in der
> ISR wartet.

Hallo Philip,
wolltest du dich nicht eigentlich ruhig verhalten, und nichts mehr im 
Forum schreiben?

Interrupter schrieb:
> Meine Konsequenz war, hier erst mal Tschüss zu sagen, und erst mal
> (fast) nur lesend teilzunehmen. Als dann dieser Thread kam, konnte ich
> mich leider nicht zurückhalten. Ich hoffe, das gelingt mir nun besser!

Stimmt. Da steht es ja.
Das Thema muss dich ja sehr bewegen, weil ich die Sache schon wieder 
vergessen hatte.
Tut mir auch leid, dass ich PeDa und Karl-Heinz nur zustimmen kann.

Interrupter schrieb:
> Als ich das gelesen hatte, musste ich lachen. Du warst auch in besagtem
> Thread, also kennst Du meine Methode längst! Da bist Du nicht darauf
> eingegangen und eine andere Version habe ich nicht.

Warum sollte man auch zum xten Mal die gleiche Lösung rezitieren?
Da reicht schon das Lesen.
[/OT]

Zum Thema:
Man kann zum Aufwecken eines Timers gerne Interrupts benutzen.
Wenn der Controller aber nicht schläft, ist das Polling die einzig 
sinnvolle Lösung.

m.n. schrieb:
> Bevor hier die Messer gezückt werden, meine 'timerfreie'
> Tasterentprellung aus dem letzten Jahrhundert:
> http://www.mino-elektronik.de/power_at90s/powerat90s.htm
> Aktuell habe ich eine abgemagerte C-Version für den ATtiny13 angehängt,
> die einfacher nachzuvollziehen ist.

Goil! Mitm externen Kondensator. Das wäre dann das andere Thema 
Entprellen.
Sachen, die man als Software erledigen kann, sparen externe Bauteile.
Strombegrenzung per Portpin ist mal was neues.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Interrupter schrieb:
> Was "besser funktionieren" bedeutet, hängt wohl vom Einzelfall ab. Wenn
> eine Anforderung in maximaler Stromersparnis liegt, ist der power-down
> Mode die beste Wahl, aber der erlaubt nun mal kein Timer-gesteuertes
> Aufwachen.

Das macht man dann aber so:
Erste Flanke am ISR wacht die CPU auf, im ISR wird der ISR abgestellt 
und die Pollroutinen übernehmen.
Beim Schlafenlegen word die ISR wieder aktiviert.

Hatte auch schonmal gesagt wieso man das nicht mit ISRs macht:
Schalter könne im khz Bereich prellen und dann arbeitet der Prozessor 
nurnoch ISRs ab und nicht das eigentliche Programm!
Es ist egal ob da nurn if drinnesteht mit wenigen Funktionsaufrufen.

Interrupter schrieb:
> Antwort (falls überhaupt) nur wieder das Dannegger Unser gebetet.

Na, ich nutze meine eigenen Routinen.

von m.n. (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Goil! Mitm externen Kondensator. Das wäre dann das andere Thema
> Entprellen.

Nicht wahr?

> Sachen, die man als Software erledigen kann, sparen externe Bauteile.

Ich stehe auf Luxus!

> Strombegrenzung per Portpin ist mal was neues.

Ich kann das Datenblatt lesen und bin kein elektronischer Salafist. Bei 
höherer Versorgungsspannung spendiere ich noch gerne 220 Ohm (siehe 
Luxus).

von STK500-Besitzer (Gast)


Lesenswert?

Martin Wende schrieb:
> Interrupter schrieb:
>> Antwort (falls überhaupt) nur wieder das Dannegger Unser gebetet.
>
> Na, ich nutze meine eigenen Routinen.

Ich auch, da ich noch nie eine Repeat-Taste brauchte.
Die Dannegger-Routine ist ja auch die einzige, die hier im Forum mal 
gepostet wurde, weil sie halt sehr gut ist.
Alle andere Routinen sind trivial.
Ob man nun nach einem Flankenwechsel eine gewisse Zeit mit einem Delay 
verschwendet oder man in regelmäßigen Abständen den Status der Taste 
einliest, ist da gehupft wie gesprungen, nur dass sich der Controller 
bei der Timer-Pollig-Methode auch noch um andere Sachen kümmern kann.
Die meisten Probleme bereitet es Anfängern offensichtlich, zu verstehen, 
dass ein Schalter prellt (idealiserter Schaltter trifft auf  realen 
Schalter... ).
Und die Auswirkungen dieses Prellens sind dann auch noch nicht bewusst.
Dass hier gerne die Timer-Poll-Routine "vorgebetet" wird, liegt einfach 
daran, dass einige Menschen weiter denken...
Mit einigen Programmierlösungen landet man unweigerlich in einer 
Sackgasse.
Manchen reicht das aber...

von Peter II (Gast)


Lesenswert?

Martin Wende schrieb:
> Hatte auch schonmal gesagt wieso man das nicht mit ISRs macht:
> Schalter könne im khz Bereich prellen und dann arbeitet der Prozessor
> nurnoch ISRs ab und nicht das eigentliche Programm!

bei khz langweilt sich der µC nur. Wenn der schalter 100mal prellt dann 
hat das keinen einfluss auf die Abarbeitungsgeschwinigkeit der 
Hauptschleife.

von Zitat (Gast)


Lesenswert?

Interrupter schrieb:

> aber wiederum, ohne auf meinen Code einzugehen, der eben nicht in der
> ISR wartet.
<--->
1
// Interrupt vom EIN-AUS-Schalter
2
ISR(PCINT0_vect)
3
{
4
int8_t temp=0;
5
  PCMSK &= ~BIT(EIN_AUS_TASTER);  // sperren
6
  while(--temp);                  // ein bißchen warten
7
  if(PINB & BIT(EIN_AUS_TASTER)) {  // steigende flanke
8
    c_aufladen();                  // Kondensator auf vollen Pegel bringen
9
  } else {
10
    PORTB ^= BIT(LED_AUSGANG);
11
    c_entladen();                   // Kondensator entladen
12
  }
13
  GIFR = BIT(PCIF);                // flag löschen 
14
  PCMSK |= BIT(EIN_AUS_TASTER);      // zulassen
15
}

naja da steht "ein bißchen warten", was auch warten ist! Aber es sind ja 
"nur" 255 Timerzyklen ROFL

von m.n. (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Ich auch, da ich noch nie eine Repeat-Taste brauchte.
> Die Dannegger-Routine ist ja auch die einzige, die hier im Forum mal
> gepostet wurde,

Wie die Zeit vergeht. In zehn Tagen ist es zehn Jahre her:
Beitrag "Entprellung von Tastern"
Mit 'ohne Widerstand' und mit 'ohne Kondensator'!
Aber Du brauchst ja keine 'repeat'-Funktion :-)

von STK500-Besitzer (Gast)


Lesenswert?

m.n. schrieb:
> Wie die Zeit vergeht. In zehn Tagen ist es zehn Jahre her:
> Beitrag "Entprellung von Tastern"
> Mit 'ohne Widerstand' und mit 'ohne Kondensator'!
> Aber Du brauchst ja keine 'repeat'-Funktion :-)

Da war ich hier noch nicht unterwegs ;)

Die Funktion macht auch nicht wirklich was anderes als die danneggersche 
(das hat er aber auch schon selbst dort geschrieben).

von m.n. (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Da war ich hier noch nicht unterwegs ;)

Dann hätte ich für Dich auch noch Routinen für 6502+6522, die 30 Jahre 
alt sind und auch nichts Anderes machen. Und für mehr Taster liest der 
6522 mehrere CD4021 aus und entprellt 32 Taster.
consecutio temporum :-)

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Peter II schrieb:
> Martin Wende schrieb:
>> Hatte auch schonmal gesagt wieso man das nicht mit ISRs macht:
>> Schalter könne im khz Bereich prellen und dann arbeitet der Prozessor
>> nurnoch ISRs ab und nicht das eigentliche Programm!
>
> bei khz langweilt sich der µC nur. Wenn der schalter 100mal prellt dann
> hat das keinen einfluss auf die Abarbeitungsgeschwinigkeit der
> Hauptschleife.

Bei 16MHz sicherlich, bei 1MHz sieht das schon anders aus.
Zudem kannste im Tastenpolltimer noch andere sachen erledigen:
Multiplexen
Zeitnormal vorgeben
etc

Da würde dann der Tastenprell ISR dazu kommen -> viel Spaß.

Interrupter schrieb:
> Dazu kommt, dass die Danneger-Routine die Tastatureingabe unnötig
> verzögert

OH WOW!
Das bissel Verzögerung merkt man voll...
Jede USB Tastatur hat ne höhere Verzögerung.

von Lacher (Gast)


Lesenswert?

Zitat schrieb:
> Interrupter schrieb:
>
>> aber wiederum, ohne auf meinen Code einzugehen, der eben nicht in der
>> ISR wartet.
> <--->// Interrupt vom EIN-AUS-Schalter
> ISR(PCINT0_vect)
> {
> int8_t temp=0;
>   PCMSK &= ~BIT(EIN_AUS_TASTER);  // sperren
>   while(--temp);                  // ein bißchen warten
>   if(PINB & BIT(EIN_AUS_TASTER)) {  // steigende flanke
>     c_aufladen();                  // Kondensator auf vollen Pegel bringen
>   } else {
>     PORTB ^= BIT(LED_AUSGANG);
>     c_entladen();                   // Kondensator entladen
>   }
>   GIFR = BIT(PCIF);                // flag löschen
>   PCMSK |= BIT(EIN_AUS_TASTER);      // zulassen
> }
>
> naja da steht "ein bißchen warten", was auch warten ist! Aber es sind ja
> "nur" 255 Timerzyklen ROFL

Das ist nun billigste Unterstellung.
DAS IST NICHT MEIN CODE!!!

Martin Wende schrieb:
> Das macht man dann aber so:
> Erste Flanke am ISR wacht die CPU auf, im ISR wird der ISR abgestellt
> und die Pollroutinen übernehmen.
> Beim Schlafenlegen word die ISR wieder aktiviert.

Das macht mein Code ganz ähnlich. Wenn man ihn auch lesen würde, anstatt 
nur über ihn her zu ziehen, ...

> Hatte auch schonmal gesagt wieso man das nicht mit ISRs macht:
> Schalter könne im khz Bereich prellen und dann arbeitet der Prozessor
> nurnoch ISRs ab und nicht das eigentliche Programm!
Dafür das Abstellen der ISR in der ISR!
1
ISR(TASTE_INTERRUPT_VEKTOR)
2
{
3
  // Würde gerne Interrupts einschalten, ohne ständig aufgerufen zu werden:
4
  DeaktiviereTasteInterrupt();
5
  PrellenAbwartenTimerStarten();
6
  ...

STK500-Besitzer schrieb:
> Alle andere Routinen sind trivial.

Was Routinen enthält, die in irgendeiner Form delay() aufrufen (egal ob 
innnerhalb der ISR oder nicht) gebe ich Dir recht, dass sie Muff sind.
Mein Code passt aber nicht in dieses Schema.

Martin Wende schrieb:
> Interrupter schrieb:
>> Dazu kommt, dass die Danneger-Routine die Tastatureingabe unnötig
>> verzögert
>
> OH WOW!
> Das bissel Verzögerung merkt man voll...
> Jede USB Tastatur hat ne höhere Verzögerung.

Ich habe nicht geschrieben, dass diese Verzögerung den Anwender stört, 
sondern nur auf den konzeptionellen Fehler hingewiesen, der dahinter 
steckt. Wenn eine Einschalt-Flanke kommt, tut sich wohl etwas am Taster, 
und man kann schon mal die Eingabe behandeln, während der Taster noch 
prellt. In der Zeit des Prellens, die dann durch einen Timer gegeben 
wird, darf halt nicht auf das Prellen reagiert werden.

von Interrupter (Gast)


Lesenswert?

Lacher = Interrupter

von Peter D. (peda)


Lesenswert?

Interrupter schrieb:
> Dazu kommt, dass die Danneger-Routine die Tastatureingabe unnötig
> verzögert.

Das ist nicht unnötig, sondern volle Absicht.

Es können sich ja Störimpulse einkoppeln, z.B. wenn die Hausfrau in der 
Nähe ihren Staubsauger (1800VA) einschaltet. Oder jemand kommt mit 
seinem elektrostatisch aufgeladenen Pullover der Taste zu nahe.
Ist der Puls also zu kurz, wird er verworfen und es erfolgt keine 
Fehlschaltung.
Die 40ms Verzögerung merkt außerdem kein Mensch.
Auch sind die 10ms Abtastung nicht in Stein gemeißelt, man kann 
irgendwas zwischen 2 .. 50ms nehmen.

Ich benutze diese Entprellung/Störunterdrückung daher auch, wenn das 
Signal zwar prellfrei ist, aber über eine längere Leitung zugeführt 
wird.
Bei größeren Anlagen ist das sehr wichtig.

Lacher schrieb:
> sondern nur auf den konzeptionellen Fehler hingewiesen, der dahinter
> steckt.

Aber nur wenn Dein Konzept geringe Störsicherheit heißt.
Im meinem Konzept ist es jedoch ein Muß.


Peter

von m.n. (Gast)


Lesenswert?

Zitat schrieb:
> naja da steht "ein bißchen warten", was auch warten ist! Aber es sind ja
> "nur" 255 Timerzyklen ROFL

Kannste weglassen. Ist beim Kopieren fälschlicherweise dort gelandet.
Lade das .c-Programm ins AVR-Studio und kompiliere: alles ist 
wegoptimiert ;-)

von Hannes L. (hannes)


Lesenswert?

Interrupter schrieb:
> Wenn die erste Flanke auftritt, wurde die Taste gedrückt, und
> da muss nicht mehr gewartet werden, bis sie fertig geprellt hat,

Die erste Flanke kann aber auch durchaus ohne Tasterbetätigung durch 
einen Störimpuls verursacht worden sein, z.B. durch Einschalten oder 
Ausschalten eines Gerätes in der Nähe.

Lacher schrieb:
> Wenn eine Einschalt-Flanke kommt, tut sich wohl etwas am Taster,

Oder es tut sich was in der Umgebung, was die als Antenne wirkende 
Tasterleitung mal so nebenher aufschnappt.

> und man kann schon mal die Eingabe behandeln, während der Taster noch
> prellt.

Damit reagiert die Schaltung dann nicht nur auf reale Tastendrücke, 
sondern auch auf jeden Müll. Ein Feature, das man unbedingt haben muss, 
gelle?

Interrupter schrieb:
> Lacher = Interrupter

Gespaltene Persönlichkeit?
Verfolgungswahn?
Sockenpuppe?

Nochmal zum Thema:
Braucht man den stromsparenden Tiefschlaf, dann hängt man die Taster an 
einen PCI, den man erst beim Schlafenlegen scharfstellt. In dessen ISR 
wird dieser deaktiviert, ein TimeOut rückgesetzt und der Sleep-Mode auf 
Idle umgestellt. Weiter nichts. Nun klappert der Timer und das 
Entprellen mittels timerbasiertem Polling der Tasten beginnt. War es ein 
Tastendruck, so wird darauf reagiert. War es keiner, so läuft der 
TimeOut ab, der den Sleep-Mode auf Tiefschlaf stellt und den PCI wieder 
scharf macht. Dieser TimeOut wird auch vom Hauptprogramm regelmäßig 
zurückgesetzt, solange es noch Aktionen ausführt.

Somit hat man zwei Vorteile vereinigt: Stromsparmodus bei hellhörigen 
Tastern und wartezeitfreie wirksame Entprellung mit Störunterdrückung 
und den ganzen in Peters Algorithmus einbaubaren Features, wie separate 
Erkennung von Einschalt- und Ausschaltflanken, Autorepeat bzw. 
Unterscheidung kurz/lang.

Und nein, ich nutze Peters Code nicht einfach so unverstanden, ich habe 
den Algorithmus verstanden, für verdammt gut befunden und nutze ihn in 
eigenen Routinen, die ich gelegentlich auch mal an den Bedarf anpasse.

Eigentlich wollte ich nicht mehr für Peters Entprellung missionieren, 
wer sie nicht nutzt ist selbst schuld. Aber das, was Du hier von Dir 
gibst kann nicht unwidersprochen stehen bleiben.

...

von (prx) A. K. (prx)


Lesenswert?

Peter Dannegger schrieb:
> Die 40ms Verzögerung merkt außerdem kein Mensch.

Aus der Ballerspiel-Generation bist du offenbar schon raus. ;-)

von Hannes L. (hannes)


Lesenswert?

A. K. schrieb:
> Aus der Ballerspiel-Generation bist du offenbar schon raus. ;-)

Dann wird das Abtastintervall eben verkleinert... ;-)
Dann bekommt der ultimative Joystick eben noch ein Poti, mit dem die 
Abtastrate der Entprellung eingestellt wird. Ist doch ein nettes 
Feature, das sicher einen Markt findet... ;-)

...

von Thomas E. (thomase)


Lesenswert?

Interrupter schrieb:
> Ich hatte jedenfalls vor etwa 1 Monat eine entsprechende Methode
> implementiert, ausführlich getestet, gut dokumentiert, und mit
> Quelltexten unter Beitrag "Re: AVR Einstieg / Probleme mit Programm
> Interrupt" hier vorgestellt.
Typischer Fall von "Anfänger hat das Ei des Kolumbus entdeckt".
Hast du aber nicht. Sondern du machst wie jeder andere Anfänger auch, 
die gleichen Fehler und versuchst es mit hohem Aufwand irgendwie 
hinzubiegen. Was auch durchaus gelingt. Solange das Programm klein und 
überschaubar bleibt.
In deinem "gut kommentierten Code" schmeisst du mit Begriffen rum, deren 
Bedeutung du nicht ansatzweise kennst(Callback-Funktion), innerhalb 
einer ISR die Interrupts global frei zu geben, hälst du für höflich 
usw...
Und jetzt verhälst Du dich wie einer, der ein Auto mit Vollgummireifen 
erfunden hat und rumheult, weil ihm BMW und Mercedes nicht applaudieren.
Obwohl es doch auch fährt und niemals einen Platten kriegen kann.

Mit deinen Lösungsansätzen haben viele mal angefangen, auch die Buch- 
und Danneggers. Die haben das auch nicht mit der Muttermilch aufgesaugt. 
Aber irgendwann kommt man auf die richtige Lösung. DIE richtige Lösung 
heisst "Pollen mit Timer". Und DIESE richtige Lösung ist die einzige.
Das Schöne dabei ist: Irgendwann, sofern du dich lange genug ernsthaft 
mit Programmierung beschäftigst, kommst du auch selber drauf und fragst 
dich, was du da vor ein paar Jahren für einen Mist gemacht hast. Sowas 
nennt man dann Erfahrung.
Und ja. Es nervt, sich immer wieder mit diesem Thema auf diesem Niveau 
auseinander zu setzen. Das ist wie mit den LEDs ohne Vorwiderstand.

mfg.

von Stefan S. (kami)


Angehängte Dateien:

Lesenswert?

Hi Leute,

erstmal vielen Dank für die ganzen Idee und Vorschläge. Echt super 
Sachen mit dabei. Ich habe mir die Lösung von  Fabian O. (xfr) 
angeschaut. Die finde ich eigentlich recht logisch und sollte ja für 
meinen Anwendungsfall passen. Ich haben den Schalter so :

http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen

angeschlossen also eine Seite an GND und die andere an den Pin und den 
Pull-Up-Widerstand. Nun ist im Normalfall der Schalter geschlossen und 
deswegen ja das Signal immer LOW oder?

Irgendwie klappt das jetzt nämlich nicht mit der Abfrage. Angehängt mein 
Quellcode dazu.

Vielen DAnk für Hilfe.

Gruß kami

von Paul B. (paul_baumann)


Lesenswert?

Thomas schrob:
>...auch die Buch- und Danneggers.

Das ist eine schöne Formulierung!
:-))

>Die haben das auch nicht mit der Muttermilch aufgesaugt.

Nein, sie sind mit 115200 Baud seriell gefüttert worden....

nicht hauen,*bitte*
;-)
MfG Paul

von Fabian O. (xfr)


Lesenswert?

Stefan S. schrieb:
> Nun ist im Normalfall der Schalter geschlossen und
> deswegen ja das Signal immer LOW oder?

Hast Du das denn vorher nicht ausprobiert, zum Beispiel mit einer LED? 
Wenn Du Dir nicht mal sicher bist, ob die Abfrage des Schalters 
überhaupt funktioniert, bringt es doch nichts gleich Entprellung, Funk 
und Sleepmodus auf einmal einzubauen ...

Ich glaube nicht, dass jemand Lust hat, in dem Wust an zusammenkopierten 
Code jetzt den Fehler (den Du nicht mal beschrieben hast) zu suchen.

Meine Empfehlung wäre, den Code mal Schritt für Schritt aufzubauen und 
zu testen. Erstmal ganz ohne Entprellung nur auf den Taster reagieren 
(LED ein/ausschalten). Dann den Interrupt testen. Dann die Entprellung 
einbauen. Dann das Senden der Funknachricht. Und wenn alles fehlerfrei 
läuft, ganz am Schluss den Sleepmodus.

von (prx) A. K. (prx)


Lesenswert?

Paul Baumann schrieb:
> Nein, sie sind mit 115200 Baud seriell gefüttert worden....

In der Generation fing man mit 1200bd oder maximal 9600bd an. Oder gar 
mit einem 50bd Fernschreiber/Lochstreifen.

von Hannes L. (hannes)


Lesenswert?

Hannes Lux schrieb:
> Interrupter schrieb:
>> Lacher = Interrupter
>
> Gespaltene Persönlichkeit?
> Verfolgungswahn?
> Sockenpuppe?

Erst jetzt, nachdem ich auch den Link weiter oben:

Interrupter schrieb:
> Ich hatte jedenfalls vor etwa 1 Monat eine entsprechende Methode
> implementiert, ausführlich getestet, gut dokumentiert, und mit
> Quelltexten unter Beitrag "Re: AVR Einstieg / Probleme mit Programm Interrupt"
> hier vorgestellt.

verfolgt habe, stelle ich fest, dass wir ab hier:
Beitrag "Re: Verweis auf "Niedrig-Niveau" Forum"
schonmal eine Diskussion hatten, bei der Du Dich von mir ans Bein 
gepisst fühltest. Sorry, zu diesem Zeitpunkt wusste ich nicht, dass Du 
Deine recht untaugliche Entprellung für das Nonplusultra hältst und auf 
(berechtigte) Kritik recht mimosenhaft reagierst. Ich hätte dabei wohl 
nicht so beschwichtigend reagieren sollen...

...

von STK500-Besitzer (Gast)


Lesenswert?

A. K. schrieb:
> In der Generation fing man mit 1200bd oder maximal 9600bd an. Oder gar
> mit einem 50bd Fernschreiber/Lochstreifen.

Wohlgemerkt 1200 zu 75 baud und Telefonhörer... ;)

@Hannes: Danke für den Hinweis mit dem Lowlevel-Niveau-Thread.

von (prx) A. K. (prx)


Lesenswert?

STK500-Besitzer schrieb:
> Wohlgemerkt 1200 zu 75 baud und Telefonhörer... ;)

Ich sehe, wir verstehen uns. ;-)

von STK500-Besitzer (Gast)


Lesenswert?

A. K. schrieb:
> STK500-Besitzer schrieb:
>> Wohlgemerkt 1200 zu 75 baud und Telefonhörer... ;)
>
> Ich sehe, wir verstehen uns. ;-)

Inzwischen auch im Mbit-Bereich ;)

von bitte löschen (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> ypischer Fall von "Anfänger hat das Ei des Kolumbus entdeckt".

Hannes Lux schrieb:
> .., dass Du
> Deine recht untaugliche Entprellung für das Nonplusultra hältst und ..

Das sind wieder Unterstellungen. Ich habe nie behauptet, dass mein Code 
etwas besonders ist. Hier wurde in Gemeinschaftsarbeit ein ganz übles 
Bild von mir gezeichnet, das mir nicht entspricht. Der Gesamteindruck, 
der entsteht, wenn man die betreffenden Threads liest, lässt sich nicht 
mehr korrigieren, eher verschlimmbessern, so dass ich in Zukunft damit 
leben muss, dass mögliche Arbeitgeber o.Ä. nach kurzer Recherche meinen 
Namen mit dieser Katastrophe hier in Verbindung bringen.

Ich habe gerade eine Mail an Andreas geschickt, mit der Bitte, meinen 
Account zu löschen.

von STK500-Besitzer (Gast)


Lesenswert?

Erstmal abwesend schrieb:
> Hier wurde in Gemeinschaftsarbeit ein ganz übles
> Bild von mir gezeichnet, das mir nicht entspricht.

Das nenne ich dann mal eine richtige Unterstellung.

Da hier mehrere Leute unabhängig voneinander zum selben Schluß kommen, 
scheint ja was an der Sache dran zu sein.

Erstmal abwesend schrieb:
> dass mögliche Arbeitgeber o.Ä. nach kurzer Recherche meinen
> Namen mit dieser Katastrophe hier in Verbindung bringen.

Wenn die deine Kommentare lesen, reicht das schon, da braucht niemand 
noch Öl ins Feuer zu gießen.

Das Ursprungsthema dürfte sich inzwischen sowieso erledigt haben.

von Thomas E. (thomase)


Lesenswert?

bitte löschen schrieb:
> so dass ich in Zukunft damit
> leben muss, dass mögliche Arbeitgeber o.Ä. nach kurzer Recherche meinen
> Namen mit dieser Katastrophe hier in Verbindung bringen.
Deine Katastrophe ist, daß du zeigst völlig beratungs- und lernresistent 
zu sein. Sich mal auf dem Holzweg zu befinden, ist absolut nichts 
schlimmes.

mfg.

von m.n. (Gast)


Angehängte Dateien:

Lesenswert?

Ich komme noch einmal auf das eigentliche Thema zurück.

Oben hatte ich in der 'ein_aus_13.c' gezeigt, dass man durchaus per 
PCINT eine Tasterentprellung vornehmen kann. Sofern der Taster nicht 
direkt neben dem µC verbaut ist, ist allein auf Grund der Störsicherheit 
eine RC-Glied (hier 10k + 100nF) notwendig.
Um die Funktion der Schaltung zu verdeutlichen, habe ich zwei Bilder 
angehängt, bei denen die blaue Linie das Signal am µC-Eingang (am 
Kondensator) und das gelbe Signal den erzeugten Rechteck zeigen.

Beim Einschalten sieht man ca. 1,6ms vor dem Triggerpunkt die 
Prellversuche des Tasters, bis die Spannung am Eingang als '0' erkannt 
wird und der Kondensator restlos (und schnell) entladen wird. Das 
Rechtecksignal kommt hier erst etwa 1,2ms nach dem Einschaltvorgang, da 
noch per ADC+Filterung auf gültige Versorgungsspannung geprüft wird.

Beim Ausschalten ist keine zusätzlich Verzögerung notwendig.

von Peter D. (peda)


Lesenswert?

m.n. schrieb:
> Beim Ausschalten ist keine zusätzlich Verzögerung notwendig.

Es gibt Taster, die auch beim Loslassen prellen.

Bei einem älteren Taster kann Staub oder eine Oxydschicht auf den 
Kontakten eine kurzzeitige Unterbrechung verursachen.

Und bei meiner Entprellung spare ich mir eine gesonderte Behandlung von 
Drücken und Loslassen, d.h. weniger und schnellerer Code.


Peter

von m.n. (Gast)


Lesenswert?

Peter Dannegger schrieb:
> m.n. schrieb:
>> Beim Ausschalten ist keine zusätzlich Verzögerung notwendig.
>
> Es gibt Taster, die auch beim Loslassen prellen.

Den Kurven kann man doch entnehmen, dass es beide Male um das Drücken 
des Tasters geht und nicht um das Loslassen und dessen Prellen, was im 
Übrigen völlig unproblematisch ist.

> Und bei meiner Entprellung spare ich mir eine gesonderte Behandlung von
> Drücken und Loslassen,

Wenn Du Dir meine Routine überhaupt einmal angesehen hättest, würdest Du 
nicht so einen Unsinn schreiben.

> d.h. weniger und schnellerer Code.

Was zu beweisen wäre und ein Argument aus der Steinzeit ist.
Nimm einen IAR-Compiler und dann hast Du wenig und schnellen Code.

von Peter D. (peda)


Lesenswert?

@m.n.

Natürlich habe ich gesehen, daß Du eine HW-Entprellung benutzt.

Ich fand nur Deine Formulierung etwas mißverständlich, als ob man das 
Loslassen nicht entprellen müßte und das wollte ich erklären.
Kein Grund, gleich ausfallend zu werden.

Deine HW-Entprellung entprellt (verzögert) das Loslassen ja auch, egal 
ob Du es willst oder nicht.


Peter

von m.n. (Gast)


Angehängte Dateien:

Lesenswert?

Bevor morgen der Weltuntergang kommt, schnell noch zwei Bilder, die das 
Prellen realer Taster zeigen.

Das 1. Bild zeigt die Wellenform direkt am Taster (Schadow digitast, 
vergoldeter Springkontakt) und am µC-Eingang.
Bild 2 zeigt das Prellen eines >15 Jahre alten Installationstasters 
250VAC/10A (Berker) an den gleichen Meßpunkten wie zuvor, der als 
Ersatzteil im Keller gelagert wurde.

Die Interpretation überlassee ich Euch.

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.