Hallo Forum,
ich bin gerade am Programmieren eines Arduinos.
An diesen habe ich ein Display angeschlossen und einen Taster.
Folgendes soll geschehen:
1) SOLANGE der Taster NICHT betätigt wird, soll am Display etwas
("Drück mich") angezeigt werden (das tut er auch korrekt).
2) SOLANGE der Taster (Schließer) gedrückt gehalten wird, soll auf dem
Display "HALLO" angezeigt werden.
3) SOBALD der Taster losgelassen wird, soll für 5 sec. auf dem Display
"losgelassen" erscheinen. Anschließend soll zu 1) zurückgekehrt werden
und gewartet werden, bis wieder der Taster gedrückt/gehalten wird und
das Spiel beginnt von Neuem.
Ich dachte mir, eine "Flankenerkennung" (from HIGH to LOW) zu nutzen, um
das Loslassen des Tasters zu detektieren. Allerdings weiß ich nicht, ob
es dies beim Arduino überhaupt gibt. Ansonsten weiß ich nicht, wie ich
es realisieren könnte.
Zum momentanen Verhalten des Arduinos:
- Im nicht-gedrückten Zustand zeigt er im Display "Drück mich" an.
-Passt!
- Halte ich den Taster gedrückt, zeigt er auch "HALLO" an, solange ich
den Taster gedrückt halte. -Passt!
- Lasse ich den Taster los, erscheint nur "manchmal" für 5 sec.
"losgelassen". Dies ist völlig willkürlich. Manchmal zeigt er
"losgelassen", manchmal kehrt er nach dem Loslassen direkt wieder zu
"Drück mich" zurück.
Hier der Code:
1
loop()
2
{
3
...
4
printDrueckMich();
5
6
if(digitalRead(2)==HIGH)
7
{
8
display.clearDisplay();
9
display.setTextSize(2);
10
display.setCursor(10,10);
11
display.println("HALLO");
12
display.display();
13
14
if(digitalRead(2)==LOW)
15
{
16
display.clearDisplay();
17
display.setTextSize(2);
18
display.setCursor(10,10);
19
display.println("losgelassen");
20
21
display.display();
22
delay(4000);
23
}
24
}
25
}
Frage:
- Ist mein Code eventuell fehlerhaft?
- Gibt es eine Flankenerkennung beim Arduino?
Gruß & Danke
B.
Das Problem ist, wie ich abfrage, ob direkt VOR dem Loslassen des
Tasters der Taster gedrückt gehalten wurde.
Schreibe ich nämlich die LOW-If-Anweisung außerhalb der
HIGH-If-Anweisung, wird mir das "Drück mich" nie angezeigt, da ich ja
dann den Taster nicht drücke und somit der Dig.Eingang LOW ist und er
immer in die LOW-If-Anweisung springt.
Habe irgendeinen Denkfehler..
Lagere wenigstens das Unnötige aus. Und definiere fixe Werte global am
Anfang, so hast es später viel einfacher wenn das Programm mal grösser
werden sollte. Anpassungen sind dann viel schneller gemacht. Auch an
eine Namenskonvention musst Du dich gewöhnen.
Beispiel:
1
constintiButtonPin=2;
2
constintiTextSize=2;
3
constintiCursorX=10;
4
constintiCursorY=10;
5
boolbButtonFlag=false;
6
7
voidloop()
8
{
9
printDrueckMich();
10
11
if(digitalRead(iButtonPin)==HIGH)
12
{
13
PrintFunc("HALLOOOO");
14
bButtonFlag=true;
15
}
16
else
17
{
18
if(bButtonFlag==true)
19
{
20
PrintFunc("losgelassen");
21
delay(4000);
22
bButtonFlag=false;
23
}
24
}
25
}
26
27
voidPrintFunc(StringstrText)
28
{
29
display.clearDisplay();
30
display.setTextSize(iTextSize);
31
display.setCursor(iCursorX,iCursorY);
32
display.println(strText);
33
display.display();
34
}
Für die harten uC Jungs ist das immer noch Murks, aber egal.
Wird gemacht, danke für den Tipp.
Jetzt habe ich aber noch ein anderes Problem:
Während des Tasterdrückens sollen von einem Analogeingang (Sensor) Werte
eingelesen werden, die in ein int.-Array mit 200 Elementen geschrieben
werden sollen.
Wird der Taster losgelassen, soll ein Mittelwert aus diesen gebildet
werden und dieser auf dem Display ausgegeben werden. Anschließend wieder
in den "warte auf Tastendruck"-Screen gewechselt werden.
Wieso komme ich nicht in die IF-Anweisung (i == 199)?
Ich dachte, ich brauche keine Schleife in der besagten IF-Anweisung, da
die IF-Anweisung ja sowieso solange durchlaufen wird, solange ich den
Taster drücke und dies ja quasi wie eine Schleife durch die Loop vom
Arduino außen herum funktionieren sollte?!
Ich habe den folgenden Code entsprechend kommentiert, wie es
funktionieren SOLLTE aber nicht tut:
1
loop()
2
{
3
...
4
if((digitalRead(2)==HIGH)&&(array_filled==0))
5
{
6
display.clearDisplay();
7
display.setTextSize(2);
8
display.setCursor(10,10);
9
display.println("HALLO");
10
display.display();
11
tasterFlag=1;
12
13
wertereihe[i]=readSensor();
14
if(i==199)// Warum geht er hier nicht rein?
15
{// wenn allen Elementen im Array "wertereihe" Werte zugewiesen wurden...
16
display.clearDisplay();
17
display.setTextSize(2);
18
display.setCursor(10,10);
19
display.println("STOP!");
20
array_filled=1;// setze Flag, dass "wertereihe" befüllt ist.
21
display.display();
22
delay(3000);
23
}
24
i++;// erhöhe Zählvariable für "wertereihe" um jeweils 1
25
}
26
27
if((tasterFlag==1)&&(digitalRead(2)==LOW))// nachdem Taster losgelassen wurde...
28
{
29
display.clearDisplay();
30
display.setTextSize(2);
31
32
display.setCursor(3,8);
33
display.println("Berechnung");
34
display.setTextSize(1);
35
display.setCursor(3,25);
36
display.println("des Mittelwerts...");
37
display.display();
38
delay(2000);
39
40
41
display.clearDisplay();
42
display.setTextSize(1);
43
display.setCursor(3,25);
44
45
for(i=0;i<200;i++)//... soll der Mittelwert aus "wertereihe" berechnet werden
46
{
47
if(wertereihe[i]!=0)// Überprüfen, ob Elemente von "wertereihe" = 0 sind..
Nachtrag:
Zählvariable "i" (int) wurde außerhalb der loop() global mit 0
initialisiert,
Die Variable "y" (int) wurde außerhalb der loop() global mit 200
initialisiert.
überleg mal, was mit dem 'i' passiert, wenn Du den gesamten Ablauf im
Kopf komplett durchgehst. Immer daran denken, es wird immer der gesamte
Loop durchlaufen.
Bis i voll ist vergehen 600s, ist das so gewollt, dass Du so lange den
Schalter drücken musst oder nicht zuende gedacht?
(9.95 min).
Generell: Nimm Berechnungen ausserhalb vor, benutze Tasterfunktionen
nur für die Anzeige.
>überleg mal, was mit dem 'i' passiert, wenn Du den gesamten Ablauf im>Kopf komplett durchgehst.
Also, in meinen Worten:
- sobald der Taster gedrückt wird, wird in die erste If-Anweisung
gesprungen
- solange dieser gedrückt wird, durchläuft er die If-Anweisung, weist
dem Array die gew. Analogwerte zu und inkrementiert "i"
- sobald "i" == 199, soll er in die if(i == 199)
- das Flag "array_filled" wird gesetzt, sodass keine weiteren Werte
mehr ins Array geschrieben werden sollen
- wird VOR Erreichen von i = 199 der Taster losgelassen, soll in die
zweite If-Anweisung "if((tasterFlag == 1) && (digitalRead(2) == LOW))"
gesprungen werden.
(ich sehe gerade, dass ich array_filled" in der zweiten If-Anweisung am
Ende nicht auf 0 setze)
- In der zweiten IF-Anweisung soll dann der Mittelwert aus dem Array
gebildet und am Display ausgegeben werden
>Immer daran denken, es wird immer der gesamte>Loop durchlaufen.
Aber wenn ich in einer z.B. If-Anweisung oder Schleife innerhalb der
Loop aufgrund einer gewissen Bedingung (wie bei mir z.B. der gedrückte
oder losgelassene Taster, müsste ich doch solange die Bedingung erfüllt
ist, darin verharren?!
>Bis i voll ist vergehen 600s, ist das so gewollt
Nein, gewollt, ist das nicht. :-)
Es sollen die Werte bis max. zum Erreichen der max. Anzahl der
Array-Elemente erfasst werden. Sollte man vorher den Taster loslassen,
soll
man ebenfalls in der "if((tasterFlag == 1) && (digitalRead(2) == LOW))"
landen.
Aber wie kommt man auf die 600sec.?
Die erste Zeitfunktion ( delay()) ist in der "if(i == 199)", die wird
aber ja erst bei Erreichen von i == 199 aufgerufen. Oder liege ich
falsch?
Ich werde das Ganze, wie du beschrieben hast, eleganter lösen, was die
Berechnungen in Funktionen etc. beinhaltet.
Aber so wie es nun da steht, sollte es der Funktion ja keinen Abbruch
machen.
Wo liegt nun konkret mein Fehler?!
Danke im Voraus!
>// WEIL DIESES IF EBENFALLS NUR GEFÜLLT WIRD, WENN AN TASTER HIGH ANLIEGT
Das soll es auch, wird der Taster vorher losgelassen (also wenn i <
199), soll die if(i == 199) auch nicht ausgeführt werden, denn dann hat
dies ja keinen "Überlauf" des Arrays zur Folge, wenn i < 199 ist.
Ich teste gleich mal deinen Code und gebe Bescheid.
Danke derweil!
Gruß
Philipp G. schrieb:> überleg mal den gesamten Ablauf im Kopf
dito
es würde auch gehen:
if(digitalRead(2) == HIGH) // Taste gedrückt?
{ while(!array_filled) // solange noch nicht alle Werte im Array lesen
{
dauert halt -> bleibt halt solange in der Schleife, egal ob die Taste
noch gedrückt ist oder nicht
oder
while( (digitalRead(2) == HIGH) && !array_filled ) // bleibt nur solange
in der Schleife wie Taste gedrückt und Array noch nicht gefüllt
{
Taste loslassen und Array gefüllt beendet die Schleife
Das Schwierigste am Programmieren erst mal zu wissen was man will und
ALLE möglichen Bedingungen im Kopf sortieren und was passiert wenn
Joachim B. schrieb:> Das Schwierigste am Programmieren erst mal zu wissen was man will und> ALLE möglichen Bedingungen im Kopf sortieren und was passiert wenn
Ja und deswegen ist es weitaus einfacher die grossen
1
display.clearDisplay();
2
display.setTextSize(2);
3
display.setCursor(10,10);
4
display.println("STOP!");
Blöcke von Anfang an auszulagern und mit sprechenden Countern zu
arbeiten bis alles funktioniert. z.B iArrayCounter
>dauert halt -> bleibt halt solange in der Schleife, egal ob die Taste>noch gedrückt ist oder nicht
oben schreibt er, dass das nicht erwünscht ist, warum auch immer.
Fussgängerampel button: Egal wie kurz oder lang oder wieviel man darauf
drückt, es soll immer dieselbe Funktion ausgeführt werden.
Philipp G. schrieb:> oben schreibt er, dass das nicht erwünscht ist, warum auch immer.>> Fussgängerampel button: Egal wie kurz oder lang oder wieviel man darauf> drückt, es soll immer dieselbe Funktion ausgeführt werden.
nun ja eine Tastenentprellung sehe ich auch noch nicht, das wird ein
weiter Weg noch für den TO.
Ich nutze ja gerne die ISR Tastenentprellung nach Dannegger bullet
proof, die auch die mistigsten Tasten entprellt, noch NIE damit Probleme
gebabt.
Man drückt einmal, nach 40ms ist sie im IRQ gespeichert und wenn Zeit in
der main loop ist kann man sie abarbeiten +- 100ms kommt bei mir nicht
so drauf an, Hauptsache der Tastendruck wurde erkannt, nach Abarbeitung
kann ich das Flag dann löschen.
Dummerweise läuft es an meinem PKW Lenkrad nicht oder anders, die Tasten
prellen nach 3 Jahren wie Sau, einmal gedrückt gleich wieder alle
Senderspeicher durchlaufen, na mal sehen ob Putzen was gebracht hat.
Ist es Can Bus oder Widerstandserkennung das weiss ich noch nicht.
Joachim B. schrieb:> nun ja eine Tastenentprellung sehe ich auch noch nicht, das wird ein> weiter Weg noch für den TO.
Anscheinend hat man dich im Elektronik-Mittelalter eingefroren und aus
Versehen aufgetaut :-)
Nachdem du dir die Augen getrocknet hast schaue hier mal nach:
https://github.com/thomasfredericks/Bounce2
Wenn man seine Taster 'gebounced' hat ist eine Flankenerkennung
eigentlich nur noch ein Kinderspiel!
Baumüller schrieb:> Ich dachte mir, eine "Flankenerkennung" (from HIGH to LOW) zu nutzen, um> das Loslassen des Tasters zu detektieren. Allerdings weiß ich nicht, ob> es dies beim Arduino überhaupt gibt.
Lieber 'TO' ein bisschen Programmieren ist schon noch gefragt!
Es gibt weitaus interessantere Dinge sich mit Ardunio zu beschäftigen.
Ein Tipp:
Wenn jemand erwägt Arduino für halb-kommerzielle Zwecke einzusetzen,
dann empfiehlt sich der Einsatz Von TEENSY Modulen > 3.0 .
Die sind Arduino kompatibel und im Vergleich dazu sauschnell.
Das gilt in in Zukunft gleich 3x so viel für die TEENSY Module > 4.0,
die sind nämlich supersauschnell.
Argumente wie 'Spielkram', 'Langsam' 'Kinderspielzeug' lassen einem
dann alle kalt und erzeugen höchstens ein müdes Lächeln!
Die Produktivität zu althergebrachten uController Anwendungen ist um
Klassen besser!
Joachim B. schrieb:> Dummerweise läuft es an meinem PKW Lenkrad nicht oder anders, die Tasten> prellen nach 3 Jahren wie Sau, einmal gedrückt gleich wieder alle> Senderspeicher durchlaufen, na mal sehen ob Putzen was gebracht hat.> Ist es Can Bus oder Widerstandserkennung das weiss ich noch nicht.
Tasten, sind doch glatt eine Widerstandskette und die Stifte unverlötet,
geputzt, gelötet, schaun mer mal
il Conte schrieb:> Nachdem du dir die Augen getrocknet hast schaue hier mal nach:>> https://github.com/thomasfredericks/Bounce2>> Wenn man seine Taster 'gebounced' hat ist eine Flankenerkennung> eigentlich nur noch ein Kinderspiel!
Das weiss der Jar schon selber.
Joachim B. schrieb:> Tasten, sind doch glatt eine Widerstandskette und die Stifte unverlötet,> geputzt, gelötet, schaun mer mal
BMW?
Philipp G. schrieb:> BMW?
ne das erste Auto welches schon in der Bibel erwähnt wurde.....
und putzen hat nicht geholfen, also den Widerstand finden der
unterbrochen ist.
Oder ist es gar eine Durchkontaktierung?
Die Widerstände jedenfalls sind plausibel.
>Fussgängerampel button: Egal wie kurz oder lang
Das stimmt schon, aber bei mir WIRD SOLANGE GEMESSEN, BIS ICH den Taster
LOSLASSE.
Ich möchte bewusst nicht eine vorgegebene Zeit lang messen bzw. bis ein
Counter einen bestimmten Wert hat.
Ich bin nun ein Stück weitergekommen, allerdings habe ich noch zwei
Probleme:
Angefangen mit dem wohl dümmlichsten Problem, das ich je hatte.
Der berechnete Mittelwert ist falsch! (siehe Screenshot)
Ich weiß beim besten Willen nicht, warum er diesen richtig berechnet.
Vielleicht habe ich auch Tomaten auf den Augen...
Alle Variablen sind mit 0 initialisiert und und vom Datentyp "int".
Die Bedingung in der for-Schleife habe ich wie man sieht auch
abgeändert, um Array-Elemente mit dem Wert 0 nicht mit in die Berechnung
einfließen zu lassen..
Das zweite Problem ist noch, dass solange der Taster gedrückt wird, im
Display das "HALLO" in etwa im Sekunden(?)-Takt "blinkt".
Wie kann ich dieses ungewollte "blinken" unterbinden?
Vorhin, als ich den Taster gehalten habe, hatte ich das Problem nicht.
Vielleicht könnt ihr mir nochmal kurz helfen.
Danke schonmal!
Zur Terminalausgabe noch kurz (im Screenshot):
der erste Wert ist die Zählvariable und somit das Element der Array.
der zweite Wert ist der Wert des jeweiligen Elements, usw.
"iCount nach for" ist der Wert, den iCount angenommen hat, nachdem die
for-Schleife durchlaufen wurde.
Und dann der falsche Mittelwert, der sich aus den Werten der
Array-Elemente und dem iCount berechnet bzw BERECHNEN SOLLTE.
an JEDER Stelle Werte ausgeben mit Serial.print und überlegen
ich bekomme weder 19 noch deinen echten Mittelwert raus nicht mal
Summe/3 oder Summe/4
dein Index ist ja schon einen Wert weiter also 4 wenn du rechnest.
Irgendwas passt vorne und hinten nicht, Code als Bild ist auch
ungünstig, da kann man nicht mal eben den Compiler anwerfen und nicht
jeder hat Lust unvollständigen Code einzutippen, es fehlt einfach zuviel
Hallo nochmal,
hier nun der Code in Textform und ein aktueller Screenshot der
Terminalausgabe, nachdem ich nun noch mehr Serial.print() eingefügt
habe.
Wie du bereits sagtest:
Warum zum Henker wird der iCount nochmals um 1 erhöht, obwohl innerhalb
der for-Schleife keinerlei Zuweisung an iCount geht? Ich erhöhe iCount
lediglich bei jedem Schleifendurchgang um 1.
Baumüller schrieb:> Wie du bereits sagtest:> Warum zum Henker wird der iCount nochmals um 1 erhöht, obwohl innerhalb> der for-Schleife keinerlei Zuweisung an iCount geht?
(wertereihe[iCount] != 0)); iCount++
du musst programmieren lernen, solange
(wertereihe[iCount] != 0));
wird iCount erhöht, wenn (wertereihe[iCount] != 0))
ist durch
iCount++ davor!
ja schon ein weiter!
Baumüller schrieb:> hier nun der Code in Textform
sag mal das ist nicht der komplette Code, das eingegeben gibt NIX
keine #include
keine #define
kein main usw....
willst du uns veräppeln?
lerne abweisende Schleife und nicht abweisende Schleife
deine For Schleife incrementiert am ENDE den Index zu 3 (von 0-2 sind 3
Werte)
und prüft dann wieder am Anfang huch nanu da ist ja nichts mehr ->
&& (wertereihe[iCount] != 0) also raus hier
und dann mittelst du durch (iCount+1) = 4
mittelwert = mittelwert / (iCount+1);
was soll da rauskommen wenn du nur 3 Werte hast?
hey "Baumüller (Gast)",
1) vllt. könntest du dir ja auch ein account anlegen,
dann würde man dich auch per "pn" erreichen...
2) deine fehler / bzw. warum du die fehler nicht siehst,
entstehen dadurch, dass du dein code nicht sauber gliederst und
somit den überblick verlierst.
ja ich bin ehrlich, ich hab mal nen blick drauf geworfen und direkt
aufgehört irgendwelche variablen oder logik zu suchen.
damit kommen wir zu punkt 3.
3) bitte nicht alles in die loop() funktion schreiben!
die zeilen für deine lcd-ausgaben wiederholen sich ca 4-5mal,
immer das gleiche nur andere parameter, schreib dafür eine eigene
funktion.
4) ich werde morgen vllt. mal zeit haben, dann poste ich dir mal aus
deinem code ein kleines bsp. wie du es "sauberer" gestallten kannst.
5) Tasten-Entprellung: ja da hätte ich auch was für dich, weil immer mit
if und else überall rumprüfen bringt auch nix.
da helfen dir funktionen.
... leider musst dich bis morgen gedulden, aber vllt. schaust dir mal
an, dass man auch eigene funktionen erstellen kann um sein code
lessbarer zu machen und nicht alles in eine 100000 zeilen loop()
funktion packt ;-)
gruß
Adam P. schrieb:> immer mit> if und else überall rumprüfen bringt auch nix
Doch mit if und else kannst Du alles, ohne fremde Hilfe,
realisieren.
Was mich hier stört ist delay.
Während des delay ist der Arduino praktisch unter
Vollnarkose und kann nichts machen.