Forum: Mikrocontroller und Digitale Elektronik Schrittmotor Starten/Stoppen


von Lutz (Gast)


Lesenswert?

Hallo, ich habe an einen Nano einen Schrittmotor angeschlossen. Ich 
verwende die Bibliothek stepper.h Der Beispielsketch "Stepper One 
Revolution" funktioniert. Ich möchte nun den Schrittmotor auf 
Tastendruck einschalten und beim loslassen ausschalten. Der Motor soll 
solange drehen wie der Taster gedrückt wird. Mit einem anderen Taster 
das Gleiche anders herum. Ich vermisse aber in der Bibliothek die 
Funktionen ähnlich wie stepper.start() und stepper.stop(). Eigentlich 
könnte ich ja einen kleinen DC-Getriebemotor nehmen, da es auf eine 
genaue Positionierung nicht ankommt, aber ich habe nun mal gerade ein 
paar von diesen Steppern herum liegen. Die sind eigentlich optimal bei 
Drehzahl und Kraft. Vielen Dank für Tipps

von Zweifler (Gast)


Lesenswert?

Gemeint ist wohl:
https://www.arduino.cc/en/reference/stepper


Ich würde dieses Beispiel ausbauen an Deiner Stelle ...
https://www.arduino.cc/en/Tutorial/StepperOneStepAtATime

Von einer while-Schleife hast Du sicher schon gehört?

von Martin K. (maart)


Lesenswert?

Pseudocode:

loop{
  solangeTasterVorwärtsGedrückt{
     step(1);
  }

    solangeTasterRückwärtsGerückt{
      step(-1);
    }
}

von Lutz (Gast)


Lesenswert?

Ja, so ähnlich habe ich es schon versucht. Hier macht aber der Motor 
immer nur einen Schritt und stoppt dann kurz und die Drehzahl ist 
wesentlich langsamer  als wenn ich ihn z.B. eine ganze Umdrehung machen 
lassen würde. Ich habe auch schon versucht, eine sehr große Anzahl von 
Schritten einzugeben, aber dann habe ich ja keine Möglichkeit das Teil 
vorher (wenn die Taste losgelassen wird) zu stoppen.

von JojoS (Gast)


Lesenswert?

Der Pseudocode von Martin müsste funktionieren. Wenn die Lib wie hier 
oben genannt verwendet wurde muss ja noch die Geschwindigkeit gesetzt 
werden. Laut Doku ist die Funktion blockierend und step(1) sollte daher 
warten bis ein Schritt fertig ist, abhängig von der Geschwindigkeit. 
Wenn die Geschwindikeit sehr hoch ist und der Stepperdriver viele 
Mikroschritte macht dann wird die Schrittfrequenz auch sehr hoch und die 
Laufzeiten der Tastenabfrage spielen eine Rolle.

von Lutz (Gast)


Lesenswert?

Ja, ich glaube auch, das es funktioniert. So ähnlich hatte ich es auch 
schon probiert. Das Problem ist nur, das durch die einzelnen Schritte 
die Drehzal deutlich sinkt und auch der Lauf wesentlich rauher ist, als 
wenn man z.B.
1000 Schritte auf einmal macht. Aber dann ist ja das Problem, das 
steps()
den Nano blockiert und man keine Möglichkeit hat eine einmal begonnene 
Bewegung  (von z.B. 40000 Schritten) vorzeitig zu stoppen.

von Martin K. (maart)


Lesenswert?

Zeig mal deinen Code.
1
#include <Stepper.h>
2
3
Stepper myStepper(200, 8, 9, 10, 11);
4
void setup() {
5
  // put your setup code here, to run once:
6
  myStepper.setSpeed(200);
7
  pinMode(2, INPUT);
8
}
9
10
void loop() {
11
  // put your main code here, to run repeatedly:
12
  int in;
13
  in = digitalRead(2);
14
  if(in == 1) {
15
    myStepper.step(1);
16
  }
17
}

