Schrittmotor Referenzpunkt anfahren

Hallo zusammen,
ich bin gerade dabei die Steuerung für einen Schrittmotor zu programmieren.
Im Prinzip soll der Motor nur einen Arm hoch und runter bewegen; was ich auch schon realisieren konnte.
Allerdings möchte ich dass der Arm zu aller erst einmalig so lange abwärts fährt bis ein Eingang geschaltet wird. (Referenzpunkt nach Spannung Aus)
Bisher schlugen alle versuche Fehl.

Könnte mir jemand einen Tipp geben wie ich das mit diesem Script bewerkstelligen kann.
Vielen Dank schonmal und ein schönes Wochenende.
Manuel

const int motorPin1 = 8;      // Blue   - In 1
const int motorPin2 = 9;     // Pink   - In 2
const int motorPin3 = 10;  // Yellow - In 3
const int motorPin4 = 11; // Orange - In 4
                                    // Black  - GND
                                   // Red    - VCC
                                  // ---    - VM
const int Endschalter = 7; 

unsigned int highSpeed =  2000; // nicht über 16000 (kleiner=schneller)

void setup() {
 pinMode(motorPin1, OUTPUT);
 pinMode(motorPin2, OUTPUT);
 pinMode(motorPin3, OUTPUT);
 pinMode(motorPin4, OUTPUT);
 pinMode(Endschalter, INPUT);
}

void loop()
{ unsigned long n = millis() / 2000; // 2 Sekunde (Fahrdauer)

 switch(n % 6) // Pausenzeit?
 { case 1: stop();               break;
   case 2: linksrum(highSpeed);  break; //Arm ab
   case 3: stop();               break;
   case 4: rechtsrum(highSpeed); break; //Arm auf; //if(digitalRead(Endschalter)== HIGH)
   }
}

void rechtsrum(unsigned int motorSpeed) //Arm Auf
{ // 1
 digitalWrite(motorPin4, HIGH);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin1, LOW);
 delayMicroseconds(motorSpeed);

 // 2
 digitalWrite(motorPin4, HIGH);
 digitalWrite(motorPin3, HIGH);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin1, LOW);
 delayMicroseconds(motorSpeed);

 // 3
 digitalWrite(motorPin4, LOW);
 digitalWrite(motorPin3, HIGH);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin1, LOW);
 delayMicroseconds(motorSpeed);

 // 4
 digitalWrite(motorPin4, LOW);
 digitalWrite(motorPin3, HIGH);
 digitalWrite(motorPin2, HIGH);
 digitalWrite(motorPin1, LOW);
 delayMicroseconds(motorSpeed);

 // 5
 digitalWrite(motorPin4, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin2, HIGH);
 digitalWrite(motorPin1, LOW);
 delayMicroseconds(motorSpeed);

 // 6
 digitalWrite(motorPin4, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin2, HIGH);
 digitalWrite(motorPin1, HIGH);
 delayMicroseconds(motorSpeed);

 // 7
 digitalWrite(motorPin4, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin1, HIGH);
 delayMicroseconds(motorSpeed);

 // 8
 digitalWrite(motorPin4, HIGH);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin1, HIGH);
 delayMicroseconds(motorSpeed);
 
 // 9 (gegen Überhitzung)
 digitalWrite(motorPin4, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin1, LOW);
 delayMicroseconds(motorSpeed);
}

void linksrum(unsigned int motorSpeed) //Arm Ab
{ // 1
 digitalWrite(motorPin1, HIGH);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin4, LOW);
 delayMicroseconds(motorSpeed);

 // 2
 digitalWrite(motorPin1, HIGH);
 digitalWrite(motorPin2, HIGH);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin4, LOW);
 delayMicroseconds(motorSpeed);

 // 3
 digitalWrite(motorPin1, LOW);
 digitalWrite(motorPin2, HIGH);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin4, LOW);
 delayMicroseconds(motorSpeed);

 // 4
 digitalWrite(motorPin1, LOW);
 digitalWrite(motorPin2, HIGH);
 digitalWrite(motorPin3, HIGH);
 digitalWrite(motorPin4, LOW);
 delayMicroseconds(motorSpeed);

 // 5
 digitalWrite(motorPin1, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin3, HIGH);
 digitalWrite(motorPin4, LOW);
 delayMicroseconds(motorSpeed);

 // 6
 digitalWrite(motorPin1, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin3, HIGH);
 digitalWrite(motorPin4, HIGH);
 delayMicroseconds(motorSpeed);

 // 7
 digitalWrite(motorPin1, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin4, HIGH);
 delayMicroseconds(motorSpeed);

 // 8
 digitalWrite(motorPin1, HIGH);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin4, HIGH);
 delayMicroseconds(motorSpeed);
 
 // 9 (gegen Überhitzung)
 digitalWrite(motorPin1, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin4, LOW);
 delayMicroseconds(motorSpeed);
}

void stop()
{ digitalWrite(motorPin4, LOW);
 digitalWrite(motorPin3, LOW);
 digitalWrite(motorPin2, LOW);
 digitalWrite(motorPin1, LOW);
}

