Forum: Mikrocontroller und Digitale Elektronik Schalter entprellen Arduino


von Raj (Gast)


Lesenswert?

Nabend zusammen,

ich bin momentan auf ein Problem gestoßen bei dem ich irgendwie nicht 
weiter komme und zwar habe ich bei meinen bisherigen Projekten bei denen 
ich Taster zur Eingabe verwendet habe immer eine Entprell Routine 
verwendet bei der ich auch gedrückt gehaltene Tasten auslesen kann.
Ich hänge unter diese Nachricht einmal den Code den ich immer wieder 
verwende, dieser wird dann nur mit den Tasten angepasst.

Nun habe ich bei einem neuen Projekt einen StufenSCHALTER! mit 4 Stufen 
die ich auch gerne entprellt hätte. Dafür habe ich dann wie immer meine 
Entprell Routine genommen. Aber ich bin da jetzt auf ein Problem 
gestoßen welches beim EINSCHALTVORGANG auftritt. Und zwar wenn ich die 
Schaltung in Betrieb nehme, dann wird der aktuelle gedrückte 
Schalterzustand nicht aufgenommen und kann dann auch nicht ausgewertet 
werden.

Sobald ich den Schalter einmal in der Position verändere funktioniert 
es.

Nun eine Frage an Euch sollte ich für dieses Vorhaben da in meiner 
Taster Entprellroutine rumpfuschen oder lieber anders lösen?

Ich habe es noch nicht geschafft den Code so anzupassen das im 
Einschaltvorgang auch der richtige ausgewählte Schaltzustand erkannt 
wird.

Vielleicht könnte mir da jemand helfen.

Viele Grüße, Raj


1
/*
2
3
Anleitung:
4
5
1. Im Array "buttonPins" die Pins eintragen, an denen jeweils ein Taster hängen soll. (Index 0 = Taste 1)
6
2. Entprellzeit festlegen.
7
3. Die zweite ENUM-Liste an die Anzahl der Tasten anpassen.
8
4. Halteaktionen für das gedrückt halten mehrerer Tasten selbst definieren.
9
10
*/
11
12
#include <Bounce2.h>
13
14
#define INPUTMODE INPUT_PULLUP            // INPUT oder INPUT_PULLUP
15
byte buttonPins[] = {                     // Pin-Nummern der angeschlossenen Buttons
16
  2, 3, 4, 5, 6, 7};
17
#define NUMBUTTONS sizeof(buttonPins)     // Die Anzahl der Tasten durch die Anzahl der Bytes des Arrays buttonPins ermitteln (wird automatisch definiert)
18
19
Bounce debouncer[NUMBUTTONS];             // Mehrere Bounce-Instanzen erstellen
20
21
boolean buttonState[NUMBUTTONS];          // Speichert den aktuellen HIGH/LOW Status der Pins
22
byte buttonChange[NUMBUTTONS];            // Speichert die Zustandswechsel an den Pins
23
24
enum{
25
  UNCHANGED, PUSH, RELEASE};
26
27
byte buttonPressCount;                    // Speichert wie viele Tasten gleichzeitig gedrückt gehalten werden
28
29
byte buttonAction;                        // Gibt an, für welche Einzeltaste eine Aktion ausgelöst wird.
30
31
enum {
32
  NOACTION,                                                    // Index 0 = unbelegt/ keine Aktion
33
  BUT1PUSH, BUT2PUSH, BUT3PUSH, BUT4PUSH, BUT5PUSH, BUT6PUSH,  // Index 1 bis (NUMBUTTONS) = EinzeltastendruckAktionen
34
  BUT1HOLD, BUT2HOLD, BUT3HOLD, BUT4HOLD, BUT5HOLD, BUT6HOLD,  // Index (NUMBUTTONS + 1) - (NUMBUTTONS + NUMBUTTONS) = EinzeltastenHalteAktionen
35
  BUT12HOLD};                                                  // Selbst zu definierende MehrfachtastenHalteAktionen
