MoBa Tools Notstop

Ich habe ein inzwischen gut laufendes Stepper-Motor Projekt (danke nochmals für die Unterstützung @MicroBahner !) mit Moba Tools im Einsatz.

Als kleine Draufgabe zur Motorsteuerung habe ich jetzt auch einen HC-SR04 Ultraschallsensor angeschlossen, der mit sich mit meinem Rig mitbewegt und im Grunde ein Abstandssensor zum Endpunkt/ ein Park-Piepserl sein soll.

Im manuellen Fahrmodus (Einmal klicken startet stepper.rotate, ein zweites Mal klicken stepper.stop) funktioniert ein Notstop durch ein vom Sensor ausgelöstes stepper.stop einwandfrei.

Im "Normalmodus", also einer Fahrt mittels stepper.move, schafft er aber die Unterbrechung nicht. Ich habe das Sensorsystem über millis() realisiert um keine Verzögerungen durch Delay zu erhalten, aber stepper.move lässt sich, einmal gestartet, nicht von seinem Weg abbringen. Gibt es hier eine andere Möglichkeit für einen Notstop?

Ich kopiere zur besseren Übersicht jetzt nur mal die Normal Run, Manual Run und Stepper Funktionen hier rein. Sollte der ganze Code (inkl. ner Menge Touchscreen Code und anderer Funktionen, die nichts mit dem Sensor zu tun haben) notwendig werden, stelle ich ihn gerne noch hoch.

Normal:

/***************************************************************************
 * normal run function
 ****************************************************************************/
void doNormalRun(int speed_set, int ramp_set, long distance_set){
      stepper.setMaxSpeed(speed_set); 
      stepper.setRampLen(ramp_set);   

      updateStr("Starting Normal Run");   
      tft.fillRect(0, tft.height()-35, tft.width(), 5, RED); // Create Red Progress Bar Basis

      currentPos = stepper.currentPosition();
      stepper.move(distance_set*10*motorDirection);

      while(stepper.stepsToDo() > 0){
        Serial.println(stepper.moving());
        tft.fillRect(0, tft.height()-35, tft.width()-(tft.width()/100*stepper.moving()), 5, GREEN); // Progress Bar   
      } 
          if(stepper.stepsToDo() == 0)
          { 
            tft.fillRect(0, tft.height()-35, tft.width(), 5, BLACK); // "Remove" Progress Bar
          }   
          if(return_to_home == true){
            updateStr("Returning Home");
            stepper.moveTo(currentPos);
                while(stepper.stepsToDo() > 0){ // Progress Bar for Home Run
                Serial.println(stepper.moving());
                tft.fillRect(tft.width(), tft.height()-35, -(tft.width()-(tft.width()/100*stepper.moving())), 5, BLUE); 
                }
              if(stepper.currentPosition() == currentPos){
            tft.fillRect(0, tft.height()-35, tft.width(), 5, BLACK); // "Remove" Progress Bar
              }       
          } 
}

Manual:

//--------------------MANUAL button - RETURN TO HOME BUGGY?
      if ((p.y >= 10) && (p.x >= 140) && (p.y <= 100) && (p.x <= 210) ) { 
      
      currentPos = stepper.currentPosition();
      //Set Basic Speed and Acceleration/Ramp of each Steppers at startup
      stepper.setMaxSpeed(speed_set);
      stepper.setRampLen(ramp_set); 

      if(manual_start_or_stop == true){ //start run on first click   
      //stepper.setZero(0); //set current Position as 0 
      updateStr("Starting Manual Run");
      stepper.rotate(motorDirection);
      manual_start_or_stop = !manual_start_or_stop;
      }
      else{ // stop run on second click
        //Serial.println(stepper.currentPosition()); // DEBUG
         String traveledMsg = "Manual Run stopped after ";
        traveledMsg.concat(stepper.currentPosition());
        traveledMsg.concat(" Steps.");
        updateStr(traveledMsg);
        manual_start_or_stop = !manual_start_or_stop;
          if(return_to_home == true){
            Serial.print("Current Position: "); Serial.println(stepper.currentPosition());
            Serial.print("Start Position: ");Serial.println(currentPos);
            updateStr("Returning Home"); 
            stepper.moveTo(currentPos);
              if(stepper.currentPosition() == currentPos){ // turn motor of after reaching Home
            stepper.stop();
              }       
          } else{stepper.stop();} //motor off 
          }
      }

