Schrittmotor Takt Richtung

Hallo liebes Forum

Über die Google Suche bin ich schon öfters auf dieses Forum gestossen und konnte auch schon einige hilfreiche Tipps mitnehmen. Unteranderem sah ich in diesem Forum ein Thema, dass meinem ziemlich ähnlich oder gleich kommt.

Ich möchte über eine serielle Eingabe der Drehzahl, das entsprechende Rechtecksignal erzeugen und damit auf den Takteingang gehen. Für den Motor gilt: 1 Umdrehung = 800 Flankensetzer. Mit diesen Angaben kann ich ja die Frequenz bestimmen bzw. Pulsabstand bestimmen. So sieht mein Code aus:


Dieser funktioniert allerdings nicht. Doch wegen was nicht? Diese Frage würde ich gerne en Euch liebes Forum weitergeben.

Hallo,

was funktioniert mit dem Code nicht?
Kommt kein Takt?
Der falsche Takt?
Schwankt der Takt zu stark?

Dein Problem wird wohl der falsche Vergleich sein.
Ändere das einmal in

if (micros() - start_puls >= tp)
  {
    start_puls = start_puls + tp;  	// neue Vergleichszeit setzen
    ...
  }

Um Driftungen zu vermeiden addiert man das Intervall einfach auf.

Sorry, da war ich in meinem Beitrag unpräzise. Der Motor läuft beim Abspielen keinen einzigen Schritt. Die berechnete Periodendauer die stimmt soweit (Habe ich nochmals überprüft, die Rechnung sollte also stimmen).

Fehlt in deinem Vorschlag nicht eine erste Initialiserung von start_puls? Er hat ja noch keinen micros() Wert wenn man es weglässt? Oder irre ich mich da?

Plausibilitätskontrolle: Je schneller die rpm werden sollen, desto länger wird die Zeit zwischen den Impulsen???

Die Information ist ein wenig arg dünn. Nanotech baut sicher nicht nur einen Schrittmotor :wink: .
Poste mal Links zu deiner verwendeten Hardware ( Motor und Treiber ).

Gruß
Franz-Peter

Danke für die Antworten bisher.

Ich habe den Code bzw. die Pulsabstandsrechnung gestern noch angepasst, da wirklich etwas schief war. Es muss eine Division sein.

Nochmals der Code mit dem eingebauten Vorschlag von Doc_Arduino:

Allerdings immer noch ohne erkennbare Schritte am Motor, wenn man den Code ausführt.

Das ist auch Murks, die Differenz wird im if abgefragt.

Und 75000 sollte auch UL sein, sonst könnte tp irgendwo im Wald liegen…

1 Like

Hallo,

