Entfernung mehrfach abfragen

Hey Community,

habe ein Projekt bei dem ich die Distanz messe. Die Entfernung soll so oft gemessen werden, bis sie kleiner als 25cm ist. Danach sollen die Motoren darunter angesteuert werden. Habe den Code schon so weit fertig, jedoch wird die Distanz nur einmal abgefragt. (Die Distanzmessung und das Programm funktionieren)

Hier der Codeausschnitt:

                          // z-Achse faehrt aus
                  digitalWrite(dirPinz,HIGH); 
                    for(int x = 0; x < 14750; x++) {
                      digitalWrite(6, LOW);
                      digitalWrite(stepPinz,HIGH); 
                      delayMicroseconds(speedz); 
                      digitalWrite(stepPinz,LOW); 
                      delayMicroseconds(speedz);   
                   } 



digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance= duration*0.034/2;
Serial.print("Distance: ");
Serial.println(distance);
              





if (distance < 25){                  
                  
digitalWrite(dirPinz,LOW); 
                    while(digitalRead(zachsevorne) == LOW) {
                      digitalWrite(stepPinz,HIGH); 
                      delayMicroseconds(speedz); 
                      digitalWrite(stepPinz,LOW); 
                      delayMicroseconds(speedz);
                       
                      
                    }
                    digitalWrite(dirPinx,HIGH);
                    while(digitalRead(referenzx) == LOW) {
                      digitalWrite(6, HIGH);
                      digitalWrite(stepPinx,HIGH); 
                      delayMicroseconds(speedx); 
                      digitalWrite(stepPinx,LOW); 
                      delayMicroseconds(speedx); 
                    }

                     digitalWrite(dirPinx,HIGH); 
                    for(int x = 0; x < 320; x++) {
                      digitalWrite(stepPinx,HIGH);                      
                      delayMicroseconds(speedx); 
                      digitalWrite(stepPinx,LOW); 
                      delayMicroseconds(speedx); 
                    }
                   

                    
                    digitalWrite(dirPiny,HIGH);
                    for(int x = 0; x < 1000; x++) {
                      digitalWrite(stepPiny,HIGH); 
                      delayMicroseconds(speedy); 
                      digitalWrite(stepPiny,LOW); 
                      delayMicroseconds(speedy); 
                    }
                    delay(500);
                    digitalWrite(dirPiny,LOW);
                    while(digitalRead(referenzy) == LOW) {
                      
                      digitalWrite(stepPiny,HIGH); 
                      delayMicroseconds(speedy); 
                      digitalWrite(stepPiny,LOW); 
                      delayMicroseconds(speedy); 
                    }
                    digitalWrite(dirPiny,HIGH); // Enables the motor to move in a particular direction
                     // Makes 200 pulses for making one full cycle rotation
                    for(int x = 0; x < 500; x++) {
                      digitalWrite(stepPiny,HIGH); 
                      delayMicroseconds(speedy); 
                      digitalWrite(stepPiny,LOW); 
                      delayMicroseconds(speedy); 
                    }
                    islevelchecked = false;
                    isboxselected = false;
                    lcd.clear();
                    etage = 0;
                    spalte = 0;
                    counter + 1;
       }
       else{
                lcd.print("Bitte zuerst");
             lcd.setCursor(0, 1);
             lcd.print("Box auswaehlen");
             delay(3000);
               
        lcd.clear();
       }
      break;

      default:
        Serial.println(key);
    }
  }

Wir mögen keine Ausschnitte. Das ist nämlich so wie wenn Du die Autoschlüssel suchst aber nur im Bad suchen mußt, in dem Du aber seit Du gekommen bist nicht drin warst.
Gib und bitte den gesamten Sketch.
Grüße Uwe

Der Code ist fürs Forum zu lang :o

Habs mal auf Pastebin:

Pgoo:
Der Code ist fürs Forum zu lang :o

Dann bitte als Anhang

uwefed:
Dann bitte als Anhang

Hier der Sketch als Anhang:

sketch.ino (19.7 KB)

Pgoo:
Hier der Sketch als Anhang ...

Dein Sketch ist IMO irre schlecht zu lesen. Die Einrückungen folgen irgendeinem undurchschaubaren (esoterischen?) Muster und viele Zeilen sind länger als 80 Zeichen.

