Soweit, so gut..

Hallo zusammen,

Ich habe mich bei meinem derzeitigem Projekt an einem anderem aus diesem Forum orientiert, da er etwa dieselbe Problemstellung hatte, wie ich. Aber eben nur fast…

(https://forum.arduino.cc/index.php?topic=574851.0)

Meine Problemstellung:

Mit einem Taster drei (bestehende) Programmteile durchschalten und wenn der Bewegungssender bewegung meldet, die LED blinken lassen entsprechend des Programmteils.

Das Script:

int buttonPin = 8; //Taster "buttonPin" an Pin 2 angeschlossen
int ledPin = 7; //LED "ledPin" an Pin 13 angeschlossen
int sensorPin = 9; //Pin für den Bewegungssender


//Variablen des Zwischenspeichers:
int buttonPushCounter = 0;   //Zählt Tastendrücke
int buttonState = 0;         //Aktueller Tastenstatus
int lastButtonState = 0;     //Vorheriger Tastenstatus
int sensorState = LOW;         //Sensorstatus zu Beginn
unsigned long previousMillis = 0; //Speichert vergangene Zeit
const long interval = 500; //Intervall wo Tasterdrücke registriert wurden

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT);
  sensorState=digitalRead(sensorPin);
}

void loop() {

  unsigned long currentMillis = millis(); //Zählt Millisekunden
  buttonState = digitalRead(buttonPin); //Taster an buttonPin wird gelesen und in Zwischenspeicher buttonState gespeichert
 
  if (buttonState != lastButtonState) { //Wenn buttonState nicht gleich lastButtonState, dann...
   
    if (buttonState == LOW) { //Wenn buttonState gleich gedrückt, dann...
      buttonPushCounter ++; //buttonPushCounter +1
      lastButtonState = buttonState; //Speichert buttonState in lastButtonState
      previousMillis = currentMillis; //Speichere jetzige Millisekunden in previousMillis
      delay(50);
    }
  else {
      lastButtonState = buttonState;
    }
  }

  if (currentMillis - previousMillis >= interval && buttonState == lastButtonState) { //Wenn gezählte Millisekunden minus vorherige Millisekunden (gespeicherte, vergangene Zeit) grösser/gleich interval ist und buttonState gleich lastButtonState ist, dann...

    //Taster wird 1 Mal gedrückt:
    if (buttonPushCounter == 1) { //Wenn buttonPushCounter gleich 1, dann...
      digitalWrite(ledPin, HIGH); //Schalte ledPin an
      delay(200);
      digitalWrite(ledPin, LOW);
      Serial.println();
      Serial.println("kurz");
    }
   
  

    //Taster wird 2 Mal gedrückt:
    if (buttonPushCounter == 2) { //Wenn buttonPushCounter gleich 2, dann...
      digitalWrite(ledPin, HIGH); //Schalte ledPin an
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      Serial.println();
      Serial.print("mittel");
    }

    //Taster wird 3 Mal gedrückt:
    if (buttonPushCounter == 3) { //Wenn buttonPushCounter gleich 3, dann...
      digitalWrite(ledPin, HIGH); //Schalte ledPin an
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      Serial.println();
      Serial.print("lang");
    }

    //Taster wird 4 Mal gedrückt:
    if (buttonPushCounter == 4) { //Wenn buttonPushCounter gleich 4, dann...
      digitalWrite(ledPin, HIGH); //Schalte ledPin an
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      Serial.println();
      Serial.print("float overflow");
    }

    buttonPushCounter = 0; //Setze buttonPushCounter auf 0

     
    if  (digitalRead(sensorState == HIGH)&(lastButtonState == 1)){
    digitalWrite (ledPin, HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin, HIGH);
    delay (1000);
     } 
     
    if (digitalRead(sensorState == HIGH)&(lastButtonState == 2)){
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
  }
    if (digitalRead(sensorState == HIGH)&(lastButtonState == 3)){
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (1000);
    }
    if (digitalRead(sensorState == HIGH)&(lastButtonState == 4)){
    digitalWrite (ledPin, LOW);
    delay (2000);
    }
  }
  }