Pustefix.ino (4.16 KB)

Hallo,

Na ja , du könntest im Setup die Funktion recht oder links so lange aufrufen bis der Schalter betätigt ist und dann das Setup beenden.

Oder du schreibst eine eigene Function dazu und rufst sie im loop abghängig von einer Statusvariabeln "Refdone" auf.

Heinz

Alternativ zum Vorschlag von Heinz kann man das auch in loop machen, was manchmal Vorteile hat, wenn man einen Merker verwendet (ungetesteter Pseudocode):

void loop()
{ static bool einmal = true;
  if (einmal)
  { einmal = referenzbewegung();
  } else {
    unsigned long n = millis() / 2000; // 2 Sekunde (Fahrdauer)

    switch (n % 6) // Pausenzeit?
    { case 1: stop();               break;
      case 2: linksrum(highSpeed);  break; //Arm ab
      case 3: stop();               break;
      case 4: rechtsrum(highSpeed); break; //Arm auf; //if(digitalRead(Endschalter)== HIGH)
    }
  }
}

bool referenzbewegung()
{
  ...
  return true; // solange die Referenzbewegung andauert
  ...
  return false; // nach Ende der Referenzbewegung
}

Was soll eigentlich bei n == 0 oder n == 5 passieren?

Hey zusammen,
erst mal vielen Dank für die Rückmeldungen.
Ich habe heute das ganze nochmals an meinem Micro komplett neu gemacht.

Allerdings überspringt das Programm meistens die Referenzfahrt und startet direkt den Step mit automatischer auf- & abfahrt.
Ich dachte erst dass der “Low” an meinem Referenzschalter prellt/Probleme macht; allerdings funktioniert es auch nicht wenn ich diesen direkt auf Masse lege; bzw die Logic umdrehe und ihn direkt mit 5 Volt beschalte.
Hat jemand eine Idee für mich? (Arbeite übrigens mit einem Arduino Micro)
Vielen lieben Dank,
Manuel

//Pustefix

// Aktivier Arduino Stepper.h Library:
#include <Stepper.h>

// Definiere Armhub:
const int stepsPerRevolution = 700;
const int Referenzimpulse = 20;

// Definiere Variablen
const int motorPin1 = 8;  // Blue   - In 1
const int motorPin2 = 9;  // Pink   - In 2
const int motorPin3 = 10; // Yellow - In 3
const int motorPin4 = 11; // Orange - In 4
                         // Black  - GND
                         // Red    - VCC
                         // ---    - VM
int Endschalter = 2;      // Referenzschalter bzw. Sensor   
int Merker = 0;           // Merker ob Referenzfahrt erfolgt ist

// Initiiere 'myStepper' / Drehbewegungen
Stepper myStepper = Stepper(stepsPerRevolution, 8, 10, 9, 11);

void setup() {
 // Definiere Geschwindigket der Bewegung:
 myStepper.setSpeed(30);
 
 // Setze Pin 2 als Eingang
 pinMode(Endschalter,INPUT);
 // Setze Merker auf 0
 digitalWrite(Merker, 1);
}

// Eigentlicher Programmablauf
void loop() {
 //Referenzfahrt starten
 if ((digitalRead(Endschalter)==LOW)||(digitalRead(Merker)==0))
 {delay(10);
 Serial.println("clockwise");
 myStepper.step(Referenzimpulse);
 stop();
 delay(10);}

 // Merker nach Referenzfahrt setzen (+ Entprellen)
 if (digitalRead(Endschalter)==HIGH)
 {delay(10);
 if (digitalRead(Endschalter)==HIGH); 
  digitalWrite(Merker, 1);}
  
// Arm abwährts bewegen:
 if (digitalRead(Merker)==1)
 {delay(500);
 Serial.println("clockwise");
 myStepper.step(stepsPerRevolution);
 stop();
 delay(500);
 // Arm aufwärts bewegen:
 Serial.println("counterclockwise");
 myStepper.step(-stepsPerRevolution);
 stop();}
}

void stop()
{ digitalWrite(motorPin4, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin1, LOW);
}

Pustefix.ino (1.72 KB)

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Hallo,

ich habe mal in meiner Bastelkiste gesucht und das gefunden. Versuche mal ob Du damit zurecht kommst.

Heinz

/*Versuch zum Steppermotor 28BYJ-48
   Referenzpunkt anfahren in minus Richtung bis Endschalter
   da ist die Null Position. Taster Start fährt auf Pos1
   nach zeit wird auf pos2 gefahren.
   Hardware UNO , Schalter gegen 0V schaltend
   Anzeige auf Plotter möglich
   März2019
*/


#include <AccelStepper.h>

const byte butonRev = 8;
const byte butonStart = 9;
const byte led = 13;

bool rev_Pos, startbtn; // status Taster
bool rev_OK;    // status rev erfolgt

unsigned long altzeit, altwzeit;

long aktpos; // aktuelle Position
const long setpos1 = 2068;    // Sollposition 1&2
const long setpos2 = 200;

