MOBA-Tools Stepper stromlos schalten

Hallo,

für ein Teamaker-Projekt möchte ich einen kleinen Getriebe-Steppermotor (28BYJ-48) mit einem Treiber ULN2003 ansteuern. Dazu habe ich die Libary Moba-Tools ausprobiert. Das hat auch soweit funktioniert.
Mein Problem ist, ich möchte das ganze über Accus laufen lassen aber der Motor bleibt nach Beendigung der Bewegung im Haltemodus und zieht noch ordentlich Strom (wird sogar etwas warm). Meine Frage, gibt es eine Möglichkeit den Motor stromlos zu schalten? Ich habe versucht, den Befehl “detach” einzubinden. Aber dann hat sich gar nichts mehr getan. Ich habe hier nur das Unterprogramm eingefügt, dass bei Aufruf einmal durchlaufen wird.

#include <MobaTools.h>
MoToStepper Winde(4096, FULLSTEP);

void setup()
 {
  Winde.attach( 6, 5, 4, 3 ); // IN1,IN2,IN3,IN4
  Winde.setSpeed( 500 );        // 50 U/Min
  Winde.setZero();             
 }

void BeutelHoch()
 {  
  Winde.write(360);
  Winde.setZero();
 }

Viele Grüße

Gerald

Hallo Gerald,
Grundsätzlich sollte das mit detach schon gehen. Allerdings gehen dabei alle Informationen über die momentane Stepperposition verloren. Du musst ja dann vor der nächsten Bewegung wieder ein attach aufrufen, und das stellt alles wieder auf 'Anfang'.
Du musst allerdings auch bedenken, dass die Aufrufe nicht blockierend sind. Mit dem 'Winde.write(360);' startest Du die Bewegung des Stepper. Es wird aber nicht gewartet, bis die Bewegung abgeschlossen ist. Dein Sketch läuft sofort weiter. Deshalb macht auch dein 'Winde.setZero();' nicht das was Du vermutlich willst. Der Referenzpunkt wird da nämlich bereits bei Start der Bewegung zu 0 gesetzt, und nicht erst wenn das Ende erreicht ist.
Genauso wäre es beim detach. Das darfst Du erst aufrufen, wenn die Bewegung abgeschlossen ist und der Stepper seine Zielposition erreicht hat.
Ob die Bewegung abgeschlossen ist, kannst Du mit der 'moving' Methode feststellen. Solange die noch einen Wert >0 zurückgibt, bewegt sich der Motor noch.

Hallo Franz-Peter,

danke für die Hilfe.
Ich werde also erst abfragen, ob der Motor zum Stillstand gekommen ist und dann erst auf 0 setzen und abschalten.

Grüße

Gerald

Ja, wobei Du dir das 0 setzen sparen kannst, wenn Du detach nutzt. Das wird dann beim nächsten attach automatisch gemacht.

Hi

Man sollte vll. noch erwähnen, daß diese Lösung nur bei den 28BYJ-48 auf ULN2003 funktioniert, da hier die Steuersignale zum ULN abgeschaltet werden und daraufhin die Spulen nicht mehr bestromt werden. (... nach GND gezogen ...)

Bei einem 'normalem' Stepper bekommt zwar auch dort der Treiber keinen Input mehr, Das ändert aber Nichts an Dessen Ausgängen - dort hätte man einen EN Pin (Enable) oder ähnlich, um den Stepper stromlos zu bekommen.

MfG

Ja richtiger Hinweis. Für die Treiber mit enable-Eingang hat die aktuelle MobaTools-Version auch eine Möglichkeit, diesen Eingang zu steuern. Das hilft aber umgekehrt bei den 28BYJ-48 mit ULN2003 nichts.

Hallo,

anbei der Code für die Teemaschine:

 #include <Button.h>
 #include <Wire.h> 
 #include <LiquidCrystal_I2C.h>
 #include <MobaTools.h>
 Stepper4 Winde(4096, FULLSTEP);  
 LiquidCrystal_I2C lcd(0x27, 16, 2); // Adresse, Zeichenzahl, Reihenzahl
  // LCD-Displayanschluss: SCL an A5 und SDA an A4
 #define NachObenTasterPin 7
 #define NachUntenTasterPin 8
 #define EnterTasterPin 9
 int ScrollTasterZaehler =0;
 int EnterTasterZaehler =0;
 unsigned long previousMillis = 0;
 unsigned long currentMillis = millis();
 Button NachObenTaster(NachObenTasterPin);
 Button NachUntenTaster(NachUntenTasterPin);
 Button EnterTaster(EnterTasterPin);
 
 void setup()
  {
  Winde.attach( 6, 5, 4, 3 );
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  Winde.setSpeed( 500 );
  Winde.setZero();
  NachObenTaster.begin();
  NachUntenTaster.begin();
  EnterTaster.begin();
  Serial.begin(9600);
  lcd.init();
  lcd.clear();
  lcd.backlight();
  lcd.print("P1");
  EnterTasterZaehler = 0;
  ScrollTasterZaehler = 0;
  }
