Serial.print-Zeilen reduzieren Steppermotorgeschwindigkeit

Hallo,

ich habe eine Fräse, mit der ich Macroaufnahmen von kleinen Objekten machen möchte. Die Kamera ist an der Z-Achse befestigt. Der Abstand der Kamera zum Objekt soll immer gleich sein. Dafür habe ich einen Sharp IR GP2D120 (4-30 cm) neben der Kamera montiert und zum Aufnahmebereich ausgerichtet.
Der Code der Z-Achse alleine funktioniert. Der Code um allgemein die Achsen ohne Delay zu bewegen funktioniert nun auch. Ich bin aber nicht sicher wie ich die beiden zusammenfüge.

Die Bewegung der X- und Y-Achse verläuft unabhängig von Z. Wenn ich mit Switch case arbeite, werden bestimmte Wege abgefahren und jede Bewegungsänderung bekommt ein eigenes Case. Die Z-Achse muß aber Case-Übergreifend bewegt werden.
So wie der Code nun aussieht, bewegen sich die X- und Y- Achsen und auch die Z-Achse. Die Z-Achse reagiert zufriedenstellend auf die Messwerte. Aber X- und Y-Achsen laufen extrem reduziert. Die Bewegung ist mit dem Auge fast nicht wahr zu nehmen. Ich habe zum Spass den unteren Codebereich, der Sensordaten und Umsetzung in Z-Achsenbewegung beinhaltet, Zeile für Zeile einkopiert und die Fräse jedesmal angefahren. Die Serial.print-Zeilen sind das Problem. Je mehr Serial.print-Zeilen um so langsamer laufen X- und Z-Achse. :o
Hat jemand eine Idee?

#include <Arduino.h>

int dirPin_X = 5;
int stepperPin_X = 2;

int dirPin_Y = 6;
int stepperPin_Y = 3;

int dirPin_Z = 7;
int stepperPin_Z = 4;

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

//sensor
int sensorPin = A5;
int Distance = 0;
int sollAbstand = 104; //Abstand des Sensors zum Objekt; Kameraabstand dann 90mmm zum Objekt


void setup()
{
  Serial.begin (9600);
  pinMode(dirPin_X, OUTPUT);
  pinMode(stepperPin_X, OUTPUT);
  pinMode(dirPin_Y, OUTPUT);
  pinMode(stepperPin_Y, OUTPUT);
  pinMode(dirPin_Z, OUTPUT);
  pinMode(stepperPin_Z, OUTPUT);
  }

  void step_1(boolean dir, int steps) // Einstellungen für die Z-Achse
  {
  digitalWrite(dirPin_Z,dir);
  delay(50);
    for(int i=0;i<steps;i++)
    {
    digitalWrite(stepperPin_Z, HIGH);
    delayMicroseconds(600);
    digitalWrite(stepperPin_Z, LOW);
    delayMicroseconds (600);
    }
}
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(dirPin_X, 1);
      digitalWrite(stepperPin_X, 1);
      delayMicroseconds(500);
      digitalWrite(stepperPin_X, 0);
      delayMicroseconds(500);
      interval = move_x;
      break;  
      
      case 2:
      digitalWrite(dirPin_Y, 1);
      digitalWrite(stepperPin_Y, 1);
      delayMicroseconds(2000);
      digitalWrite(stepperPin_Y, 0);
      delayMicroseconds(2000);
      interval = move_y;      
      break;
    }
--------------------//////////////-------------------
    // der untere Bereich umfasst die Messdaten 
    //des Sharpsensors und die Übergabe an die Z-Achse
    // die Serial.print Zeilen haben Einfluß auf die Geschwindigkeit der X- und Y-Achse
    // je mehr Zeilen um so langamer die X- und Y-Achse
    
    Distance = analogRead(sensorPin);
    Serial.print("Messwert: "); Serial.print(Distance); Serial.print(" ");
    int DistanceConverted = (207600 / (Distance-11))/10;

    DistanceConverted = constrain(DistanceConverted, 50, 150); 
    Serial.print("abs. Abstand: "); Serial.print(DistanceConverted); Serial.print("mm ");
    Serial.print("rel. Abstand: "); Serial.print(DistanceConverted - sollAbstand); Serial.println(" mm");
    
    if (DistanceConverted == 50)
    {
      step_1(true,0);
    }
    else if (DistanceConverted == 150)
    {
      step_1(true,0);
    }  
    else if (DistanceConverted > 104)
    {
      step_1(true,300);
    }  
    else if (DistanceConverted < 104)
    {
      step_1(false,300);
    } 

 }