Ich kann kein Rattern feststellen.

von Lutz (Gast)


Lesenswert?

Ich habe zum Starten keinen Taster sondern eine IR-Fernbedienung 
genommen. Der Motor soll so lange drehen, wie die Taste gedrückt wird. 
Es funktioniert, aber der Motor dreht total langsam.
1
#include <IRremote.h>
2
#include <Stepper.h>
3
#define MAX_TIME 200
4
5
long lastPressTime = 0;
6
int state = LOW;
7
int LED1=11;
8
int LED2=10;
9
const int stepsPerRevolution = 2048;
10
Stepper myStepper(stepsPerRevolution,2,3,4,5);
11
IRrecv irrecv(12);
12
decode_results results;
13
14
void setup()
15
{
16
  pinMode(LED1, OUTPUT);  // Status on pin 3 LED
17
  pinMode(LED2, OUTPUT);  
18
  irrecv.enableIRIn(); // Start the receiver
19
   myStepper.setSpeed(15);
20
  
21
}
22
23
void loop() {
24
  if (irrecv.decode(&results)) {
25
    Serial.println(results.value, DEC);
26
    //if (1) // Can check for a specific button here
27
    if (results.value == 58016) //richtige Taste erkannt
28
    {  Serial.println(results.value, DEC);
29
      if (state == LOW) { 
30
        state = HIGH;  // Button pressed, so set state to HIGH
31
        digitalWrite(LED1, HIGH);
32
       
33
      }
34
    }  
35
  if (state == HIGH) 
36
  {myStepper.step(1);}
37
      lastPressTime = millis();
38
     
39
    
40
    irrecv.resume(); // Receive the next value
41
  }
42
  if (state == HIGH && millis() - lastPressTime > MAX_TIME) {
43
    state = LOW; // Haven't heard from the button for a while, so not pressed
44
    digitalWrite(LED1, LOW);
45
    
46
  }
47
}

von Johannes S. (Gast)


Lesenswert?

Dann ist es wohl besser das Stepper Ojekt nicht zu benutzen und die 
Pulse 'von Hand' in einem Timer Interrupt selber zu erzeugen. Dann 
bleibt die Schrittfrequenz konstanter und ist unabhägig von der main 
loop.

von Lutz (Gast)


Lesenswert?

Hab ich mir einfacher vorgestellt. Trotzdem vielen Dank für die Hilfe.

von Johannes S. (Gast)


Lesenswert?

einfacher ginge es mit Schrittmotortreiber in Hardware, da brauchst du 
nur einen Takt und die Richtung vorzugeben.

Wenn du bei der SW Lösung bleiben willst nimm eine Lib wie
http://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html
Die arbeitet non-blocking und sollte auch funktionieren.

von Lutz (Gast)


Lesenswert?

Danke, werde ich testen.

von Georg (Gast)


Lesenswert?

Lutz schrieb:
> Hab ich mir einfacher vorgestellt

Noch eine kleine Komplikation: ein Schrittmotor hat eine maximale 
Anlauffrequenz, die ist nur ein Bruchteil der maximal möglichen 
Schrittfrequenz. Wird die überschritten, läuft er nicht an, sondern 
brummt höchstens vor sich hin. Also muss man entweder sich auf diese 
niedrige Geschwindigkeit beschränken oder per Software die 
Schrittfrequenz in einer Rampe hochfahren.

Georg

von Johannes S. (Gast)


Lesenswert?

Das wäre noch ein Grund für die AccelStep Lib weil die auch 
beschleunigen kann

von Walter S. (avatar)


Lesenswert?

dein Programmaufbau verhindert eine schnellere Schrittfolge,
beim Überfliegen glaube ich das dein Programm immer auf ein Signal von 
der Fernbedienung wartet bis ein Step ausgeführt wird. Und das Signal 
kommt natürlich nicht ausreichend oft

