Forum: Mikrocontroller und Digitale Elektronik Schrittmotor Treiber-Ansteuerung (Atmel 98C51)


von konrad m. (ati) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hy,

Ich realisiere mittels zwei Schrittmotoren mit befestigten Spiegeln eine 
Lasershow. Diese werden über einen Treiber-IC (DRV8821)angesteuert.

Dessen Eingänge steuer ich über einen Mikrocontroller an.

Eingänge vom DRV8821:

ABSTEP: steigende Flanke->ein Schritt
ABDIR: 0 oder 1 bestimmt die Richtung
ABENBLn: 0
ABUSM0: 0
ABUSM1: 0
ABDECAY: 1
ABRESETn: 1

Da ich wirklich nicht so der Software-Erfahren bin, hoffe ich jemand von 
euch kann mir helfen.

Die zwei Bits ABSTEP und ABDIR müssen leicht verzögert am Treiber 
anliegen und da liegt mein Problem. Ich hoffe ihr könnt mir einen 
Denkanstoss geben.
Ich denke ich werde wohl um ein kleines Timer Unterprogramm nicht herum 
kommen.

Wie lange die Bits verzögert sein müssen, kann man dem Bild im Anhang 
entnehmen und hier wäre noch das gesamte Datenblatt des DRV8821:
http://www.ti.com/product/drv8821

Freundliche Grüsse
ati

von MaWin (Gast)


Lesenswert?

Kein Timer.
Du musst nur vorher das Port-Bit für die Richtung setzen,
und dann erst frühestens in der nächsten Instruktion das Bit für den 
Takt, denn die 200ns zu unterbieten schafft der C51 gar nicht.

von spess53 (Gast)


Lesenswert?

Hi

>Die zwei Bits ABSTEP und Die zwei Bits ABSTEP und ABDIR müssen leicht verzögert 
am Treiber
anliegen und da liegt mein Problem. Ich hoffe ihr könnt mir einen
Denkanstoss geben. müssen leicht verzögert am Treiber
>anliegen und da liegt mein Problem. Ich hoffe ihr könnt mir einen
>Denkanstoss geben. ABDIR muss gültig sein bevor du anfängst Schritte zu senden. 
Und das bleibt auf dem Pegel solange du in dieser Richtung fahren willst.

MfG Spess

von Reinhard Kern (Gast)


Lesenswert?

MaWin schrieb:
> denn die 200ns zu unterbieten schafft der C51 gar nicht.

Bei einem 20MHz-Prozessor würde ich da sicherheitshalber im Datenblatt 
nachschauen, aber mit grosser Wahrscheinlichkeit hast du recht. Wenn 
nicht, tut's auch der eine oder andere NOP, einen Timer braucht man 
definitiv nicht.

Gruss Reinhard

von spess53 (Gast)


Lesenswert?

Hi

da ist etwas durcheinander gekommen

>Die zwei Bits ABSTEP und Die zwei Bits ABSTEP und ABDIR müssen leicht >verzögert 
am Treiber anliegen und da liegt mein Problem. Ich hoffe ihr >könnt mir einen 
Denkanstoss geben.

ABDIR muss gültig sein bevor du anfängst Schritte zu senden.
Und das bleibt auf dem Pegel solange du in dieser Richtung fahren 
willst.

MfG Spess

von konrad m. (ati) Benutzerseite


Lesenswert?

Erstmals Danke für die schnellen Antworten.

Das heisst, es ist möglicherweise nicht ganz so kompliziert wie ich 
anfangs dachte.

Kann ich also einfach nach und nach ein Bitmuster an den Ausgang 
ausgeben? zB:
P1= 1100000      //H-Brücke freigegeben, STEP-MODE bestimmt
P1= 1100010      //DIR=1
P1= 1100011      //STEP=1
P1= 1100001      //DIR=0
P1= 1100000      //STEP=0
//1 Schritt in eine Richtung gemacht!

Ich schau mal noch im Datenblatt wegen den 200nS nach.

Ist es möglich, dass ich paralell dazu noch ein Bitmuster für den 
CD-Motor ausgeben kann?
Denn die Spiegel müssen sich ja auch gegensätzlich bewegen lassen.