void BeutelHoch()
{
 lcd.setCursor(0, 0);
 lcd.print("Beutel hoch     ");
 lcd.setCursor(0, 1);
 lcd.print("bitte warten    ");
 Winde.attach( 6, 5, 4, 3 );
 Winde.write(360);
 }

void BeutelRunter()
{
 lcd.setCursor(0, 0);
 lcd.print("Beutel runter    ");
 lcd.setCursor(0, 1);
 lcd.print("bitte warten    ");
 Winde.attach( 6, 5, 4, 3 );
 Winde.write(-360);
}

void Kamille()
 {
  lcd.setCursor(0, 0);
  lcd.print("Zubereitung     ");
  lcd.setCursor(0, 1);
  lcd.print("bitte warten    ");
  lcd.noBacklight();
  delay(60000*10);
  BeutelHoch();
 }
 void Schwarztee()
 {
  Serial.println("Programm läuft");
  lcd.setCursor(0, 0);
  lcd.print("Zubereitung     ");
  lcd.setCursor(0, 1);
  lcd.print("bitte warten    ");
  delay(60000*4);
  lcd.noBacklight();
  BeutelHoch();
 } 
 void GruenerTee()
 {
  Serial.println("Programm läuft");
  lcd.setCursor(0, 0);
  lcd.print("Zubereitung     ");
  lcd.setCursor(0, 1);
  lcd.print("bitte warten    ");
  lcd.noBacklight();
  delay(60000*3);
  BeutelHoch();
 } 
void KraeuterTee()
 {
  Serial.println("Programm läuft");
  lcd.setCursor(0, 0);
  lcd.print("Zubereitung     ");
  lcd.setCursor(0, 1);
  lcd.print("bitte warten    ");
  lcd.noBacklight();
  BeutelHoch();
  delay(60000*6); 
 } 
  
 void loop()
 {
  if(!Winde.moving())
 {
  Winde.detach();
 }
  EnterTasterZaehler = 0;
  EnterTaster.read();
  NachUntenTaster.read();
  NachObenTaster.read();
  
  if (EnterTaster.pressed())
  {
      EnterTasterZaehler=1;
      Serial.print("EnterTasterZaehler= ");
  }
  if (NachObenTaster.pressed())
  {
     //taster1modus wird um +1 erhöht
     ScrollTasterZaehler++;
  }

  if (NachUntenTaster.pressed())
   {
    
      //taster1modus wird um -1 verkleinert
      ScrollTasterZaehler--;
   }

 if (ScrollTasterZaehler == 6)
 {
  ScrollTasterZaehler = 0;
 }
 if (ScrollTasterZaehler == -1)
 {
  ScrollTasterZaehler = 5;
 }
 
 
 if (ScrollTasterZaehler == 0)
 {
   // set the cursor to column 0, line 1
   // (note: line 1 is the second row, since counting begins with 0):
   lcd.setCursor(0, 0);
   lcd.print("Kamille  10 min.");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
  
 }
 if (ScrollTasterZaehler == 1)
 {
   lcd.setCursor(0, 0);
   lcd.print("Schwarztee 4 min");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
 }
 if (ScrollTasterZaehler == 2)
 {
   lcd.setCursor(0, 0);
   lcd.print("Gruener Tee 3 min");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
 }

 if (ScrollTasterZaehler == 3)
 {
   lcd.setCursor(0, 0);
   lcd.print("Kraeutetee 6 min");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
 }
 if (ScrollTasterZaehler == 4)
 {
   lcd.setCursor(0, 0);
   lcd.print("Beutel hoch     ");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
 }
 if (ScrollTasterZaehler == 5)
  {
   lcd.setCursor(0, 0);
   lcd.print("Beutel runter   ");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
  }
  
 
  if (ScrollTasterZaehler == 0 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   Kamille();
   }
  if (ScrollTasterZaehler == 1 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   Schwarztee();
  }
  if (ScrollTasterZaehler == 2 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   GruenerTee();
  }
  if (ScrollTasterZaehler == 3 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   KraeuterTee();
  }
  if (ScrollTasterZaehler == 4 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   BeutelHoch();
  }
  if (ScrollTasterZaehler == 5 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   BeutelRunter();
  }
 }

