Arduino Uno Schrittmotor Abstandssensor

Hallo Zusammen,


```cpp
#include <Adafruit_VL53L0X.h>

const int dirPin = 9; 
const int stepPin = 10; 
const int taster1 = 2;
const int taster2 = 3;
const int taster3 = 4;
const int endschalter1 = 8;
bool taster3Gedrueckt = false; 

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

void setup() {
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(taster1, INPUT_PULLUP);
  pinMode(taster2, INPUT_PULLUP);
  pinMode(taster3, INPUT_PULLUP);
  pinMode(endschalter1, INPUT_PULLUP);

  // VL53L0X Sensor initialisieren
  if (!lox.begin()) {
    Serial.println("Fehler beim Initialisieren des VL53L0X Sensors!");
    while (1);
  }
}

void loop() {
  // Taster 1 (Uhrzeigersinn)
  if (digitalRead(taster1) == LOW) {
    // Abstand messen
    VL53L0X_RangingMeasurementData_t measure;
    lox.rangingTest(&measure, false); 

    if (measure.RangeStatus != 4) { 
      if (measure.RangeMilliMeter <= 30) {
        // Motor stoppen
        digitalWrite(stepPin, LOW); 
        return; 
      } else {
        // Wenn der Abstand größer als 30 mm ist, drehe den Motor
        digitalWrite(dirPin, LOW); 
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(1400); // Schrittgeschwindigkeit
        digitalWrite(stepPin, LOW);
      }
    }
  }

  // Taster 2 (Gegen den Uhrzeigersinn bis Endschalter)
  if (digitalRead(taster2) == LOW) {
    digitalWrite(dirPin, HIGH); 
    if (digitalRead(endschalter1) == LOW) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1400);
      digitalWrite(stepPin, LOW);
    }
  }

  // Taster 3 (Einmaliger Dreh gegen den Uhrzeigersinn bis Endschalter)
  if (digitalRead(taster3) == LOW && !taster3Gedrueckt) {
    taster3Gedrueckt = true; 
    digitalWrite(dirPin, HIGH); 
    while (digitalRead(endschalter1) == LOW) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(900); 
      digitalWrite(stepPin, LOW);
    }
    taster3Gedrueckt = false; 
  }
}



ich bin neu im Forum und möchte mich vorab für jede Antwort bedanken.
Folgendes Projekt würde ich gerne umsetzen.

Steuerung eines bipolaren Schrittmotor per TB6600 über Arduino Uno R3
Es sollen 3 Taster zur Steuerung der Drehrichtungen verbaut werden.
Taster 1 Drehrichtung positiv im Tippbetrieb bis Abstandssensor 30mm erfasst
Taster 2 Drehrichtung negativ im Tippbetrieb bis Endschalter.
Taster 3 Drehrichtung negativ einmaliger Druck bis Endschalter.

Aber jetzt zu meinem aktuellen Problem. Die Steuerung funktioniert einwandfrei bis ich die  Abstandsfunktion einfüge.
Sobald der VL53L0X 30mm erfasst wird der Motor gestoppt. Aber der Motor dreht sich nur schrittweise/ getaktet.
Ich vermute es ist ein Problem mit dem verwendeten Sensor, da dieser zulange benötig bis eine Messung abgeschlossen ist.

Ist das Problem bekannt?
Vielleicht kann mir jemand helfen, gerne auch über einen anderen Sensor oder vielleicht habe ich einfach einen Fehler im Code.


Gruß
Flo

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Hallo flolan

herzlich willkommen im Arduino-Forum,

Man kann so in etwa erahnen was der Schrittmotor macht aber richtig präzise ist das nicht beschrieben.

Du machst die Schrittmotoransteuerung "zu Fuß" mit dem delayMicroseconds()

Es gibt eine library bei der die Schrittimpulse-Erzeugung unabhängig vom sonstigen Code gemacht wird. Diese Library heißt MobaTools

Damit bekommst du den Motorlauf gleichmäßig.

Ansonsten solltest du mal einen Gesamtüberblick geben wozu der Schrittmotor sich so bewegen soll. Wenn man das weiß, dann kann man passende Vorschläge machen.

Schrittmotoren werden so betrieben, dass sie keine Schritte verlieren. Jedenfalls nicht im Normalbetrieb. Man mancht eine Referenzfahrt zum Endschalter und durch die Referenzfahrt weiß man dann die Position.
Die MobaTools erledigen dann auch gleich das Schritte zählen automatisch mit.
Damit kannst du dann jede beliebige Position anfahren und auch der Tippbetrieb kann dann jeweils eine ganz bestimmte Schrittanzahl fahren.

Das ist an der Stelle falsch.
Um festzustellen, ob das Abstand messen Deinen Code stört, habe ich mal was eingefügt.
Las den mal bitte laufen:

#include <Adafruit_VL53L0X.h>

const int dirPin = 9;
const int stepPin = 10;
const int taster1 = 2;
const int taster2 = 3;
const int taster3 = 4;
const int endschalter1 = 8;
bool taster3Gedrueckt = false;

Adafruit_VL53L0X lox = Adafruit_VL53L0X();
VL53L0X_RangingMeasurementData_t measure;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start... "));
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(taster1, INPUT_PULLUP);
  pinMode(taster2, INPUT_PULLUP);
  pinMode(taster3, INPUT_PULLUP);
  pinMode(endschalter1, INPUT_PULLUP);
  // VL53L0X Sensor initialisieren
  if (!lox.begin())
  {
    Serial.println("Fehler beim Initialisieren des VL53L0X Sensors!");
    while (1);
  }
}

void loop()
{
  // Taster 1 (Uhrzeigersinn)
  if (digitalRead(taster1) == LOW)
  {
    // Abstand messen
    uint32_t startZeit = millis();
    lox.rangingTest(&measure, false);
    uint32_t endZeit = millis();
    Serial.print(F("Messzeit: "));
    Serial.println(endZeit-startZeit);
    
    if (measure.RangeStatus != 4)
    {
      if (measure.RangeMilliMeter <= 30)
      {
        // Motor stoppen
        digitalWrite(stepPin, LOW);
        return;
      }
      else
      {
        // Wenn der Abstand größer als 30 mm ist, drehe den Motor
        digitalWrite(dirPin, LOW);
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(1400); // Schrittgeschwindigkeit
        digitalWrite(stepPin, LOW);
      }
    }
  }
  // Taster 2 (Gegen den Uhrzeigersinn bis Endschalter)
  if (digitalRead(taster2) == LOW)
  {
    digitalWrite(dirPin, HIGH);
    if (digitalRead(endschalter1) == LOW)
    {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1400);
      digitalWrite(stepPin, LOW);
    }
  }
  // Taster 3 (Einmaliger Dreh gegen den Uhrzeigersinn bis Endschalter)
  if (digitalRead(taster3) == LOW && !taster3Gedrueckt)
  {
    taster3Gedrueckt = true;
    digitalWrite(dirPin, HIGH);
    while (digitalRead(endschalter1) == LOW)
    {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(900);
      digitalWrite(stepPin, LOW);
    }
    taster3Gedrueckt = false;
  }
}

Die Ausgabe auf dem seriellen Monitor ist die Messzeit in millisekunden.

Hallo Stefan,

erstmal danke für die Unterstützung.

Die Funktion das der Motor auf null fährt und dann eine bestimmte Anzahl an Schritten wäre umsetzbar.

Folgend der Grund warum ich per Abstandsmessung fahren/ stoppen möchte:

Der Motor treibt einen höhenverstellbaren Lasertisch an.
Auf dem Tisch liegen immer unterschiedliche Materialstärken.
Also wäre es schön wenn ich nur das Material auflege einen Taster drücke und der Tisch fährt zur richtigen Position.
Der Abstandssensor ist am Lasermodul befestigt.

Ich hoffe ich konnte die Funktion verständlich erklären.

Gruß Florian

Hallo my_xy_projekt,

vielen Dank für die Hilfe.

Ich werde den Code gleich Mal ausprobieren.

my_xy_projekt,
so jetzt habe ich den code ausprobiert.

Der Motor stoppt wenn der Abstand unterschritten wird.
Aber der Motor dreht sich immer noch, nur sehr langsam und ruckelt.

Ich habe Mal ein Video gemacht. Vielleicht hilft das.
Link zum download:

Gruß Florian

Ich will die Zeit haben, die Dir der serielle Monitor ausgibt!

Ohne die macht das keinen Sinn.

sach mal .... bist du dir sicher dass du da das richtige Foto verlinkt hast?
Außerdem schreibst du was von Video. Das ist nur ein JPG-Bild aber kein Video

Bilder kann man direkt aus der Zwischenablage in ein Posting klatschen aber nur wenn man trustlevel 1 erreicht hat. Dazu musste 30 Minuten Online gelesen haben und 10 thread s angeschaut haben.
Videos auf Youtube hochladen. Die kann man dann auch direkt hier anschauen.

Auch wenn es dir nicht so vorkommen mag: Du arbeitest an einem Informatik-Projekt
Und das was in einem Informatik-Projekt am meisten gerbaucht wird ist präzise und detaillierte Information.

Warum sollte man das tun?

Hallo Stefan,

danke für den Hinweis.
Da hab ich anscheinend die falsche Datei erwischt sorry.

Hier das Video.

Die ausgeben Zeit ist 41.

HUI!
Also 10 hätte ich ja auch erwartet, aber das 4 fache ist schon happig.

Ich denk mal drüber nach.

Also das Auslesen des VL53L0X zusammen mit der Ausgabe der Zeitdauer dauert 41 Millisekunden.

Macht dann eine Schrittfrequenz von 1 / 0.041 sec = 24,39 Hz.
Deswegen knötert der Schrittmotor so vor sich hin.
Problemlösung: library MobaTools verwenden.

Wenn der Schrittmotor eine Referenzfahrt gemacht hat, kennt er seine Position und die Höhe des Tisches ohne Material drauf.
Dann Material auflegen und dann vor dem Losfahren messen was jetzt der Abstand mit Material ist.
Aus diesem gemessenen Abstand kann man dann berechnen wie weit der Tisch hochfahren muss.
Zusätzlich kannste dann wenn der Tisch hochgefahren ist noch einmal messen

// EDIT: Code von einem Rechtschreibfehler befreit

Hab ich gemacht.

EN- mit GND verbinden.
EN+ mit PIN 8 am Arduino verbinden.

#include <Adafruit_VL53L0X.h>

const int dirPin = 9;
const int stepPin = 10;
const int taster1 = 2;
const int taster2 = 3;
const int taster3 = 4;
const int endschalter1 = 8;
bool taster3Gedrueckt = false;

Adafruit_VL53L0X lox = Adafruit_VL53L0X();
VL53L0X_RangingMeasurementData_t measure;

constexpr uint8_t EN_Pin {8};


void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start... "));
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(taster1, INPUT_PULLUP);
  pinMode(taster2, INPUT_PULLUP);
  pinMode(taster3, INPUT_PULLUP);
  pinMode(endschalter1, INPUT_PULLUP);
  pinMode(EN_Pin, OUTPUT);
  digitalWrite(EN_PIN, LOW);
  // VL53L0X Sensor initialisieren
  if (!lox.begin())
  {
    Serial.println("Fehler beim Initialisieren des VL53L0X Sensors!");
    while (1);
  }
}

void loop()
{
  // Taster 1 (Uhrzeigersinn)
  if (digitalRead(taster1) == LOW)
  {
    // Abstand messen
    lox.rangingTest(&measure, false);
    if (measure.RangeStatus != 4)
    {
      if (measure.RangeMilliMeter <= 30)
      {
        // Motor stoppen
        digitalWrite(stepPin, LOW);
        digitalWrite(EN_pin, LOW);
        return;
      }
      else
      {
        // Wenn der Abstand größer als 30 mm ist, drehe den Motor
        digitalWrite(EN_Pin, HIGH);
        digitalWrite(dirPin, LOW);
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(1400); // Schrittgeschwindigkeit
        digitalWrite(stepPin, LOW);
      }
    }
  }
  // Taster 2 (Gegen den Uhrzeigersinn bis Endschalter)
  if (digitalRead(taster2) == LOW)
  {
    if (digitalRead(endschalter1) == LOW)
    {
      digitalWrite(EN_Pin, HIGH);
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1400);
      digitalWrite(stepPin, LOW);
      digitalWrite(EN_Pin, LOW
    };
  }
  // Taster 3 (Einmaliger Dreh gegen den Uhrzeigersinn bis Endschalter)
  if (digitalRead(taster3) == LOW && !taster3Gedrueckt)
  {
    taster3Gedrueckt = true;
    digitalWrite(dirPin, HIGH);
    while (digitalRead(endschalter1) == LOW)
    {
      digitalWrite(EN_Pin, HIGH);
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(900);
      digitalWrite(stepPin, LOW);
      digitalWrite(EN_Pin, LOW);
    }
    taster3Gedrueckt = false;
  }
}

Erklär mal.

(Solltest Du wieder Probleme mit kurzen Fragen haben, dann erörtere ich das auch gerne)

Also halt nochmal: Die MobaTools ermöglichen, dass die Schrittimpulsausgabe unabhängig vom sonstigen Code gemacht wird. Das wird über einen Timer-Interrupt realisiert.
Die MobaTools haben einen internen Schrittzähler wie viele Schritte wurden in Plus-Richtung oder Minus-Richtung ausgegeben. Man kann also jederzeit die Position in Bezug auf einen vom User gesetzten Nullpunkt abfragen.

Der zweite von mir beschriebene Ansatz: vor dem Positionieren den Abstand messen funktioniert auch ohne MobaTools. Wenn man mehr als 20 bis 30 Schritte pro Sekunde ausgeben will dann braucht zwingend eine sehr schnell durchlaufende Schleife.
Wie schnell hängt dann von der maximalen Schrittfrequenz ab.
Entweder diese Schleife befindet sich im Haupt-Code oder man benutzt wie die MobaTools einen Timer-Interrupt. Beide laufen schnell und ermöglichen dadurch die zeitlich korrekte Schrittausgabe.

Vermutlich ist das jetzt (schon wieder nicht das) was du lesen wolltest.
Nun meine Gehirnwindungen sind nun mal ganz anders geschnörkelt als deine.
Und die Kommunikation lässt sich deutliche effektiver gestalten wenn auch du präzise beschreibst was du meinst.
Könnte auch sein das "Erklär mal" heißen soll poste mal einen MobaTools Democode.
Bin ich heute nicht in Stimmung für Democodes.

Kannst Du mal erklären, wie Du damit den Motor schneller machen willst?

Wobei das hier:

auch etwas missverständlich ist. Ich gehe mal davon aus, dass der erste Satz so stimmt, wie er da steht. Dann kann sich der 2. Satzt nur darauf beziehen, dass der Motor zu langsam dreht, solange der Abstand eben noch nicht unterschritten ist. Und nicht, dass sich der Motor noch dreht, wenn der Abstand unterschritten ist, denn das wäre ein Widerspruch zum 1. Satz.
Hier zeigt sich, dass Kommas nicht nur schmückendes Beiwerk sind, sondern manchmal essentiell für die Bedeutung. Ich denke es sollte

Aber der Motor dreht sich immer noch nur sehr langsam und ruckelt.

heißen.
Das sollte @flolan mal eindeutig klären.

Ja das war nicht ganz eindeutig formuliert.

Also wenn ich den Taster 1 drücke und der Abstand kleiner als die 30mm sind, dreht sich der Motor nicht.

Wenn der Taster 1 gedrückt wird und der Abstand größer 30mm ist dreht sich der Motor, aber nur sehr langsam und ruckelt.

Die Option von Stefan habe ich auch schon in Erwägung gezogen.
Ich wollte halt eine möglichst einfache Steuerung und Bedienung.

Ich denke aber, dass der verwendete Abstandssensor vl53l0x nicht schnell genug messen kann.

Gruß Florian