Herzlichen Dank,
ati

von r0fler (Gast)


Lesenswert?

>Kann ich also einfach nach und nach ein Bitmuster an den Ausgang
>ausgeben? zB:
>P1= 1100000      //H-Brücke freigegeben, STEP-MODE bestimmt
>P1= 1100010      //DIR=1
>P1= 1100011      //STEP=1
>P1= 1100001      //DIR=0
>P1= 1100000      //STEP=0
>//1 Schritt in eine Richtung gemacht!

DIR kannst du auf 1 lassen, ich denke kaum dass du nach jedem Schritt 
die Richtung ändern willst oder?
Soweit ich das verstanden habe, muss DIR einfach mindestens 200ns vor 
einem Schritt auf den gewünschten Wert gesetzt werden.

>Ich schau mal noch im Datenblatt wegen den 200nS nach.

Sollte kein Problem darstellen, kannst du bedenkenlos vernachlässigen. 
Sollte es dir dennoch lieber sein kannst du ja immer noch einen kleinen 
Delay einbauen (würde ich aber nicht mache, da sich bei so einer 
Lasershow die Spiegelchen recht schnell bewegen müssen und du so nur 
wertvolle Zeit verplemperst).

>Ist es möglich, dass ich paralell dazu noch ein Bitmuster für den
>CD-Motor ausgeben kann?

Klar! wenn du genügend Ausgänge hast..

von Karl H. (kbuchegg)


Lesenswert?

Tim Alder schrieb:

> Kann ich also einfach nach und nach ein Bitmuster an den Ausgang
> ausgeben? zB:

und wenn du das mit logischen Verknüpfungen machst, dann kannst du den 
ganzen VCorgang in 2 Teile aufspalten:
erst mal alles freigeben und einstellen

> P1= 1100000      //H-Brücke freigegeben, STEP-MODE bestimmt
> P1= 1100010      //DIR=1


und dann für jeden Schritt, den du in diese Richtung machen musst 
einfach nur das Bit 0 auf 1 ziehen und wieder auf 0 fallen lassen

P1 = P1 | 0x01;   // Bit 0 auf 1
P1 = P1 & ~0x01;  // Bit 0 wieder auf 0

Und diese Seqeuenz machst du so oft, wie du Schritte brauchst.
Eventuell musst du eine kleine Pause dazwischen machen, aber das hängt 
dann unter anderem auch vom Motor, der angehängten Last etc. ab.

von Möve (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Eventuell musst du eine kleine Pause dazwischen machen, aber das hängt
> dann unter anderem auch vom Motor, der angehängten Last etc. ab.

Bei den kleinen Spiegelchen für die fächerung des Lasers kannst du mit 
dem richtigen Motor ziemlich schnell schalten ohne Angst zu haben dass 
Schritte "verschluckt" werden.

Vlt. noch einen Schrittzähler verwenden oder mal im Datenblatt des 
Treiber-IC's nachschauen ob ein solcher vieleicht schon mit dabei ist.

"verschluckte" Schritte könnten unter Umständen zu einem Problem werden 
wenns zu häufig vorkommt.. dann verschiebt sich der Abstrahlwinkel des 
Lasers und er wird vlt. im extremfall gar nicht mehr reflektiert.

von konrad m. (ati) Benutzerseite


Lesenswert?

Das hat mir jetzt schon sehr weitergeholfen. Ich freue mich schon, wenn 
mein Print am Mittwoch ferig ist und ich das Ganze anschliessen und 
programmieren/austesten kann. :)

r0fler schrieb:
> DIR kannst du auf 1 lassen, ich denke kaum dass du nach jedem Schritt
> die Richtung ändern willst oder?
> Soweit ich das verstanden habe, muss DIR einfach mindestens 200ns vor
> einem Schritt auf den gewünschten Wert gesetzt werden.

So habe ich das auch verstanden.