Was macht er?

Nun, solange ich den eigenen Teil weg lasse (mit if (digitalRead(sensorState == HIGH)&(lastButtonState == 1)){, usw. ) funktioniert die Schaltung, so wie ich will. Im seriellen Monitor zeigt er mir an, sobald ein Programm durch mehrfach Druck ausgelöst wird.

Alles andere Blinkt quasi nur noch, manchmal zeigt er mir am seriellen Monitor an, das ein Programm durchkommt.

Frage:

Was muss ich für einen Befehl eintragen, damit er mich bei erkannter Bewegung an den Taster lässt? Währen des Drückens am Taster ist es wurscht ob er Blinkt. Es geht ja um das Durchschalten.

Vielen Dank schonmal!

VG

Thomas

sketch_nov08a.ino (4.69 KB)

Bitte das Deutche board benutzen oder in English schreiben :-)

Makers_Prototype: Frage:

Was muss ich für einen Befehl eintragen, damit er mich bei erkannter Bewegung an den Taster lässt? Währen des Drückens am Taster ist es wurscht ob er Blinkt. Es geht ja um das Durchschalten.

C++ hat Funktionen und keine Befehle. Du musst unblockierend programmieren. Die vielen Delays blockieren Deinen Programmablauf, deshalb kann er während der Zeit nicht anderes machen, auch nicht den Bewegungsmelder einlesen.

Schaue Dir in der IDE das Beispiel BlinkWithoutDelay an und [u]verstehe es[/u]. Dabei kann Dir z.B. die Nachtwächtererklärung helfen.

Gruß Tommy

Neben den vielen delays ist mir aber aufgefallen, dass du den Sensor nur einmal im setup() ausliest, also beim Start des µC's und sonst nicht mehr.

Edit: Ich hab übersehen, dass der Sensor weiter unten doch ausgelesen wird.

Tommy56: ... Dabei kann Dir z.B. die Nachtwächtererklärung helfen. Gruß Tommy

Siehe hier.

Gruß

Gregor

Und hier die Zeile:

