PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schrittmotor, PWM, Anfahrkurve und Bremskurve



brundle
01.06.2005, 15:51
Hallo,

ich habe einen Schrittmotor mit 10000 Steps/Umdrehung.
(40V 5,8A Typ Positec VRDM 397/50 LHB made by Sig Berger Lahr)

Der Motor wird über eine mitgelieferte Karte bestromt.

Eingänge der Karte:
Puls, TOR, Richtung

Der Schrittmotor macht genau einen Step bei einem Puls.
ALSO=>
Der Motor dreht also um so schneller, je höher die Frequenz der Takte
am Pulseingang ist.

DAS PROBLEM:
DER MOTOT SOLL LANGSAM ANFAHREN (ca. 2sec.) DANN ca. 5sec. AUF VOLLGAS FAHREN UND DANN WIEDER WEICH BREMSEN (ca. 2sec.)

Zur PWM habe ich bereits nachgelesen:
dass PWM ja nicht die Frequenz verändert (bzw. die Periodendauer), sondern nur das Puls-Pausen-Verhältnis.

Jetzt zur Frage:
Kann ich diesen StepMotor mit der mitgelieferten Karte über PWM steuern(Geschwindigkeitssteuern) ?
Was ich doch eigentlich brauche ist eine Frequenzveränderung, oder?


MEIN LÖSUNGSANSATZANSATZ:
Das habe ich bis jetzt wie folgt programmiert (WINAVR):

//code
Puls von low nach high
delay
Puls von high nach low
delay

den delay kann ich über eine Schleife verändern, sodass sich auch die Frequenz verändert und somit auch die Geschwindigkeit.

Das Problem bei dieser Lösung ist es, dass (bei WinAvr) die Übergänge zwischen Anfahren und Vollgas und Vollgas und bremsen nicht weich genug sind, bzw. das das für 10000 Steps/Umdrehung zu langsam wird


Generelle Verständnisfrage:
Ist PWM überhaupt das richtige für dieses Problem?

Wie löse ich das Problem mit der Anfahrkurve?

******
zusatz:
******
Ich habe es das Timer-Beispiel von http://www.mc-project.de für mich abgeändert und ein paar Fortschritte gemacht.

Hat jemand vielleicht ein WINAVR Code-Schnippel für mich?
(ich programmiere in C und Bascom:keine Ahnung von

Also ich benötige eine gleitende Frequenz von ca.5kHz...40kHz für die Anfahrt.

Frage zur gleitende Frequenzn beim Anfahren, Bremsen:
-linear Ansteigend
-logarithmisch mit e-Funktion
-Sinus-Funktion
was ist besser ?

mfg


Vielen Dank für jeden Hinweis.


PS: Ich weis, das ist nicht nett einen Topic 2x im Forum zu posten, ich habe bereits unter:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=9729

RoboterNetz.de Foren-Übersicht » Roboter-Foren » Motoren » Schrittmotor, PWM, Anfahrkurve und Bremskurve

gepostet, aber irgendwie komme ich ohne Euch WinAVRler nicht richtig weiter.

RCO
01.06.2005, 18:47
Hi, welchen AVR verwendest du, manche haben die Möglichkeit die Frequenz des PWms zu verändern. Eine andere Möglichkeit ist, über einen Timer alle x Takte einen Interrupt auszulösen, je nach Geschwindigkeit halt öfter oder weniger oft. Der Timer wird dann im Interrupt schon mit einem Startwert beladen, also nicht 0 sondern z.B. schon 200 von 255 und springt dann entsprechend schneller wieder in den Interrupt. Der PWM wird dich da in der Tat nicht sehr weit bringen.

Ich habe mich jetzt mit dem Schrittmotor nicht näher beschäftigt, aber 10k Steps (0,036°)? Würde ja heißen, er macht bei 5Khz gerade mal eine Umdrehung in 2 Sekunden!

Schau mla bei http://www.mc-project.de/ unter Timer, da wirst du fündig werden.

Wenn du fragen hast, nur zu ;-)

brundle
02.06.2005, 13:10
Hallo zusammen.
Und schon wieder einmal habe ich mir selbst geholfen ;-)
Vielen Dank für die Anregungen.

Hier mein Quellcode:



#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

//Zählvariablen
int i=0; //setzt den TCNT0
int j=0;
int z=0;



//Motorparameter
int steps=10000; //Steps des Scrittmotors für eine volle Umdrehung
int Richtung=1; //wenn Richtung=0 ist => Linksinkslauf
//wenn Richtung=1 ist => Rechtslauf
int steilheit=1200; //großer Wert: langsames Beschleunigen und Bremsen
//kleiner Wert: schnelles Beschleunigen und Bremsen
int umdrehungen=30; //Anzahl der Umdrehungen im Vollgasbetrieb

int beschleunigen =0; //wenn beschleunigen = 1 ist, so beschleunigt der Motor
int schneller =0; //Hilfsvariable beim Beschleunigen
int bremsen =0; //wenn bremsen = 1 ist, so bremst der Motor
int langsamer =0; //Hilfsvariable beim Bremsen
int vollgas =0; //wenn vollgas = 1 ist, so hat der Motor seinen Maximum-Speed erreicht

int maxspeed=255; //Werte zwischen 0...255
//Der Timer-Wert TCNT0 wird mit maxspeed gesetzt
//kleiner Wert => Motor bei Vollgas langsam
//großer Wert => Motor bei Vollgas schnell