if (micros() - start_puls < tp)
  {
    start_puls = micros();        // Vergleichswert nachziehen
    start_puls = start_puls + tp; // Vergleichswert nachziehen
    ...

Du solltest dich für eine Variante entscheiden. Ich plädiere für die zweite Variante.
Außerdem ist der Vergleich-Pfeil immer noch falsch herum. Man wartet ja bis die Differenz den gewünschten Wert überschritten hat.

Ein sauberer Takt ohne Timer wäre

const byte pin_freigabe {5};
const byte pin_richtung {7};
const byte pin_takt {9};

void setup()
{
  pinMode(pin_freigabe, OUTPUT);
  pinMode(pin_takt, OUTPUT);
  pinMode(pin_richtung, OUTPUT);
  digitalWrite(pin_freigabe, HIGH);
}

void loop()
{
  takt(50);  // Periode = x[ms] * 2
}

void takt (const unsigned long interval)                     
{
  static unsigned long lastMillis {0};
  static bool state {LOW};
    
  if (millis() - lastMillis >= interval)
  {
    lastMillis += interval;
    state = !state;
    digitalWrite(pin_takt, state);
  }
}

damit sollte irgendwas passieren.

start_puls ist global definiert, globale Variablen werden automatisch mit 0 initialisiert, wenn man keinen Wert festlegt.

2 Likes

@Doc_Arduino
Ich habe deinen Code kopiert und hat auf Anhieb funktioniert! Vielen Dank dafür. Ich werde mich noch daran machen dein Vorschlag in allen Details zu verstehen. Auf die Kürze konnte ich feststellen, dass ein Takt von 1ms (entspricht ja 75 Umdrehungen pro Minute) sich nicht mehr gut anhört. Vielleicht ist der Takt-Richtungs Modus nicht das richtige, da auch sonst mitten im Lauf Holpergeräusche auftreten.

Ich habe zudem den Vergleichspfeil noch in meinem eigenen Code geändert und habe dann festgestellt, dass der Schrittmotor genau nur einen Schritt ausführt. Man sieht es kaum, aber kann es fühlen. Habe dann den Code mit Serial.print Ausgaben ergänzt und man kann feststellen, dass bei meinem Code die Schleife genau einmal ausgeführt wird (darum auch nur einzelne Schritt) und danach im Loop nach einer neuer Serial Eingabe verlangt wird. Muss das nochmals genauer anschauen, warum genau nur der einzelne Schritt kommt. Eigentlich war mein ursprüngliches Ziel, dass man zu Beginne einen Wert angibt und danach für eine unbestimmte Zeit (bis Reset) dieser Takt ausgeführt wird.

Hallo,

ich vermute das deine Einlesefunktion wartet und damit die loop blockiert.
Guck mal was du damit machen kannst. Notfalls millis mit micros ersetzen.

// https://forum.arduino.cc/t/rechtecksignal-nanotech-schrittmotor-takt-richtung/854997/10

const byte USART_BUFFERSIZE {10};
char rxBuffer [USART_BUFFERSIZE + 1];

const byte pin_freigabe {5};
const byte pin_richtung {7};
const byte pin_takt {9};
unsigned long halfPeriode {10}; // default

void setup (void)
{
  pinMode(pin_freigabe, OUTPUT);
  pinMode(pin_takt, OUTPUT);
  pinMode(pin_richtung, OUTPUT);
  digitalWrite(pin_freigabe, HIGH);
  
  Serial.begin(9600);
  Serial.println("\nStart");
}

void loop (void)
{

  if(readSerial(Serial) )
  {
   halfPeriode = strtoul(rxBuffer, NULL, 10);
   Serial.print("neuer Wert: ");
   Serial.println(halfPeriode);
  }
  
  takt(halfPeriode);  // Periode = x[ms] * 2
}


// ****** Funktionen ******

bool readSerial (Stream &out)
{
  static byte index {0};
  bool finish {false};

  if (out.available() )
  {
    char c = out.read();

    if ( (c >= 32) && (index < USART_BUFFERSIZE) ) {
      rxBuffer[index++] = c;
    }
    else if ( (c == '\n') || (c == '\r') ) {
      rxBuffer[index] = '\0';
      index = 0;
      finish = true;
    }
  }
  return finish;
}

void takt (const unsigned long interval)                     
{
  static unsigned long lastMillis {0};
  static bool state {LOW};
    
  if (millis() - lastMillis >= interval)
  {
    lastMillis += interval;
    state = !state;
    digitalWrite(pin_takt, state);
  }
}
1 Like

Hallo Doc

Dein Code ging perfekt! Viele Dank. Sieht sehr professionell aus. Sowas hätte ich nicht gekonnt. Muss das alles noch erstmal verstehen können (vor allem die readSerial Funktion).

Sowas hätte ich noch nicht gekonnt. :wink:

Ich reiche den Dank an Serenifly weiter. Der hat mir das damals beigebracht. Von dem Gerüst gibts gefühlt tausende Variationen. Du findest das hier im Forum immer wieder einmal wenn es um die Serielle geht. Um die 32 etc. zu verstehen musste dir eine ASCII Tabelle anschauen.