von Helmut H. (helmuth)


Lesenswert?

Würde zunächst mal das Überflüssige aus dem Code entfernen:
    Serial.println(results.value, DEC);
    Serial.println(results.value, DEC);
    digitalWrite(LED1, HIGH);
    digitalWrite(LED1, LOW);

Walter S. schrieb:
> beim Überfliegen glaube ich das dein Programm immer auf ein Signal von
> der Fernbedienung wartet bis ein Step ausgeführt wird.

irrecv.decode ist nicht blockierend, da ein Timer verwendet wird um den 
recvpin zu pollen, siehe 
https://github.com/z3t0/Arduino-IRremote/blob/master/irRecv.cpp

: Bearbeitet durch User
von Christian M. (Gast)


Lesenswert?

Ohne jetzt den Code studiert zu haben: Wahrscheinlich wird so nur alle 
ca. 25ms ein Schritt gemacht, wenn ein ganzes Telegramm eingegangen 
ist...?!?!

Gruss Chregu

Beitrag #4995343 wurde vom Autor gelöscht.
von Helmut H. (helmuth)


Lesenswert?

Risiken und Nebenwirkungen der C&V Programmierung:

Aktuell macht er nur einen Step wenn ein IR_Signal empfangen wird.
Obiger Code richtig formatiert (Ctrl-T in der IDE):
1
 if (irrecv.decode(&results)) {
2
        Serial.println(results.value, DEC);
3
        //if (1) // Can check for a specific button here
4
        if (results.value == 58016) //richtige Taste erkannt
5
        {  
6
            Serial.println(results.value, DEC);
7
            if (state == LOW) { 
8
                state = HIGH;  // Button pressed, so set state to HIGH
9
                digitalWrite(LED1, HIGH);
10
            }
11
        }  
12
        if (state == HIGH) 
13
        {
14
            myStepper.step(1);
15
        }
16
        lastPressTime = millis();
17
        irrecv.resume(); // Receive the next value
18
    }

Original von 
https://github.com/z3t0/Arduino-IRremote/wiki/Receiving-with-the-IRremote-library
1
  if (irrecv.decode(&results)) {
2
    if (1) {  // Can check for a specific button here
3
      if (state == LOW) { 
4
        state = HIGH;  // Button pressed, so set state to HIGH
5
        digitalWrite(LED_PIN, HIGH);
6
      }
7
      lastPressTime = millis();
8
    }
9
    irrecv.resume(); // Receive the next value
10
  }

Richtig wäre es danach den Stepper aufzurufen, auch wenn kein Signal 
dekodiert wurde
1
 if (state == HIGH) 
2
 {
3
     myStepper.step(1);
4
 }

: Bearbeitet durch User
von Walter S. (avatar)


Lesenswert?

Helmut H. schrieb:
> Aktuell macht er nur einen Step wenn ein IR_Signal empfangen wird.

hmm, sagte ich das nicht schon weiter oben?

von Helmut H. (helmuth)


Lesenswert?

Walter S. schrieb:
> hmm, sagte ich das nicht schon weiter oben?

Ja, Sorry. Hatte das faslch interpretiert und nur auf die Formatierung 
geschaut und nicht auf die {}. Auf den ersten (Python-geschädigten) 
Blick sah das so aus, als ob der step nach dem "}" von "if 
(irrecv.decode(&results)) {" aufgerufen wird :
1
 if (irrecv.decode(&results)) {
2
    Serial.println(results.value, DEC);
3
    //if (1) // Can check for a specific button here
4
    if (results.value == 58016) //richtige Taste erkannt
5
    {  Serial.println(results.value, DEC);
6
      if (state == LOW) { 
7
        state = HIGH;  // Button pressed, so set state to HIGH
8
        digitalWrite(LED1, HIGH);
9
       
10
      }
11
    }  
12
  if (state == HIGH) 
13
  {myStepper.step(1);}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.