if  (digitalRead(sensorState == HIGH)&(lastButtonState == 1)){

muss so lauten:

if  (digitalRead(sensorState == HIGH)&&(lastButtonState == 1)){

das '&' muss doppelt geschrieben sein, also '&&'. Ist bei allen Vergleichen so, der Operator muss doppelt geschrieben sein.

LG Stefan

Hallo,

hier ist die Runde Klammer noch falsch und ich denke Du willst auch den Pin einlesen

if (digitalRead(sensorState == HIGH)&(lastButtonState == 2)){

sollte dann so sein:

if(digitalRead(sensorPin)==HIGH && lastButtonState==2)

Heinz

Stefan war etwas schneller

@Heinz, dankeschön, da hast Du natürlich recht, ist mir beim überfliegen gar nicht aufgefallen, sonst hätte ich das natürlich auch erwähnt.

LG Stefan

Deltaflyer: das '&' muss doppelt geschrieben sein, also '&&'. Ist bei allen Vergleichen so, der Operator muss doppelt geschrieben sein.

Nicht immer, denn && ist logisches Und, aber & ist bitweises Und.

if(digitalRead(sensorPin)==HIGH && lastButtonState==2)

Das ist ein weißer Schimmel (Pleonasmus), besser:

if(digitalRead(sensorPin) && lastButtonState==2)

Denn digitalRead() liefert bool zurück, noch boolscher geht es nicht.

agmue: Das ist ein weißer Schimmel (Pleonasmus).

Interessanter Artikel, und ein interessantes Beispiel hast du auch geliefert ;)

Beispiel: „Weißer Schimmel“ ist kein Pleonasmus, da die als Schimmel bezeichneten Pferde einerseits nicht von Geburt an ein weißes Fell haben und es zudem eine Anzahl weiterer Farb- und Zeichnungsvarianten gibt, z. B. den Apfelschimmel

Wow,

da gehst Du (gefühlt) kurz offline und dann ist der ganze Threat voll.

Vielen Dank, für die schnellen Antworten!

Heisst das, ich war auf nem guten weg, nur das Format ist nicht ganz richtig?

Ich werde mir das jetzt mal zu gemühte führen und verbessern.

Vielen Dank erstmal.

Thomas

agmue: Nicht immer, denn && ist logisches Und, aber & ist bitweises Und.

if(digitalRead(sensorPin)==HIGH && lastButtonState==2)

Das ist ein weißer Schimmel (Pleonasmus), besser:

if(digitalRead(sensorPin) && lastButtonState==2)

Denn digitalRead() liefert bool zurück, noch boolscher geht es nicht.

nach meinem dafürhalten sind ButtonState und lastButtonState doch auch als int deklarierte bool Variablen, die nicht 2 werden können, ich vermute mal es soll mit buttonPushCounter verglichen werden.

lastButtonState ist int und kann natürlich 2 sein. Das Ergebnis des Vergleichs lastButtonState==2 ist allerdings bool.

ElEspanol: Interessanter Artikel, und ein interessantes Beispiel hast du auch geliefert ;)

Bravo, Du hast den Artikel tatsächlich gelesen :grin:

ElEspanol:
lastButtonState ist int und kann natürlich 2 sein. Das Ergebnis des Vergleichs lastButtonState==2 ist allerdings bool.

wie kann lastButtonState hier 2 werden?

buttonState = digitalRead(buttonPin); //Taster an buttonPin wird gelesen und in Zwischenspeicher buttonState gespeichert

lastButtonState = buttonState;

wie kann lastButtonState hier 2 werden?

Ist überhaupt lastButtonState gemeint ? ( Oder vielleicht buttonPushCounter ?)

Ist überhaupt lastButtonState gemeint ? ( Oder vielleicht buttonPushCounter ?)

vermute ich auch, siehe #11.

Ich hab den Sketch nicht weiter angeschaut, nur die Variablen Deklarationen. Daher meine Aussage, das eine als int deklarierte Variable durchaus den Wert 2 annehmen kann. Ob das im Sketch so sein könnte, k. A.

Hallo und ein schönes Wochenende zusammen,

danke an euch für weitere Überlegungen. Weiterhin ist nun das Problem, das er zwar den Status ändert und nach dem erstmlaigem Blinken im Seriellen Monitor den Status ausgibt, aber meine angehängten "Unterprogramme" nicht ausführt, sondern nur den des ersten buttonsState :

if (digitalRead(sensorPin) == HIGH && buttonState == 1){ digitalWrite (ledPin, HIGH); delay (2000); digitalWrite (ledPin, LOW); delay (2000); digitalWrite (ledPin, HIGH); delay (1000); digitalWrite (ledPin, LOW); }

Danke an Rentner für die Formale Hilfestellung, auch an Agmue für den Hinweiß. Man muss ja nicht mehr reinschreiben als notwendig.

Der Code sieht nun folgendermaßen aus:

int buttonPin = 8; //Taster "buttonPin" an Pin 2 angeschlossen
int ledPin = 7; //LED "ledPin" an Pin 13 angeschlossen
int sensorPin = 9; //Pin für den Bewegungssender


//Variablen des Zwischenspeichers:
int buttonPushCounter = 0;   //Zählt Tastendrücke
int buttonState = 0;         //Aktueller Tastenstatus
int lastButtonState = 0;     //Vorheriger Tastenstatus
int sensorState = LOW;         //Sensorstatus zu Beginn
unsigned long previousMillis = 0; //Speichert vergangene Zeit
const long interval = 500; //Intervall wo Tasterdrücke registriert wurden

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT);
  sensorState=digitalRead(sensorPin);
}

