Bin Anfänger im Bereich Arduino. Habe ein Verständnissproblem mit der Abfrage eines Tasters.
Der Code läuft und für mein Vorhahen ist das folgende Problem auch nicht wichtig. Nur Zum Verständnis:warum schaltet die LED erst beim loslassen des Tasters und nicht schon beim betätigen.
Ich würde mich über eine kurze Erklärung freuen.
int led=13;
int taster=2;
int tasterwert;
int ledzustand;
void setup() {
pinMode(led,OUTPUT);
pinMode(taster,INPUT_PULLUP);
digitalWrite(led,LOW);
}
void loop() {
tasterwert=digitalRead(taster);
if (tasterwert==0){
delay(5);
if (digitalRead(taster)){
if(ledzustand==0){
digitalWrite(led,HIGH);
ledzustand=1;
}
else{
digitalWrite(led,LOW);
ledzustand=0;
}
}
}
}
Du fragst den Taster ab und gehst weiter, wenn der Taster gedrückt ist (also auf LOW).
Nun legst Du eine 5ms Pause ein und fragst den Taster erneut ab, dieses Mal aber auf HIGH (also los gelassen).
Erst hier änderst Du den LED-Status, also schaltest Aus, wenn zuvor An und umgekehrt.
Warum Das, wenn auch 'falsch herum, zuverlässig funktioniert, ist mir aber noch nicht klar.
Hier musst Du den Taster gedrückt haben bei der ersten Zuweisung und gelöst, wenn die zweite Abfrage vorbei kommt.
Hätte jetzt eher erwartet, daß Du nur sehr selten die LED beeinflusst bekommst, da Du den Umschaltzeitpunkt, Den Du im Programm 'forderst', nur sehr schwer treffen kannst.
postmaster-ino:
Warum Das, wenn auch 'falsch herum, zuverlässig funktioniert, ist mir aber noch nicht klar.
Weil der Tasterzustand in einer Variable zwischengespeichert wird. Sobald der Taster gedrückt (und gehalten) wird, geht das Programm bei jeder loop auch in die if Abfrage, da der Wert ja LOW ist. Läßt man den Taster wieder los, wechselt der Wert auf HIGH (abgesehen vom Prellen) und dadurch wird auch die zweite if Abfrage Wahr.
So ist die LED nur an wenn der Taster GEDRÜCKT bleibt.
int led = 13;
int taster = 2;
int tasterwert;
int ledzustand;
void setup() {
pinMode(led, OUTPUT);
pinMode(taster, INPUT_PULLUP);
digitalWrite(led, LOW);
}
void loop() {
tasterwert = digitalRead(taster);
if (tasterwert == 0) {
digitalWrite(led, HIGH);
ledzustand = 1;
}
else {
digitalWrite(led, LOW);
ledzustand = 0;
}
}
Nach dem einfügen in die IDE, einfach mal "Strg+T" drücken, damit der Code schön formatiert ist.
Danke für die Antworten.
Ich glaube ich habe mich angesichts der Zeit des Post nicht richtig ausgedrückt.
Die Led (später ein Relais) soll beim betätigen angehen und bleiben. Bei erneuten betätigen wieder aus.
Macht sie auch aber der zustand wird erst nach dem loslassen des Tasters geändert.
Sprich:
Led aus > Taster drücken und halten > Led aus >Taster wird losgelassen > Led an
und umgekehrt:
Led an > Taster drücken und halten >Led an > Taster wird losgelassen> Led aus
Dabei spielt es keine Rolle wie lang der taster gedrückt wird.
Für mein Vorhaben spielt das Verhalten keine Rolle es ist aber schöner wenn der Zustand
sich nach dem betätigen ändern würde und nicht erst beim loslassen.
Sprich:
Led aus > Taster drücken und halten > Led an >Taster wird losgelassen > Led an
und umgekehrt:
Led an > Taster drücken und halten >Led aus > Taster wird losgelassen > Led aus
PS
sie 5ms und erneute Tastenabfrage entprellen den Taster .Gigt sicherlich bessere Lösungen aber geht
Hatte ich oben bereits geschrieben, Du fragst den Taster auf GEDRÜCKT ab, dann 5ms Pause, dann auf NICHT_GEDRÜCKT und dann erst wechselst Du die LED.
Wenn Du die 2.te Abfrage, das NICHT_GEDRÜCKT in ein GEDRÜCKT änderst - wird sich der LED-Wechsel bereits beim Drücken zeigen.
Ab und zu auch Lesen, was die anderen hier so absondern - vll. ist die Lösung da schon drin enthalten.
MfG
PS: Das mit dem 'zuverlässig falsch herum funktionieren' ist mir mittlerweile klar geworden - die 5ms Wartezeit sind der Großteil der Durchlaufzeit, somit ist es sehr wahrscheinlich, daß man sich bei Änderungen des Taster gerade in diesem delay() befindet.
Danke für's hin-schubsen.
Danke für eure Tipp's. Habe es jetzt hinbekommen.Es haben eigentlich nur 2 Zeilen Code gefällt.
Ich habe bewusst nicht in die Beispiele geschaut , wenn ich einen funktionierenden Code gefunden hätte würde ich mir vielleicht um das warum geht es nicht so große Gedanken machen und den Code nur verwenden ohne zu wissen was passiert. So bin ich durch eure Denkanstöße zum Erfolg gekommen und muss bei einem ähnlichen Problem nicht wieder zu viele Fragen stellen.
Wie gesagt noch mal vielen Dank
MfG
Thorsten4171
int led = 13;
int taster = 2;
int tasterwert;
int letztertasterwert;
int ledzustand;
void setup() {
pinMode(led, OUTPUT);
pinMode(taster, INPUT_PULLUP);
digitalWrite(led, LOW);
}
void loop() {
tasterwert = digitalRead(taster);
if (tasterwert != letztertasterwert) {
delay(5);
if ( digitalRead(taster) == 0) {
if (ledzustand == 0) {
digitalWrite(led, HIGH);
ledzustand = 1;
}
else {
if (ledzustand == 1) {
digitalWrite(led, LOW);
ledzustand = 0;
}
}
}
}
letztertasterwert == tasterwert;
}
Ich geb Dir eine Aufgabe wenn Du willst:
Es sind 7 LEDs die an den Pins 2,3,9,5,11,12,7 angeschlossen. Sie sollen in dieser Reihenfolge mit einem Abstand von 2 Sekunden zum leuchten beginnen. Die folgende Zeile muss die erste sein und Du darfst nur noch 4 Zeilen, wohl eher Befehle verwenden. Es können ja Anfangs mehr sein...
const int pins[] = {2,3,9,5,11,12,7}; // Das int gehört noch ersetzt, siehe #8
Aber was Dir eher wirklich was bringt: schmeiß das delay() raus. Stichwort: BlinkWithoutDelay.
Bin immer für Denksportaufgaben werde mal probieren.
Mein delay hab ich durch milli ersetzt.
eine Frage hätte ich noch .
Wenn ich die Variablen duch Konstanten ersetze, welchen Vorteil bringt es mir?
Hauptsächlich benutzt man Konstanten weil sie schreibgeschützt sind und niemals versehentlich geändert werden können. Würdest du das tun würde es dir der Compiler sofort melden. Mit einer Variablen würde der Fehler durch rutschen und könnte unter Umständen eine sehr aufwendige Fehlersuche nötig machen. Du machst deinen Code also weniger Fehleranfällig und erleichterst dir, und jedem der deinen Code liest die Arbeit. Denn wenn dort ein "const" steht, und dein Compiler nicht meckert, wissen wir schon dass die Konstante nirgends im Code versehentlich beschrieben wird, ohne erst jede Zeile lesen zu müssen.
Ich habe auch mal gelesen dass mit Konstanten mit anderen Compilern, und gewissen Compilereinstellungen, geringerer RAM Verbrauch beobachtet wurde, als mit Variablen. Ich weiß aber nicht ob da was dran ist. Ich kann mir zumindest nicht erklären wieso das sein sollte. Es sei denn der Compiler erkennt vielleicht wenn eine 32bit Konstante nur einen 8bit Wert enthält, und legt dann nur 8bit in den RAM. Noch besser wäre aber wenn man die Größe seiner Konstanten gleich richtig wählt.
Ich habe auch mal gelesen dass mit Konstanten mit anderen Compilern, und gewissen Compilereinstellungen, geringerer RAM Verbrauch beobachtet wurde, als mit Variablen.
Weniger Ram und weniger Flash!
Variablen müssen ins RAM, ohne Frage.
Desweiteren haben sie oft noch eine Initialisierung im Flash, also im Programmcode.
Der Zugriff erfolgt indirekt.
Über die Adresse der Variablen wird der Wert ins Rechenwerk geholt.
Und umgekehrt.
Konstanten brauchen keine Adresse im Ram, und auch nicht im Flash.
Dort ist der Wert im Programmcode eingelagert und landet ohne Umwege ins Rechenwerk.
Gelten tut das alle male für kleine Konstanten.
Bei größeren Strukturen ist diese Reduktion auf Null nicht möglich.
Grundsätzlich:
Das Konstant Attribut ermöglicht weitgehende automatische Optimierungen.
Also überall, wo es nur geht, "const" hinschreiben.
Damit sollte man nicht sparen.
Ich habe auch mal gelesen dass mit Konstanten ... geringerer RAM Verbrauch beobachtet wurde, als mit Variablen.
Es ist eher erstaunlich, wie gut der avr-gcc Compiler optimiert.
Wenn du selber testest, musst du erstmal sicherstellen, dass dein Test nicht komplett wegoptimiert wird, weil er sinnlos ist. (Daher die Serial.print unten)
int Basis = 1000;
const int Diff = 500; // Diff braucht keinen RAM, wenn const
void setup() {
Serial.begin(9600);
Serial.println(Basis);
//Serial.println(Basis-Diff);
Serial.println(Basis-500); // Alternative: sollte das gleiche wie die obige Zeile bewirken
}
void loop() {
Basis += Diff;
Serial.println(Basis);
delay(Basis);
}
Konstanten brauchen keine Adresse im Ram.
Dort ist der Wert im Programmcode und landet ohne Umwege ins Rechenwerk.
Ich bin da bei der Arduino IDE noch nie ganz durch gestiegen, benutze sie aber normalerweise auch nicht. Jetzt habe ich aber nichts anderes zum testen da. Ist mit "dynamischem Speicher" am Ende der Compilerausgabe nicht der RAM gemeint?
const uint32_t array[500] = {10};
void setup() {
for (int i = 0; i < 500; i++) delay(array[i]);
}
void loop() {
}
Das belegt den gleichen "dynamischen Speicher" wie ohne const.
@michael_x, Wie müsste ich denn mit deinem Test testen um einen Unterschied zu sehen? Ich komme da auch immer nur auf den gleichen Wert, mit oder ohne const.
gsezz: @michael_x, Wie müsste ich denn mit deinem Test testen um einen Unterschied zu sehen? Ich komme da auch immer nur auf den gleichen Wert, mit oder ohne const.
So wie angedeutet erhalte ich (mit der 1.8.5 für einen Uno):
Der Sketch verwendet 2008 Bytes (6%) Flash. 190 Bytes RAM.
Tausche ich die zwei Zeilen,
Serial.println(Basis-Diff);
//Serial.println(Basis-500); // Alternative: sollte das gleiche wie die obige Zeile bewirken
ändert sich wie erwartet nichts: Diff belegt keinen Platz im RAM.
Entferne ich das const und füge in setup die Initialisierung ein
int diff;
void setup() {
diff=500;
...
}
habe ich die Optimierung verhindert
Der Sketch verwendet 2036 Bytes (6%) Flash. 192 Bytes (9%) RAM
Welchen Sinn sollte ein constantes Array von 500 Werten haben, von denen nur 1 Wert belegt ist?
In C++ werden, wenn eine Arraygröße angegeben ist, bei der initialisierung eines Wertes alle übrigen mit Null belegt. Ich wollte eigentlich mit {0} alle mit Null belegen, aber wegen zu fetter Finger ist eine 10 daraus geworden.
-edit- Was ich hier noch geschrieben hatte stimmte nicht ganz. Ich muss mir das noch mal genauer ansehen.