Forum: Mikrocontroller und Digitale Elektronik Schrittmotor soll Encoder Signal folgen. Arduino


von mr.T (Gast)


Lesenswert?

Nabend in die Runde,
ich dachte eigentlich das es recht einfach ist, wurde aber eines 
besseren belehrt.

Ich möchte das ein Schrittmotor möglichst genau einem Drehencoder 
Signal, der an einem anderen Motor hängt, Synchron folgt mit 
einstellbarem Multiplikator. Die start Position und Endposition soll er 
sich merken um später im selben Winkel wieder an zu fangen...

Soweit so gut, Arduino bietet ja Bibliotheken die aber durch die 
Interrupts des Encoders nicht sonderlich sauber Laufen. Was ich suche 
wäre eine Bibliothek ähnlich wie die aus der AppNote von Atmel 466. Also 
über den Timer gesteuerte Takte samt linearer Rampenfunktion. Eigentlich 
dachte ich das es ein Tägliches Problem währe und ich die Qual der Wahl 
habe... Der Stepper wird über Step/Dir angesprochen.

1. Gibt es eine Bibliothek die mit dem Timer arbeitet?
2. Kann man den Quellcode aus der AppNote 466 auf den Mega2560 Anpassen?
3. Wie könnte die Positions Regelung aussehen?

Grüße und Danke T

von mr.T (Gast)


Lesenswert?


von Reinhard Kern (Gast)


Lesenswert?

mr.T schrieb:
> Die start Position und Endposition soll er
> sich merken um später im selben Winkel wieder an zu fangen...

Das ist das erste Problem, um das du dich kümmern musst - weder der 
Encoder noch der Schrittmotor haben ohne weiteres eine definierte 
Nullpunktstellung. Ein Encoder kann eine dritte Spur mit Nullsignal 
haben, aber die ist erst verwertbar, wenn nach dem Einschalten diese 
Position überfahren wird. Ein Schrittmotor hat überhaupt keine 
definierte Nullstellung, die kann man nur extern erzeugen, etwa mit 
einem Schalter oder einer Lichtschranke, und auch die müssen erst mal 
angefahren werden.

Was auch so funktioniert: beide stehen wie sie eben stehen, nach dem 
Einschalten bewegt sich der Motor nach links wenn du nach links drehst 
usw. Du darfst nur nicht im ausgeschalteten Zustand was bewegen.

Die Sache ist auch nicht ganz so einfach: wenn der Motor von selbst in 
Nullstellung fährt, sollte ja auch der Drehgeber auf Null stehen, das 
tut er aber nicht, es sei denn man baut einen Motor dran...

Gruss Reinhard

von mr.T (Gast)


Lesenswert?

Hallo,

ich verwende zur zeit
1
#define encoder0PinA 2
2
#define encoder0PinB 3
3
#define resolution 800
4
#define CCW 0
5
#define CW 1
6
7
8
boolean _direction;
9
volatile long encoder0Pos = 0; //absolut 
10
volatile  int encoderWPos = 0; //Winkel
11
unsigned int tmp = 0;
12
unsigned int Aold = 0;
13
unsigned int Bnew = 0;
14
void setup() {
15
  pinMode(encoder0PinA, INPUT); 
16
  pinMode(encoder0PinB, INPUT);
17
// encoder pin on interrupt 0 (pin 2)
18
  attachInterrupt(0, doEncoderA, CHANGE);
19
// encoder pin on interrupt 1 (pin 3)
20
  attachInterrupt(1, doEncoderB, CHANGE);
21
// set up the Serial Connection 
22
  Serial.begin (115200);
23
}
24
void loop(){
25
  //Check each changes in position
26
  if (tmp != encoder0Pos) {
27
    Serial.println(encoder0Pos, DEC);
28
    Serial.println(encoderWPos, DEC);
29
    Serial.println(_direction, DEC);
30
    tmp = encoder0Pos;
31
  }
32
  delay(500);
33
}
34
// Interrupt on A changing state
35
void doEncoderA(){
36
  Bnew^Aold ? encoder0Pos++:encoder0Pos--;
37
  Bnew^Aold ? encoderWPos++:encoderWPos--;
38
  Bnew^Aold ? _direction = CW :_direction = CCW ;
39
  
40
  // winkelpositionen !! 0 und resolution liegen auf einem punkt, 0 = resolution!!
41
  if (encoderWPos >= resolution  ){encoderWPos = 0; }
42
  if (encoderWPos < 0){encoderWPos = resolution-1 ;}
43
  Aold=digitalRead(encoder0PinA);
44
}
45
// Interrupt on B changing state
46
void doEncoderB(){
47
  Bnew=digitalRead(encoder0PinB);
48
  Bnew^Aold ? encoder0Pos++:encoder0Pos--;
49
  Bnew^Aold ? encoderWPos++:encoderWPos--;
50
  Bnew^Aold ? _direction = CW :_direction = CCW ;
51
  
52
  // winkelpositionen !! 0 und resolution liegen auf einem punkt, 0 = resolution!!
53
  if (encoderWPos >= resolution  ){encoderWPos = 0; }
54
  if (encoderWPos < 0){encoderWPos = resolution-1 ;}
55
}

