Kugelbahn-Maschine

Habe jetzt habe ich dem Servo mal (4000) Delay gegeben. Jetzt bewegt er sich.

und um das Ende der Liftbewegung abzuwarten, hab ich das noch eingefügt:

 if (!stepLift.moving())

Sowohl if (!stepLift.moving() ) für den Schrittmotor wie auch if (!servoArm.moving() )` für die Servobewegung benötigst Du noch häufiger in Deinem Programm. Du mußt die Schrittkette solange aufhalten, bis die jeweilige Bewegung laut Bibliothek abgeschlossen ist.

Daher muß das Weiterschalten der Schrittkette auch in die Bedingung eingebunden werden:

    case Schritt::ARM_SCHWENKT_HIN: // Arm schwenkt zur Bahn
      if (!stepLift.moving() ) {
        servoArm.write(-60);
        Serial.println("ARM_SCHWENKT_HIN:Arm schwenkt rüber");
        schritt = Schritt::KUGEL_ABSTREIFEN;  // ←────
      }
      break;

Und das sollte es doch hier auch machen, oder?

 case Schritt::ARM_SCHWENKT_HIN: // Arm schwenkt zur Bahn
      if (!stepLift.moving() ) {
        servoArm.write(-60);
        Serial.println("ARM_SCHWENKT_HIN:Arm schwenkt rüber");
        schritt = Schritt::KUGEL_ABSTREIFEN;  // ←────
      }
      break;

Die markierte Zeile steht in Deinem Programm eine Zeile tiefer, also hinter der geschweiften Klammer. Das macht einen großen Unterschied, weil der Ablauf nicht aufgehalten wird.

Ah ok, danke. :wink:

Bitte!

Grundsätzlich benötigst Du nach jedem .write() ein Warten auf das Ende der Bewegung.

Also nochmal nur damit ich das richtig verstehe. So wäre es richtig?

 case Schritt::ARM_SCHWENKT_HIN: // Arm schwenkt zur Bahn
      if (!stepLift.moving() ) {
        servoArm.write(-60);
        Serial.println("ARM_SCHWENKT_HIN:Arm schwenkt rüber");
        schritt = Schritt::KUGEL_ABSTREIFEN;  // ←────
      }
      break;

Ja!

Gut :laughing:

Im Moment habe ich diesen Sketch am Laufen, aber offensichtlich habe ich da noch etwas nicht richtig verstanden. Es bewegt sich zur Zeit nur der Servo, der Lift (Schrittmotor) jedoch nicht:

#include <MobaTools.h>
#include "Wire.h"




constexpr uint16_t NULLPOSLIFT = 200; // Abstand Referenzpunkt (LS) zum Nullpunkt

const byte dirPin = 3;
const byte enaPin = 4;
const byte stepPin = 5;
const int servoPin = 9;  //  servo

int buttonState = 0;

//const byte refLift = A0;
//const int sensor = A1;

const byte inPins[] = { A0, A1 };
const byte pinAnzahl = sizeof(inPins);
const int stepsPerRevLift = 2000;

enum : byte { refLift, sensor};
#define MAX8BUTTONS     // optional, spart Speicherplatz ( Standard ist maximal 16 Taster )
MoToButtons Taster ( inPins, pinAnzahl, 20, 2000 );  // Einrichten der Tasterverwaltung

enum class Schritt : byte { REF_CHK_LIFT, REF_FREI_LIFT, REF_LIFT, REF_LIFT_GEFUNDEN, LIFT_RUNTER, LIFT_HOCH, ARM_SCHWENKT_HIN, KUGEL_ABSTREIFEN, LIFT_ETWAS_RUNTER, ARM_SCHWENKT_RETOUR };

MoToStepper stepLift(stepsPerRevLift, STEPDIR);  // Schrittmotor Lift
MoToServo servoArm;    // Servo ArmMoToButtons Taster(inPins, pinAnzahl, 20, 2000); // Einrichten der Tasterverwaltung
bool SchrittmotorAUSMsgPrinted = false;

void setup() {

  Serial.begin(9600);

  stepLift.attachEnable(enaPin, 100, LOW);
  stepLift.attach(stepPin, dirPin);
  stepLift.setSpeed(800);
  stepLift.setRampLen(100);

  servoArm.attach(servoPin); // servo at pin 9
  servoArm.setSpeed( 20 );    // set servo speed
}

void loop() {
  Taster.processButtons();



  // Erkennen des Referenzpunktes ( unabhängig von der FSM )

  if (Taster.pressed(refLift)) {   // Wenn Referenzpunkt erreicht, Bewegung anhalten und Nullpunkt setzen.
    stepLift.setZero(NULLPOSLIFT);  // Nullpunkt etwas hinter den referenzpunkt setzen, um ihn auch bei Schrittverlusten sicher zu erreichen
    stepLift.write(0);
    Serial.println("Ref-Lift erreicht");

  }
  static Schritt schritt = Schritt::REF_CHK_LIFT;

  switch (schritt) {

    case Schritt::REF_CHK_LIFT:
      if (!Taster.state(refLift)) {    // checken, ob Mikroschalter gedrückt ist
        stepLift.write(-300);
        delay(4000);
        Serial.println("REF_CHK_LIFT:checken ob Kugel am Mikroschalter");
        schritt = Schritt::REF_FREI_LIFT;

      } else {
        schritt = Schritt::REF_LIFT;  // Refpunkt suchen
      }
      break;

    case Schritt::REF_FREI_LIFT:

      if (!stepLift.moving()) {
        if (Taster.released(refLift))
          stepLift.write(-100);  // Schalter frei fahren
        delay(2000);
        Serial.println("REF_FREI_LIFT:Mikroschalter wird frei gefahren");
        schritt = Schritt::REF_LIFT;

      }
      break;

    case Schritt::REF_LIFT:
      stepLift.write(200);
      delay(2000);
      Serial.println("REF_LIFT:Kugel fährt zum Mikroschalter");
      schritt = Schritt::REF_LIFT_GEFUNDEN;

      break;

    case Schritt::REF_LIFT_GEFUNDEN:
      if (Taster.state(refLift)) {   // Bewegung Lift starten
        Serial.println("REF_LIFT_GEFUNDEN:Referenzpunkt gefunden und Nullpunkt gesetzt");
        schritt = Schritt::LIFT_RUNTER;

      }
      break;

    case Schritt::LIFT_RUNTER:
      if (!SchrittmotorAUSMsgPrinted) {
        stepLift.attachEnable(enaPin, 100, HIGH);  // Lift fährt runter
        Serial.println("SchrittmotorAUS");
        SchrittmotorAUSMsgPrinted = true;
      }

      if (Taster.pressed(sensor)) {
        SchrittmotorAUSMsgPrinted = false;
        stepLift.attachEnable(enaPin, 100, LOW);
        Serial.println("SchrittmotorAN");
        stepLift.write(-2000);
        delay(8000);
        Serial.println("LIFT_RUNTER:Lift fährt hinunder");
        schritt = Schritt::LIFT_HOCH;
      }
      break;

    case Schritt::LIFT_HOCH:  // Lift fährt hoch
      if (!stepLift.moving()) {
        stepLift.write(2000);
        delay(8000);
        Serial.println("LIFT_HOCH:Lift fährt hoch");
        schritt = Schritt::ARM_SCHWENKT_HIN;
      }
      break;

    case Schritt::ARM_SCHWENKT_HIN: // Arm schwenkt zur Bahn

      if (!stepLift.moving()) {

        servoArm.write(45);
        delay(2000);
        servoArm.write(0);
        delay(2000);
        Serial.println("ARM_SCHWENKT_HIN:Arm schwenkt rüber");

        schritt = Schritt::KUGEL_ABSTREIFEN;
      }
      break;

    case Schritt::KUGEL_ABSTREIFEN:  // Kugel wird abgestreift
      stepLift.write(20);
      Serial.println("KUGEL_ABSTREIFEN:Kugel wird abgestreift");
      schritt = Schritt::LIFT_ETWAS_RUNTER;


    case Schritt::LIFT_ETWAS_RUNTER:  // Lift fährt etwas runter
      stepLift.write(-20);
      Serial.println("Lift fährt ein wenig runter");
      schritt = Schritt::ARM_SCHWENKT_RETOUR;
      break;


    case Schritt::ARM_SCHWENKT_RETOUR: //Arm schwenkt zurück



      servoArm.write(90);
      delay(4000);
      Serial.println("ARM_SCHWENKT_RETOUR:Arm schwenkt zurück");
      schritt = Schritt::LIFT_RUNTER;
      break;

  }
}

Doch funktioniert :smile:

Nur die Abläufe sind noch nicht in trockenen Tücher. Da muss ich noch einige skorrigieren.

Irgendwie gehorcht mir die Maschine nicht. Wenn der Lift hochfährt und auf den Mikroschalter drückt sollte der Lift stoppen und wieder etwas nach runter fahren. Macht er aber im;oment nicht sondern fährt einfach weiter hoch.

#include <MobaTools.h>
#include "Wire.h"




constexpr uint16_t NULLPOSLIFT = 200; // Abstand Referenzpunkt (LS) zum Nullpunkt

const byte dirPin = 3;
const byte enaPin = 4;
const byte stepPin = 5;
const int servoPin = 9;  //  servo

int buttonState = 0;

//const byte refLift = A0;
//const int sensor = A1;

const byte inPins[] = { A0, A1 };
const byte pinAnzahl = sizeof(inPins);
const int stepsPerRevLift = 2000;

enum : byte { refLift, sensor};
#define MAX8BUTTONS     // optional, spart Speicherplatz ( Standard ist maximal 16 Taster )
MoToButtons Taster ( inPins, pinAnzahl, 20, 2000 );  // Einrichten der Tasterverwaltung

enum class Schritt : byte { REF_CHK_LIFT, REF_FREI_LIFT, REF_LIFT, REF_LIFT_GEFUNDEN, LIFT_RUNTER, LIFT_HOCH, ARM_SCHWENKT_HIN, KUGEL_ABSTREIFEN, LIFT_ETWAS_RUNTER, ARM_SCHWENKT_RETOUR };

MoToStepper stepLift(stepsPerRevLift, STEPDIR);  // Schrittmotor Lift
MoToServo servoArm;    // Servo ArmMoToButtons Taster(inPins, pinAnzahl, 20, 2000); // Einrichten der Tasterverwaltung
bool SchrittmotorAUSMsgPrinted = false;

void setup() {

  Serial.begin(9600);

  stepLift.attachEnable(enaPin, 100, LOW);
  stepLift.attach(stepPin, dirPin);
  stepLift.setSpeed(80);
  stepLift.setRampLen(100);

  servoArm.attach(servoPin); // servo at pin 9
  servoArm.setSpeed( 20 );    // set servo speed
}

void loop() {
  Taster.processButtons();

  // Erkennen des Referenzpunktes ( unabhängig von der FSM )

  if (Taster.pressed(refLift)) {   // Wenn Referenzpunkt erreicht, Bewegung anhalten und Nullpunkt setzen.
    stepLift.setZero(NULLPOSLIFT);  // Nullpunkt etwas hinter den referenzpunkt setzen, um ihn auch bei Schrittverlusten sicher zu erreichen
    stepLift.write(0);
    delay(3000);
    Serial.println("Ref-Lift erreicht");

  }
  static Schritt schritt = Schritt::REF_CHK_LIFT;

  switch (schritt) {

    case Schritt::REF_CHK_LIFT:
      if (!Taster.state(refLift)) {    // checken, ob Mikroschalter gedrückt ist
        stepLift.doSteps(-2000);
        delay(3000);
        Serial.println("REF_CHK_LIFT:checken ob Kugel am Mikroschalter");
        schritt = Schritt::REF_FREI_LIFT;

      } else {
        schritt = Schritt::REF_LIFT;  // Refpunkt suchen
      }
      break;

    case Schritt::REF_FREI_LIFT:

        if (Taster.released(refLift)) {
          stepLift.doSteps(100);  // Schalter frei fahren
        delay(3000);
        Serial.println("REF_FREI_LIFT:Mikroschalter wird frei gefahren");
        schritt = Schritt::REF_LIFT;
}
      break;

    case Schritt::REF_LIFT:
      stepLift.write(-200);
      delay(3000);
      Serial.println("REF_LIFT:Kugel fährt zum Mikroschalter");
      schritt = Schritt::REF_LIFT_GEFUNDEN;

      break;

    case Schritt::REF_LIFT_GEFUNDEN:
      if (Taster.state(refLift)) {   // Bewegung Lift starten
        Serial.println("REF_LIFT_GEFUNDEN:Referenzpunkt gefunden und Nullpunkt gesetzt");
        schritt = Schritt::LIFT_RUNTER;

      }
      break;

    case Schritt::LIFT_RUNTER:
      if (!SchrittmotorAUSMsgPrinted) {
        stepLift.attachEnable(enaPin, 100, HIGH);  // Lift fährt runter
        Serial.println("SchrittmotorAUS");
        SchrittmotorAUSMsgPrinted = true;
      }

      if (Taster.pressed(sensor)) {
        SchrittmotorAUSMsgPrinted = false;
        stepLift.attachEnable(enaPin, 100, LOW);
        Serial.println("SchrittmotorAN");
        stepLift.doSteps(2500);
        delay(11000);
        Serial.println("LIFT_RUNTER:Lift fährt hinunder");
        schritt = Schritt::LIFT_HOCH;
      }
      break;

    case Schritt::LIFT_HOCH:  // Lift fährt hoch
      if (!stepLift.moving()) {
        stepLift.doSteps(-2500);
        delay(11000);
        Serial.println("LIFT_HOCH:Lift fährt hoch");
        schritt = Schritt::ARM_SCHWENKT_HIN;
      }
      break;

    case Schritt::ARM_SCHWENKT_HIN: // Arm schwenkt zur Bahn

      if (!stepLift.moving()) {

        servoArm.write(45);
        delay(2000);
        servoArm.write(0);
        delay(2000);
        Serial.println("ARM_SCHWENKT_HIN:Arm schwenkt rüber");

        schritt = Schritt::KUGEL_ABSTREIFEN;
      }
      break;

    case Schritt::KUGEL_ABSTREIFEN:  // Kugel wird abgestreift
      stepLift.write(-50);
      Serial.println("KUGEL_ABSTREIFEN:Kugel wird abgestreift");
      schritt = Schritt::LIFT_ETWAS_RUNTER;


    case Schritt::LIFT_ETWAS_RUNTER:  // Lift fährt etwas runter
      stepLift.write(20);
      Serial.println("Lift fährt ein wenig runter");
      schritt = Schritt::ARM_SCHWENKT_RETOUR;
      break;


    case Schritt::ARM_SCHWENKT_RETOUR: //Arm schwenkt zurück



      servoArm.write(90);
      delay(4000);
      Serial.println("ARM_SCHWENKT_RETOUR:Arm schwenkt zurück");
      schritt = Schritt::LIFT_RUNTER;
      break;

  }
}

Dann nutze bitte den seriellen Monitor zur Fehlersuche :wink:

Kannst Du mal eine Prinzipskizze machen, aus der ersichtlich ist wie sich Stepper und Servo bewegen, und wo die entsprechenden Schalter sind?

Ausserdem mischt Du im Sketch Schritte und Winkel beim Stepper. ist das Absicht?

ich bin dran :wink:

Nicht unbedingt. Ich bin am ausprobieren, was am Besten funktioniert.

Funktion:

Refrenzierung: Lift fährt nach oben, drückt auf den Microschalter, Null wird gesetzt, Lift geht wieder etwas nach unten um den Schalter zu verlassen.

Ablauf: Lift fährt nach unten, holt sich die Kugel. fährt hoch bis zum Schalter, wieder etwas runter, Servo dreht nach links, Lift fährt etwas hoch und streift die Kugel ab, fährt wieder etwas runter, danach dreht der Servo wieder nach rechts an die Ausgangsposition.

Ok, das Problem waren glaube ich die Delay nach dem Kontakt mit dem Mikroschalter. Die habe ich jetzt rausgenommen. Jetzt stoppt die Sache jedoch danach und die Schrittkette wird nicht ausgeführt.

  if (Taster.pressed(refLift)) {   // Wenn Referenzpunkt erreicht, Bewegung anhalten und Nullpunkt setzen.
    stepLift.setZero(NULLPOSLIFT);  // Nullpunkt etwas hinter den referenzpunkt setzen, um ihn auch bei Schrittverlusten sicher zu erreichen
    stepLift.write(0);
    //delay(3000);
    Serial.println("Ref-Lift erreicht");

Das ist gut. Und wenn Du uns zu einer Frage auch den Inhalt des seriellen Monitors zusätzlich zum aktuellen Programm zeigst, wäre eine Hilfe eventuell leichter.

Danke, das Bild hilft schon etwas beim Verständnis.

Ist das nicht beides dasselbe? Weshalb brauchst Du eine getrennte Referenzierung, wenn Du im Ablauf eh immer bis zum Schalter fährst? Oder andersrum: Warum fährst Du im Ablauf bis zum Schalter und dann wieder ein Stück zurück, wenn Du nach der Referenzierung gleich nur bis zu dem Punkt fahren könntest, wo das Schwenken stattfindet?

Im Sketch gibt es auch noch einen 'sensor', der in deinem Bild nicht vorkommt.

Schalte auch mal die Warnungen ein, da fehlt wohl noch ein break;
Die stepLift.attachEnable gehören aus dem Ablauf raus ( hatten wir aber glaube ich schonmal ... )

Den ganzen Ablauf im Sketch muss ich mir jetzt mal genauer anschauen. Irgendwie stimmen da auch die Kommentare nicht, und das Warten auf das jeweilige Bewegungsende sieht auch suspekt aus :roll_eyes: ...

Ich stecke allerdings gerade ziemlich tief in einem eigenen Projekt, kann also immer ein wenig dauern bis ich mich melde :innocent: