Go Down

Topic: Schrittmotor 28BYJ-48 mit Potentiometer als max/min Endschlater (Read 307 times) previous topic - next topic

Fallanor

Hi,

ich bin doch sehr neu was Arduinos betrifft.
Ich habe hier eine IKEA Ps lampe die ich mit einem Arduino Uno
und einem 28BYJ-48 Schrittmotor betreiben will.
Der max und min Schalter soll ein Potentiometer sein, anstatt oben und unten Schalter anzubringen.

Durch einen Test, mit dem ich die Werte der offenen und geschlossenen Stellung der Lampe, ausgelesen habe, bin ich auf geschlossen Wert 1 und offen wert 67 gekommen.
Da dieser olle Motor nicht so einfach zum fahren zu bringen war, habe ich mit dem ein oder anderem Sketch aus dem Forum herumexperimentiert und die besagten 2 Kabel gedreht.
Soweit so gut. Leider ist das Ganze jetzt relativ langsam und Ich bin leider noch zu doof diese Entwerte für die jeweilige Position mit in den Kontext zu bringen.

Der Code sieht zur Zeit so aus:

Code: [Select]


//declare variables for the motor pins
int motorPin1 = 8;    // Blue   - 28BYJ48 pin 1
int motorPin2 = 9;    // Pink   - 28BYJ48 pin 2
int motorPin3 = 10;    // Yellow - 28BYJ48 pin 3
int motorPin4 = 11;    // Orange - 28BYJ48 pin 4
                        // Red    - 28BYJ48 pin 5 (VCC)

int motorSpeed = 2000;  //variable to set stepper speed
int count = 0;          // count of steps made
int countsperrev = 2048; // number of steps per full revolution
int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};
int potPin = 2;   //potentiometer connected to A2
int potValue = 2;   //variable to read A0 input

//////////////////////////////////////////////////////////////////////////////
void setup() {
  //declare the motor pins as outputs
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  Serial.begin(9600);
}

//////////////////////////////////////////////////////////////////////////////
void loop(){
  if(count < countsperrev )
    anticlockwise();
  else if (count == countsperrev * 2)
    count = 0;
  else
    clockwise();
  count++;
potValue = analogRead(potPin);
Serial.println(potValue);
}

//////////////////////////////////////////////////////////////////////////////
//set pins to ULN2003 high in sequence from 1 to 4
//delay "motorSpeed" between each pin setting (to determine speed)
void anticlockwise()
{
  for(int i = 0; i < 8; i++)
  {
    setOutput(i);
    delayMicroseconds(motorSpeed);
  }
}

void clockwise()
{
  for(int i = 7; i >= 0; i--)
  {
    setOutput(i);
    delayMicroseconds(motorSpeed);
  }
}

void setOutput(int out)
{
  digitalWrite(motorPin1, bitRead(lookup[out], 0));
  digitalWrite(motorPin2, bitRead(lookup[out], 1));
  digitalWrite(motorPin3, bitRead(lookup[out], 2));
  digitalWrite(motorPin4, bitRead(lookup[out], 3));
}


Wie man sehen kann, kamen meine Künste nicht über den Wert auslesen und im Serialmonitor anzeigen und die Anzahl der jeweiligen Umdrehungen durch "int countsperrev = 2048" hinaus.
Geplant ist eigentlich jetzt die Endwerte in die Bewegung Clockwise und anticlockwise als Endpunkte zu übernehmen und dann später noch einen Pir-sensor auf A0 zu legen, der die Bewegung der Lampe dann triggert.
Wie designe ich die Schleife, dass die jeweiligen Endwerte berücksichtigt werden?
Wie baue ich die Abfrage des PIr sensors in die Schleife mit ein?

Hat da jemand noch den ein oder anderen Tipp für mich?

Danke im Voraus


Rentner

Hallo,

ganz verstanden hab ich nicht was Du vorhast. Der Potiwert soll  den Sollwert sein ? oder  der Istwert. Wozu ein Istwert bei einem Stepper. ?