Karl Heinz Buchegger schrieb:
> und wenn du das mit logischen Verknüpfungen machst, dann kannst du den
> ganzen VCorgang in 2 Teile aufspalten:
> erst mal alles freigeben und einstellen
>
>> P1= 1100000      //H-Brücke freigegeben, STEP-MODE bestimmt
>> P1= 1100010      //DIR=1
>
>
> und dann für jeden Schritt, den du in diese Richtung machen musst
> einfach nur das Bit 0 auf 1 ziehen und wieder auf 0 fallen lassen
>
> P1 = P1 | 0x01;   // Bit 0 auf 1
> P1 = P1 & ~0x01;  // Bit 0 wieder auf 0
Ahaa, mit logischen Verknüpfungen geht das natürlich noch besser. Ich 
muss dieses Thema unbedingt nochmals anschauen. Danke für den Anstoss.
Für die andere Richtung müsste ich dann nur am Anfang Bit 1 auf 0 
setzen, aber die log. Verknüpfungen bleiben die selben.

Möve schrieb:
> Bei den kleinen Spiegelchen für die fächerung des Lasers kannst du mit
> dem richtigen Motor ziemlich schnell schalten ohne Angst zu haben dass
> Schritte "verschluckt" werden.
>
> Vlt. noch einen Schrittzähler verwenden oder mal im Datenblatt des
> Treiber-IC's nachschauen ob ein solcher vieleicht schon mit dabei ist.
>
> "verschluckte" Schritte könnten unter Umständen zu einem Problem werden
> wenns zu häufig vorkommt.. dann verschiebt sich der Abstrahlwinkel des
> Lasers und er wird vlt. im extremfall gar nicht mehr reflektiert.

Ich verwende zwei Schrittmotoren von Trinamic:   QSH4218-51-10-049 
heisst das Ding. Ich denke, die bringen einen rechten Drehmoment hin und 
sollten keine Mühe mit so kleinen Spiegel'n haben.
Aber das mit dem Schritte verschlucken macht mir auch ein wenig Mühe. 
Zuerst dachte ich, ich baue noch eine Lichtschranke ein, um die Schritte 
zu zählen. Doch dies bedeutet einen grossen zusätzlichen Hardware 
Aufwand.
Da wäre eine Software-mässige Lösung wohl einfacher zu realisieren.

Evt. eine Variable, die bei 0 anfängt, und je nach Richtung 1+ oder 1- 
zählt. Bei Unstimmigkeiten könnte ich so die ursprüngl. Ausgangslage 
wieder anfahren.
Im Treiber ist, so wie ich das sehe, kein Schrittzähler mit dabei.

Ich schreibe auf jeden Fall wie die ersten Tests gelaufen sind. Hoffe, 
dass die Print-Fräsmaschine am Mi. wieder läuft. :)

Vielen Dank,
gruss ati.

von Cööder (Gast)


Lesenswert?

>Da ich wirklich nicht so der Software-Erfahren bin, hoffe ich jemand von
>euch kann mir helfen.

Mal ein Gedankenanstoss:


void drive (char dir, char mode) // dir -> richtung, mode -> effekt
                                 // (mehrere effekte?)
{ P1= 1100000      //H-Brücke freigegeben, STEP-MODE bestimmt
  if (dir == 1)
  {
   P1= 1100010      //DIR=1
  }
  else
  {
   P1= 1100000      //DIR=0
  }

switch(mode)
{
  case 0: while(???){P1 = P1 | 0x01; P1 = P1 & ~0x01;}  // mit delay?
  break;
  case 1....
  ...
}

}

void main (void)
{
  drive(1, 1);
}


Schonmal sorry für falsche Funktionen? Bin schon länger nicht mehr mit C 
im Rennen ;) aber die Funktion sollte (hoffe ich) verständliche und 
ausbaufähig sein

von Karl H. (kbuchegg)


Lesenswert?

> void drive (char dir, char mode) // dir -> richtung, mode -> effekt


Das ist doch eine unsinnige Schnittstelle. Du mischt da wild 
Mustergenerierung und Schrittrichtung durcheinander.

Die Schrittrichtung ergibt sich aus dem abzufahrenden Muster. Auf 
tieferer Ebene, also alles unter den Softwareebene 'Muster' existiert 
kein Muster mehr. Da geht es nur noch darum, dass ein Motor 25 Schritte 
nach links machen soll, dann 10 Schritte rechts und wieder 35 Schritte 
links.

