Forum: Mikrocontroller und Digitale Elektronik Wenn ich 3mal auf den Schalter gedrückt habe.


von Simon N. (ardi)


Lesenswert?

Hi,
ich wollte einen kleinen nützlichen Codeblock einbauen aber ich weiß 
nicht genau wie ich es schreibe:
Wenn ich 3mal angenommen auf einen bestimmten Schalter gedrückt habe 
soll eine LED
angehen.
Habt ihr eine Idee?
Gruß und Danke

von Thomas E. (thomase)


Lesenswert?

Simon Name schrieb:
> Habt ihr eine Idee?
Kannst du bis 3 zählen?
Dann bring deinem Controller bei, das auch zu tun.
Und dann überlegst du dir, was er machen soll, wenn er damit fertig ist.

mfg.

von Udo S. (urschmitt)


Lesenswert?

Simon Name schrieb:
> Habt ihr eine Idee?

Ja

von Simon N. (ardi)


Lesenswert?

Natürlich kann ich bis drei zählen aber es nicht meinem Arduino bei 
bringen weil bei diesem Thema stehe ich auf dem Schlauch: muss ich while 
einsetzen oder for???
Da ich von diesen Befehlen nur die grobe Ahnung wie sie funktionieren 
und was sie bedeuten aber ich kann sie nicht genau anwenden.
So, zufrieden?

von A. F. (elagil)


Lesenswert?

In C vielleicht so, unter der annahme, dass ein drücken einen interrupt 
hervorruft:
1
// ....
2
volatile unsigned int counter = 0;
3
// ....
4
5
6
ISR(PCINT0_vect) {
7
   counter++;
8
   if(counter==3) {
9
      PORTB ^= (1<<PB0); //toggle PB0
10
      counter=0;
11
   }
12
}

oder kürzer:
1
// ....
2
volatile unsigned int counter = 0;
3
// ....
4
5
6
ISR(PCINT0_vect) {
7
   if(++counter==3) {
8
      PORTB ^= (1<<PB0); //toggle PB0
9
      counter=0;
10
   }
11
}

von Simon N. (ardi)


Lesenswert?

Was bedeutet "ISR (PCINT0_vect)"???

von Harald W. (wilhelms)


Lesenswert?

Simon Name schrieb:
> Natürlich kann ich bis drei zählen aber es nicht meinem Arduino bei
> bringen weil bei diesem Thema stehe ich auf dem Schlauch: muss ich while
> einsetzen oder for???
> Da ich von diesen Befehlen nur die grobe Ahnung wie sie funktionieren
> und was sie bedeuten aber ich kann sie nicht genau anwenden.

Ich würde einen Zähler nehmen, auf neudeutsch "counter".
Gruss
Harald

von blub (Gast)


Lesenswert?

Simon Name schrieb:
> Da ich von diesen Befehlen nur die grobe Ahnung wie sie funktionieren
> und was sie bedeuten aber ich kann sie nicht genau anwenden.
Dann wird es Zeit für den Klassiker (KHB wo bist du?): Kernighan & 
Ritchie, Programmieren in C, 2. Edition

Adrian Figueroa schrieb:
> volatile unsigned int counter = 0;
Wenn die Variable nur im Interrupt verwendet wird ist das volatile 
überflüssig.

Simon Name schrieb:
> Was bedeutet "ISR (PCINT0_vect)"???
GCC-Syntax für Interrupts. Keine Ahnung wie das beim Arduino geht.

von Michael (Gast)


Lesenswert?

Simon Name schrieb:
> Hi,
> ich wollte einen kleinen nützlichen Codeblock einbauen aber ich weiß
> nicht genau wie ich es schreibe:

Du hast so ziemlich ALLES vergessen was notwendig ist:
Was genau ist dein Problem?
Die Programmiersprache? Erlerne Sie zunächst, bevor du konkrete 
Eigenaufgaben angehen willst
Die Hardware? Die ist nur dir Bekannt, offensichtlich weißt du darüber 
aber auch nichts, geschweige denn kannst du sie ansteuern.

Nimm einen Counter (74xx4059) und ein paar Und-Gatter und beschalte sie 
entsprechend. Da benötigt es keinen Code (denn davon hast du keine 
Ahnung)

MFG

von blub (Gast)


Lesenswert?

Mal nebenbei bemerkt, bei der Version von Adrian Figueroa fehlt jede Art 
von Entprellung...

von Simon N. (ardi)