Du kannst mit dem Poti den Sollwert vorgeben und dann fährt der Motor auf die zugehörige Position. Da müsste dann eine Rolle drann zum Aufwickeln. Beim einschalten musst du allerdigs erst mal auf eine Refferenz ( Grundstellung ) fahren , das kann ein Endschalter oder Sensor sein.

warum benutzt Du bicht das Beispiel "MotorKnob" aus der stepper Lib. ich hab das zwar nicht selbst probiert aber ich denke für den Anfang sollte es genau das sein was Du willst.

Heinz

uwefed

Der besagte Motor ist einfach nicht für Geschwindigkeit gemacht. Durch das Getriebe ist er langsam und hat Kraft.
Um es schneller zu haben brauchst Du einen stärkeren Motor, der dann größer, schwerer und mehr Aufwand zur ansteuerung braucht.
Mein Ratschlag: bleib bei diesem Motor und freunde Dich mit dieser Geschwindigkeit an.
Grüße Uwe

Fallanor

Hallo,

ganz verstanden hab ich nicht was Du vorhast. Der Potiwert soll  den Sollwert sein ? oder  der Istwert. Wozu ein Istwert bei einem Stepper. ?

Du kannst mit dem Poti den Sollwert vorgeben und dann fährt der Motor auf die zugehörige Position. Da müsste dann eine Rolle drann zum Aufwickeln. Beim einschalten musst du allerdigs erst mal auf eine Refferenz ( Grundstellung ) fahren , das kann ein Endschalter oder Sensor sein.

warum benutzt Du bicht das Beispiel "MotorKnob" aus der stepper Lib. ich hab das zwar nicht selbst probiert aber ich denke für den Anfang sollte es genau das sein was Du willst.

Heinz
Hallo Heinz,

der Poti soll quasi die Endpunkte angeben. Habe inzwischen ein wenig umgebaut. Fährt die Lampe auf gibt das Poti am gewünschten Endpunkt den Wert 369 auf A2 aus.
Fährt die Lampe zu gibt das den Wert 520 auf A2 aus.

Diese werte sollen als Endpunkte gelten.
Heisst ich will einen Loop der irgendwie so funktioniert.

Wenn "A2" 520 oder größer fahre

Serial.println("clockwise");
myStepper.step(stepsPerOutputRevolution)

bis Wert A2 369.

Bleibe dann 5Minuten auf und fahre dann zu auf Wert 369 "A2"

Es sei denn Der PIr Sensor auf "A0" sendet in dieser Zeit ein High

Ich weiss ich ein wenig verwirrend.

Habe jetzt so viel Codeschnippsel probiert, werde aber nicht schlauer.

Mein momentaner Code sieht wie folgt aus.
Code: [Select]


/*
Stepper Motor Control

B Version - change to "Firing Sequence 1-3-2-4" and change speed to 200
RESULT: Full turn in 8 seconds instead of 30 at speed of 30. Try speed 300? no faster

C Version - re-jig from Yourduino example "Yourduino1"

*/

#include <Stepper.h>

const int stepsPerMotorRevolution = 32;  //No of steps per internal revolution of motor,
                                       //4-step mode as used in Arduino Stepper library
                                  
const int stepsPerOutputRevolution = 32*64; //no of steps per revolution of the output shaft

const int motorpin1 = 8;                    //Assign motor (ie board) pins to Arduino pins
const int motorpin2 = 9;                    //
const int motorpin3 = 10;                   //
const int motorpin4 = 11;                   //

int potPin = A2; //Mittenabgriff eines Potis. Damit steuern man Drehrichtung und -Geschwindigkeit
int potValue = 0; //Variable um den Wert vom Eingang A0 zu speichern

//Settings
const long TOP_POSITION = 369;
const int BOTTOM_POSITION = 520;

// initialize the stepper library on pins 8 through 11, Motor rev steps, "Firing" sequence 1-3-2-4,
Stepper myStepper(stepsPerMotorRevolution, motorpin1,motorpin3,motorpin2,motorpin4);            