Also wenn schon dann
1
void drive( unsigned char direction, int steps )
2
{
3
  P1= 1100000;
4
  if( direction )
5
    P1 |= 0x02;
6
7
  for( int i = 0; i < steps; ++i )
8
  {
9
    P1 |= 0x01;
10
    P1 &= ~0x01;
11
  }
12
13
  P1 = 0x00;
14
}

(wobei ich die Initialisierung und das Einschalten des Treibers sogar 
noch aus dieser Funktion raushalten würde.

Über dieser Funktion liegt dann eine Funktion, die den mode (also eine 
Musternummer) bekommt und aus der Musterbeschreibung dann entsprechende 
Aufrufe für drive generiert.

So könnte aus dem ganzen ein Schuh werden, denn die interessante Frage 
kommt ja erst noch: wie werden eigentlich 2 Schrittmotoren gleichzeitig 
angesteuert, so dass sich auch Bewegungen realisieren lassen, die nicht 
entlang der Hauptachsen von statten gehen.

von ati (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> So könnte aus dem ganzen ein Schuh werden, denn die interessante Frage
>
> kommt ja erst noch: wie werden eigentlich 2 Schrittmotoren gleichzeitig
>
> angesteuert, so dass sich auch Bewegungen realisieren lassen, die nicht
>
> entlang der Hauptachsen von statten gehen.

Ich hab jetzt meine Platine fertig und kann Sie über mein uC-Board 
ansteuern. Jetzt stellt sich mir genau diese Frage?

Mit dem Programm, das ich bis jetzt geschrieben habe, kann ich die 
Anzahl Schritte und die Geschwindigkeit einfach verändern.
Aber nur für ein Motor.
1
#include <reg51xD2.h>
2
3
long int i=0,k=0;
4
sbit S1= P0^7;
5
int X=1;
6
7
8
void main (void)
9
{
10
11
while (1)
12
{
13
14
15
16
//******** Automatisches Laserbild1************//
17
  if (S1)  {
18
19
20
  switch (X)  {
21
22
23
  case 1:
24
    P1=0x40;          //Gegenuhrzeigersinn
25
    P1=P1|0x24;          //Konfig.
26
    for(i=0;i<500;i++);      //Pause
27
    P1=P1|0x01;          //1 Step
28
    for(i=0;i<500;i++);      //Pause
29
30
    if (k<30)          //Anzahl Schritte
31
    {
32
    X=1;
33
    k++;
34
    }
35
    else 
36
    {
37
    X=2;
38
    k=0;
39
    }
40
  break;
41
42
  case 2:
43
    P1=0x40;          //Uhrzeigersinn
44
    P1=P1|0x20;          //Konfig
45
    for(i=0;i<500;i++);      //Pause
46
    P1=P1|0x01;          //1 Step
47
    for(i=0;i<500;i++);      //Pause
48
  
49
    if (k<30)          //Anzahl Schritte
50
    {
51
    X=2;
52
    k++;
53
    }
54
    else 
55
    {
56
    X=1;
57
    k=0;
58
    }
59
  break;
60
   
61
62
  }
63
  }
64
}
65
}

Hoffe mir kann jemand helfen.
Gruss ati

von R. W. (quakeman)


Lesenswert?

Also wenn ich das richtig mitbekommen habe, dann benutzt er doch einen 
8051 kompatiblen Controller. Wieso verwendet ihr dann nicht auch dessen 
spezielle Eigenschaft die Bitadressierbarkeit, welche die Programmierung 
sowie die Lesbarkeit des Codes deutlich vereinfachen?
Zumindest in dem Fall, dass nur ein Bit verändert werden soll braucht 
man keine Zuweisung des gesamten Bytes auf den Port. Ebenfalls keine 
"and" oder "or" Verknüpfungen.

Also anstatt folgenden Code zu schreiben:
1
void drive( unsigned char direction, int steps )
2
{
3
  P1= 1100000;
4
  if( direction )
5
    P1 |= 0x02;
6
7
  for( int i = 0; i < steps; ++i )
8
  {
9
    P1 |= 0x01;
10
    P1 &= ~0x01;
11
  }
12
13
  P1 = 0x00;
14
}

Solltet ihr lieber direkt die Pins ansprechen:
1
void drive( unsigned char direction, int steps )
2
{
3
  P1= 1100000;
4
  if( direction )
5
    P1^1 = 1;
6
7
  for( int i = 0; i < steps; ++i )
8
  {
9
    P1^1 = 1;
10
    P1^1 = 0;
11
  }
12
13
  P1 = 0x00;
14
}

Das direkte Ansprechen der Bits hat gleich zwei Vorteile.
Erstens braucht dieser Befehl nur 2 Byte Codespeicher im Gegensatz zur 
und/oder-Verknüpfung oder der byteweisen Zuweisung, welche 3 Byte 
benötigen.
Zweitens wird der Befehl in der Hälfte der Zeit abgearbeitet.

Also insofern nur ein einzelner Portpin verändert werden soll, sollte 
man doch diesen auch direkt ansprechen. :)

Ciao,
     Rainer

PS: Ob die korrekte Syntax nun P1^1 oder P1.1 lautet hängt etwas vom 
Compiler ab.

von konrad m. (ati) Benutzerseite


Lesenswert?

Hallo miteinander,

Ich habe mein Programm jetzt soweit, dass ich meine Motoren/Spiegel 
Schritt für Schritt justieren und somit in Stellung bringen kann.
Also der manuelle Modus ist soweit fertig.
Mit dem automatischen Modus komme ich überhaupt nicht zurecht.

Jetzt stehe ich vor dem Problem, dass ich es nicht hinbekomme, meine 
Spiegel "gleichzeitig" zu bewegen.

Ich möchte als erstes ein ganz simples Bild an die Wand zaubern. Es soll 
wie eine "Laserwand" aussehen die sich hin und her bewegt.

Das heisst Motor 2 (Y-Achse) soll sich immer ein Schritt hin und wieder 
zurück bewegen.
Motor 1 (X-Achse) hingegen soll gleichzeitig -etwas langsamer- 5 
Schritte hin und wieder zurück fahren.

Die Ports sind P1 und P2.
Bit 0 ist jeweils das STEP-Bit (steigende Flanke=1 Schritt)
Bit 2 ist jeweils das DIR-Bit  (0=Uhrzeigersinn, 1=Gegenuhrzeigersinn)

Ich hoffe jemand von euch hat eine Idee, wie man das realisieren könnte.

Hier wäre der Code, den ich bis jetzt geschrieben habe.
1
#include <reg51xD2.h>
2
3
sbit MODE = P0^7;
4
sbit motorwahl = P0^6;
5
sbit DIR = P0^5;
6
sbit STEP = P0^4;
7
unsigned char pegel_vorher,pegel_vorher1;
8
int k,i,modus,manuell,automatisch=10, motor;
9
10
void main (void)  {
11
12
P1=0x00;
13
P2=0x00;
14
P3=0x00;
15
while (1)  {
16
17
while (MODE==0)  {
18
  
19
20
//***********************MANUELLER MODUS**************************************///
21
/////////////////////////////////////////////////////////////////////////////////
22
                      //Manuell
23
24
    if ((motorwahl == 0)&&(DIR==0))        //Motor1, Uhrzeigersinn
25
    motor=10;
26
    
27
    if ((motorwahl == 0)&&(DIR==1))        //Motor1, Gegenuhrzeigersinn
28
    motor=20;
29
    
30
    if ((motorwahl == 1)&&(DIR==0))        //Motor2, Uhrzeigersinn
31
    motor=30;
32
    
33
    if ((motorwahl == 1)&&(DIR==1))        //Motor2, Gegenuhrzeigersinn
34
    motor=40;
35
36
37
    switch (motor)  {
38
39
    //*****************Motor1, Uhrzeigersinn*************//
40
    case 10:                
41
    P2=0x60;
42
    if ((STEP==1)&&(pegel_vorher1==0))  {  //positive Flanke  
43
      for(i=0;i<500;i++);          //Pause
44
      P2=P2|0x01;              //STEP=1;
45
      for(i=0;i<500;i++);          //Pause
46
      P2=P2&0x60;              //STEP=0;
47
      pegel_vorher1=1;
48
    }
49
  
50
    
51
    if ((STEP==0)&&(pegel_vorher1==1))  {   //negative Flanke
52
      for(i=0;i<500;i++);          //Pause
53
      P2=P2|0x01;              //STEP=1;
54
      for(i=0;i<500;i++);          //Pause
55
      P2=P2&0x60;              //STEP=0;
56
      pegel_vorher1=0;
57
    }    
58
59
  break;
60
    //*****************Motor1, Gegenuhrzeigersinn*************//
61
    case 20:            
62
    P2=0x64;
63
    if ((STEP==1)&&(pegel_vorher1==0))  {  //positive Flanke  
64
      for(i=0;i<500;i++);          //Pause
65
      P2=P2|0x01;              //STEP=1;
66
      for(i=0;i<500;i++);          //Pause
67
      P2=P2&0x64;              //STEP=0;
68
      pegel_vorher1=1;
69
    }
70
  
71
    
72
    if ((STEP==0)&&(pegel_vorher1==1))  {   //negative Flanke
73
      for(i=0;i<500;i++);          //Pause
74
      P2=P2|0x01;              //STEP=1;
75
      for(i=0;i<500;i++);          //Pause
76
      P2=P2&0x64;              //STEP=0;
77
      pegel_vorher1=0;
78
    }    
79
  break;
80
81
    //*****************Motor2, Uhrzeigersinn*************//
82
    case 30:            
83
    P1=0x64;
84
    if ((STEP==1)&&(pegel_vorher1==0))  {  //positive Flanke  
85
      for(i=0;i<500;i++);          //Pause
86
      P1=P1|0x01;              //STEP=1;
87
      for(i=0;i<500;i++);          //Pause
88
      P1=P1&0x64;              //STEP=0;
89
      pegel_vorher1=1;
90
    }
91
  
92
    
93
    if ((STEP==0)&&(pegel_vorher1==1))  {   //negative Flanke
94
      for(i=0;i<500;i++);          //Pause
95
      P1=P1|0x01;              //STEP=1;
96
      for(i=0;i<500;i++);          //Pause
97
      P1=P1&0x64;              //STEP=0;
98
      pegel_vorher1=0;
99
    }
100
  break;
101
102
    //*****************Motor2, Gegenuhrzeigersinn*************//
103
    case 40:            
104
    P1=0x60;
105
    if ((STEP==1)&&(pegel_vorher1==0))  {  //positive Flanke  
106
      for(i=0;i<500;i++);          //Pause
107
      P1=P1|0x01;              //STEP=1;
108
      for(i=0;i<500;i++);          //Pause
109
      P1=P1&0x60;              //STEP=0;
110
      pegel_vorher1=1;
111
    }
112
  
113
    
114
    if ((STEP==0)&&(pegel_vorher1==1))  {   //negative Flanke
115
      for(i=0;i<500;i++);          //Pause
116
      P1=P1|0x01;              //STEP=1;
117
      for(i=0;i<500;i++);          //Pause
118
      P1=P1&0x60;              //STEP=0;
119
      pegel_vorher1=0;
120
    }    
121
  break;
122
    }
123
}
124
125
//***********************AUTOMATISCHER MODUS**************************************///
126
/////////////////////////////////////////////////////////////////////////////////
127
128
      switch  (automatisch)  {
129
130
//!!!!Nach dem im manuellen Modus die Spiegel Waagrecht justiert wurden, werden Sie im "case 10" in Stellung gebracht!!!
131
      case 10:                   
132
            P1=0x60;          
133
            P2=0x64;
134
            for(i=0;i<500;i++);      //Pause
135
            P1=P1|0x01;          //1 Step
136
            P2=P2|0x01;          //1 Step
137
            for(i=0;i<500;i++);      //Pause
138
        
139
            if (k<23)          //Anzahl Schritte
140
            {
141
            automatisch=10;
142
            k++;
143
            }
144
            else 
145
            {
146
            automatisch=20;
147
            k=0;
148
            
149
            }
150
151
       break;
152
//!!!! AB HIER SOLLTE ES MIT DER SICH HIN UND HER BEWEGENDEN LASERWAND LOSGEHEN!!!!!!!
153
154
       case 20:                
155
156
       break;
157
158
159
160
      }
161
162
}
163
}

Mit freundlichem Gruss
ati

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.