Solchen Code lese ich äußerst ungern und lasse es daher bleiben.

Gruß

Gregor

Die Einrückungen folgen irgendeinem undurchschaubaren (esoterischen?) Muster

Na ja. Da hab ich schon Schlimmeres gesehen.

habe ein Projekt bei dem ich die Distanz messe. Die Entfernung soll so oft gemessen werden, bis sie kleiner als 25cm ist. Danach sollen die Motoren darunter angesteuert werden. Habe den Code schon so weit fertig, jedoch wird die Distanz nur einmal abgefragt

Wenn du das keypad und evtl. auch die lcd-Anzeigge rausschmeisst und die Motor-Ansteuerung durch eine Demo simulierst, hast du einen Sketch der zu der Problembeschreibung passt, und anhand dessen wir leicht über dein Problem reden können.

Dein Problem zu verstehen wäre mir übrigens auch recht:
So wie du es beschreibst, wäre dein ganzer Sketch nichts als:

void loop() {
  int distance = getDistance(trigPin, echoPin);
  if ( distance > 0  // kein Fehler bei Messung  ?
          &&  distance < 25 ) moveMotors();
}

5 Zeilen ist erstens nicht sehr groß, und macht zweitens das was du willst (lt. deiner Beschreibung)

Beeinflussen die Motoren irgendwie die Entfernung die gemessen wird?
Man könntevoid moveMotors()auch so schreiben, dass es nicht blockiert und währenddessen die Entfernungsmessung weiter läuft. Dann könnte man das Ganze auch um ein keypad erweitern ...


Zeile 579 :                    counter + 1; bewirkt übrigens nichts

michael_x:
Na ja. Da hab ich schon Schlimmeres gesehen.

Wenn du das keypad und evtl. auch die lcd-Anzeigge rausschmeisst und die Motor-Ansteuerung durch eine Demo simulierst, hast du einen Sketch der zu der Problembeschreibung passt, und anhand dessen wir leicht über dein Problem reden können.

Dein Problem zu verstehen wäre mir übrigens auch recht:
So wie du es beschreibst, wäre dein ganzer Sketch nichts als:

void loop() {

int distance = getDistance(trigPin, echoPin);
  if ( distance > 0  // kein Fehler bei Messung  ?
          &&  distance < 25 ) moveMotors();
}



5 Zeilen ist erstens nicht sehr groß, und macht zweitens das was du willst (lt. deiner Beschreibung)

Beeinflussen die Motoren irgendwie die Entfernung die gemessen wird? 
Man könnte` void moveMotors() `auch so schreiben, dass es nicht blockiert und währenddessen die Entfernungsmessung weiter läuft. Dann könnte man das Ganze auch um ein keypad erweitern ...





---


` Zeile 579 :                     counter + 1;` bewirkt übrigens nichts

Danke schon mal für deine Antwort.
Der Sketch ist für einen Getränkeautomaten, der 3 Motoren ansteuert(X,Y,Z). Die Motoren sind dazu da einen Schieber zu positionieren, der dann einen Bolzen an das jeweilige Fach schiebt und das Getränk somit in die Ablage fällt. (Bolzen wird mit einem Relais vorgefahren, der automatisch zurück fährt wenn keine Spannung mehr anliegt) Dies mache ich mit

 digitalWrite(6, LOW);

Das Fach in dem das Getränk liegt wird durch das Keypad angesteuert und die LCD-Anzeige gibt Anweisungen. So weit funktioniert auch alles. Ich kann das jeweils gewünschte Fach anfahren.

Jetzt wird der Ultraschallsensor gebraucht um zu überprüfen ob das Getränk auch durch eine Rutsche durchgefallen ist. Die Idee hierbei: Ich messe die Distanz zur Wand (sind etwa 35 cm) und sehe dann wenn das Getränk die Rutsche pasiert hat (<25cm). Schlägt also der Ultraschallsensor an soll der Schieber aufhören vorzufahren. Relais wird wieder abgeschaltet:

 digitalWrite(6, HIGH);

Das Problem an meinem Code ist eben, dass durch meinen if Befehl die Distanz nur einmal abgefragt wird. Somit wird die Distanz abgefragt bevor das Getränk überhaupt hätte herausfallen können. Ich bräuchte eine Möglichkeit die Entfernung etwa alle 20ms abzufragen und dann, wenn die Distanz <25cm ist, das Programm erst weiterläuft.