Leider habe ich noch folgendes Problem.
Nach dem Start und dem ersten ausführen des Befehls “Beutel runter” macht der Motor nur halb so viel Umdrehungen wie nach dem anschließenden “Beutel hoch” und wieder Beutel runter. Auch bewegt sich der Motor nicht, wenn ich “Beutel runter” 2x hintereinander starten möchte. Ich komme leider nicht dahinter woran das liegen könnte.

Gruß

Gerald

Hallo Gerald,
leider enthält dein Sketch keinerlei Kommentare, an denen man erkennen könnte, was Du dir gedacht hast, wozu die jeweiligen Programmblöcke sein sollen bzw was sie bewirken sollen. Das macht das Helfen sehr schwer,
Aber auch für dich wird das ein Problem werden, wenn Du den Sketch in ein paar Wochen oder Monaten nochmal hernimmst, und dich nicht mehr an alle Einzelheiten erinnerst.
Kommentare sind beim Programmieren kein schmückendes Beiwerk, sondern eine Notwendigkeit.

Solche Kommentare

    //taster1modus wird um -1 verkleinert
    ScrollTasterZaehler--;

sind dabei allerdings wenig hilfreich :wink: . Interessanter wäre warum das gemacht wird.

Hallo,

gut ein bisschen mehr Erklärung. Das meiste im LOOP dient der Menüführung.
Auf dem Display kann ich mit einer "Hoch-Taste" auf- und mit einer "Runter-Taste" abscrollen. Dabei wird ein Zähler hoch bzw. runter gezählt. Der wird dann abgefragt und der zugehörige Test erscheint im Display. Wird nun eine weitere Taste (Enter-Taste) gedrückt wird das zugehörige Unterprogramm aufgerufen.
Das Gerät selbst ist so eine Art Kran mit einer Winde wo man an einem Haken einen Teebeutel einhängen kann, der je noch aufgerufenem Programm nach einer vorgegebenen Zeit aus der Tasse gehoben wird.
Sicher sind Kommentare sehr nützlich aber ich bin Minimalist und auch kein besonders schneller Schreiber immer in der Hoffnung genug zu kommentieren, dass ich auch später noch verstehe was ich da gemeint habe.

Gruß

Gerald

Pauli58:
Sicher sind Kommentare sehr nützlich aber ich bin Minimalist

Da könnte Dir theoretisch folgende Antwort passieren (Sorry, konnte ich mir nicht verkneifen):

Sicher wäre eine Hilfe für Dich sinnvoll, aber ich bin Minimalist und das würde über das Minimum hinaus gehen. :wink:

Gruß Tommy

Hallo,
hab die Teemaschine nun ohne Benutzung einer Steppermotor-Libary zun laufen gebracht. Ist zwar jetzt blockierend aber macht was es soll.

 #include <Button.h>
 #include <Wire.h> 
 #include <LiquidCrystal_I2C.h>
 LiquidCrystal_I2C lcd(0x27, 16, 2); // Adresse, Zeichenzahl, Reihenzahl
  // LCD-Displayanschluss: SCL an A5 und SDA an A4
 #define NachObenTasterPin 7
 #define NachUntenTasterPin 8
 #define EnterTasterPin 9
 int x =0;
 int MotorSchritte =600;
 unsigned int MotorGeschwindigkeit =  1000;
 int ScrollTasterZaehler =0;
 int EnterTasterZaehler =0;
 Button NachObenTaster(NachObenTasterPin);
 Button NachUntenTaster(NachUntenTasterPin);
 Button EnterTaster(EnterTasterPin);
 const int motorPin1 = 6;  
 const int motorPin2 = 5;  
 const int motorPin3 = 4; 
 const int motorPin4 = 3; 
 
void setup()
{
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
   NachObenTaster.begin();
  NachUntenTaster.begin();
  EnterTaster.begin();
  Serial.begin(9600);
  lcd.init();
  lcd.clear();
  lcd.backlight();
  lcd.print("P1");
  EnterTasterZaehler = 0;
  ScrollTasterZaehler = 0;
}

 void BeutelHoch()
 {
  while (x<MotorSchritte)
  { 
  // 1
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 2
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 3
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 4
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 5
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 6
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, HIGH);
  delayMicroseconds(MotorGeschwindigkeit);
  // 7
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delayMicroseconds(MotorGeschwindigkeit);
  // 8
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delayMicroseconds(MotorGeschwindigkeit);
  x++;
  }
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
}