void setup() {
// Stepper library sets pins as output

myStepper.setSpeed(400);                 //Set the speed
Serial.begin(9600);                      // initialize the serial port:

}
//                                          MAIN LOOP +++++++++++++++++++
void loop() {

if
 potValue = analogRead(A2);     // Spannung am Poti umgerechnet auf Werte zwischen 1023 = ~5V und 0 = ~0V
 Serial.print("\nA2: "); Serial.print(potValue);   // \n = neue Zeile, \t = Tabulator
// step one revolution  in one direction:
 Serial.println("clockwise");
 myStepper.step(stepsPerOutputRevolution*4);                          
 delay(1000);

potValue = analogRead(A2);     // Spannung am Poti umgerechnet auf Werte zwischen 1023 = ~5V und 0 = ~0V
 Serial.print("\nA2: "); Serial.print(potValue);   // \n = neue Zeile, \t = Tabulator
 // step one revolution in the other direction:
 Serial.println("counterclockwise");
 myStepper.step(-stepsPerOutputRevolution*4);
 delay(1000);


// potValue = analogRead(A2);     // Spannung am Poti umgerechnet auf Werte zwischen 1023 = ~5V und 0 = ~0V
// Serial.print("\nA2: "); Serial.print(potValue);   // \n = neue Zeile, \t = Tabulator
 // Quarter revolution clockwise
// Serial.println("clockwise 1/4 rev");
// myStepper.step(stepsPerOutputRevolution/4);                          
// delay(1000);


 //potValue = analogRead(A2);     // Spannung am Poti umgerechnet auf Werte zwischen 1023 = ~5V und 0 = ~0V
 //Serial.print("\nA2: "); Serial.print(potValue);   // \n = neue Zeile, \t = Tabulator
 // Half revolution counterclockwise
 //Serial.println("counterclockwise clockwise 1/2 rev");
 //myStepper.step(-stepsPerOutputRevolution/2);                          
 //delay(1000);
}
//                                  END OF MAIN LOOP +++++++++++++++++++++





Der besagte Motor ist einfach nicht für Geschwindigkeit gemacht. Durch das Getriebe ist er langsam und hat Kraft.
Um es schneller zu haben brauchst Du einen stärkeren Motor, der dann größer, schwerer und mehr Aufwand zur ansteuerung braucht.
Mein Ratschlag: bleib bei diesem Motor und freunde Dich mit dieser Geschwindigkeit an.
Grüße Uwe
Hallo Uwe,

mit dem Tempo habe ich mich inzwischen arrangiert.
Bin nur ein absoluter Codeanfänger.
Habe so viele verschiedene Wege gesehen, wie das alles programmiert werden kann, nur kann ich das nicht so auf mich portieren.


uwefed

Du willst also per Poti den Istwert messen und per Sketch die Bewegung vorgeben.

Verbesserungen.
Die Übersetzung des Potis sollte so sein daß dieses die max mögliche Drehung mit dem gewünschten Bewegung hat. Also unten fast 0 und oben fast 1023.
Da Du einen Schrittmotor verwendest ist kein poti notwendig sndern nur einen Endschalter oder Lichtschranke an einem Endpunkt. Du drest den motor solange bis der Endpunkt erkannt wird und machst alle anderen Bewegungen durch die Schrittanzahl.

Grüße Uwe

Rentner

Hallo
Ach ja noch wichtig . Die Stepper lib arbeitet blockieren . Wenn ein Fahrbefehl abgearbeitet wird kannst du somit den Endschalter nicht erkennen , bzw das Poti nicht einlesen.

Desshalb ist das bei dem knob Beispiel so gemacht das immer nur kleine Schritte gefahren werden , dann wieder Poti einlesen ,usw

Es gibt da noch eine andere lib mit vielen unterschiedlichen Fahrbefehlen, die blockiert nicht , damit kann man dann bei Erreichen des Endschalters anhalten .

uwefed


Fallanor

Hallo danke für die Tipps.

Du möchtest sowas machen?
https://www.heise.de/select/make/2017/2/1492782620783356
Ja so ein Projekt soll es werden. Fand die Geschichte mit dem Poti eleganter, weil man da nicht noch Bleche mit Endschalter drantüdeln hätte müssen.
Die einbbauposition ergibt leider nur den beschränkten Bewegungsbereich, da das Teil keine volle Strecke fährt.
Hier mal Bilder wie ich es gelöst habe.