MakroPix:
Hat jemand eine Idee?

Mit 9600 Baud kannst Du nicht mehr als 960 Zeichen pro Zekunde ausgeben, dann ist Schicht im Serial-Schacht.

Versuch's mal mit:

 Serial.begin (115200);

oder:

 Serial.begin (500000);

Bei 500000 Baud kannst Du allerdings dann nicht mehr den Seriellen Monitor der Arduino-IDE verwenden, der diese Baudrate nicht unterstützt, sondern Du müßtest ein "Serielles Terminalprogramm" starten, bei dem Du diese Baudrate auch einstellen kannst.

Sobald der Serial Buffer voll ist, ist Serial.print() und sein Bruder blockierend.

@jurs
Die Umstellung auf 115200 hat bei mir keine Auswirkung auf die Geschwindigkeit der Motoren.

MakroPix:
@jurs
Die Umstellung auf 115200 hat bei mir keine Auswirkung auf die Geschwindigkeit der Motoren.

Wenn selbst eine Beschleunigung der Serial-Ausgabe um das mehr als 10-fache keinen sichtbaren Unterschied zeigt, aber es sicher ist, dass Serial die Ausgabe bremst, müßtest Du die Anzahl der Serial-Ausgaben drastisch reduzieren.

Zum Beispiel einen Sekundenzähler (Halbsekundenzähler, Viertelsekundenzähler) machen und dann nur alle viertel, halbe oder ganze Sekunde einmal die Serialausgabe machen:

 if (HalbsekundenWechsel())
 {
   Serial.print("abs. Abstand: "); Serial.print(DistanceConverted); Serial.print("mm ");
   Serial.print("rel. Abstand: "); Serial.print(DistanceConverted - sollAbstand); Serial.println(" mm");
}

Wenn Du Dir eine geeignete "HalbsekundenWechsel()" Funktion machst, die bei zigtausend aufeinander folgenden Aufrufen immer nur einmal in einer halben Sekunde 'true' zurückliefert, so dass die Ausgabe nur zweimal pro Sekunde erfolgt, sollte Dein Programm dann nicht mehr so stark ausgebremst werden.

Bekommst Du so eine Funktion alleine hin?

Ich hatte schon, um den Datenschwall am seriellen Monitor etwas zu auszubremsen, ganz am Ende eine delay(150) Funktion eingebaut. So hatte ich weniger Daten, aber immer noch keine bessere Bewegung an X-und Y-Achse. Hier fürs Forum habe ich Sie dann aber wieder rausgenommen.Vielleicht nicht so clever.

Den Halbsekundenwechsel kriege ich alleine nicht hin. Das ist sicher etwas eleganter als mit delay().

Aber ich bin mir nicht sicher ob der serielle Output tatsächlich das Problem ist.
Und was noch interessant ist: die Funktion der Z-Achse ist nicht eingeschränkt. Die bewegt sich schnell und flüssig.

MakroPix:
Den Halbsekundenwechsel kriege ich alleine nicht hin. Das ist sicher etwas eleganter als mit delay().

Aber ich bin mir nicht sicher ob der serielle Output tatsächlich das Problem ist.

Oben hattest Du aber noch geschrieben:

Die Serial.print-Zeilen sind das Problem.
Je mehr Serial.print-Zeilen um so langsamer laufen X- und Z-Achse. :o

Jetzt plötzlich bist Du nicht mehr sicher?

Ich wäre mir auch nicht sicher, ob nur Serial-Ausgaben das Problem sind. Denn Du hast Dein Programm haufenweise gespickt mit "delay()" und "delayMicroseconds()" Aufrufen, die Dein Programm ständig ausbremsen.

Und mit "ständig ausbremsen" kannst Du nie ein flüssig laufendes Programm schreiben.

Hier ist der Code für eine "HalbsekundenWechsel()" Funktion ohne delay:

boolean HalbsekundenWechsel()
{
  static unsigned long oldMillis;
  if (millis()-oldMillis>=500)
  {
    oldMillis+=500;
    return true;
  }
  return false;
}

Wenn es wirklich nur die Serial Ausgaben sind, die Deinen Code ausbremsen, sollte der Ablauf flüssiger werden, wenn Du die angegebenen Änderungen machst, so dass nur zweimal pro Sekunde die Zeilen auf Serial ausgegeben werden.