void BeutelRunter()
{
 lcd.setCursor(0, 0);
 lcd.print("Beutel runter    ");
 lcd.setCursor(0, 1);
 lcd.print("bitte warten    ");
 while (x<MotorSchritte)
  { 
    // 1
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 2
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 3
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 4
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 5
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(MotorGeschwindigkeit);
  // 6
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(MotorGeschwindigkeit);
  // 7
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(MotorGeschwindigkeit);
  // 8
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(MotorGeschwindigkeit);
  x++;
  }
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
}

void Kamille()
 {
  lcd.setCursor(0, 0);
  lcd.print("Zubereitung     ");
  lcd.setCursor(0, 1);
  lcd.print("bitte warten    ");
  lcd.noBacklight();
  delay(60000*10);
  BeutelHoch();
 }
 void Schwarztee()
 {
  Serial.println("Programm läuft");
  lcd.setCursor(0, 0);
  lcd.print("Zubereitung     ");
  lcd.setCursor(0, 1);
  lcd.print("bitte warten    ");
  delay(60000*4);
  lcd.noBacklight();
  BeutelHoch();
 } 
 void GruenerTee()
 {
  Serial.println("Programm läuft");
  lcd.setCursor(0, 0);
  lcd.print("Zubereitung     ");
  lcd.setCursor(0, 1);
  lcd.print("bitte warten    ");
  lcd.noBacklight();
  delay(60000*3);
  BeutelHoch();
 } 
void KraeuterTee()
 {
  Serial.println("Programm läuft");
  lcd.setCursor(0, 0);
  lcd.print("Zubereitung     ");
  lcd.setCursor(0, 1);
  lcd.print("bitte warten    ");
  lcd.noBacklight();
  BeutelHoch();
  delay(60000*6); 
 } 
  
 void loop()
 {
  x = 0;
  EnterTasterZaehler = 0;
  EnterTaster.read();
  NachUntenTaster.read();
  NachObenTaster.read();
  
  if (EnterTaster.pressed())
  {
      EnterTasterZaehler=1;
      Serial.print("EnterTasterZaehler= ");
  }
  if (NachObenTaster.pressed())
  {
     //taster1modus wird um +1 erhöht
     ScrollTasterZaehler++;
  }

  if (NachUntenTaster.pressed())
   {
    
      //taster1modus wird um -1 verkleinert
      ScrollTasterZaehler--;
   }

 if (ScrollTasterZaehler == 6)
 {
  ScrollTasterZaehler = 0;
 }
 if (ScrollTasterZaehler == -1)
 {
  ScrollTasterZaehler = 5;
 }
 
 
 if (ScrollTasterZaehler == 0)
 {
   // set the cursor to column 0, line 1
   // (note: line 1 is the second row, since counting begins with 0):
   lcd.setCursor(0, 0);
   lcd.print("Kamille  10 min.");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
  
 }
 if (ScrollTasterZaehler == 1)
 {
   lcd.setCursor(0, 0);
   lcd.print("Schwarztee 4 min");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
 }
 if (ScrollTasterZaehler == 2)
 {
   lcd.setCursor(0, 0);
   lcd.print("Gruener Tee 3 min");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
 }

 if (ScrollTasterZaehler == 3)
 {
   lcd.setCursor(0, 0);
   lcd.print("Kraeutetee 6 min");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
 }
 if (ScrollTasterZaehler == 4)
 {
   lcd.setCursor(0, 0);
   lcd.print("Beutel hoch     ");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
 }
 if (ScrollTasterZaehler == 5)
  {
   lcd.setCursor(0, 0);
   lcd.print("Beutel runter   ");
   lcd.setCursor(0, 1);
   lcd.print("weiter mit Pfeil");
  }
  
 
  if (ScrollTasterZaehler == 0 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   Kamille();
   }
  if (ScrollTasterZaehler == 1 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   Schwarztee();
  }
  if (ScrollTasterZaehler == 2 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   GruenerTee();
  }
  if (ScrollTasterZaehler == 3 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   KraeuterTee();
  }
  if (ScrollTasterZaehler == 4 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   BeutelHoch();
  }
  if (ScrollTasterZaehler == 5 && EnterTasterZaehler == 1)
  {
   EnterTasterZaehler = 0;
   BeutelRunter();
  }
 }

Gruß
Gerald

Wenn's tut was Du willst ist es doch ok. Und soweit ich das in deinem Sketch erkannt hatte, ist es da vom Ablauf eh besser, wenn es blockiert.
Das hätte man bei den MobaTools 'künstlich' einbauen müssen. Alternative wäre denn noch die Arduino-Stepper lib gewesen, die blockiert auch. Aber das ist jetzt auch egal.