36
37
38
void eingabe()  // Tastenpins auslesen und deren Status mit buttonState und buttonChange an die Verarbeitung übergeben (Reicht bereits für einfachste Anwendungen)
39
{
40
  memset(buttonChange,0,sizeof(buttonChange));         // Alle alten Zustandswechsel verwerfen (buttonChange wird deshalb komplett mit Nullen überschrieben)
41
  for(int i = 0; i < NUMBUTTONS; i++)
42
  {
43
    debouncer[i].update();   // Status prüfen
44
    if(debouncer[i].fell())  // Wenn die Taste gedrückt wird
45
    {
46
      buttonChange[i] = PUSH;
47
      buttonState[i] = 1;
48
    }
49
    if(debouncer[i].rose())  // Wenn die Taste losgelassen wird
50
    {
51
      buttonChange[i] = RELEASE;
52
      buttonState[i] = 0;
53
    }
54
  }
55
}
56
57
58
59
void verarbeitung()
60
{
61
  static boolean buttonActionCheck;     // Hält fest, ob bereits eine EinzelTastenaktion stattgefunden hat (0= noch keine Aktion, 1= Aktion fand bereits statt)
62
  static unsigned long buttonPushTime;  // Gibt den Zeitpunkt an, wann zuletzt eine Taste gedrückt wurde
63
  static boolean actionsBlocked;        // Gibt an, ob weitere Aktionen unterbunden werden sollen
64
65
  if(!buttonPressCount)       // Sobald keine Taste mehr gedrückt gehalten wird
66
  {                           // Dieser if-Block (inkl. memset) bildet den Abschluss des eigentlichen Codes
67
    buttonActionCheck = 0;    // Reset
68
    buttonPressCount = 0;     // Reset
69
    actionsBlocked = 0;       // Reset
70
  }
71
  buttonAction = NOACTION;    // AktionsByte zurücksetzen damit die letzte Aktion nicht mehrmals ausgelöst wird.
72
73
  for(int i = 0; i < NUMBUTTONS; i++)
74
  {
75
    if(buttonChange[i] == 1)  // Taste wurde gedrückt
76
    {
77
      if(buttonPressCount < NUMBUTTONS) buttonPressCount++;  // Wenn die Taste gedrückt wird, die Anzahl der gleichzeitig gedrückt gehaltenen Tasten inkrementieren.
78
      buttonPushTime = millis();                             // Den Zeitpunkt festhalten, wann eine Taste gedrückt wurde 
79
      if(!buttonActionCheck)                                 // Wenn noch keine Aktion für das drücken einer Taste ausgelöst wurde
80
      {
81
        buttonActionCheck++;   // Aktionszähler inkrementieren
82
        buttonAction = i + 1;  // Aktion (im weiteren Verlauf des Sketchs) auslösen (0 = keine Aktion)
83
      }
84
    }
85
86
    if(buttonChange[i] == 2)  // Taste wurde losgelassen
87
    {
88
      if(buttonPressCount) buttonPressCount--;  // Wenn die Taste losgelassen wird, die Anzahl der gleichzeitig gedrückt gehaltenen Tasten dekrementieren.
89
      actionsBlocked = 1;                       // Sorgt dafür, dass keine Tastenaktionen mehr ausgeführt werden können.
90
    }
91
92
    if(!actionsBlocked)
93
    {
94
      if(millis() - buttonPushTime >= 1200)
95
      {
96
        if(buttonState[i] && buttonPressCount == 1)  // Halteaktionen der einzelnen Tasten
97
        {
98
          buttonAction = i + NUMBUTTONS + 1;   // Aktion (im weiteren Verlauf des Sketchs über ENUM) auslösen (s.o. ENUM-Liste)
99
          actionsBlocked = 1;                  // Sorgt dafür, dass keine Tastenaktionen mehr ausgeführt werden können.
100
        }
101
        if(buttonState[0] && buttonState[1] && buttonPressCount == 2)  // Definierte Halteaktion für mehrere Tasten
102
        {
103
          buttonAction = BUT12HOLD;
104
          actionsBlocked = 1;         // Sorgt dafür, dass keine Tastenaktionen mehr ausgeführt werden können.
105
        }
106
      }
107
    }
108
  }
109
}
110
111
112
113
void ausgabe()
114
{
115
  if(buttonAction == BUT1PUSH) Serial.println(F("BUT1PUSH"));
116
  if(buttonAction == BUT2PUSH) Serial.println(F("BUT2PUSH"));
117
  if(buttonAction == BUT3PUSH) Serial.println(F("BUT3PUSH"));
118
  if(buttonAction == BUT4PUSH) Serial.println(F("BUT4PUSH"));
119
  if(buttonAction == BUT5PUSH) Serial.println(F("BUT5PUSH"));
120
  if(buttonAction == BUT6PUSH) Serial.println(F("BUT6PUSH"));
121
122
  if(buttonAction == BUT1HOLD) Serial.println(F("BUT1HOLD"));
123
  if(buttonAction == BUT2HOLD) Serial.println(F("BUT2HOLD"));
124
  if(buttonAction == BUT3HOLD) Serial.println(F("BUT3HOLD"));
125
  if(buttonAction == BUT4HOLD) Serial.println(F("BUT4HOLD"));
126
  if(buttonAction == BUT5HOLD) Serial.println(F("BUT5HOLD"));
127
  if(buttonAction == BUT6HOLD) Serial.println(F("BUT6HOLD"));
128
129
  if(buttonAction == BUT12HOLD) Serial.println(F("BUT12HOLD"));
130
 
131
  static unsigned long lasttime;
132
  if(millis() - lasttime >= 1000)
133
  {
134
    Serial.print(F("\t\t\tAnzahl gedrueckt gehaltener Tasten: "));
135
    Serial.println(buttonPressCount);
136
    lasttime = millis();
137
  }
138
}
139
140
141
142
void setup()
143
{
144
  Serial.begin(9600);
145
  for(int i = 0; i < NUMBUTTONS; i++)
146
  {
147
    pinMode(buttonPins[i], INPUTMODE);
148
    debouncer[i].attach(buttonPins[i]);
149
    debouncer[i].interval(10);
150
  }
151
}
152
153
154
155
void loop()
156
{
157
  eingabe();
158
  verarbeitung();
159
  ausgabe();
160
}