Hast du die Ultraschallmessung als einzelnen Sketch in dem Automaten getestet? Weil Ultraschall hat eine keulenförmige Charakteristik beim messen. U.U. Brauchst du besondere Sensoren mit engem Öffnungswinkel.

Wenn du es kompliziert halten willst, wird die ganze Getränkeausgabe innerhalb eines einzigen loop-Durchlaufs abgehandelt. Auch da hilft dir eine Gliederung in mehrere Funktionen.

while(getDistance() > 25 ) {} // nichts tun

... wäre prinzipiell deine Lösung. Das Haupt-Problem an einer eigenen Schleife ist, dass du da nur über einen Reset wieder rauskommst, wenn mal was schief läuft.

Fehlerbehandlung (was du bisher weggelassen hast) nachträglich bei einem solchen Konzept hinzufügen, ist problematisch, weil du dann das Ganze an vielen Stellen verworren machen musst.

Wenn du es einfacher haben willst, nutzt du die Tatsache, dass loop() beliebig oft und schnell drankommen kann und du dir nur den aktuellen Zustand ( Taster-Wahl / Ansteuerung des Fachs / zurück / ... ) ausserhalb von loop() als globale Variable merken musst.

Im optimalen Fall langweilt sich der Arduino permanent, weil die 20 ms des Ultaschall-Mess-Intervalls noch nicht um sind und ein Stepper-Motor bei normaler Geschwindigkeit viele µs für jeden Schritt braucht.

Die Distanzmessung ist im
if(key) drinnen.

eine Zusammenfassung:

void loop() 
   {
   digitalWrite(6, HIGH);
   if (counter == 10)   // wird 1x augeführt
       {
       Referenzfahrt; 
       counter = 0;
       } 
   char key = kpd.getKey();
   if(key)  // Check for a valid key.
      {
      switch (key)
          {
          ...
          case '>':
             ...
             switch (etage)
                      { ... }
             switch (spalte)
                      { ... }
              // z-Achse faehrt aus
             digitalWrite(dirPinz,HIGH); 
             for(int x = 0; x < 14750; x++) 
                { ... }
             digitalWrite(trigPin, LOW);   /// Distanzmessung
             delayMicroseconds(2);
             digitalWrite(trigPin, HIGH);
             delayMicroseconds(10);
             digitalWrite(trigPin, LOW);
             duration = pulseIn(echoPin, HIGH);
             distance= duration*0.034/2;
             Serial.print("Distance: ");
             Serial.println(distance);
              
             if (distance < 25){ ... }
             }
        }                      
   }

Da Du nicht dauernd Tasten drückst und die Taste nicht dauernd ">" ist wird das nur einmal ausgeführt.

Außerdem ist die Distanzmessung nicht im der Schleife für die Z Achse

Gewöhne Dir mal an richtig einzurücken; so behälst Du den Überblick wo was in welcher Bedingung bzw Schleife ist.
Speichere die Eingabe ab und starte die Bewegung erst wenn die Eingabe bestätigt wird.
Tastendruck -> Eingaben Speichern -> Start -> Motore ansteuern.

Außerdem funktioniert eine Ultraschallmessung in einem ganz oder Teilweise geschlossenen Box sehr schlecht. Nimm Infrarotdistanzmesser.

Die Referenzfahrt solltest Du im setup() machen. Das wird automatisch einmal ausgeführt.

Grüße Uwe

michael_x:
Wenn du es kompliziert halten willst, wird die ganze Getränkeausgabe innerhalb eines einzigen loop-Durchlaufs abgehandelt. Auch da hilft dir eine Gliederung in mehrere Funktionen.

while(getDistance() > 25 ) {} // nichts tun

... wäre prinzipiell deine Lösung. Das Haupt-Problem an einer eigenen Schleife ist, dass du da nur über einen Reset wieder rauskommst, wenn mal was schief läuft.

Fehlerbehandlung (was du bisher weggelassen hast) nachträglich bei einem solchen Konzept hinzufügen, ist problematisch, weil du dann das Ganze an vielen Stellen verworren machen musst.