SIGNAL (SIG_OVERFLOW0) {


if(beschleunigen)
{
j++;
if(j==steilheit)
{
j=0;
schneller=1;
}

if(schneller)
{
schneller=0;

if(i<maxspeed)
{
i++;
if(i==maxspeed)
{
beschleunigen=0;
vollgas=1;
}
}
}
}



if(vollgas)
{
i=maxspeed;

j++;
if(j==steps)
{
j=0;

z++;
if(z==umdrehungen)
{
z=0;
vollgas=0;
bremsen=1;
}
}
}



if(bremsen)
{
j++;

if(j==steilheit)
{
j=0;
langsamer=1;
}

if(langsamer)
{
langsamer=0;

if(i>1)
{
i--;
if(i==1)
{
beschleunigen=1;
bremsen=0;

PORTD^=(1<<PD6); //RICHTUNG: Bit 6 in PORTD invertieren

//Warteschleife
for(int u=0;u<32000;u++)
{
for(int v=0;v<8000;v++)
{
//nop
}
}
}
}
}
}




TCNT0 = i; // Timer-0 Startwert setzen
PORTD^=(1<<PD4); //PULS: Port D: BIT PD4 invertieren (toggeln)

}



// HAUPTPROGRAMM
int main (void) {
/*
_______________________
PORT D des ATMEGA32 µC:
_______________________

PDx PIN Funktion Bemerkung
================================================== =======================================
PD0 (RXD) 14 rs232 empfangen
PD1 (TXD) 15 rs232 senden
PD2 (INT0) 16
PD3 (INT1) 17
PD4 (OC1B) 18 Puls: für Schrittmotor
PD5 (OC1A) 19
PD6 (ICP) 20 Richtung: links(low), rechts(high)
PD7 (OC2) 21 TOR: high=offen low=geschlossen

__________________________________________________ ________________________________________
*/





beschleunigen=1; //muss ein mal auf 1 gesetzt werden, um zu starten

DDRD = 0xFF; // Setzt das Richtungsregister des Ports D auf 0xFF (alle Pins als Ausgang)
PORTD |= (1<<6); //RICHTUNG: setzt Bit 6 in PORTD auf "1" für rechtslauf
PORTD |= (1<<7); //TOR: setzt Bit 7 in PORTB auf "1" für TOR


//Timer-0 initialisieren
TIMSK |= (1<<TOIE0); //Timer Overflow Interrupt enable
//TCCR0 = (5<<CS00); // Timer-0 Vorteiler auf 1024
//TCCR0 = (1<<CS01) | (1<<CS00); //Prescaler von 64
TCCR0 = (1<<CS00); //Prescaler von 1
TCNT0 = 0; // Timer-0 Startwert setzen
//Timer-0 initialisieren ENDE.





sei();
for (;;) {} // Endlosschleife

}
//HAUPTPROGRAMM ENDE.



ok.

Q.Was macht das Programm?
A:Das Programm generiert einen gleitenden Frequenzgang von über! 80kHz, das bedeutet mein Stepmotor mit 10000Steps/Vollumdrehung dreht im Vollgasmodus über 8x pro Secunde! Der Motor wird sanft beschleunigt und gebremst. Die Steilheit kann angegeben werden.

Aber jetzt noch einige Probleme:
-Ich will das ganze Programm in eine Funktion packen, damit ich über rs232 die Motorparameter übergeben kann.
Q:Wie mache ich das? Kann ich der Funktion SIGNAL (SIG_OVERFLOW0) {...} Parameter übergeben?

-Im Augenblick läuft das Programm ununterbrochen.
Erst beschleunigt der Motor auf Maximum-Speed, dann dreht er sich ein paar Umdrehungen und dann bremst er wieder ab. (An dieser Stelle will ich eigendlich hier wieder aussteigen)
Danach Kommt ein Richtungswechsel und eine Warteschleife für ca. 3 Sekunden. Danach geht das gleiche Spiel wieder in die Andere Richtung los.
Q:Wie bringe ich das Programm dazu, dass es nach dem Bremsen aussteigt?

Wie immer vielen Dank für alle! anregungen

mfg

PS: µC ist ein Atmega32@16MHz (RN-CONTROL)

RCO
02.06.2005, 20:51
Wie mache ich das? Kann ich der Funktion SIGNAL (SIG_OVERFLOW0) {...} Parameter übergeben?

Du kannst einfach globale Variablen definieren:
volatile int Variablenname;
In die globale Variable kannst du dann z.B. schreiben welches Programm gerade laufen soll, Beschleunigen, Bremsen etc. und das in der ISR abfragen.


Q:Wie bringe ich das Programm dazu, dass es nach dem Bremsen aussteigt?

Du könntest den Interrupt-Enable für den Timer-Overflow löschen, dann springt er nicht mehr in die ISR. Soll dann ein neues Programm gestartet werden (z.B. Rückwärtslaufen) dann setzt du das Flag wieder.

Das Senden von Motordaten würde ich nicht in Interrupts machen. Ich würde das einfach in main() laufen lassen. Wenn du über RS232 sendest, dann musst du ja eh immer warten, bis der Buffer zum senden leer ist.

while (!(UCSRA & (1<<UDRE)));

Du kannst ja unmöglich in der ISR warten! Hoffe, ich konnte helfen.

Gottfreak
03.06.2005, 23:20
Das UART löst auch einen eigenen Interrupt aus, wenn ein neues Bit vorliegt(in der ISR kannst du den Wert dann in 'ne globale Variable schreiben, die in der ISR für die Motorsteuerung verwendet wird.).
Zu RCOs Vorschlag: Verstehe ich das richtig, dass der AVR über das UART die Motordaten EMPFANGEN soll(und dann den Motor entsprechend steuert)?