PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Servo PWM Steuerung



markeis
09.11.2008, 21:45
Hi,
ich hab folgendes Problem, ich habe an den OC2 Port meines Atmel32 die PWM für einen Servo gelegt, der die Lenkung von etwas übernehmen soll.

Ich hab schon ein bisschen herumprobiert, allersdings hab ich es bisher nur so hinbekommen, das 3 PWM Einheiten meinen Kompletten lenkeinschlag darstellen (wohlgemerkt für rechts, gerade aus und links)

kann mir jemand einen Tipp geben, welcher Prescaler, welcher PWM Typ etc. man für Servos benutzt?

danke im Vorraus

gruss

radbruch
09.11.2008, 22:21
Hallo

Willkommen im RN-Forum.

Hardware-PWM scheint mir zur Ansteuerung für Servos nicht gut geeignet. Das Impulse-Pause-Verhältniss der Servos ist wohl zu groß, ich habe das aber noch nicht versucht.

Gute Erfahrungen habe ich mit einfachen Softwareansteuerungen mittels Timerinterrupt gemacht. Recht übersichtlich und, je nach Kontrollertakt, auch für mehrere Servos geeignet. Das Prinzip wird im RN-Wiki beschrieben: https://www.roboternetz.de/wissen/index.php/Servos#Ansteuerung

Gruß

mic

Ceos
10.11.2008, 07:29
Atmega8, Timer 1, WGM 14

8000000Hz / 64(PS) / 1000(Fast PWM, Top = ICR1)

macht 8ms von 0 - 1000 gezählt,

ich übersteuere meine servos ein wenig und meine stellwerte sind links = 200, mitte = 300, rechts = 400 für alternativ OCR1A bzw. OCR1B

in der compare match ISR schalte ich das DDRB für die PINs B1 und B2 nur alle 4 interrupts auf ausgang, so bekomm ich ausreichend pause zwischen 2 impulsen

EDIT: hardware benutze ich nur wenn ich der meinung bin, dass meine servos ungenau laufen oder sie anfangen zu ruckeln um den fehler einzugrenzen

markeis
10.11.2008, 18:43
Hi,
danke für die Antworten, ich habe jetzt versucht das mit Interrupt umzusetzen. Alle 10 µs wird ein Interrupt ausgelöst bei dem eine 'TimerVariable' hochgezählt wird. Mit einer Funktion frage ich diese Variable ab und mache über zwei Vergleichswerte (Periodendauer und Highzeit) die PWM zu steuern:

Theoretisch sollte die PWM den Port 1,5 ms anschalten und 20,5 ms aus sein.
Praktisch ist das Verhältniss von high und low aber 50 %.

Ich hab schon einiges an den Werten geändert, es hat sich allerdings nichts getan. Ich seh im moment den Wald vor lauter Bäumen nicht ;-) Habt ihr eine idee?



void init()
{
//--- Timer 2 initialisieren ---
TCCR2=0x01; // Teiler 1/1
TCCR2|=0x28; // Modus: Zählen bis Vergleichswert
OCR2=80; // Vergleichswert speichern
TIMSK=0x80; // Interrupt bei Vergleichswert A
//--- Interrupts erlauben ---
sei();
sbi(DDRC,3); // PortC3 auf Ausgang
}
//--------------------------------------------------------------------
// TIMER2_COMP_vect - Timer2 Interrupt bei Vergleichswert A
// aktuelle Einstellung: 100000 Hz 10 µs
//--------------------------------------------------------------------
volatile int timer01=0; //Timer zählvariable
int spwm=50; // PWM-Wert
bool x = false;

ISR(TIMER2_COMP_vect)
{
timer01++;
}

