Hallo an Alle, ich stehe hier vor einem kleinem Problem, vielleicht kann mir Jemand von euch helfen. Für meine Projektarbeit benötige ich einen Schrittmotor. Ich benutze einen ATMega32 dazu kommt eine Schrittmotorsteuerung aus L297/L298. Den Schrittmotor habe ich am laufen aber mit einer Einschränkung. Hier die Schilderung des Problems. Der Schrittmotor wird gestartet und soll danach 600 Schritte lange drehen. Das ganze ist Interrupt gesteuert über einen Timer. Das macht er auch. Danach sollen 30 Sekunden vergehen, dann soll er wieder 600 Schritte drehen, und nach 30 Sekunden das gleiche Spiel. Und das über 6 Minuten. Allerdings kommt es jetzt gelegentlich vor das anstatt 600 Schritte, nur 512 Schritte gemacht werden. Und das unregelmäßig, kein festes Muster zu erkennen. Mal macht er es 1 mal in den 6 Minuten, manchmal 2 mal. Ich lasse in der Interruptroutine eine Variable hochzählen und auf dem Display ausgeben, so das ich sehen kann wie oft in die Interruptroutine gesprungen wird. In der Funktion, welche den Timer einschaltet, gebe ich die Schrittanzahl vor, wenn diese erreicht wird, wird der Timer ausgeschaltet. Ich verstehe es nicht wirklich. Vielleicht hat von euch so etwas schon mal gehabt und kann mir einen Tip geben. Danke René
René Geßner schrieb: > Vielleicht hat von euch so etwas schon mal gehabt und kann mir einen Tip > geben. Das könnte am Programm oder an Störungen auf der Stromversorgung liegen.
Hallo Michael, vielen Dank für deine Antwort. Was ich bis jetzt ausschliessen kann ist, das es nicht am Schrittmotor bzw. an der Schrittmotoransteuerung ( L297/L298) liegt. Ich poste mal meinen Source Code. Da ich kein Profi bin kann mir schon mal ein Fehler unterlaufen. Und hier die Kurzbeschreibung dazu. Das Ganze läuft natürlich in einer Main ab, da das Programm doch sehr umfangreich ist, ist es nicht sinnvoll den gesamten Source Code zu posten. Ich springe zuerst in die Schrittmotor Funktion, dort wird neben einer Ausgabe auf dem Display auch der Timer2 eingeschaltet solange die Anzahl der Schritte unter 600 ist. Ist der Timer2 eingeschaltet, und das Overflow Bit ist gesetzt wird in der ISR die Variable Schritte um eins erhöht. Wenn Schritte 600 erreicht hat wird der Timer2 wieder ausgeschaltet und ich springe in die Startfunktion. Dort startet dann die Zeit von 30 Sekunden. Ist diese erreicht geht es zurück zur Schrittmotorfunktion. Und das Ganze läuft wieder bis 600 und geht zurück zur Startfunktion. Da ich ja die Aufrufe der ISR in der ISR mitzähle und danach auf dem Display ausgebe muss wohl der Fehler in der Schrittmotorfunktion liegen, denn da wird wohl zu früh der Timer2 ausgeschaltet. Und das nur ab und zu und sehr unregelmäßig. Also kein festes Schema zu erkennen, eher Zufallsprinzip. Lasse ich z.B. nur eine Umdrehung, also 200 Schritte, den Motor verfahren läuft es ohne ohne Probleme. Es werden exakt alle 30 Sekunden 200 Takte verfahren über die 6 Minuten. Dazu läuft paraell der Timer1, aber das sollte ja nicht das Problem sein. Sind ja zwei getrennte Bits zum ein- und ausschalten im TIMSK Register. Also wer einen Fehler in meiner Programmierung findet darf es mir gern sagen. Ich weiß das es nicht professional programmiert ist, aber es funktioniert mit dieser einen Einschränkung. Danke schon mal. René
1 | // ISR Routine
|
2 | |
3 | ISR( TIMER2_OVF_vect ) |
4 | |
5 | {
|
6 | |
7 | Schritte++; // hochzählen der Schritte |
8 | schritte++; // Hilfsvariable um die Anzahl der ISR Aufrufe zu zählen und auf Display auszugeben |
9 | PORTB ^= ( 1 << 2 ) | (1<<0) | (1<<3); // Ausgabe am PortB, Enable, Clock und Drehrichtung |
10 | TIFR = 0x40; // Rücksetzen des Interruptes |
11 | }
|
12 | |
13 | // Schrittmotorfunktion
|
14 | |
15 | void Schrittmotor () |
16 | {
|
17 | |
18 | lcd_clear(); |
19 | lcd_setcursor(2, 1 ); |
20 | lcd_string("Belichtungstest 1"); |
21 | lcd_setcursor(7, 3 ); |
22 | lcd_string(": min"); |
23 | |
24 | lcd_setcursor(6, 3 ); |
25 | lcd_data(M + 48); |
26 | lcd_setcursor(8, 3 ); |
27 | lcd_data(S10 + 48 ); |
28 | lcd_setcursor(9, 3 ); |
29 | lcd_data(S +48); |
30 | |
31 | |
32 | while(1) |
33 | {
|
34 | if (M >=0) |
35 | Richtung=links; |
36 | else
|
37 | Richtung=rechts; |
38 | |
39 | if (Schritte <= 599) |
40 | {
|
41 | TIMSK = 0x44; // Timer2 einschalten solange Schritte kleiner 600 ( 600 = Anzahl Schritte) |
42 | }
|
43 | else
|
44 | {
|
45 | TIMSK = 0x04; // Timer2 ausschalten wenn 2000 Schritte erreicht sind. |
46 | Schritte=0; |
47 | Intervall=0; // Zählen der Intervalle |
48 | Start (); |
49 | }
|
50 | }
|
51 | }
|
52 | |
53 | void Start () |
54 | {
|
55 | lcd_clear(); |
56 | lcd_setcursor(2, 1 ); |
57 | lcd_string("Belichtungstest 1"); |
58 | lcd_setcursor(7, 3 ); |
59 | lcd_string(": min"); |
60 | |
61 | |
62 | lcd_setcursor(3,2); // Nur für Anzeige der gezälten Schritte |
63 | itoa(schritte, f,10); // Nur für Anzeige der gezälten Schritte |
64 | lcd_string(f); // Nur für Anzeige der gezälten Schritte |
65 | |
66 | do
|
67 | {
|
68 | lcd_setcursor(6, 3 ); |
69 | lcd_data(M + 48); |
70 | lcd_setcursor(8, 3 ); |
71 | lcd_data(S10 + 48 ); |
72 | lcd_setcursor(9, 3 ); |
73 | lcd_data(S +48); |
74 | |
75 | if (S >9) |
76 | {
|
77 | S=0; |
78 | S10++; |
79 | }
|
80 | |
81 | if (S10>5) |
82 | {
|
83 | S10=0; |
84 | M++; |
85 | }
|
86 | |
87 | if (S==1) |
88 | Zyklus=0; |
89 | |
90 | if (M >= 0 && Zyklus==0) |
91 | {
|
92 | if ((S10 == 0 || S10 == 3 ) && S == 0 ) //((S10 == 0 || S10 == 1 || S10 == 2 || S10 == 3 || S10 == 4 || S10 == 5) && (S == 0 || S == 5)) |
93 | {
|
94 | Intervall=1; // |
95 | Zyklus=1; // Verhindert Zweimaliges durchlaufen der Schrittmotorfunktion |
96 | }
|
97 | }
|
98 | |
99 | while( Intervall != 1); // Ende Belichtung |
100 | {
|
101 | if (M >= 6) |
102 | {
|
103 | M=0; |
104 | S10=0; |
105 | S=0; |
106 | schritte=0; |
107 | TIMSK = 0x00; |
108 | Test1(); |
109 | }
|
110 | |
111 | else
|
112 | {
|
113 | Schrittmotor (); |
114 | }
|
115 | }
|
116 | }
|
René Geßner schrieb: > PORTB ^= ( 1 << 2 ) | (1<<0) | (1<<3); // Ausgabe am PortB, Enable, Clock und Drehrichtung Das Timing der Ansteuerung für den L297 solltest du dir noch mal genauer im Datenblatt ansehen. Du darfst nicht alle Pins gleichzeitig umschalten.
Normalerweise sollte das Timing stimmen, der Schrittmotor dreht sich sauber und zügig, verbraucht auch wenig Strom. Ich hatte erst eine andere Variante um den Clock zu erzeugen für die Geschwindigkeit.
1 | PORTB = (1<<PB2) | (1<<PB0) | (Richtung<<PB3); |
2 | |
3 | for (i = 0; i <= 150; i++) |
4 | {
|
5 | }
|
6 | PORTB = (0<<PB2) | (0<<PB0); |
Da habe ich sozusagen jeden Interrupt genutzt um einen Clock auf den Schrittmotor zu geben. Mit der For-Schleife konnte ich die Dauer des High-Signals einstellen. Und so lange diese High-Flanke kürzer war als die Periodenzeit des Timers sollte das auch kein Problem sein. Dies hatte den Vorteil das eben bei 600 Schritte 3 Umdrehungen gemacht wurden. Mit der Methode jetzt brauche ich ja die doppelte Anzahl von Schritten. Aber das spielt für mich im Moment nicht die Rolle. Und damit hatte es auch nicht funktioniert. Dadurch das es jetzt toggelt, ist bei einem Low, Enable auch auf Low. Aber das macht nichts. Allerdings habe ich es jetzt geschafft das die Anzahl der Schritte stabil bleibt und exakt 600 Schritte sich der Motor weiter dreht aller 30 Sekunden. Aber verstehen kann ich es nicht wirklich. Ich habe jetzt nur noch eine kleine Zeitschleife in der Schrittmotorfunktion, bevor der Timer2 eingeschaltet wird. Seitdem keine Probleme mehr bei 600 Schritten. Hier der Source Code
1 | void Schrittmotor () |
2 | {
|
3 | lcd_clear(); |
4 | lcd_setcursor(2, 1 ); |
5 | lcd_string("Belichtungstest 1"); |
6 | lcd_setcursor(7, 3 ); |
7 | lcd_string(": min"); |
8 | |
9 | lcd_setcursor(6, 3 ); |
10 | lcd_data(M + 48); |
11 | lcd_setcursor(8, 3 ); |
12 | lcd_data(S10 + 48 ); |
13 | lcd_setcursor(9, 3 ); |
14 | lcd_data(S +48); |
15 | |
16 | |
17 | while(1) |
18 | {
|
19 | |
20 | |
21 | |
22 | if (M >=0) |
23 | Richtung=links; |
24 | else
|
25 | Richtung=rechts; |
26 | |
27 | if (Schritte <= 599) |
28 | {
|
29 | |
30 | for(i=0; i <= 20; i++) // Neu, für genaue Schritte |
31 | {
|
32 | }
|
33 | |
34 | TIMSK = 0x44; // Timer2 einschalten solange Schritte kleiner 600 ( 600 = Anzahl Schritte) |
35 | |
36 | }
|
37 | else
|
38 | |
39 | {
|
40 | TIMSK = 0x04; // Timer2 ausschalten wenn 2000 Schritte erreicht sind. |
41 | |
42 | Schritte=0; |
43 | Intervall=0; |
44 | Start (); |
45 | }
|
46 | }
|
47 | |
48 | }
|
Hallo Michael, du hattest Recht, es lag am Timing für die Schrittmotoransteuerung. Habe mich heute Morgen noch einmal, ausgeschlafen, daran gesetzt die Datenblätter zu wälzen und danach das Timing korrekt eingestellt und seit dem gibt es keine Probleme mehr. Die Clockimpulse werden jetzt exakt am PortB ausgegeben, egal welche Anzahl ich einstelle. Ich danke dir für deine Hilfe. René
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.