Forum: Mikrocontroller und Digitale Elektronik Schrittmotor nicht linear ansteuern


von YoYo (Gast)


Lesenswert?

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???

von Walter T. (nicolas)


Lesenswert?

Das Thema, das Du suchst, heißt "Beschleunigungsrampe" und ist kein 
Grund, mehrere Threads zu eröffnen.

von georg (Gast)


Lesenswert?

YoYo schrieb:
> Ich gebe ein PWM Signal auf den Motortreiber

Wozu? Es genügt ein einfaches (Rechteck) Signal. Variables 
Taktverhältnis ist Unsinn.

Georg

von m.n. (Gast)


Lesenswert?

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?

von Mi E. (brainpain)


Lesenswert?

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

von Thomas (Gast)


Lesenswert?

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....

von Nico W. (nico_w)


Lesenswert?

Nein, Bresenham hat mit der Beschleunigung wenig zu tun. Der sorgt dafür 
dass mehrere Stepper zur gleichen Zeit an unterschiedlichen Positionen 
ankommen.

: Bearbeitet durch User
von Thomas (Gast)


Lesenswert?

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

von Nico W. (nico_w)


Lesenswert?

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!

von Thomas (Gast)


Lesenswert?

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

von Nico W. (nico_w)


Lesenswert?

Dann zeig doch einmal deinen Bresenham wie dieser einen Motor 
beschleunigt. Vielleicht kannst mir da noch was zeigen, was ich nicht 
kenne.

von Thomas (Gast)


Lesenswert?

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

von Forist (Gast)


Lesenswert?

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?

von Thomas (Gast)


Lesenswert?

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

von Thomas (Gast)


Lesenswert?

Thomas schrieb:
> if (BresE >= 100)

Fehler:

if (BresE >= 0)



Thomas

von Nico W. (nico_w)


Lesenswert?

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.

von Thomas (Gast)


Lesenswert?

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

von Nico W. (nico_w)


Lesenswert?

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

von m.n. (Gast)


Lesenswert?

Thomas schrieb:
> Für mich funktioniert es......

Wie ist T0 initialisiert (Frequenz)?
Welche Schrittfrequenzen verwendest Du?

von Thomas (Gast)


Lesenswert?

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

von m.n. (Gast)


Lesenswert?

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