Schrittmotor, delayMicroseconds() ersetzen

Hallo,
ich möchte in meiner Schrittmotorsteuerung die blockierenden delays ersetzen. Das ist aber gar nicht so einfach. Ich hatte den Beitrag von Robin2 gelesen Simple Stepper Program - Motors, Mechanics, Power and CNC - Arduino Forum, dort der zweite Sketch.
Den habe ich nun mit meinem alten Code kombiniert. Bewegt sich aber nichts. >:(

Kann mir bitte jemand sagen wie ich delayMicroseconds() ersetzen kann bzw. millis() richtig einsetze?

Viele Grüsse
Jan

#include <Arduino.h>

// Achsen Belegung der Ausgänge
int X_STEP_PIN =   54;
int X_DIR_PIN =    55;
int X_ENABLE_PIN=  38; //Active LOW


unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 200;

unsigned long move_x =200;
unsigned long interval;

void setup()//#################
{
  pinMode(X_STEP_PIN, OUTPUT);
  pinMode(X_DIR_PIN, OUTPUT);
  pinMode(X_ENABLE_PIN,OUTPUT);
}

void X_Achse()//#################
{
  if (curMillis - prevStepMillis >= millisBetweenSteps)
  {
    prevStepMillis += millisBetweenSteps;
    digitalWrite(X_STEP_PIN, HIGH);
    digitalWrite(X_STEP_PIN, LOW);
   }
}

void loop()//###################
{
  {
  static unsigned long lastMillis = 0;
  unsigned long currentMillis = millis();
  static byte step = 1;
 
  if(currentMillis - lastMillis >= interval)
  {
    lastMillis = currentMillis;
      if (++step == 3) step =1;
    }
 
    switch (step)
    {
      case 1:
      digitalWrite(X_DIR_PIN, 1);
      digitalWrite(X_ENABLE_PIN, 0);
      X_Achse();
      interval = move_x;
      break;
            
      case 2:
      digitalWrite(X_DIR_PIN, 0);
      digitalWrite(X_ENABLE_PIN, 0);
      X_Achse();
      interval = move_x;
      break;

      }
   }
}

Was stört dich an delayMicroseconds? Es könnte das Problem auftreten, dass du die Timings dann nicht mehr einhalten kannst.

Ich möchte noch einen Infrarot-Sensor auslesen und damit einen anderen Schrittmotor bewegen.

Mir wurde damals mit Nachdruck empfohlen den Code nochmal ganz von vorne aufzubauen und alle delay() und delayMicroseconds() rauszuschmeißen. Serial.print-Zeilen reduzieren Steppermotorgeschwindigkeit - #9 by MakroPix - Deutsch - Arduino Forum #6

Das versuche ich nun.

Ich habe millisBetweenSteps von 200 auf 1 geändert und nun bewegt sich der Motor. Allerdings doch arg langsam. Mit delayMicroseconds() war es sehr einfach die Motorgeschwindigkeit einzustellen.
Kann mir jemand einen Vorschlag machen, wie ich die Motorgeschwindigkeit erhöhen kann?

Viele Grüsse
Jan

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 1;

unsigned long move_x =2000;
unsigned long interval;

Neben millis() gibt es auch micros() um die µs zu zählen. Ich weiß aber nicht wie gut das auf die Art funktioniert.

könntest ein gemeinsames

void loop() {
   ...

  // alle Motoren, die sich bewegen sollen, STEP_PIN HIGH setzen und steps-- merken.
     ...  
  delayMicroseconds(300);
  digitalWrite(X_STEP_PIN, LOW);  
  digitalWrite(Y_STEP_PIN, LOW);
  digitalWrite(Z_STEP_PIN, LOW);
  delayMicroseconds(300);
}

an das ende von loop hängen.

Wenn vorher ca. 1300 Hz Pulse für 1 Motor ok war, laufen auch alle zusammen, genauso schnell.

Vielen Dank für die Vorschläge.

@ michael_x...habe ich noch nicht probiert. Aber mit micros() scheint es zu funktionieren.

@ Serenifly..ich habe mich eben mal mit deinem micros()-Vorschlag beschäftigt. Es gibt einen Menschen der einen nichtblockierenden Code entwickelt hat.

.....ziemlich weit unten ist der Ausgangscode......

das ergibt einen neuen Code für mich:

#include <Arduino.h>

// Achsen Belegung der Ausgänge
int X_STEP_PIN =   54;
int X_DIR_PIN =    55;
int X_ENABLE_PIN=  38; //Active LOW

unsigned long t = 0;
unsigned long STEP_DELAY_SHOW = 0;

unsigned long move_x =3000;
unsigned long interval;

void setup()//#################
{
  pinMode(X_STEP_PIN, OUTPUT);
  pinMode(X_DIR_PIN, OUTPUT);
  pinMode(X_ENABLE_PIN,OUTPUT);
}

void X_Achse_positv(long stepDelay)//#################
{
  digitalWrite(X_DIR_PIN, HIGH);
  digitalWrite(X_STEP_PIN, HIGH);
  delayMicroseconds(stepDelay);
  digitalWrite(X_STEP_PIN, LOW);
  
  unsigned long dt = micros() - t;
  if(dt < STEP_DELAY_SHOW)
  {
    delayMicroseconds(STEP_DELAY_SHOW - dt);
    }
  t = micros();
}
void X_Achse_negativ(long stepDelay)//#################
{
  digitalWrite(X_DIR_PIN, LOW);
  digitalWrite(X_STEP_PIN, HIGH);
  delayMicroseconds(stepDelay);
  digitalWrite(X_STEP_PIN, LOW);
  
  unsigned long dt = micros() - t;
  if(dt < STEP_DELAY_SHOW)
  {
    delayMicroseconds(STEP_DELAY_SHOW - dt);
    }
  t = micros();
}
void loop()//###################
{
  {
  static unsigned long lastMillis = 0;
  unsigned long currentMillis = millis();
  static byte step = 1;

  if(currentMillis - lastMillis >= interval)
  {
    lastMillis = currentMillis;
      if (++step == 3) step =1;
    } 
    switch (step)
    {
      case 1:
      X_Achse_positv(300);
      interval = move_x;
      break;
      
      case 2:
      X_Achse_negativ(300);
      interval = move_x;
      break;
   
      }
   }
}

Damit lässt sich die Geschwindigkeit gut regeln und es ist deutlich schneller als mit dem alten Code. Ich werde jetzt mal einen IR Sensor und einen zweiten Motor dazunehmen um zu testen ober er nicht doch blockierend ist.
Vielen Dank noch einmal für deinen Tip.

Alles in Großbuchstaben sind Konstanten! Keine Variablen. Du hast aus STEP_DELAY_SHOW eine Variable gemacht und die noch dazu auf 0 gesetzt.

Auf der Webseite ist das nicht deklariert. Das hat dich wohl verwirrt. Auf der Github Seite ist es 250

ober er nicht doch blockierend ist

Brauchst du nicht zu testen. Ist er. Aber immer gleich lang (ist jedenfalls das Ziel), damit der Motor gleichmässig schnell steppt, und innerhalb jeden Schritts kurz mal eine Funktion ausgeführt werden kann.

Hallo,
@serenifly: habe ich gändert, STEP_DELAY_SHOW ->StepDelayShow = 250;

Mit dem folgenden Code fährt die X-Achse hin und her. Ich höre auch ein ein Klopfen vom Halbsekundenwechsel an der Z-Achse. Sie dreht sich aber pro Halbsekundenwechsel nur um 1 bis zwei Schritte.

@michael_x: Ich möchte erreichen, dass der X-Motor einen vorgegebenen Weg abfährt, parallel dazu der IR-Sensor in einem bestimmten Intervall (Halbsekundenwechsel) die Distanz zu einem Objekt misst und der Z-Motor auf den Wert reagieren kann. Die Reaktion des Z-Motors soll aber den X-Motor möglichst nicht beeinflussen. Geht das überhaupt?

Welchen Wert muß ich denn ändern, dass "DoOtherStuff" so klein ist, das die Funktion in jedem Step ausgeführt werden kann?

#include <Arduino.h>

// Achsen Belegung der Ausgänge
int X_STEP_PIN =   54;
int X_DIR_PIN =    55;
int X_ENABLE_PIN=  38; //Active LOW

int Z_STEP_PIN =   46;
int Z_DIR_PIN =    48;
int Z_ENABLE_PIN=  62; //Active LOW

unsigned long t = 0;
unsigned long StepDelayShow = 250;

unsigned long move_x =1000;
unsigned long move_z =1000;
unsigned long interval;

//sensor
int sensorPin = A12;
int Distance;
int sollAbstand = 94; //Abstand des Sensors zum Objekt; Kameraabstand dann 90mmm zum Objekt

void setup()//#################
{
  Serial.begin (9600);
  pinMode(X_STEP_PIN, OUTPUT);
  pinMode(X_DIR_PIN, OUTPUT);
  pinMode(X_ENABLE_PIN,OUTPUT);

  pinMode(Z_STEP_PIN, OUTPUT);
  pinMode(Z_DIR_PIN, OUTPUT);
  pinMode(Z_ENABLE_PIN,OUTPUT);
  

}
void X_Achse_positv(long stepDelay)//#################
{
  digitalWrite(X_ENABLE_PIN, LOW);
  digitalWrite(X_DIR_PIN, HIGH);
  digitalWrite(X_STEP_PIN, HIGH);
  delayMicroseconds(stepDelay);
  digitalWrite(X_STEP_PIN, LOW);
  
  unsigned long dt = micros() - t;
  if(dt < StepDelayShow)
  {
    delayMicroseconds(StepDelayShow - dt);
    }
  t = micros();
}
void X_Achse_negativ(long stepDelay)//#################
{
  digitalWrite(X_ENABLE_PIN, LOW);
  digitalWrite(X_DIR_PIN, LOW);
  digitalWrite(X_STEP_PIN, HIGH);
  delayMicroseconds(stepDelay);
  digitalWrite(X_STEP_PIN, LOW);
  
  unsigned long dt = micros() - t;
  if(dt < StepDelayShow)
  {
    delayMicroseconds(StepDelayShow - dt);
    }
  t = micros();
}
void Z_Achse_positiv (long stepDelay)//#################
{
  digitalWrite(Z_ENABLE_PIN, LOW);
  digitalWrite(Z_DIR_PIN, HIGH);
  digitalWrite(Z_STEP_PIN, HIGH);
  delayMicroseconds(stepDelay);
  digitalWrite(Z_STEP_PIN, LOW);
  
  unsigned long dt = micros() - t;
  if(dt < StepDelayShow)
  {
    delayMicroseconds(StepDelayShow - dt);
    }
  t = micros();
}
void Z_Achse_negativ (long stepDelay)//#################
{
  digitalWrite(Z_ENABLE_PIN, LOW);
  digitalWrite(Z_DIR_PIN, LOW);
  digitalWrite(Z_STEP_PIN, HIGH);
  delayMicroseconds(stepDelay);
  digitalWrite(Z_STEP_PIN, LOW);
  
  unsigned long dt = micros() - t;
  if(dt < StepDelayShow)
  {
    delayMicroseconds(StepDelayShow - dt);
    }
  t = micros();
}
boolean HalbsekundenWechsel()//beeinflusst den Abruf von Daten im Seriellen Monitor
{
  static unsigned long oldMillis;
  if (millis()-oldMillis >= 500)
  {
    oldMillis += 500;
    return true;
    }
   return false;

  }
void loop()//###################
{   
  if (HalbsekundenWechsel())
    {
      
    Distance = analogRead(sensorPin);
    Serial.print("Messwert: "); Serial.print(Distance); Serial.print(" ");
    int DistanceConverted = (207600 / (Distance-11))/10;

    DistanceConverted = constrain(DistanceConverted, 50, 130); 
    Serial.print("abs. Abstand: "); Serial.print(DistanceConverted); Serial.print("mm ");
    Serial.print("rel. Abstand: "); Serial.print(DistanceConverted - sollAbstand); Serial.println(" mm");
    

    if (DistanceConverted == 130)//umgerechneter Messwert ist gleich 130
    { Z_Achse_negativ(0);
      interval = move_z;}    
    else if (DistanceConverted == 50)//umgerechneter Messwert ist gleich 50
    {Z_Achse_negativ(0);
      interval = move_z;}    
    else if (DistanceConverted == 90)
    {Z_Achse_negativ(0);
      interval = move_z;}
    else if (DistanceConverted > 91) //umgerechneter Messwert ist größer als 90
    {Z_Achse_positiv(100);
     interval = move_z;}
    else if (DistanceConverted < 91) //umgerechneter Messwert ist kleiner als 90
    {Z_Achse_negativ(100);
     interval = move_z;}
     }
    

  static unsigned long lastMillis = 0;
  unsigned long currentMillis = millis();
  static byte step = 1;
  
    if(currentMillis - lastMillis >= interval)
  {
    lastMillis = currentMillis;
      if (++step == 3) step =1;
    } 
    switch (step)
    {
      case 1:
      X_Achse_positv(500);
      interval = move_x;
      break;
      
      case 2:
      X_Achse_negativ(500);
      interval = move_x;
      break;
        }
    }

Hallo,
ich könnte mir vorstellen, die Verwendung der Programmbibliothek AccelStepper könnte Dich schneller zum Ziel führen. Da gibt man verschiedene Parameter an und schon drehen sich die Motoren.

Wenn Du es ohne Programmbibliothek schaffen möchtest, müßtest Du m. E. das Konzept ändern.