https://cdn.instructables.com/F60/9FCU/ILJWOYBO/F609FCUILJWOYBO.LARGE.jpg?auto=webp&width=393

https://cdn.instructables.com/F57/XVBH/ILSRXN4U/F57XVBHILSRXN4U.LARGE.jpg

Wenn es mit den Endschaltern einfacher ist, dann bau ich die dann morgen ein.
Aber wie setze ich die dann mit dem Pir in den Sketch ein.
Läuft dann in dem jeweiligen Loop eine Abfrage der beiden Schalter?

Danke für die Hilfe soweit und Beste Grüße

Serenifly

Läuft dann in dem jeweiligen Loop eine Abfrage der beiden Schalter?
Ja. Du musst halt wie gesagt alle paar Schritte die Schalter abfragen. Theoretisch auch nach jedem Schritt, aber das muss je nach Anwendung nicht unbedingt sein.

postmaster-ino

Hi

Mit der AcellStepper-Library kannst Du nicht-blockierend arbeiten.
Dort gibst Du ebenfalls die maximale Geschwindigkeit und Beschleunigung an, kannst den IST-Wert resetten (letztens erst gefunden und selber noch nicht benutzt).
Damit könntest Du Deinen Endschalter suchen, resetten und ab jetzt von Null bis zu Deinem Endwert verfahren.
Den anzufahrenden Wert übergibst Du der Lib per .moveto(Soll-Schritt); oder relativ mit .move(relative_Schritte);

Auch wäre Es möglich, mehrere Stepper 'nebeneinander' fahren zu lassen - also unabhängig von einander.

Da die Motoren in jedem loop()-Durchlauf abgearbeitet werden (die Lib entscheidet, ob ein Step gemacht wird oder eben nicht), kannst Du quasi immer auf Alles reagieren.

MfG

PS: Hier habe ich vor einigen Tagen aufgeschrieben, wie ich die 28BYJ-48 aktuell betreibe.
MultiStepper-Beispiel der AccellStepper Library mit 28BYJ-48 5V Stepper
Die 'gekreuzten' mittleren Drähte sind dort auch wieder zu finden :)
anscheinend ist Es nicht erwünscht, einen Foren-internen Link als 'Homepage' einzubinden, damit JEDER nur einen Klick von combie's Liste zum Thema State-Maschine entfernt ist.
... dann eben nicht ...

uwefed



Die Elemente der Lampe werden durch eine Schnur bewegt. Im Bild aus der Montageanleitung ist das der untere Kranz der auf dem senkrechten Führung mittels 2 Schnüren auf und ab bewegt wird.
Der Motor ersetzt die Herausgeführten Schnüre und wickelt diese auf und ab. Einen Endpunkt kann man durch Kontrolle der Schnur (zB ein Knoten) oder positin des Unteren Kranzes erreichen. Die Messung eines Winkels eines Hebels ist meiner Meinung nicht der richtige Ansatzpunkt.
Grüße Uwe

Fallanor

Hallo an alle,

ich habe die Hardware soweit fertig. Die Schnur war schon ab bevor ich mich hier gemeldet hatte =)

LInk zum Ordner

Habe wie man sehen kann jetzt auf Endschalter umgebaut und den Poti stillgelegt.
Was ich nicht hin bekomme ist der Code.

Bin jetzt auf die ACCELSTEPPER bib umgestiegen und habe versucht mir aus diversen quellen ein paar Schnipsel zu nutzen.
Ich habe aber null plan wie ich den kram sinnvoll zusammen bekomme.
Mal abgesehen von dem PIR sensor eher ein Radarsensor (RCWL-0516), den ich da gerne mit anklemmen würde.
Nach dem Motto Signal vom sensor fahre motor bis endstop offen
nach 5Minuten fahre wieder bis endstop zu bis zum nächsten signal vom Sensor.

Ich vermute für euch ist das einfach aber ich dreh beinahe durch, weil es so viele Wege gibt und ich jetzt nicht einen gefunden habe, den ich verstehe.

Code: [Select]

