Schrittmotor Änderung der Geschwindigkeit - Nema17, a4988

Hallo liebes Forum!

für ein kleines Heimprojekt benötige ich eure Hilfe. Bis vor 2 Wochen hatte ich noch keine Berührungspunkte mit nem Arduino, sprich ich bin ein ziemlicher Anfänger auf dem Gebiet. Seitdem hab ich viel ausprobiert und blick auch langsam durch jedoch ergeben sich auch immer mehr Fragen. Ich hoffe, ihr könnt mir weiterhelfen.

Erstmal kurz zur groben Hardware: 2 x Nema17 Schrittmotor (Bipolar); Arduino Mega2506 und 2 x a4988 Treiber, LED, Fotowiderstand

Was soll passieren: Zu Beginn fällt Licht auf den Fotowiderstand und beide Motoren drehen gleich schnell. Wird der Fotowiderstand abgedunkelt, soll Schrittmotor 1 seine Geschwindigkeit verdoppeln.
Am Anfang habe ich alles ohne Bibliothek mit delay programmiert. Da ich aber gerne die Umdrehungsgeschwindigkeit definiert einstellen möchte und gelesen habe, dass die Programmierung mit delays nicht so das Wahre ist, bin ich auf die accelstepper-Bibliothek umgestiegen. Da komme ich aber auch nicht weiter. Das Hauptproblem ist die Erhöhung der Geschwindigkeit aus dem „Lauf“ von Motor 1 bei konstanter Geschwindigkeit des Motors 2.

Ich hab es jetzt soweit programmiert, dass beide Motoren sich gleich schnell drehen und und bei Abdunklung der Motor 1 stehen bleibt. (In Wahrheit soll er aber nicht stehen bleiben sondern seine Geschwindigkeit verdoppeln)

Meinen „Delay-Code“ sieht wie folgt aus:

//Variablendefinition
int dirPin1 = 4;
int stepPin1 = 3;
int dirPin2 = 7;
int stepPin2 = 6;
int PRPin = A0;
int Genauigkeit = 50;
int StartValuePR;

void setup() {
  pinMode(PRPin,INPUT);
  pinMode(dirPin1, OUTPUT);     
  pinMode(stepPin1, OUTPUT);
  digitalWrite(dirPin1, HIGH);
  digitalWrite(stepPin1, LOW);
  pinMode(dirPin2, OUTPUT);     
  pinMode(stepPin2, OUTPUT);
  digitalWrite(dirPin2, HIGH);
  digitalWrite(stepPin2, LOW);
  StartValuePR = analogRead(PRPin); //Startwert der Photozelle wird ausgelesen
}

void loop() {
 
    if (analogRead(PRPin) - Genauigkeit < StartValuePR){
    digitalWrite(stepPin1, HIGH);
    digitalWrite(stepPin2,HIGH);    
    delay(10);       
    digitalWrite(stepPin1, LOW); 
    digitalWrite(stepPin2,LOW); 
    delay(10); 
    }

    if (analogRead(PRPin) - Genauigkeit > StartValuePR){
    digitalWrite(stepPin2, HIGH);
    delay(10);       
    digitalWrite(stepPin2, LOW); 
    delay(10); 
    }
}

Ich hoffe sehr, dass ihr mir weiterhelfen könnt. Vielen Dank im Voraus!

Hast Du es mit der stepper oder AccelStepper Bibliothek versucht?

Mit der Accelstepper-Bibliothek. Die ist aber wohl nicht für die gewünschte Geschwindigkeitsänderung geeignet.

Hallo,

habe schon Schrittmotoren eingesetzt , weiß also wie sie funktionieren allerdings nicht in Zusammenhang mit Arduino. Ich weiss also nicht wirklich wie man das hier machen kann.

ich hab jetzt noch nicht ganz verstanden wie Du die Geschwindigkeit überhaupt einstellst.
Mit dem H setzen , delay(10) L setzen , delay(10) ?

Damit ein ein Rechtecksignal mit 50 Hz.

Du kannst natürlich das delay ersetzten durch millis() , dazu gibts das Beispiel "blink witout delay"

ganz blöde Idee !! hast Du schon mal tone() versucht macht doch nichst anderes, geht aber nur bis 31 Hz runter. weiss aber auch nicht ob man damit zwei Ausgänge gleichzeitig bedienen kann.

Auf der anderen Seite kann ich mir nicht vorstellen das es keine lib geben soll die das kann.

Heinz

Danke dir Heinz.

Ich hab mich jetzt nochmal mit der Accelstepper-Bibliothek auseinandergesetzt und ich hab auch einen kleinen Teilerfolg erzielen können.

Dafür hab ich die ganze Sache etwas vereinfacht und erstmal nur einen Schrittmotor genommen und einen Button statt dem Fotowiderstand.

Der Motor dreht mit 1/sek, wenn der Button gehalten wird beschleunigt der Motor auf 2/sek.

#include <AccelStepper.h>

//AccelStepper stepper (1, 3, 4); // pin 3 = step, pin 4 = direction

AccelStepper stepper (1, 3, 4); // pin 3 = step, pin 4 = direction
int buttonpin = 8;


void setup() {
  stepper.setMaxSpeed(600);
  stepper.setSpeed(200);
  pinMode(buttonpin, INPUT_PULLUP);  
}

void loop() { 
   if (digitalRead(buttonpin) == HIGH){ 
   stepper.setSpeed(200);
   stepper.runSpeed();
}
   if (digitalRead(buttonpin) == LOW){ 
   stepper.setSpeed(400);
   stepper.runSpeed();
}
}

