Hallo Leute, ich brauche eure Hilfe. ich möchte den Schrittmotor 103H5205-5240 über Raspberry PI und Python ansteuern, jedoch ist die Ansteuerung so anspruchsvoll... Bei einer linearen Ansteuerung fängt der Motor an zu zittern oder bleibt bei gewissen Werten stehen. Ich gebe ein PWM Signal auf den Motortreiber, wobei ich immer die Frequenz des Signals immer erhöhe. Ich muss von 1 bis aus 10000 Pulse pro Sekunde kommen, da ich 50Hz am Motor erreichen möchte. Wie kann ich in meinem Code die Erhöung der Prequenz abhängig von einer Kurve machen und wie Wartezeit immer variieren???
Das Thema, das Du suchst, heißt "Beschleunigungsrampe" und ist kein Grund, mehrere Threads zu eröffnen.
YoYo schrieb: > Ich gebe ein PWM Signal auf den Motortreiber Wozu? Es genügt ein einfaches (Rechteck) Signal. Variables Taktverhältnis ist Unsinn. Georg
YoYo schrieb: > Ich muss von 1 bis aus 10000 Pulse > pro Sekunde kommen, da ich 50Hz am Motor erreichen möchte. Auch, wenn das Datenblatt eine Schrittfrequenz von 10 kHz angibt, wirst Du die gewünschten 50 Umdrehungen/s so einfach nicht erreichen. Für diese Drehzahl brauchst Du einen sehr resonanzfreien Antrieb, einen Motortreiber mit >= 24 V Versorgungsspannung und nur einen geringen Teil des max. Drehmomentes. Ich weiß nicht, ob RPi+Python geeignet sind, die Schritte störungsfrei zu erzeugen. Für Schrittfrequenzen < 200 - 300 Hz braucht man keine Beschleunigungsrampe; hier verliert der Motor im Start-Stopp-Betrieb noch keine Schritte. Es ist aber ratsam, den Motor im unteren Drehzahlbereich mit Mikroschritten (zum Beispiel 1/16) und nicht im Vollschritt (200 Schritte/Umdrehung) zu betreiben. Dadurch werden Resonanzen stark reduziert. Wie sieht denn Deine Anwendung aus? Welchen Motortreiber setzt Du ein?
Hallo, ich würde auch auf PWM verzichten und durch die Geschwindigkeit der Signale (z.B. time.sleep-Methode) die Geschwindigkeit bestimmen. Ich schließe mich den o.g. Gast an: Welcher Treiber wird denn verwendet? Gruß BrainPaiN
Guten Tag, wie schon oben erwähnt..... 1. "Beschleunigungsrampe" 2. Das Zauberwort dazu heisst "Bresemham Algorithmus" 3. "über Raspberry PI und Python ansteuern" Schlechte Wahl !!!!! da wird wohl keine saubere Taktung kommen...... Da einen Arduino Nano dazwischen, der den Bresenham macht schon ist es kein Problem mehr... Gruß Thomas PS: Mein Projekt ist eine SchlossUhr. PC- ATmega328 auf eigener Platine USB Anschluss I/O Referenz Eingänge usw....
Nein, Bresenham hat mit der Beschleunigung wenig zu tun. Der sorgt dafür dass mehrere Stepper zur gleichen Zeit an unterschiedlichen Positionen ankommen.
Nico W. schrieb: > Nein, Bresenham hat mit der Beschleunigung wenig zu tun. Stimmt. Deshalb stand es auch unter Punkt 2 und nicht unter Punkt 1. Die Rampe kann man aber dann dort super unterbringen. Alle x Zyklen Bresenham, die Takte um eines erhöhen oder erniedrigen --> Fertig. Gruß Thomas
Keine Ahnung was du hier mit Bresenham willst. Ich konnte bisher nicht rauslesen, dass es hier um mehr als einen Schrittmotor geht. Du etwa? Beim Bresenham gibt der schnellste Motor den Takt an. Der schnellste Motor fährt seine Beschleunigung, sein Tempo und seine Verzögerung. Noch hat hier Bresenham nichts zu tun. Wenn jetzt eine zweite Achse dazu kommt muss diese sich in den Takt der schnellsten Achse unterordnen. Aber erst dann. Ein Motor = kein Bresenham!
Nico W. schrieb: > Wenn jetzt eine zweite Achse dazu kommt muss diese sich in den Takt der > schnellsten Achse unterordnen. Aber erst dann. Ein Motor = kein > Bresenham! Das sehe ich nicht so..... Das Problem was du ansprichst, ist der Interpolator. Das hat mit Bresenham nichts zu tun. Der Bresenham ist nur die Takterzeugung.... Es ist eine Einfache schöne Möglichkeit, ohne viel Auswand die Takte zu erzeugen und dabei, nur für einen Motor, Rampen mit einzubauen. Ich habe diesen Weg gewählt. Und er funktioniert auch. Der Bresenham ist nicht um "Mehere Motoren" zu integrieren, sondern ein Möglichkeit mit einfacher Addition Subbtraktion und einen Vergleich ein solchen Problem zu lösen.... Und das ist in einer einfachen 8-Bit CPU gefragt. Gruß Thomas
Dann zeig doch einmal deinen Bresenham wie dieser einen Motor beschleunigt. Vielleicht kannst mir da noch was zeigen, was ich nicht kenne.
Nico W. schrieb: > Dann zeig doch einmal deinen Bresenham wie dieser einen Motor > beschleunigt.
1 | interrupt [TIM0_OVF] void timer0_ovf_isr(void) |
2 | { |
3 | char Stop; |
4 | |
5 | //TCNT0=0xFC; |
6 | TCNT0=0xFF; |
7 | |
8 | InPort = (((PIND & 0b00111100) >> 2) ^ 0b1111) ^ Cfg_InversIn; |
9 | OutPort = (PORTC & 0b00111111) |((PORTB & 0b00000011)<<6); |
10 | |
11 | |
12 | if (Step) |
13 | { |
14 | PORTC = portc;// ^ InversC; // Jetzt geht alles raus |
15 | PORTB = portb;// ^ InversB; |
16 | |
17 | if (portc & P_Step) // wir haben einen Schritt gemacht |
18 | { |
19 | Position ++; // Position hochzählen |
20 | ModuloCnt++; // Modulo Schritte hochzählen |
21 | if (ModuloCnt == Cfg_Modulo) // Wenn wir die Anzahl erreicht haben null machen |
22 | { |
23 | // Alles was im Vollschritt gemacht werden darf |
24 | |
25 | ModuloCnt=0; |
26 | // hier für die Referenz |
27 | if (Mode & M_Reference) |
28 | { |
29 | // Erst mal Schauen ob wir Freifahren müssen |
30 | // Das Bedeutet beide Sensoren müssen frei sein |
31 | |
32 | if (Mode & M_ReferenceFree) |
33 | { |
34 | if (!In_RefH && !In_Ref) Mode &=~M_ReferenceFree; |
35 | } |
36 | |
37 | if ((Mode & M_ReferenceFree) == 0 ) |
38 | { |
39 | if (In_RefH) Mode |= M_ReferenceH; // Stunde ist gefunden |
40 | |
41 | // ReferenzOK mit betrachten, dass wir nur die Flanke sehen |
42 | // Wir haben Stunde und Minute und keine Referenz und einen Vollschritt OK |
43 | if (((Mode & (M_ReferenceH|M_ReferenceOK))==M_ReferenceH) && In_Ref) |
44 | { |
45 | Position = Cfg_RefPosition; // Dann Setzen wir die Position |
46 | Mode &= ~(M_Start); // und Start wegnehmen |
47 | Mode |= (M_Stop | M_ReferenceOK); // Und Anhalten |
48 | } |
49 | } |
50 | } |
51 | } |
52 | } |
53 | Step = 0; // Step abschalten |
54 | } |
55 | else // hier sind wir mit den Schritt durch und müssen einen neunen Bauen |
56 | { |
57 | PORTC &= ~(P_Step|P_Dir);// ^InversC; // Erst mal Step aus |
58 | |
59 | portc &= ~(P_Step|P_Dir|P_Enable); // erst mal haben wir kein Step&Dir&Enable |
60 | |
61 | |
62 | // Abhier geht der Motor los |
63 | if (Mode & M_Enable) |
64 | { |
65 | if (Dir) portc |= P_Dir; // und wenn wir die Richtung haben auch die |
66 | |
67 | //hier die Entscheidungen für Stop |
68 | if (Mode & M_Position) // Fahren wir in Positionsmode |
69 | { |
70 | if (Mode & M_Start) // Wenn wir noch Fahren |
71 | { |
72 | if ((DPosition - Position) < Ramp) // Ist der Rest kleiner wie die RampenZeit |
73 | { |
74 | Mode &= ~(M_Start); // Gehen wir von Start in Stop und raus von Position |
75 | Mode |= M_Stop; |
76 | AccCnt = Cfg_ACC; // und sorgen gleicg mal dafür, dass es langsammer wird |
77 | } |
78 | } |
79 | } |
80 | |
81 | |
82 | if (Mode & M_Stop) // wenn wir anhalten Wollen |
83 | { |
84 | Stop = 1; // Wir nehmen an wir können anhalten |
85 | |
86 | if (BresStep > Cfg_BresMin) Stop=0; // Nein wenn wir zu schnell sind |
87 | if (ModuloCnt >0) Stop=0; // Nein wenn wir nicht im Vollschritt sind |
88 | |
89 | if (Mode & M_Position) // Wenn wir Position Fahren |
90 | { |
91 | if (Position < DPosition) Stop =0; // Nein wenn wir noch nicht da sind |
92 | } |
93 | |
94 | if (Stop) // Wenn aber alles passt |
95 | { |
96 | Mode &= ~(M_Stop | M_Position |M_Reference |M_ReferenceH); |
97 | } |
98 | } |
99 | |
100 | if (Mode & (M_Start|M_Stop)) // Hier sind wir aktiv haben noch was zu tun |
101 | { |
102 | if (Tick==0) |
103 | { |
104 | BresE = -50; // Mit halber vorbelegen |
105 | |
106 | AccCnt++; |
107 | if (AccCnt>=Cfg_ACC) // Haben wir Rampen Zähler erreicht |
108 | { |
109 | AccCnt = 0; // erst mal löschen |
110 | portc |=P_Enable; |
111 | if (Mode & M_Start) |
112 | { |
113 | BresStep++; // Auf Maximale Geschwindigkeit achten |
114 | } |
115 | else if (Mode & M_Stop) |
116 | { |
117 | BresStep--; // Auf Minimale Geschwindigkeit achten |
118 | } |
119 | } |
120 | } |
121 | |
122 | |
123 | if (Mode & M_Reference) |
124 | { |
125 | BresMax = Cfg_BresMaxReference; |
126 | } |
127 | else |
128 | { |
129 | BresMax = Cfg_BresMax; |
130 | } |
131 | |
132 | if (BresStep < Cfg_BresMin) BresStep = Cfg_BresMin; |
133 | if (BresStep > BresMax) BresStep = BresMax; |
134 | |
135 | /* |
136 | if (BresStep == Cfg_BresMax) |
137 | { |
138 | Mode &=~M_Start; |
139 | Mode |=M_Stop; |
140 | } |
141 | |
142 | |
143 | if (BresStep == Cfg_BresMin) |
144 | { |
145 | Mode &=~M_Stop; |
146 | Mode |=M_Start; |
147 | } |
148 | */ |
149 | |
150 | |
151 | BresE += BresStep; |
152 | |
153 | if (BresE >=0) |
154 | { |
155 | portc |=P_Step; // Wir machen einen Step |
156 | BresE -=100; // Bresenham zurücksetzen |
157 | if (BresStep < BresMax) Ramp++; |
158 | } |
159 | |
160 | Tick++; |
161 | if(Tick== 100) |
162 | { |
163 | Tick = 0; |
164 | } |
165 | } |
166 | } |
167 | |
168 | ISR_10_Cnt++; // wir erhöhen den 10 Millisekunden Zähler |
169 | |
170 | if (ISR_10_Cnt == ISR_10) // hier haben wir 10mS erreicht |
171 | { |
172 | ISR_10_Cnt = 0; // erst mal nullen |
173 | |
174 | //Alles was mit Stepper Enable zu tun hat |
175 | |
176 | if ((Mode & M_Start) || (Mode & M_Stop)) // und wir haben was zu Fahren |
177 | { |
178 | |
179 | // Soderfall wenn Enable noch an ist, dann darf er sofort weiter |
180 | if (Mode & M_Enable) EnableTimerCnt = EnableTimer; |
181 | |
182 | if (EnableTimerCnt < EnableTimer) EnableTimerCnt++; |
183 | } |
184 | else // wir haben nichts mehr zu fahren |
185 | { |
186 | if (EnableTimerCnt) EnableTimerCnt--; |
187 | } |
188 | |
189 | // Hier entscheiden wir Enable on oder nicht |
190 | if (EnableTimerCnt == EnableTimer) Mode |= M_Enable; |
191 | if (EnableTimerCnt == 0) Mode &= ~M_Enable; |
192 | |
193 | // Ende -- Alles was mit Stepper Enable zu tun hat |
194 | } |
195 | |
196 | if (EnableTimerCnt) |
197 | { |
198 | portc |= P_Enable; // ist hier was egal wieviel, Setzen wir das Bit |
199 | LedGN = 1; |
200 | } |
201 | else |
202 | { |
203 | LedGN = 0; |
204 | } |
205 | Step = 1; // Step wieder ein |
206 | } |
207 | return; |
208 | } |
Bitte Sehr.... Gruß Thomas
Thomas schrieb: > interrupt [TIM0_OVF] void timer0_ovf_isr(void) > ... Lässt sich der Algorithmus vielleicht ein bißchen kompakter beschreiben, ohne sich auf C-Code-Level mit seitenlangem Listing herab zu begeben?
Forist schrieb: > Lässt sich der Algorithmus vielleicht ein bißchen kompakter beschreiben, > ohne sich auf C-Code-Level mit seitenlangem Listing herab zu begeben?
1 | interrupt [TIM0_OVF] void timer0_ovf_isr(void) |
2 | { |
3 | TCNT0=0xFF; |
4 | if (Step) |
5 | { |
6 | PORTC = portc;// ^ InversC; // Jetzt geht alles raus |
7 | |
8 | |
9 | if (portc & P_Step) // wir haben einen Schritt gemacht |
10 | { |
11 | Position ++; // Position hochzählen |
12 | } |
13 | Step = 0; // Step abschalten |
14 | } |
15 | else // hier sind wir mit den Schritt durch und müssen einen neunen Bauen |
16 | { |
17 | PORTC &= ~(P_Step); |
18 | portc &= ~(P_Step); |
19 | |
20 | if (Tick==0) |
21 | { |
22 | BresE = -50; // Mit halber vorbelegen |
23 | |
24 | AccCnt++; |
25 | if (AccCnt>=Cfg_ACC) // Haben wir Rampen Zähler erreicht |
26 | { |
27 | AccCnt = 0; // erst mal löschen |
28 | portc |=P_Enable; |
29 | if (Mode & M_Start) |
30 | { |
31 | BresStep++; // Auf Maximale Geschwindigkeit achten |
32 | } |
33 | else if (Mode & M_Stop) |
34 | { |
35 | BresStep--; // Auf Minimale Geschwindigkeit achten |
36 | } |
37 | } |
38 | } |
39 | |
40 | |
41 | |
42 | if (BresStep < Cfg_BresMin) BresStep = Cfg_BresMin; |
43 | if (BresStep > Cfg_BresMax) BresStep = Cfg_BresMax; |
44 | |
45 | BresE += BresStep; |
46 | |
47 | if (BresE >=0) |
48 | { |
49 | portc |=P_Step; // Wir machen einen Step |
50 | BresE -=100; // Bresenham zurücksetzen |
51 | if (BresStep < BresMax) Ramp++; |
52 | } |
53 | |
54 | Tick++; |
55 | if(Tick== 100) Tick = 0; |
56 | |
57 | |
58 | |
59 | Step = 1; // Step wieder ein |
60 | } |
61 | return; |
62 | } |
oder:
1 | unsigned char Step,Tick, |
2 | Pulse, // Zeigt ein an ob ein Pulse kommt |
3 | BresStep; // Anzahl der Steps die man will (1-100) |
4 | |
5 | signed char BresE; // hier liegt der Algo |
6 | |
7 | |
8 | loop: |
9 | { |
10 | if (Step) |
11 | { |
12 | if (Pulse) MakePuls(); |
13 | Step =0; |
14 | } |
15 | else |
16 | { |
17 | ClearPuls() |
18 | if (!Tick) |
19 | { |
20 | BresE = -50; |
21 | } |
22 | |
23 | Pulse=0; |
24 | BresE += BresStep; |
25 | if (BresE >= 100) |
26 | { |
27 | BresE -=100; |
28 | Pulse =1; |
29 | } |
30 | |
31 | Tick +=1; |
32 | if (Tick == 100) Tick =0; |
33 | |
34 | Step=1; |
35 | } |
36 | } |
37 | loop End |
Dein "Breseham" ist Software-PWM mit der du die Periodendauer änderst. Kann man so machen, gibt aber auch etwas elegantere Wege. Auch für 8bit CPUs. Wie linear deine Beschleuningung ist, möchte ich jetzt nicht nachvollziehen.
Nico W. schrieb: > Wie linear deine Beschleuningung ist, möchte ich jetzt nicht > nachvollziehen. Besser machen !!! Für mich funktioniert es...... Von dir hab ich noch nichts gesehen... Sorry..... Damit ist das Thema für mich beendet .... Thomas
Keine Ahnung warum du dich jetzt so angegriffen fühlst. Mir ging es im Thema nur ums Bresenham. Und da haben wir beide eine andere Vorstellung. Ich sehe allerdings auch, dass dein Software-PWM sehr ähnlich bzw. am Breseham angelehnt ist. Ich bin seit ein paar Jahren bei Teacup [1] mit dabei. Kannst ja mal reinschaun. Die Firmware ist optimiert für kleine 8bit'er. Da kannst du auch meine Arbeit an dem Projekt sehen. [1] https://github.com/Traumflug/Teacup_Firmware
Thomas schrieb: > Für mich funktioniert es...... Wie ist T0 initialisiert (Frequenz)? Welche Schrittfrequenzen verwendest Du?
m.n. schrieb: > Wie ist T0 initialisiert (Frequenz)? > Welche Schrittfrequenzen verwendest Du? bei 16 MHz 62500Hz bei mir bei 18,...MHz (wegen der RS232) sind es 72kHz aber bei dem System hier darf ich nicht so schnell werden hab ich es auf 9kHz gedrosselt... 74kHz = 36kHz maximale Schrittgeschwindigkeit. macht bei einer Fräse bei 3200 Schritte/u und 5mm Steigung. 36000/3200 *60*5 = 3375mm 3,3m/min Der Algo kann auf X Achsen aufgebohrt werden. Bei uns im Frässystem 4 Achsen (1 Port = 4 Bit Takt und 4 bit Richtung) Gruß Thomas
Thomas schrieb: > bei 16 MHz 62500Hz > bei mir bei 18,...MHz (wegen der RS232) sind es 72kHz > aber bei dem System hier darf ich nicht so schnell werden > hab ich es auf 9kHz gedrosselt... Gut, aber wie Du schreibst, kann die Interruptlast im Hintergrund doch recht hoch werden. Ich gehe lieber den Weg über Timer1, der nur bei Bedarf Interrupts erzeugt. Zudem werden die Schritte dadurch ohne Jitter ausgegeben.
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.