Lesenswert?

Ich sollte vielleicht noch hinzufügen dass ich es mit dem Arduino 
vorhabe.

von A. F. (elagil)


Lesenswert?

die "ISR" ist eine Funktion, die aufgerufen wird, wenn ein Interrupt 
ausgelöst wird (etwa durch die Reaktion auf die Änderung eines PINs oder 
von einem Timer), wobei "PCINT0_vect" für eine Zustandsänderung der 
zuvor als "überwacht" festgelegten PINs steht. Dabei ist PCINT0 nicht 
etwa ein einzelner Pin, sondern die Zusammenfassung all derer, die du 
vorher zum Abfragen eingeschaltet hast. Die von mir vorgegebene Funktion 
schaltet bei jedem Ändern des Zustandes am Eingangspin, deswegen ist sie 
für dich gerade nicht geeignet, sie zählt auch das loslassen des 
schalters mit (und ein schwingen des schalters (--> 
http://arduino.cc/en/Tutorial/Debounce ):

Dass du mit Arduino arbeitest, hatte ich nicht gesehen, dazu gibt es was 
leichteres:

http://arduino.cc/en/Reference/AttachInterrupt

von Patrick (Gast)


Lesenswert?

Simon Name schrieb:
> Da ich von diesen Befehlen nur die grobe Ahnung wie sie funktionieren
> und was sie bedeuten aber ich kann sie nicht genau anwenden.

Hmm... In diesem Falle: Wie wäre es damit, sich mit der Bedeutung dieser 
Befehle vertraut zu machen, sprich: Zu lernen, was diese bedeuten? Ich 
denke nicht, dass die Sprache C so komplex ist, dass man das nur mit 
Habilitation begreifen kann...
Zu meiner Zeit gab es so zusammengetüddeltes Papier mit schwarzen 
Hieroglyphen drauf - nannte sich wohl Buch bzw. Bücher. Aber heutzutage 
sollte eine einfache Google-Suche reichen, um ein C-Tutorial bzw. eine 
-Referenz zu finden...

von Peter D. (peda)


Lesenswert?

Simon Name schrieb:
> Natürlich kann ich bis drei zählen aber es nicht meinem Arduino bei
> bringen weil bei diesem Thema stehe ich auf dem Schlauch: muss ich while
> einsetzen oder for???

Man nehme eine Variable, ein +1 und ein if.

von Simon N. (ardi)


Lesenswert?

void setup () {
  Serial.begin(9600);
  pinMode(2, INPUT);
  pinMode(13, OUTPUT);

}

void loop() {
  int Schalter;
  Schalter=digitalRead(2);
  Serial.println(Schalter, DEC);
  int zeahler=0;

  if(digitalRead(Schalter)==HIGH){
    zeahler++;
  }
    if(zeahler==3){
      digitalWrite(13, HIGH);
      delay(300);
      digitalWrite(13, LOW);
}
}

Mein Code aber er funktioniert nicht.

von blub (Gast)


Lesenswert?

Da fehlt die Hälfte. Wie/Wo wird loop aufgerufen? Wenn das ganze 
mehrfach funktionieren soll muss noch eine Schleife drum. Und wenns in 
einer Extrafunktion ist die ständig aufgerufen wird muss die Variable 
static sein...

von Simon N. (ardi)


Lesenswert?

Ich möchte nicht unhöfflich sein aber ich komme nicht ganz mit.
Bitte vielleicht einbisschen genauer.

von A. F. (elagil)


Lesenswert?

doch doch, der funktioniert, die schleife läuft aber auf deinem 16Mhz 
prozessor ziemlich schnell! wenn du den schalter gedrückt hälst, zählt 
der zähler hoch und ist nur sehr kurz bei "3". du kannst ja noch einen 
delay einbauen:

du brauchst nicht zweimal den taster abzufragen.
1
void setup () {
2
  Serial.begin(9600);
3
  pinMode(2, INPUT);
4
  pinMode(13, OUTPUT);
5
6
}
7
8
void loop() {
9
  int Schalter=digitalRead(2);
10
  Serial.println(Schalter, DEC);
11
  int zeahler=0;
12
13
  if(Schalter==HIGH){
14
    zeahler++;
15
  }
16
    if(zeahler==3){
17
      digitalWrite(13, HIGH);
18
      delay(300);
19
      digitalWrite(13, LOW);
20
    }
21
  delay(200);
22
}

von dein Lehrer (Gast)


Lesenswert?

Lese mal das Buch

Kernighan &  Ritchie, Programmieren in C

von Stryker_2k (Gast)


Lesenswert?

@Simon: Fehlt da nicht generell etwas drumherum was zunächst setup() und 
dann in einer Endlosschleife loop() aufruft?

Oder nimmt das der Arduino einem ab? Ich kenne mich leider nur mit 
echtem C aus...

von Simon N. (ardi)


Lesenswert?

Bei mir geht es leider nicht????
Geht es bei dir?

von Simon N. (ardi)


Lesenswert?

Es gibt ja einmal einen Void Setup und dann einen Void Loop

von Thomas E. (thomase)


Lesenswert?

Simon Name schrieb:
> So, zufrieden?
Nein.
Wie willst du programmieren, wenn du nicht einmal weisst, wie man eine 
Variable hochzählt und dass Ergebnis abfragt?
Deshalb hörst du erstmal auf deinen Lehrer:

while(!Ahnung)
{
  dein Lehrer schrieb:
  > Lese mal das Buch
}
mfg.

von Simon N. (ardi)


Lesenswert?

Ja was while ist weiß ich schon aber sorry wenn ich es doch nicht so 
genau anwenden kann

von A. F. (elagil)


Lesenswert?

entschuldige, ich habe einen fehler übersehen. du setzt in dem code bei 
jedem durchlauf den counter auf 0. setz die initialisierung nach setup.
1
int zeahler=0;
2
3
void setup () {
4
  Serial.begin(9600);
5
  pinMode(2, INPUT);
6
  pinMode(13, OUTPUT);
7
}
8
9
void loop() {
10
  int Schalter=digitalRead(2);
11
  
12
  if(Schalter==1){
13
    zeahler++;
14
    delay(200);
15
  }
16
    if(zeahler==3){
17
      digitalWrite(13, HIGH);
18
      delay(300);
19
      digitalWrite(13, LOW);
20
    }
21
}

von dein Lehrer (Gast)


Lesenswert?

Simon Name schrieb:
> Ja was while ist weiß ich schon aber sorry wenn ich es doch nicht so
> genau anwenden kann

Wenn du in ein paar Jahren mal den Führerschein machen willst, wirst du 
doch auch nicht in der ersten Minute losfahren dürfen, weil du schon 
weißt, wie man die Hupe betätigt.
Du mußt vorher lernen, wozu das Lenkrad und die drei Pedale gut sind.

von Simon N. (ardi)


Lesenswert?

Super, Danke Adrian, jetzt funktioniert es.

von Simon N. (ardi)


Lesenswert?

Hör mal vielleicht habe ich in Arduinosprache bzw. C noch nciht so eine 
Große Ahnung aber in anderen vielleicht schon und wenn ich mal nicht 
weiter weiß darf ich doch in einem Forum fragen und nicht gleich 
runtergeputzt werden

von MaWin (Gast)


Lesenswert?

> unter der annahme, dass ein drücken einen interrupt hervorruft:

Bitte liebe Kinder macht das nicht, denn Taster prellen und ein uC macht 
daraufhin dutzende von Interrupts. Man erfasst Tster NIEMALS mit 
Interrupts.

Ausserdem: Wie lange dürfen denn die 3 Tastendrücke auseinanderliegen ? 
Jeden Tag einer ? Nicht vielleicht in 10 Sekunden alle 3 ?
1
#define TASTER 2
2
main()
3
{
4
  char taster;
5
  int dauer;
6
  char letzter=digitalRead(TASTER);
7
  while(1)
8
  {
9
    char dieser=digitalRead(TASTER);
10
    if(dieser&&!letzter) 
11
    {
12
      taster++;
13
      if(taster==3)
14
      {
15
        // mach das was du bei 3 Tastendrücken willst
16
        taster=0;
17
        dauer=0;
18
      }
19
    }
20
    letzter=dieser;
21
    delay(10); // länger als die Prellzeit
22
    if(taster>0)
23
    {
24
      dauer++;
25
      if(dauer>1000) /7 1000 x 10msec = 10 sec
26
      {
27
        taster=0;
28
        dauer=0;
29
      }
30
    }
31
 }
32
}

von Simon N. (ardi)


Lesenswert?

Wieso? was ist daran so schlimm?
Geht da mein Computer bzw. Arduino kaputt 0_o :)

von A. F. (elagil)


Lesenswert?

> Man erfasst Tster NIEMALS mit Interrupts.

ich kann doch nicht die ganze zeit meine taster abfragen, während etwas 
anderes gemacht wird, der taster aber trotzdem eine funktion haben 
soll...

von Eumel (Gast)


Lesenswert?

Adrian Figueroa schrieb:
> ich kann doch nicht die ganze zeit meine taster abfragen, während etwas
> anderes gemacht wird, der taster aber trotzdem eine funktion haben
> soll...

Deswegen macht man das nebenbei in einem Timer Interrupt.
Interrupts und Taster sind idr. nur sinnvoll um einen Controller 
aufzuwecken.

von A. F. (elagil)


Lesenswert?

> Deswegen macht man das nebenbei in einem Timer Interrupt.

Der Timer interrupt ist ja sehr kurz, dann muss ich ja so kleine 
abtastabstände nehmen, dass die "drückzeit" des schalters höher ist 
(100ms vielleicht).. da kommt ja auch eine menge zusammen

von Eumel (Gast)


Lesenswert?

Adrian Figueroa schrieb:
> Der Timer interrupt ist ja sehr kurz, dann muss ich ja so kleine
> abtastabstände nehmen, dass die "drückzeit" des schalters höher ist
> (100ms vielleicht).. da kommt ja auch eine menge zusammen

Nein, da kommt keine Menge zusammen.
Man nimmt z.b. einen Timer interrupt alle 50 ms, wenn der Taster in 
diesem Interrupt 3 mal hintereinander gedrückt ist kann man davon 
ausgehen, dass er auch wirklich gedrückt ist und nicht prellt. Dann 
setzt du ein Flag das du dann in deinem Hauptprogramm auswertest.
Das alles frisst vielleicht 0.5% der Rechenzeit deines Controllers. Wohl 
eher noch weniger. Das tolle daran ist auch, dass man (fast) beliebig 
viele Taster verwenden kann.

von MaWin (Gast)


Lesenswert?

> ich kann doch nicht die ganze zeit meine taster abfragen

Du vielleicht nicht, gute Programmierer aber schon.
Timer ist zwar eine Methode aber nicht die einzige.

> dann muss ich ja so kleine abtastabstände nehmen,
> dass die "drückzeit" des schalters höher ist

Natürlich. Für einen uC ein Klacks. Lernt programmieren.

von cppler (Gast)


Lesenswert?

Es gibt hier C-Tutorials über Entprellung, das ist ganu das was Du 
brauchst.
Mit den Arduino-Bibliotheken kenne ich mich nicht aus, aber die "loop" 
dürfte der Endlosschleife im main entsprechen.
http://www.mikrocontroller.net/articles/Entprellung#Warteschleifen-Verfahren
Das Prinzip ist einfach, der Timer läuft vor sich hin und wenn eine 
Taste länger als eine vorgegebene Zeit High-Wert hat wird sie in einer 
volatilen globalen Variable gespeichert.
In Deiner loop() wertest Du un diese globale Variable aus und zählst 
eine lokale variable hoch und prüfst ob sie dreimal, viernal usw. erhöht 
wurde.

von Thomas E. (thomase)


Lesenswert?

Adrian Figueroa schrieb:
> Der Timer interrupt ist ja sehr kurz, dann muss ich ja so kleine
> abtastabstände nehmen, dass die "drückzeit" des schalters höher ist
> (100ms vielleicht).. da kommt ja auch eine menge zusammen
Taster werden 1000 Mal pro Sekunde abgefragt. Wenn sich ein Tastzustand 
geändert hat, lässt man ihn für ein paar Millisekunden in Ruhe. Das 
nennt man Entprellen. Und der arme µC macht das klaglos mit. Im 
Gegenteil. Der freut sich sogar. Sonst würden ihm nämlich irgendwann vor 
lauter Langeweile die Pins abfaulen.

Und nur dadurch bekommt er wirklich jeden Tastendruck mit. Denn die 
reine Abfrage eines Tasters dauert nur einen Prozessortakt. Egal wie oft 
oder selten man das macht. Mit Delays und Interrupts schafft man sich 
erst richtige Probleme. Der einzige Einsatzzweck  eines Tasters mit 
Interrupt ist das Aufwecken aus dem Sleepmode. Aber auch nur dafür. Der 
erste Befehl nach dem Sleep lautet dann PCICR = 0.
Und dann geht es mit der ganz normalen Entprellung weiter.

mfg.

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.