von Christian B. (cb1969)


Lesenswert?

In der Setup-Routine die Pins einlesen und daraus die Schalterstellung 
ableiten.
Ab da weiter mit Deiner Routine ...

von HildeK (Gast)


Lesenswert?

Raj schrieb:
> Ich habe es noch nicht geschafft den Code so anzupassen das im
> Einschaltvorgang auch der richtige ausgewählte Schaltzustand erkannt
> wird.

Lies doch einfach im 'Setup' ganz primitiv den Zustand der 
Schalterstellung ein und besetze vor.

von Raj (Gast)


Lesenswert?

HildeK schrieb:
> Lies doch einfach im 'Setup' ganz primitiv den Zustand der
> Schalterstellung ein und besetze vor.

Christian B. schrieb:
> In der Setup-Routine die Pins einlesen und daraus die Schalterstellung
> ableiten.
> Ab da weiter mit Deiner Routine ...


Ach mist ich habe eben gerade gesehen das ich den Text gar nicht 
abgeschickt hatte -.-
Ich habe quasi beim Start der Loop eine Sequenz eingeführt die mir 
einmal ausgibt welche Schalter gedrückt sind.

Meintet ihr beiden das mit der "Setup" Routine?
Das scheint auf Anhieb erstmal zu funktionieren die Frage wäre nun eher 
ob ich das damit elegant gelöst habe?! ;)

1
// Schalterzustände beim Erststart
2
if (digitalRead(2) == 0){
3
  Serial.println(F("Schalter Position 1"));
4
}
5
if (digitalRead(3) == 0){
6
  Serial.println(F("Schalter Position 2"));
7
}
8
if (digitalRead(4) == 0){
9
  Serial.println(F("Schalter Position 3"));
10
}

von Raj (Gast)


Lesenswert?

So ich wollte das insgesamt noch ein bisschen "schöner" schreiben und 
wollte mal ein Switch Case ausprobieren. Aber irgendwie funktioniert das 
nicht richtig. Wenn ich das Switch Case so verwende:
1
for (int i = 0; i < 3; i++){
2
  //Debug
3
  //Ausgabe buttonPins[x] = x | digitalRead(buttonPins[x] = x 
4
  Serial.print(F("buttonPins[")); Serial.print(i); Serial.print(F("] = ")); Serial.print(buttonPins[i]);
5
  Serial.print(F(" | digitalRead(buttonPins[")); Serial.print(i); Serial.print(F("] = ")); Serial.println(digitalRead(buttonPins[i]));
6
7
8
    if (digitalRead(buttonPins[i] == 0)){
9
      switch (i){
10
      case 0: Serial.println(F("Schalter Position 1")); break;
11
      case 1: Serial.println(F("Schalter Position 2")); break;
12
      case 2: Serial.println(F("Schalter Position 3"));break;
13
      default: break;
14
    }
15
    }
Dann bekomme ich immer alle 3 Cases angezeigt?! Aber das 
digitalRead(buttonPins[i] liefert nur EIN mal eine '0' wo mache ich denn 
da den Fehler ?
meine 3 einzelnen Schalterabfragen haben immer nur einen Schalterzustand 
ausgegeben.

Was mache ich falsch?
Gruß Raj
1
// Schalterzustände beim Erststart
2
if (digitalRead(2) == 0){
3
  Serial.println(F("Schalter Position 1"));
4
}
5
if (digitalRead(3) == 0){
6
  Serial.println(F("Schalter Position 2"));
7
}
8
if (digitalRead(4) == 0){
9
  Serial.println(F("Schalter Position 3"));
10
}


*******QUELLCODE*******
1
//Test des Switch Case
2
int z=1;
3
switch (z){
4
      case 0: Serial.println(F("z=0")); break;
5
      case 1: Serial.println(F("z=1")); break;
6
      case 2: Serial.println(F("z=2"));break;
7
      default: break;
8
    }
9
10
11
for (int i = 0; i < 3; i++){
12
  //Debug
13
  //Ausgabe buttonPins[x] = x | digitalRead(buttonPins[x] = x 
14
  Serial.print(F("buttonPins[")); Serial.print(i); Serial.print(F("] = ")); Serial.print(buttonPins[i]);
15
  Serial.print(F(" | digitalRead(buttonPins[")); Serial.print(i); Serial.print(F("] = ")); Serial.println(digitalRead(buttonPins[i]));
16
17
18
    if (digitalRead(buttonPins[i] == 0)){
19
      switch (i){
20
      case 0: Serial.println(F("Schalter Position 1")); break;
21
      case 1: Serial.println(F("Schalter Position 2")); break;
22
      case 2: Serial.println(F("Schalter Position 3"));break;
23
      default: break;
24
    }
25
    }
26
  delay(3000);

*******AUSGABE*******
1
z=1
2
buttonPins[0] = 2 | digitalRead(buttonPins[0] = 0
3
Schalter Position 1
4
buttonPins[1] = 3 | digitalRead(buttonPins[1] = 1
5
Schalter Position 2
6
buttonPins[2] = 4 | digitalRead(buttonPins[2] = 1
7
Schalter Position 3

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.