Hallo, bin noch relativ neu was arduino angeht. Nutzen in der Schule eine den arduino uno. Ich habe einen Taster der zählt wie oft er gedrückt wird.
Aktuell nehme ich immer den aktuellen Zustand von dem Taster wenn ich das richtig verstehe. Nun soll eine zweite Variante verwendet werden wo ich den letzten Zustand abfragen soll.
Hier auch einmal die Aufgabenstellung:
2. Lösung: Flankenerkennung mit Zustandsvariablen
Statt direkt auf HIGH zu prüfen, speichert man den vorherigen Zustand des Tasters und erkennt die steigende Flanke
Nur habe ich keine Ansatzpunkte dafür und auch nicht wirklich was gefunden bisher.
Danke schonmal im voraus
const int Taster = 4;
int Merker_Taster = 0;
int Merker = 0;
int Taster_Zahl = 0;
void setup()
{
pinMode(Taster, INPUT);
Serial.begin(9600);
}
void loop()
{
Merker_Taster = digitalRead(Taster);
if((Merker_Taster == LOW)&&(Merker == 0))
{
Merker = 1;
Taster_Zahl++;
Serial.print("So oft hab ich gedrueckt");
Serial.println(Taster_Zahl);
}
if((Merker_Taster == HIGH)&&(Merker == 1))
{
Merker = 0;
}
}
Es geht also ums Lernen, daher bin ich etwas pingeliger und liefere Dir keine fertige Lösung, sollst ja selbst drauf kommen
Wie ist der Taster angeschlossen? Ich bin faul, daher verwende ich den internen PullUp-Widerstand und schalte nach GND. Da die steigende Flanke erkannt werden soll, verwendest Du vermutlich einen externen PullDown-Widerstand und schaltest nach +5 V. Richtig?
Eine Konstante zu verwenden, ist gut, aber warum sollte sie 16 Bits lang sein? So viele Pins hat ein UNO nicht und außerdem ist der UNO ein µC mit acht Bits. Daher besser const byte Taster = 4;. Für den optimierenden Compiler ist auch int kein Problem, der macht das trotzdem richtig.
Der Taster kann nur zwei Zustände, "ein" oder "aus", was true und false entspricht. Daher verschwendest Du Speicher, wenn Du das in 16 Bits speicherst. Daher ist der Typ bool passender.
Kann dieser Wert jemals negativ werden, wenn Du immer 1 addierst? Eher nicht, daher wäre unsigned int Taster_Zahl = 0; oder uint16_t Taster_Zahl = 0; passender. Dann kannst Du 216 = 65536 Mal auf den Taster tippen, bevor die Variable überläuft.
Vielen Dank für deine Antwort.
Bin am Anfang der Techniker Schule und ist für mich ein komplett neues Thema.
Den Taster zu PULLUP zu ändern habe ich bereits gemacht. Hatte den Widerstand vorher extern realisiert.
Das mit der Belegung mit dem Taster verstehe ich auch, das ich da eine zu lange Konstante verwende.
Mit den Merker bool verstehe ich auch. Ich habe ja nur die beiden Zustände HIGH und LOW.
Der Wert für den Zähler der kann nicht negativ werden das ist richtig. Also sagt das unsigned int nur aus das ich da kein Vorzeichen habe.
unit16_t heißt dann das ich unsigned int habe was auf 16bit beschränkt ist oder versteh ich das grade flasch?
Wo wäre dann der Unterschied zwischen const byte und const uint8_t? Oder ist das das selbe weil 1 byte sind ja 8 bit.
Mir scheint das ist 98% dessen was du suchst. Die LED kannst ja weg geben. Und die empfohlenen Verbesserungen bezüglich Variablentypen kannst ja trotzdem noch machen.
const uint8_t Taster = 4; // unsigned int mit 8 bit
bool Merker_Taster = LOW;
bool Letzter_Zustand_Taster = LOW;
uint16_t Taster_Zahl = 0; // unsigned int mit 16 bit ist nicht notwendig das wir bei unsigned int sowieso nur 16bit haben
void setup()
{
pinMode(Taster, INPUT_PULLUP);
Serial.begin(9600);
}
void loop()
{
Merker_Taster = digitalRead(Taster);
if(Merker_Taster != Letzter_Zustand_Taster)
{
delay(50);
if(Merker_Taster == HIGH)
{
Taster_Zahl++;
}
Serial.print("So oft hab ich gedrueckt");
Serial.println(Taster_Zahl);
}
Letzter_Zustand_Taster = Merker_Taster; //Aktualisieren des Merkers
}
Hab mir die Sachen mal angeschaut und ein wenig geändert und selber probiert und bin aktuell bei diesem Ergebnis.
if (Merker_Taster != Letzter_Zustand_Taster) {
delay(50);
if (Merker_Taster == HIGH) {
Taster_Zahl++;
}
}
Verstehe leider deinen Punkt nicht oder mein Programm nicht richtig.
Im ersten if Schaue ich ob die beiden Werte die ich miteinander vergleiche nicht gleich sind.
Wenn das der fall ist komme ich zum zweiten if wo geschaut wird ob mein Merker HIGH ist.
Nur dann zähle ich doch. Also wenn der Taster gedrückt wird.
Also so verstehe ich mein Programm aktuell
Ah. Ok, dann mein Fehler. Ich hab die Klammer übersehen da die Einrückung so ulkig war.
Wenn Du jetzt noch das delay() auflöst, dann sieht das nicht so schlecht aus.
Du kannst es weglassen, wenn Du dafür die Routine zum entprellen änderst.
hab ich mal gemacht.
Und den Text berichtigt
const uint8_t Taster = 4; // unsigned int mit 8 bit
bool Merker_Taster = LOW;
bool Letzter_Zustand_Taster = LOW;
uint16_t Taster_Zahl = 0; // unsigned int mit 16 bit ist nicht notwendig das wir bei unsigned int sowieso nur 16bit haben
constexpr uint32_t debounceTime {50}; // Zeit in ms
uint32_t lastSwitchTime; // Merker
void setup()
{
pinMode(Taster, INPUT_PULLUP);
Serial.begin(9600);
}
void loop()
{
if (millis() - lastSwitchTime >= debounceTime)
{
Merker_Taster = digitalRead(Taster);
if (Merker_Taster != Letzter_Zustand_Taster)
{
lastSwitchTime = millis();
if (Merker_Taster == HIGH) // Taste losgelassen
{
Taster_Zahl++; //
}
Serial.print(F("So oft hab ich losgelassen"));
Serial.println(Taster_Zahl);
}
Letzter_Zustand_Taster = Merker_Taster; //Aktualisieren des Merkers
}
}
Man kann natürlich zum Entprellen etwas "ordentliches" nehmen. ( wie @my_xy_projekt gezeigt hat)
Wobei ich denke, bei der aktuellen Aufgabenstellung ist es auch OK, wenn man einfach etwas dagegen unternimmt, dass ein µController generell viel zu schnell ist:
Bei einem richtigen Taster ( statt von Hand zwei Drähte sich berühren lassen ) reicht auch ein delay(5); zum Entprellen.
Ob das nur bei einem Flankenwechsel oder bei jedem Durchlauf dran kommt, ist hier sogar egal.
Aber irgendwas zum Entprellen eines mechanischen Tasters muss sein. Probier's aus.