Sensor:

void setup() {  
    pingTimer = millis(); // Start Timer
}

void loop() {

// start optional sonar module
if (millis() >= pingTimer) {   // pingSpeed milliseconds since last ping, do another ping.
    pingTimer += pingSpeed;      // Set the next ping time.
    sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status.
  }
}

/*****************************************************************************
 * Optional Sonar Module
 ****************************************************************************/
void echoCheck() { 
  if (sonar.check_timer()) { // This is how you check to see if the ping was received.
    int myPing = sonar.ping_result / US_ROUNDTRIP_CM;
    
    Serial.print("Ping: ");
    Serial.print(myPing); // Ping returned, uS result in ping_result, convert to cm with US_ROUNDTRIP_CM.
    Serial.println("cm");
    if(myPing<=7){stepper.stop();} // Emergency Brake if closer than 7cm to Target
  }
}

Kein Wunder.
Nach den Codefragmenten wartest Du ja ununterbrechbar bis er alle Schritte gefahren ist:

      while(stepper.stepsToDo() > 0){
        Serial.println(stepper.moving());
        ...
      }

Da ist was dran :wink: D.h. ich muss mir was anderes überlegen für ne Rückmeldung, dass er am Zielort angekommen ist für den Rückfahrmodus. An sich ja durch ein If lösbar, aber dann muss ich irgendwie die Fortschrittsanzeige davon abkoppeln, dass sich das nicht spießt...

Ok, also sobald ich das while rausnehme funktioniert der Sensor. Allerdings kommt er nie in der Abfrage für den Return nach Ende der Fahrt an:

      stepper.move(distance_set*10*motorDirection);

      /*while(stepper.stepsToDo() > 0){
        Serial.println(stepper.moving());
        tft.fillRect(0, tft.height()-35, tft.width()-(tft.width()/100*stepper.moving()), 5, GREEN); // Progress Bar   
      } */
          if(stepper.moving() == 0)
          { Serial.println("Target Reached");

Ganz egal ob ich stepper.moving() == 0 oder stepper.stepsToDo() == 0 nehme.

Hast Du irgendwo (außerhalb des veröffentlichten Codes) ein Triggervariable, die das Auslösen des Ultraschallsensors mitteilt?

Dann wäre ja eine Behandlung innerhalb der while()-Schleife möglich:

      while(stepper.stepsToDo() > 0) {
        if (endPunktTrigger)
        {
          // behandle den vorzeitig erkannten Endpunkt hier
          // Motor stop oder so was in der Art
        }
        else
        {
          Serial.println(stepper.moving());
          tft.fillRect(0, tft.height()-35, tft.width()-(tft.width()/100*stepper.moving()), 5, GREEN); // Progress Bar   
        }
      }

Ja, inzwischen habe ich eine eingebaut, werde deinen Vorschlag auch gleich mal testen, vielen Dank!


   if(sonar.ping(MAX_DISTANCE)!=0){ //Make one Ping on max Distance to test if ultrasonic module is attached
      tft.fillRect(0, 0, tft.width(), 2, GREEN); // Green Bar shows that Ultrasonic Sensor has been connected
      Serial.print("Sonar Module attached.");
      sonar_attached = true;
    } else {Serial.print("Sonar Module not found or no obstacle in range.");}
}

Also Es ist immer am besten den kompletten Sketch zu posten. Auch wenn dann wenn der komplette Sketch 3000 Zeilen hat.

