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
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.
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
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
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
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
>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..
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.
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.
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.
>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
> 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.
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.