PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer verwenden zur Servoansteuerung



beginner1101
27.02.2009, 13:12
Hallo mal wieder =; ,

nachdem ich mein Timer funktioniert, hab ich mich an meine nächste Aufgabe gesetzt. ich wollte ein modellbauservo ansteuern. Dazu habe ich meinen Timer umgebaut. Wie ein Servo funktioniert hab ich kapiert. Ich hab mir jetzt gedacht ich schalte meinen Servoport an und nach 1.5ms schalte ich ihn wieder ab (hört sich erstmal nicht sooo sinnig an, will aber step by step weiter machen). Somit müßte ich doch einen definierten Ausschlag haben. Und zwar Mittelstellung. Mein Code habe ich angehängt.

Das Servo verhält sich aber folgendermaßen: Es läuft in Stufen auf eine Position, leider auf keine definierte. Wenn ich den uC resete läuft er weiter. Dürfte doch eigenltich nicht sein oder?

LG Anna
#include <stdlib.h>
#include <avr/interrupt.h>

volatile uint16_t Izeit_1; // Timervariable
volatile double servopos;


void wait_1_5ms(void) //kann eingestellt werden bis zu 3 s
{
cli();
Izeit_1 = 0;
sei();

while(Izeit_1<(20*servopos)) //zweite zahl in klammern steht für die zeit in ms
{
{
}
}
}


void Timer2_init(void)
{
TCCR2 |= (1<<WGM21) | (1<<CS01); // Prescaler eingestellt auf 8
OCR0 = 100; // nach der Formel foc0=fclk/(2*N*(1+ocr0))
TIMSK |= (1<<OCIE2);
}


ISR(TIMER2_COMP_vect)
{
if (Izeit_1 <= 60000)
Izeit_1 ++;

else
{
Izeit_1 = 0;
}

}

int main(void)
{
Timer2_init();
DDRC |= 0xff;
DDRD |= 0xff;
PORTC=0x00;
PORTD=0x00;

//while(1)
{
PORTC |= (1<<PC0); //LED anschalten, zur Kontrolle
PORTD |= (1 << PD5); //Servoport anschalten
servopos =1.5;
wait_1_5ms();
PORTD &= ~(1 << PD5); //Servoport ausschalten
PORTC &= ~(1 << PC0); //LED ausschalten, zur Kontrolle




}
}

Mixxer
27.02.2009, 15:44
Hallo,

bisschen ungewöhnlicher Ansatz:-)
Von deiner Kontroll-LED wirst du nicht viel sehen - höchstens mit m Oszi und dann kannst du auch den Servopin beobachten.
Wenn ich das richtig aus deinem mainloop interpretiere gibst du nicht wirklich n richtiges Servosignal aus.
Dabei sollte eine Pause zwischen den Impulsen sein (Periodendauer 20ms, Servoimpuls 1-2ms).

Ich habe das mit dem Timer 1 gemacht (ATmega8). Damit kannst du verschiedene Interrupts erzeugen (1x Overflow und 2x Compare). Habe den Timer so eingestellt, dass er alle 20ms einen Overflow hat und dabei den Ausgang/die Ausgänge von den Servos auf high setzen. Dann muss nur noch der/die Compare Register richtig geladen werden, damit der Impuls in dem Bereich liegt, und mit ihnen der Ausgang wieder auf low gesetzt wird.

Damit kannst du mit dem Timer 2 Servos relativ "Arbeitssparend" außerhalb dem Hauptprogramm ansteuern.

MFG Mixxer

Besserwessi
01.03.2009, 00:26
Wenn man schon Timer 1 (16 Bit) nimmt, kann man das Servosignal auch gleich im PWM mode erzeugen. Da kann man auch leicht 2 Kanäle machen. Einfach im PWM Mode starten und die Pulslänge in OCRx Register schreiben, den Rest macht die Hardware.

oberallgeier
01.03.2009, 10:18
Hi beginner1101,

so gehts "im Prinzip" - allerdings mit Änderungen. Dass man den Servo hardwareseitig an eine PWM hängen kann - und sich damit viel erspart - steht ja schon oben.

Den von Dir angedachten Weg gehe ich allerdings gelegentlich auch - aber NUR wenn die PWMs anderweitig vergeben sind. So - dann kommen wir zu den Änderungen, aber erstmal etwas Grundlegendes das auch Mixxer schon beschreibt.

Wenn das Servosignal auf high geht (die Servorampe startet) dann darf das nächste Servosignal gemäß Spezifikation erst nach 20 ms wieder auf high gehen - das ist die Periodendauer des Signals. Meist sind die Servos tolerant und manche verdauen hier Zeiten, die ein paar Millisekunden länger oder kürzer sind - aber bleib möglichst nahe bei diesen 20 ms. Dein 1,5 ms-Signal für die Mittenstellung ist ganz gut gewählt - spezifikationsmässig sogar genau richtig - aber nicht alle Servos sind exakt ! ! ! NACHDEM Du die 1,5-ms-Rampe abgeschaltet hast, musst Du warten, bis - siehe oben - die 20ms seit Rampenstart vorbei sind und darfst erst danach die Rampe wieder starten.

>>> In dieser Beziehung ist die Skizze zur Servoansteuerung (https://www.roboternetz.de/wissen/index.php/Servos#Ansteuerung) im RNWissen falsch <<< - die 20 ms gehen eben von steigender Flanke bis zur nächsten steigenden Flanke ! ! ! Genau - und etwas besser verständlich - ist die Skizze hier. (http://freakfiles.de/?site=47)

Grundlegendes ist jetzt vorbei.

Du müsstest also in Deinem main nach dem Ausschalten des Servoports noch rund 18,5 ms warten bis die Signalleitung zum Servo wieder eingeschaltet wird. !!! Dieses Verfahren solltest Du aber nur zu Übungszwecken machen - ansonsten steht Dein Controller ja meist auf "wait" und tut sonst nix.

Sinnvoll wäre folgende Lösung:
Du baust einen Timer - ähnlich wie Deine bestehende Lösung - der beispielsweise in 1 sec 10 000 Interrupts generiert. In diesem Timer zählst Du - sagen wir mal die Variable IRS_zeit hoch bis 10 000 und wenns so weit ist setzt Du den auf eins zurück. Damit wird 1 ms in 10 Teile geteilt *gggg*. Im main kannst Du jetzt eine Variable setzen auf SRV_pos - z.B. = 15. Wenn Du Deine IRS_zeit auf eins zurücksetzt, dann schaltest Du in der ISR den Servo ein, wenn IRS_zeit gleich SRV_pso (also 15) ist, dann schaltest Du den Servo in der IRS wieder aus. OK?

BTW: Kann es sein, dass Du den Code für Deine Timerroutine bei mir gefunden hast - Variablenname und "60000" deuten darauf hin? WENN Du von 0 bis (Izeit_1 <= 60000) zählst, dann sind das natürlich 60 001 Schritte ! ! !

Viel Erfolg

beginner1101
02.03.2009, 18:59
Hallo an alle,

vielen Dank für eure Unterstützung. Ich weis ist ein ungewöhnlicher ;-) Ansatz. Hab aber irgendwie die pwm nicht auf dir reihe bekommen.

Ich werd demnächst mal eure Ansätze umsetzen. :-)

Vielen Dank schon mal ich meld mich wenn es Neuigkeiten gibt.

Gruß Anna


PS: @oberallgaier: ja es der code ist teilweise von dir (du hast mir damals super geholfen :-) danke noch mal)