// Define a stepper and the pins it will use
// die  beiden mittleren gedreht mittels Software
AccelStepper stepper(AccelStepper::FULL4WIRE, 2, 4, 3, 5);

void setup()
{
  pinMode(butonRev, INPUT_PULLUP);
  pinMode(butonStart, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  Serial.begin(115200);
  stepper.setAcceleration(300);
  stepper.setMaxSpeed(300);
}

void loop()
{
  // Taster und aktuelle Position einlesen
  rev_Pos = !digitalRead(butonRev);
  startbtn = !digitalRead(butonStart);
  aktpos = stepper.currentPosition();

  if (rev_OK == false) {  // Rev noch nicht angefahren
    rev_OK =  revfahren();
  }

  // --- auf Pos 1 fahren
  if ( rev_OK && startbtn) {    // Start gedückt
    stepper.moveTo(setpos1);    // auf Pos fahren
  }
  // -----auf Pos 2 fahren
  if (rev_OK && aktpos == setpos1) {    // Pos 1 erreicht
    if (millis() - altwzeit >= 3000) {  // Wartezeit
      stepper.moveTo(setpos2);          // Position 2 anfahren
    }
  }
  else altwzeit = millis();

  // ----------- Ausgaben
  digitalWrite(led, rev_OK);  // Satus LED 
  stepper.run();              // Pulse ausgeben
  // ------------Anzeige
  if (millis() - altzeit >= 200) {
    altzeit = millis();
    //Serial.print("aktual Position ");
    Serial.println(aktpos);
  }
}// ---------- loop ende

bool revfahren() {
  stepper.setSpeed(-100);  // langsam  minus fahren
  stepper.move(2000);      // zuück fahren

  if (rev_Pos) {          // wenn schalter angefahren
    stepper.stop();

    stepper.setSpeed(300);   // normale Geschw.
    stepper.setCurrentPosition(0); // auf pos o setzten
    // stepper.moveTo(0);   // auf o fahren um stop abzuschliessen
    return 1;
  }
  return 0;
}

Dein Code ist ziemlich schlecht lesbar.
Hier die Version nach einem simplen “CTRL-T” in der Arduino-IDE.

//Pustefix

// Aktivier Arduino Stepper.h Library:
#include <Stepper.h>

// Definiere Armhub:
const int stepsPerRevolution = 700;
const int Referenzimpulse = 20;

// Definiere Variablen
const int motorPin1 = 8;  // Blue   - In 1
const int motorPin2 = 9;  // Pink   - In 2
const int motorPin3 = 10; // Yellow - In 3
const int motorPin4 = 11; // Orange - In 4
// Black  - GND
// Red    - VCC
// ---    - VM
int Endschalter = 2;      // Referenzschalter bzw. Sensor
int Merker = 0;           // Merker ob Referenzfahrt erfolgt ist

// Initiiere 'myStepper' / Drehbewegungen
Stepper myStepper = Stepper(stepsPerRevolution, 8, 10, 9, 11);

void setup() {
  // Definiere Geschwindigket der Bewegung:
  myStepper.setSpeed(30);

  // Setze Pin 2 als Eingang
  pinMode(Endschalter, INPUT);
  // Setze Merker auf 0
  digitalWrite(Merker, 1);
}

// Eigentlicher Programmablauf
void loop() {
  //Referenzfahrt starten
  if ((digitalRead(Endschalter) == LOW) || (digitalRead(Merker) == 0))
  { delay(10);
    Serial.println("clockwise");
    myStepper.step(Referenzimpulse);
    stop();
    delay(10);
  }

  // Merker nach Referenzfahrt setzen (+ Entprellen)
  if (digitalRead(Endschalter) == HIGH)
  { delay(10);
    if (digitalRead(Endschalter) == HIGH);
    digitalWrite(Merker, 1);
  }

  // Arm abwährts bewegen:
  if (digitalRead(Merker) == 1)
  { delay(500);
    Serial.println("clockwise");
    myStepper.step(stepsPerRevolution);
    stop();
    delay(500);
    // Arm aufwärts bewegen:
    Serial.println("counterclockwise");
    myStepper.step(-stepsPerRevolution);
    stop();
  }
}

void stop()
{ digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
}

Probleme:

  • Für die Pindefinitionen reicht ein const byte (int ist nicht erforderlich)
  • Wenn der Endschalter aktiv low sein soll und außen keine weitere Beschaltung vorhanden ist, sollte der Eingang als INPUT_PULLUP definiert werden
  • Merker ist eine Variable. Die schreibt man normalerweise klein (geschenkt), aber man setzt sie durch einfache Zuweisung, nicht durch digitalWrite() - das würde den Inhalt von Merker nehmen und den entsprechenden Ausgang setzen (auch überflüssige Kommentare sollten übrigens stimmen):
  // // Setze Merker auf 1
  merker = 1;

Das nur nach kurzem Draufschauen; möglicherweise gibt es da noch mehr.
Gruß Walter