das klappt eigentlich ganz gut... jetzt geht es an die Stepper Funktion 
die eigentlich der encoder0Pos erstmal folgen sollte...

von mr.T (Gast)


Lesenswert?

Jetzt wollte ich da noch eine Drehzahl und eventuell Beschleunigungs 
Erfassung einbauen...

grüße und danke Malte

von mr.T (Gast)


Lesenswert?

Ich hab das jetzt mit dem Bresenham Algorithmus gut hinbekommen...

Nun geht es darum den Schrittmotor noch ein zu koppeln...

von mr.T (Gast)


Angehängte Dateien:

Lesenswert?

http://www.youtube.com/watch?v=E1eEvpV33OQ&feature=youtu.be

Läuft nun erstmal... im Anhang die Graphen für Weg und Geschwindigkeit, 
hab da die jeweiligen Impulse addieren lassen, Rot ist die 
Geschwindigkeit, Blau der Weg des Schrittmotors... bin erstmal 
zufrieden.

A Sind meine Führungsimpulse, B mein Weg, C die Geschwindigkeit.

von Stefan (Gast)


Lesenswert?

ich sitze aktuell an dem selben problem, könntest du mir vielleicht 
deinen fertigen Code zur Verfügung stellen... stell mich gerade etwas 
glatt an

hab vielen lieben dank für deine Bemühungen


Stefan

von Florian B. (hanibal_smith)


Lesenswert?

Hallo zusammen,

ich muss zugeben, dass ich in Sachen Arduino noch neu unterwegs bin, 
jedoch mit Variablen usw. vertraut bin.

zum aktuellen Thread hier hätte ich auch eine Frage und zwar habe ich 
einen Sketch geschrieben in dem der Schrittmotor sich erst mal komplett 
nach links dreht und im anschluss wieder nach rechts.

Nun möchte ich noch eine Wegverfolgung implementieren und habe an der 
Welle des Steppers einen kleinen 
[[Drehgeber]https://www.conrad.de/de/iduino-drehgeber-1-st-se055-1485328.html?WT.mc_id=google_pla&WT.srch=1&hk=SEM&insert_kz=VQ&s_kwcid=AL!222!3!98230272297!!!g!!]] 
angeschlossen.

nun dreht sich zwar der Stepper, aber im seriellen Monitor sehe ich nur 
mit extremer Verzögerung das sich die Position ändert.
1
#include <Stepper.h>
2
3
#define TaktA 8
4
#define TaktB 9
5
6
int SPU = 2048;
7
int counter = 0;
8
int apos;
9
int apos_alt;
10
11
Stepper Motor(SPU, 3,5,4,6);
12
13
void setup() {
14
  Motor.setSpeed(15);
15
  pinMode (TaktA, INPUT);
16
  pinMode (TaktB, INPUT);
17
18
  Serial.begin (9600);
19
}
20
21
void loop() {
22
 apos = digitalRead(TaktA);
23
 if (apos!=apos_alt){
24
  if (digitalRead(TaktB) !=apos_alt){
25
    counter ++;
26
  }
27
  else {
28
  counter --;
29
 }
30
 Serial.print("Position:   ");
31
 Serial.println(counter);
32
}
33
 
34
  Motor.step(2048);
35
    delay(1000);
36
  Motor.step(-2048);
37
    delay(1000);
38
39
}

was mache ich falsch? ich wollte schon das der Zähler synchron 
hochzählt.

Bitte entschuldigt die evlt. dumme Frage, aber wie gesagt in Sachen 
Arduino bin ich noch neu :-(

von Wolfgang (Gast)


Lesenswert?

Florian B. schrieb:
> nun dreht sich zwar der Stepper, aber im seriellen Monitor sehe ich nur
> mit extremer Verzögerung das sich die Position ändert.
> ...
> was mache ich falsch?

1. delay(1000);
2. Formatiere mal deinen Code vernünftig, damit du deine Blöcke siehst

Du legst dein Programm 2x für jeweils eine Sekunde lahm. Was erwartest 
du?

von Florian B. (hanibal_smith)


Lesenswert?

Das mit der 1 Sekunde pause ist so gewollt, aber der Drehgeber zählt 
während der Drehung des Steppers nicht hoch :-(
Soweit ich weiß sind doch µC echtzeitfähig oder?

von Wolfgang (Gast)


Lesenswert?

Florian B. schrieb:
> Soweit ich weiß sind doch µC echtzeitfähig oder?

Nur, wenn man sie nicht mit delay() blockiert und das Programm 
entsprechend geschrieben ist.
Du aber fragst deinen Encoder in der zeitweise blockierten Schleife ab, 
so dass der µC jeweils über 1s nicht mitbekommt, was an den 
Encodereingängen passiert.

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.