void servo (int timer01)
{
if (timer01<=2200) //2200 * 10 µs = Periodendauer
{
if (timer01<=(spwm+100))
{
if (x == false)
{
sbi(PORTC,3);
x = true;
}
}
if (timer01>(spwm+100))
{
if (x == true)
{
cbi(PORTC,3);
x = false;
}
}
}
else {timer01=0; //Nachdem die Periode vorbei ist, wird der
//Timerzähler wieder auf null gesetzt
}

}

main()
{
init();
while (true)
{

servo(timer01);


}
}


vielen danke

gruß Tobias

Besserwessi
11.11.2008, 19:07
Ein interrupt alle 10 µs ist schon ziehmlich an der Grenze, da reicht eventuell die Rechenzeit schon nicht mehr aus, bei weniger als 6 MHz Takt.
Nur um etwas hochzuzählen brauchts auch noch keine ISR, das kann der Timer auch gleich in Hardware.

Besser wäre es da schon je Servo Kanal nur einen Interrupt auszulösen wenn der Puls zu ende gehen soll. Wenn mehr Kanäle gbraucht werden, dann die pulse nacheinander erzeugen, nicht gleichzeitig.

markeis
12.11.2008, 12:41
Hi,

also mir arbeiten mit 8 Mhz, daher sollte die von dir angesprchene Problematik ja kein Problem darstellen?

Ich verstehe einfach nur nicht, warum der µC nicht das macht, was ich brauche.
Es muss doch irgendein Fehler im Code sein oder?
Die Logik stimmt doch soweit ?

gruß

Hellsing
12.11.2008, 16:22
Ich hing bis letzte Woche auch noch daran das ich mit meinem Mega168 Servos mittels PWM steuern wollte. Als Randbedingung stellte ich mir erstmal NUR den 8bit Timer2 zu benutzen doch das wollte partou nicht gehen da das Verhältnis von High zu low ja ungefähr 1/10 entspricht und und per interrupt der ausgelöst wird wenn ein bestimmter Highwert erreicht wurde um den selbigen Timer für die Low Time zu konfigurieren und zu reseten wollte auch nicht so recht funktionieren.

Naja entnervt bin ich dann zum Soft PWM umgesprungen ,das Programmieren hat keine 10 min gedauert und es lief... Leider ist diese Art der Ansteuerung recht "Schmutzig" den in den Schleifen kann der Mega ja nun nichtsmehr machen...

Ach ja ich weis ja nicht wo die Highpegel Zeiten herkommen jedoch hab ich durch Oszi Messungen mit einem MG995 Servo ermittelt das die Mittenstellung hier bei 1,5ms high ist und jeweils für links und rechts 1ms also gesamtbereich von 0,5-2,5 ms als low bin ich inmittlerweile bei 12ms angekommen.
Edit: hab mal ein Bild der ermittelten pwm zeiten erstellt

http://img395.imageshack.us/img395/1226/pwmee0.th.jpg (http://img395.imageshack.us/my.php?image=pwmee0.jpg)http://img395.imageshack.us/images/thpix.gif (http://g.imageshack.us/thpix.php)

Falls wer was zu der Servoansteuerung mittels 8bit timer sagen kann währe ich sehr erfreut , vielleicht habe ich ja etwas übersehen :O

MFG Hellsing

Besserwessi
12.11.2008, 20:14
Die Logic in dem Programm oben sieht auf den ersten Blick OK aus. Allerdings wird der Puls durch aktives Warten ausgegeben. Für eine spätere Anwendung ist das ziehmlich unpraktisch.
Ein kleines Problem ist noch im Code: der zugriff auf Timer01 im Hauptprogramm ist nicht Atomar. das heißt es ist nicht sicher das high und low Byte immer zusammengehören, wenn mittendrin ein Interrupt auftritt. Das kann gelegentliche Fehler verursachen.
Ist denn sicher das der Controller wirklich mit 8 MHz läuft und nicht den internen 1 MHz.

Bei 8 MHz sind 10 µs gerade man 80 Zyklen. Allein das sichern der Register für die ISR kann schon so um die 30 Zyklen brauchen.