Und wenn nicht, dann sind es Deine ganzen Blockierungen des Codes mit Aufrufen von "delay()" und "delayMicroseconds()", die Du durch eine geänderte Programmlogik aus dem Programm entfernen müßtest.

Hallo jurs,

ich habe mich da vielleicht etwas mißverständlich ausgedrückt. Entschuldigung dafür.

Serial.Print macht X- und Y-Achse langsamer. Aber nicht die Z-Achse. Ich vermutete deshalb, dass die Position der serial.Print-Zeilen das Problem sind und ich sie vielleicht im Switch case einbinden muß. Deshalb sagte ich, dass ich mir nicht sicher sei, ob serial.Print das Problem ist.

Vielen Dank für die "HalbsekundenWechsel()" Funktion.

Hallo,

der HalbsekundenWechsel von jurs war die Lösung. Jetzt sind alle Achsen in etwa gleich schnell.
Danke!!

X- und Y-Achse haben jetzt die richtige Geschwindigkeit. Sie stoppen aber immer wenn ein verwertbarer Meßwert von der Z-Achse umgesetzt wird. Wie kann ich die Arbeit der x-y-Achse unabhängig von der Z-Achse und den Meßwerten machen? Muß ich den Sensor und Z-Achsen-Code in den Case von X und Y-Achse verschachteln?

#include <Arduino.h>

int dirPin_X = 5;
int stepperPin_X = 2;

int dirPin_Y = 6;
int stepperPin_Y = 3;

int dirPin_Z = 7;
int stepperPin_Z = 4;

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

//sensor
int sensorPin = A5;
int Distance = 0;
int sollAbstand = 104; //Abstand des Sensors zum Objekt; Kameraabstand dann 90mmm zum Objekt


void setup()
{
  Serial.begin (9600);
  pinMode(dirPin_X, OUTPUT);
  pinMode(stepperPin_X, OUTPUT);
  pinMode(dirPin_Y, OUTPUT);
  pinMode(stepperPin_Y, OUTPUT);
  pinMode(dirPin_Z, OUTPUT);
  pinMode(stepperPin_Z, OUTPUT);
  }

void step_1(boolean dir, int steps) // Einstellungen für die Z-Achse
  {
  digitalWrite(dirPin_Z,dir);
  delay(50);
    for(int i=0;i<steps;i++)
    {
    digitalWrite(stepperPin_Z, HIGH);
    delayMicroseconds(600);
    digitalWrite(stepperPin_Z, LOW);
    delayMicroseconds (600);
    }
}

bolean HalbsekundenWechsel()
   {
    static unsigned long oldMillis;
    if (millis()-oldMillis >= 500)
      {
       oldMillis += 500;
       returnd true;
       }
     return false;
}

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(dirPin_X, 1);
      digitalWrite(stepperPin_X, 1);
      delayMicroseconds(500);
      digitalWrite(stepperPin_X, 0);
      delayMicroseconds(500);
      interval = move_x;
      break; 
     
      case 2:
      digitalWrite(dirPin_Y, 1);
      digitalWrite(stepperPin_Y, 1);
      delayMicroseconds(2000);
      digitalWrite(stepperPin_Y, 0);
      delayMicroseconds(2000);
      interval = move_y;     
      break;
    }
--------------------//////////////-------------------
    // der untere Bereich umfasst die Messdaten
    //des Sharpsensors und die Übergabe an die Z-Achse

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

    DistanceConverted = constrain(DistanceConverted, 50, 150);
    Serial.print("abs. Abstand: "); Serial.print(DistanceConverted); Serial.print("mm ");
    Serial.print("rel. Abstand: "); Serial.print(DistanceConverted - sollAbstand); Serial.println(" mm");
   
    if (DistanceConverted == 50)
    {
      step_1(true,0);
    }
    else if (DistanceConverted == 150)
    {
      step_1(true,0);
    } 
    else if (DistanceConverted > 104)
    {
      step_1(true,300);
    } 
    else if (DistanceConverted < 104)
    {
      step_1(false,300);
  }
 }
}

Hallo,

im Post #8 hatte ich erwähnt, das jetzt zwar die X-und Y-Achsen eine ordentliche Geschwindigkeit haben, aber auch immer kurz blockieren wenn die Z-Achse einen Meßwert verarbeitet (sich also bewegt).
jurs meint, da sind zu viele delays drinne.

der aktuelle Code ist:

#include <Arduino.h>

int dirPin_X = 5;
int stepperPin_X = 2;