void loop() {

  unsigned long currentMillis = millis(); //Zählt Millisekunden
  buttonState = digitalRead(buttonPin); //Taster an buttonPin wird gelesen und in Zwischenspeicher buttonState gespeichert

  if (buttonState != lastButtonState) { //Wenn buttonState nicht gleich lastButtonState, dann...
   
    if (buttonState == LOW) { //Wenn buttonState gleich gedrückt, dann...
      buttonPushCounter ++; //buttonPushCounter +1
      lastButtonState = buttonState; //Speichert buttonState in lastButtonState
      previousMillis = currentMillis; //Speichere jetzige Millisekunden in previousMillis
      delay(50);
    }
  else {
      lastButtonState = buttonState;
    }
  }

  if (currentMillis - previousMillis >= interval && buttonState == lastButtonState) { //Wenn gezählte Millisekunden minus vorherige Millisekunden (gespeicherte, vergangene Zeit) grösser/gleich interval ist und buttonState gleich lastButtonState ist, dann...

    //Taster wird 1 Mal gedrückt:
    if (buttonPushCounter == 1) { //Wenn buttonPushCounter gleich 1, dann...
      digitalWrite(ledPin, HIGH); //Schalte ledPin an
      delay(200);
      digitalWrite(ledPin, LOW);
      Serial.println();
      Serial.println("kurz");
    }
   
  

    //Taster wird 2 Mal gedrückt:
    if (buttonPushCounter == 2) { //Wenn buttonPushCounter gleich 2, dann...
      digitalWrite(ledPin, HIGH); //Schalte ledPin an
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      Serial.println();
      Serial.print("mittel");
    }

    //Taster wird 3 Mal gedrückt:
    if (buttonPushCounter == 3) { //Wenn buttonPushCounter gleich 3, dann...
      digitalWrite(ledPin, HIGH); //Schalte ledPin an
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      Serial.println();
      Serial.print("lang");
    }

    //Taster wird 4 Mal gedrückt:
    if (buttonPushCounter == 4) { //Wenn buttonPushCounter gleich 4, dann...
      digitalWrite(ledPin, HIGH); //Schalte ledPin an
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      delay(200);
      digitalWrite(ledPin, HIGH);
      delay(200);
      digitalWrite(ledPin, LOW);
      Serial.println();
      Serial.print("float overflow");
    }

    buttonPushCounter = 0; //Setze buttonPushCounter auf 0

     
    if  (digitalRead(sensorPin) && buttonState == 1){
    digitalWrite (ledPin, HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin, HIGH);
    delay (1000);
    digitalWrite (ledPin, LOW);
     } 
     
    if (digitalRead(sensorPin) && buttonState == 2){
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin,LOW);
  }
    if (digitalRead(sensorPin) && buttonState == 3){
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (2000);
    digitalWrite (ledPin,HIGH);
    delay (2000);
    digitalWrite (ledPin, LOW);
    delay (1000);
    }
    if (digitalRead(sensorPin) && buttonState == 4){
    digitalWrite (ledPin, LOW);
    delay (500);
    }
    buttonPushCounter = 0;
  }
  }

Kann es also sein, das er den buttonState nicht in den Zwischenspeicher schiebt? Bzw. setzte er den Status in Zeile 11 wieder zurück (int lastButtonState = 0). Auskommentieren reicht hier aber nicht, da sonst das Millis nicht mehr funktioniert. Danke für den Hinweis an arubu!

Ist es evtl hilfreich einen neuen void für den buttonStatus einzuführen, der parallel den Sensorstatus bedient?

Vielen Dank schonmal. :)

Hallo nochmal,

der Umstand, das ich lastButtonState verwende, ändert leider nichts an der Ausführung des Programms.

@noiasca

Es wird mir im seriallen Monitor live angezeigt in welchem Satuts ich mich befinde. Leider reicht mir meine Erkenntnis (noch) nicht aus, weshalb er die Varialen wieder vergisst, bzw nicht im Zwischenspeicher aufnimmt. Hat es etwas mit dem int lastButtonState = 0 zu tun?

Danke!