Wenn man ganz gut programmieren kann dann findet man sich immer zurecht.
Und wenn der code dann auch noch in functions organisiert ist sowieso.

ein stepper.stop() wirkt IMMER und sofort.

Dein sonstiger Code muss das stepper.stop() einfach nur an der passenden Stelle aufrufen.
Tja und wenn du dir eine Schleife baust die keine entsprechende Abfrage enthält dann geht's nun mal nich.

Du hast keinen Link gepostet bei dem man nachlesen kann was dein Projekt als ganzes ist.
Für einen wirklichen NOT-Stop würde ich immer einen direkt hardware-mäßig verdrahteten Öffner-Kontakt der die Spannungsversorgung des Schrittmotors ganz direkt unterbricht, einbauen.

Eine Software kann immer irgendwie rumspinnen. Ein Öffner-Kontakt der bei "zu weit fahren" rein mechanisch betätigt wird und die Stromzufuhr zum Schrittmotortreiber unterbricht, ist da sehr viel zuverlässiger.

1 Like

Wenn es wirklich ein Notstop sein soll, scheidet eine Lösung in Software aus Sicherheitsgründen aus. Wenn es etwas Anderes ist, sollte man es nicht Notstop nennen.

Gruß Tommy

Wahre Worte @StefanL38 :wink: Wie @wno158 schon ganz richtig gesagt hat liegt des Pudels Kern tatäschlich in den Schleifen, weil mein Code die Unterbrecherfunktion gar nicht zu Wort kommen lässt.

Zu deiner Frage bzgl des Projektes: Es gibt noch keinen Projektthread, nur ne Menge einzelner Detailfragen weil ich hard- und softwareseitig noch dran arbeite. Es wird ein motorisierter Kameraslider (ich bin beruflich Filmschaffender) mit Touchscreensteuerung. Nur hat er sich inzwischen von nur "Fahre eine Strecke mit vorgegebenem Tempo ab" schon sehr viel weiter entwickelt. Inzwischen sind eben eine Timelapsefunktion, Return to Home Funktion, Fahrrichtungsänderung und eben auch besagter Sensor zum Abstoppen, falls ich mich mit der Fahrdistanz mal verrechnen sollte, mit an Bord.

@Tommy56 dann nennen wirs "Stop bevor der Schlitten mit der Kamera drauf am Ende ankommt und der Motor sich ausbrennt weil er versucht weiter zu drehen und nicht weiter kann". Ist aber irgendwie deutlich länger :smiley: Ich bin offen für alternative Bezeichnungen :wink:

Endstop

Gruß Tommy

1 Like

Das passiert bei einem Schrittmotor bauartbedingt nicht. Der Strom ist während sich der Schrittmotor dreht dreht genauso groß wie wenn der Schrittmotor steht. Der strom fließt durch die feststehenden Spulen. Bei Microstepping wird er in Stufen heruntergeschaltet. Aber wenn er genau auf einem "Fullstep" stehen bleibt dann ist der Strom maximal.

Das einzige was passieren kann, ist dass wenn man den Schrittmotor nun tagelang gegen einen mechanischen Endanschlag rattern lässt das sich da die Lager mechanisch schneller abnutzen.

Durchbrennen würde ein Schrittmotor nur dann wenn der Strom höher eingestellt ist als das was der Schrittmotor verträgt. Er würde dann auch im freien Lauf wenn der Motor nur seine eigene Achse dreht durchbrennen.

Wieder was gelernt, danke :slight_smile:

Das ist so nicht ganz richtig, wie man z.B. and den Tabellen eines DRV8825 oder A4988 erkennen kann. Die Stromtreiber regeln den Strom im Microstep-Betrieb immer so, dass die Summe der Verlustleistung in beiden Spulen konstant bleibt. Wenn z.B. in einer Spule der Strom beim Microstepping unter dem 'FullStep-Strom' liegt, ist er dafür in der anderen Spule höher.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.