int dirPin_Y = 6;
int stepperPin_Y = 3;

int dirPin_Z = 7;
int stepperPin_Z = 4;

unsigned long move_x =2000;
unsigned long move_y =100;
unsigned long move_z =600;
unsigned long interval;


//sensor
int sensorPin = A5;
int Distance = 0;
int sollAbstand = 104; //Abstand des Sensors zum Objekt; Kameraabstand dann 90mmm zum Objekt

/////////////////////////
void setup()
{
  Serial.begin (9600);
  pinMode(dirPin_X, OUTPUT);
  pinMode(stepperPin_X, OUTPUT);
  pinMode(dirPin_Y, OUTPUT);
  pinMode(stepperPin_Y, OUTPUT);
  pinMode(dirPin_Z, OUTPUT);
  pinMode(stepperPin_Z, OUTPUT);
  }

void step_1(boolean dir, int steps) // Einstellungen für die Z-Achse
  {
  digitalWrite(dirPin_Z,dir);
  delay(50);
    for(int i=0;i<steps;i++)
    {
    digitalWrite(stepperPin_Z, HIGH);
    delayMicroseconds(600);
    digitalWrite(stepperPin_Z, LOW);
    delayMicroseconds (600);
    }
}

//////////////////////
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()

{
  static unsigned long lastMillis = 0;
  unsigned long currentMillis = millis();
  static byte step = 1;
  
  if(currentMillis - lastMillis >= interval)
      {
    lastMillis = currentMillis;
      if (++step ==5) step =1;
    }
     switch (step)
    {
      case 1:
      digitalWrite(dirPin_X, 1);
      digitalWrite(stepperPin_X, 1);
      delayMicroseconds(300);
      digitalWrite(stepperPin_X, 0);
      delayMicroseconds(300);
      interval = move_x;
      
      break;  
      
      case 2:
      digitalWrite(dirPin_Y, 1);
      digitalWrite(stepperPin_Y, 1);
      delayMicroseconds(300);
      digitalWrite(stepperPin_Y, 0);
      delayMicroseconds(300);
      interval = move_y;      
      break;
      
      case 3:
      digitalWrite(dirPin_X, 0);
      digitalWrite(stepperPin_X, 1);
      delayMicroseconds(300);
      digitalWrite(stepperPin_X, 0);
      delayMicroseconds(300);
      interval = move_x;
      break;  
      
      case 4:
      digitalWrite(dirPin_Y, 1);
      digitalWrite(stepperPin_Y, 1);
      delayMicroseconds(300);
      digitalWrite(stepperPin_Y, 0);
      delayMicroseconds(300);
      interval = move_y;      
      break;
    }
  
    // der untere Bereich umfasst die Messdaten 
    //des Sharpsensors und die Übergabe an die Z-Achse
    
   if (HalbsekundenWechsel())
      {
    Distance = analogRead(sensorPin);    
    Serial.print("Messwert: "); Serial.print(Distance); Serial.print(" ");
    int DistanceConverted = (207600 / (Distance-11))/10;

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

    if (DistanceConverted == 50)  //Z-Achse soll sich nicht bewegen
    {
      digitalWrite(dirPin_Z, 1);
      digitalWrite(stepperPin_Z, 0);
      digitalWrite(stepperPin_Z, 0);
      interval_2 = move_z;
    }
    else if (DistanceConverted == 150)  //Z-Achse soll sich nicht bewegen
    {
      digitalWrite(dirPin_Z, 1);
      digitalWrite(stepperPin_Z, 0);
      digitalWrite(stepperPin_Z, 0);
      interval_2 = move_z;
    }  
    else if (DistanceConverted > 104)  //Z-Achse soll sich nach oben bewegen
    {
      digitalWrite(dirPin_Z, 1);
      digitalWrite(stepperPin_Z, 1);
      delayMicroseconds(600);
      digitalWrite(stepperPin_Z, 0);
      delayMicroseconds(600);
      interval_2 = move_z;
    }  
    else if (DistanceConverted < 104)  //Z-Achse soll sich nach unten bewegen
    {
      digitalWrite(dirPin_Z, 0);
      digitalWrite(stepperPin_Z, 1);
      delayMicroseconds(600);
      digitalWrite(stepperPin_Z, 0);
      delayMicroseconds(600);
      interval_2 = move_z;
   }    

}
}
}

Was muß ich ändern, dass x- und y-Achse unabhängig vom Sensor und der Z-Achse agieren?
Vielen Dank