Als nächstes würde ich gerne, dass der Button nur einmal kurz gedrückt werden muss und der Schrittmotor dann z.B. vier Umdrehungen bei 2/sek fährt.

Die Funktion “move()” und “moveTo()” helfen mir da sicher. Ich habe es nur noch nicht geschafft die sinnvoll einzubauen sodass es funktioniert. Hat einer eine Idee?

Danke
Lisa

BeatSteak4849:
Hat einer eine Idee?

Durchaus, wird aber etwas umfangreicher:

  • Mechanische Taster prellen, daher Taster entprellen z. B. durch Abfrage alle 30 ms.
  • Änderung "nicht gedrückt" nach "gedrückt" erkennen.
  • Bei Änderung Merker invertieren.
  • Steppergeschwindigkeit entsprechend Merker einstellen.

So sollte das funktionieren.

Okay, Danke! Klingt tatsächlich etwas umfangreicher.
Soll es nicht einfach möglich sein, nach/in der if-Abfrage eine gewisse Stepanzahl einzubauen, die erst abgefahren werden muss bevor die Abfrage des Buttons erneut erfolgt?

Ich bin euch für jeden Rat sehr dankbar.
Lisa

Du hast gefragt, ob jemand eine Idee hat. Und ja, ich habe gleich mehrere, wovon ich eine grob skizziert habe.

Aber Programmieren ist eine kreative Tätigkeit, da können mehrere Wege zum Ziel führen. Bitte überasche mich mit Deinem “einfachen”, dann können wir darüber diskutieren.

Hallo,

jetzt geht es darum das bestimmte Bewegungsabläufe nacheinander erfolgen sollen? Dann ist man aber bei einer Schrittkette angekommen.

Rentner:
Dann ist man aber bei einer Schrittkette angekommen.

Schrittkette == endlicher Automat == finite state machine

Wenn Du in diesem Forum nach "agmue anleitung" suchst, findest Du Text von mir und Links zum Thema von anderen.

Klar, es gibt sicher mehrere Wege die an das entsprechende Ziel führen. Ich bin auch wirklich um jeden kreativen Vorschlag sehr denkbar.

Mein Gedanke war/ist es, die folgende Abfrage des Buttons um eine Funktion zu erweitern die erst "abgearbeitet" werden muss bevor eine neue Abfrage des Buttons erfolgt.
z.B. stepper.move(800)

In meiner Vorstellung läuft es dann wie folgt ab:
Es wird fortlaufend abgefragt in welchem Zustand sich der Button befindet. Bei "nicht gedrückt" läuft er mit speed(200). Wird der Button nun gedrückt erhöht sich die Geschwindigkeit auf speed(400) für genau 4 Umdrehungen. Erst wenn die 4 Umdrehungen bei speed(400) abgelaufen sind erfolgt eine erneute abfrage.

Hier nochmal die Codestelle um die es geht:

}
   if (digitalRead(buttonpin) == LOW){ 
   stepper.setSpeed(400);
   stepper.runSpeed();
}

Ich habe mir da anscheinend mehr vorgenommen als ich dachte.
Vielen Dank für die Hinweise und Anregungen. Ich werde mich zum Thema Schrittketten mal belesen.

Viele Grüße
Lisa

Hallo

ja ok dann benötigst Du ja lediglich eine Bedingung die dann erfüllt ist wen die 4 Umdrehungen erfolgt sind. mit deiner Vorstellung des Ablaufs gehts ehr nicht um eine Schrittkette mit mehren Schritten, es wäre nur eigendlich nur ein Schritt.

Du hattes ja bereits die Funktion moveto() angesprochen könnte mir vorstellen das die ein true liefert wenn die Position erreicht, bzw die steps für den Motor abgearbeitet sind.

Aber wie bereits gesagt ich habe mit Schrittmototen in Verbindung mit Arduine keine Ahnung, ist sicher was für den nächsten Winter :wink:

Heinz

Rentner:
... könnte mir vorstellen das die ein true liefert wenn die Position erreicht, bzw die steps für den Motor abgearbeitet sind.

Das macht runSpeedToPosition(). Bislang habe ich if (stepper.distanceToGo() == 0) verwendet. Die Bibliothek bietet mehrere Ansätze.

Ich bin jetzt einen Schritt weiter, stehe aber vor einem neuen Problem.

Was macht das folgende Programm: Der Schrittmotor dreht mit speed(200). Wird der Button kurz gedrückt hält der Stepper kurz an und beschleunigt dann auf maxspeed(400) mit acceleration(100) und dreht sich vier mal. Danach hält der Stepper wieder kurz an und fährt wieder auf seine speed(200).

Mein Problem, dass ich den Button dauerhaft gedrückt halten muss ist also weg. Was mich jetzt noch stört sind die kleinen Stopps. Wenn der Motor schon eine Geschwindigkeit von speed(200) hat soll er nicht erst abbremsen um dann auf speed(400) zu beschleunigen.

Ich hoffe, ich hab es einigermaßen verständlich wiedergegeben. Danke

#include <AccelStepper.h>

//AccelStepper stepper (1, 3, 4); // pin 3 = step, pin 4 = direction

AccelStepper stepper (1, 3, 4); // pin 3 = step, pin 4 = direction
int buttonpin = 8;


void setup() {
  stepper.setMaxSpeed(400);
  stepper.setAcceleration(100);
  pinMode(buttonpin, INPUT_PULLUP);  
}

void loop() { 
   if (digitalRead(buttonpin) == HIGH){ 
   stepper.setSpeed(200);
   stepper.runSpeed();
}
   if (digitalRead(buttonpin) == LOW){ 
   stepper.move(800);
   stepper.runToPosition();
}
}

Vielen Dank