#include <AccelStepper.h>



// Define some steppers and the pins the will use
AccelStepper stepper(4, 8, 10, 9, 11);
// The first argument '5' indicates that we're using a 28byj-48 geared motor. The rest is just pin numbers.
//You can still use all the other types of motors supported by accelstepper library (e.g. 4 for a normal 4 wire step motor, 8 for a halfstepped normal 4 wire motor etc.)


//const int EndStopOpen = 5;
//const int EndStopClosed = 4;

#define ENDSWITCH_U 4   // unterer Endswitch PIN 4
#define ENDSWITCH_O  5   // oberer Endswitch PIN 5
#define STOP 0
#define LEFT -1
#define RIGHT 1
#define SPEED 500
//classes


void setup()
{  
 stepper.setMaxSpeed(1200.0); //max speed of the first motor - modify if you want to
 stepper.setAcceleration(1000.0); // rate at which the first motor accelerate -
 pinMode (ENDSWITCH_U, INPUT);
 pinMode (ENDSWITCH_O, INPUT);
 Serial.begin(9600);
 
}
int dir = STOP;
void loop()
{    

 if (stepper.distanceToGo() == 0){
   stepper.moveTo(random(7000,1500));//just an easy way to get the motors to move to random positions
 }

 

// Endschalter, soll ja nix kaputt gehen
  if ((digitalRead(ENDSWITCH_O) == LOW) && (dir == LEFT)) {
    dir = STOP;
    Serial.println("STOP BY ENDSWITCH OBEN");
  }

  if ((digitalRead(ENDSWITCH_U) == LOW) && (dir == RIGHT)) {
    dir = STOP;
    Serial.println("STOP BY ENDSWITCH UNTEN");
  }

  stepper.setSpeed(SPEED * dir);
  stepper.runSpeed();

stepper.run();
}

uwefed

Du brauchst einen Endstop nur auf einer Seite. Durch die gegebenen Schritte am Schrittmotor weißt Du jederzeit wo der untere Rahmen steht.

Im setup() fährst den Motor langsam (ohne AccelStepper.h) in Richtung Endschalter und kontrollierst nach jedem Schritt ob der Endschalter betätigt ist. Sobald dies geschiet weißt Du wo der Motor steht und in einer Variablen speicherst Du dann jede Anzahl von Step die Du den Motor machen läßt, In eine Richtung positiv in die andere Negativ.

Einmal die Home-Position erreicht kannst Du AccelStepper.h benutzen.

Grüße Uwe



postmaster-ino

Hi

Wenn Du Das MIT der AccelStepper machst, kannst Du beim Endschalter die Schritt-Anzahl resetten und bist auf Null.
(Die .h durchstöbern, da sind die enthaltenen Methoden aufgelistet)

Davon ab: Trapez-Spindel und Wellenkupplung für einen 28BYJ-48 halte ich nicht nur für Kanonen, eher ganze Bataillone auf einzelne Spatzen.
Schaut aber sonst ganz nett aus.

MfG
anscheinend ist Es nicht erwünscht, einen Foren-internen Link als 'Homepage' einzubinden, damit JEDER nur einen Klick von combie's Liste zum Thema State-Maschine entfernt ist.
... dann eben nicht ...

Rentner

Hallo,

ich hab mich vor einiger Zeit mal mit dem Stepper Motor und der AccelStepper.h beschäftigt und mal in meiner Bastel-Kiste auf der Festplatte rumgesucht. ( da muss mal wieder aufgeräumt werden :'(  )

Ich hab was gefunden, dabei wird beim  Einschalten zurück bis auf einen Endschalter gefahren (Reverenzposition) ,  dort der Motor angehalten und das System auf 0 gesetzt. Mit einem Taster kann man dann einen Ablauf starten Pos1 anfahren, Zeit warten , Pos2 anfahren. Hab da heute noch ein paar Kommentare drangeschrieben und mal probiert ob das läuft, geht.  :)

ich denke das kannst Du auf deine Anforderung hin anpassen.

Gruß Heinz  

Code: [Select]

/*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 Pins 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
   
    return 1;
  }
  return 0;
}





Go Up