Wenn du es einfacher haben willst, nutzt du die Tatsache, dass loop() beliebig oft und schnell drankommen kann und du dir nur den aktuellen Zustand ( Taster-Wahl / Ansteuerung des Fachs / zurück / ... ) ausserhalb von loop() als globale Variable merken musst.

Im optimalen Fall langweilt sich der Arduino permanent, weil die 20 ms des Ultaschall-Mess-Intervalls noch nicht um sind und ein Stepper-Motor bei normaler Geschwindigkeit viele µs für jeden Schritt braucht.

Habe das mit dem while Loop nochmals probiert:

digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance= duration*0.034/2;
Serial.print("Distance: ");
Serial.println(distance);
              
while(distance > 25 ) {
   Serial.println(distance);
      } // nichts tun                  
                  
digitalWrite(dirPinz,LOW); 
                    while(digitalRead(zachsevorne) == LOW) {
                      digitalWrite(stepPinz,HIGH); 
                      delayMicroseconds(speedz); 
                      digitalWrite(stepPinz,LOW); 
                      delayMicroseconds(speedz);

Das Problem ist, dass der Arduino einen Wert misst (z.B 39) und dieser Wert dann immer der gleiche ist. Es wird also auch nur einmal gemessen und immer der gleiche Wert mit <25 verglichen. Hat jemand eine Idee wie ich das Problem sonst noch lösen könnte?

Danke schonmal

Du kommst doch niemals aus dieser while Schleife raus.

Es fehlt doch in dieser while Schleife ein Abfragen des Sensors, der den Wert distance auch jedesmal neu einliest.

statt:
while(distance > 25 ) {
Serial.println(distance);
} // nichts tun

richtig:
while(distance > 25 ) {
distance = readsensor(); //also irgendeine Abfrage des Sensors und die Variable distance neu befüllen.
Serial.println(distance);
} // nichts tun

Joerg_L:
Du kommst doch niemals aus dieser while Schleife raus.

Es fehlt doch in dieser while Schleife ein Abfragen des Sensors, der den Wert distance auch jedesmal neu einliest.

statt:
while(distance > 25 ) {
Serial.println(distance);
} // nichts tun

richtig:
while(distance > 25 ) {
distance = readsensor(); //also irgendeine Abfrage des Sensors und die Variable distance neu befüllen.
Serial.println(distance);
} // nichts tun

Danke dir. Habe es jetzt mit folgendem Code hinbekommen:

 digitalWrite(trigPin, LOW);
          delayMicroseconds(2);
          digitalWrite(trigPin, HIGH);
          delayMicroseconds(10);
          digitalWrite(trigPin, LOW);
          duration = pulseIn(echoPin, HIGH);
          distance= duration*0.034/2;
          Serial.print("Distance: ");
          Serial.println(distance);

              
        while(distance > 20 ) {
  
            digitalWrite(trigPin, LOW);
            delayMicroseconds(2);
            digitalWrite(trigPin, HIGH);
            delayMicroseconds(10);
            digitalWrite(trigPin, LOW);
            duration = pulseIn(echoPin, HIGH);
            distance= duration*0.034/2;
            Serial.print("Distance: ");
            Serial.println(distance);
               } // Scan Distance                 
                  
                    digitalWrite(dirPinz,LOW); 
                    while(digitalRead(zachsevorne) == LOW) {
                      digitalWrite(stepPinz,HIGH); 
                      delayMicroseconds(speedz); 
                      digitalWrite(stepPinz,LOW); 
                      delayMicroseconds(speedz);

Kann geclosed werden.

Das wurde ihm in #9 bereits von michael_x gesagt. Er ignoriert die Hinweise aber beharrlich.

Gruß Tommy

Tommy56:
Das wurde ihm in #9 bereits von michael_x gesagt. Er ignoriert die Hinweise aber beharrlich.

Gruß Tommy

Bin in #11 darauf eingegangen
Mfg

Du hbast in #11 darauf geantwortet, den Hinweis

while(getDistance() > 25 ) {} // nichts tun

dabei aber ignoriert.

Gruß Tommy

Daß es jetzt funktioniert ist nur ein Zufall.
Lerne Programmieren und lerne den Sketch besser zu strukturieren und nimm einen Infrarotentfernungsmesser statt Ultraschall.
Grüße Uwe