Hallo zusammen. Ich bin neu hier im Forum, also seid bitte nicht zu
streng zu mir. :-)
Ich habe schon einige Erfahrungen mit Mikrocontrollern gemacht,
beschäftige mich heute jedoch zum ersten Mal mit Servos - bisher jedoch
erfolglos.
Als Servo benutze ich den RS-2 Modellbauservo. Als Mikrocontroller
verwende ich einen Atmega 32 mit einem 12MHZ-Quarz, den ich in C
programmiere.
Nun zu dem Problem:
Wenn ich folgendes Programm auf den Mikrocontroller übertrage, dann
sollte sich der Servo eigentlich endlos vom einen Anschlag zum anderen
Anschlag bewegen, doch er bewegt sich bei mir nur zum einen Anschlag und
bleibt dann dort, leicht zitternd. Wenn ich nun das Servohorn bewegen
möchte und dann wieder loslasse, so bewegt sich das Servohorn wieder
zurück zu dem Anschlag.
Der Code stammt ursprünglich von der Seite
https://newbiehack.com/MicrocontrollerControlAHobbyServo.aspx , dessen
Tutorial über Servos ich heute unter anderem durchgearbeitet habe.
Ein mögliches Problem ist der Quarz, der bei mir 12MHz groß ist. Dies
sorgt dafür, dass der Wert von ICR1 größer als 65535 wird. Auf der
Internetseite steht, dass man in einem solchen Fall einen sogenannten
Prescaler verwenden soll. Ich habe jedoch leider nicht verstanden, was
das genau sein soll. Doch ich habe so das Gefühl, dass dies nicht die
Ursache des Problems ist.
Ich habe auch einige - um nicht zusagen viele - Codes zu Servos aus
diesem Forum ausprobiert, doch der Servo macht nie was er soll. Bei
jedem Beispiel, das ich ausprobiert habe, bewegt sich der Servo zu einem
Anschlag, manchmal zuckt er dann noch willkürlich. Der Servo ist jedoch
nicht kaputt, da ich auch schon andere, baugleiche Servos ausprobiert,
die dieselben Bewegungen ausüben.
Ich hoffe, dass ihr mir bei meinem Problem helfen könnt und wünsche euch
ansonsten noch einen schönen Abend.
Mit freundlichen Grüßen
Marcel
Marcel Hunfeld schrieb:> ICR1 = 240000;
240000 ist etwas weit raus für einen 16 Bit Timer,
da steht einfach nicht mal ansatzweise drin was Du erwartest.
Marcel Hunfeld schrieb:> Ein mögliches Problem ist der Quarz, der bei mir 12MHz groß ist.
Erstmal solltest du klären, ob dein µC auch wirklich mit diesem 12MHz
Takt läuft. Dazu kannst du z.B. ein kleines Blinkprogramm für eine LED
schreiben, so dass du per Augenmaß prüfen kannst, ob der Prozessor mit
dem von dir angenommenen Takt läuft.
Ein Servo, der zitternd am Anschlag steht, sprich für viel zu lange
Steuerpulse.
Marcel Hunfeld schrieb:> Ein mögliches Problem ist der Quarz, der bei mir 12MHz groß ist. Dies> sorgt dafür, dass der Wert von ICR1 größer als 65535 wird.
Der Wert kann nicht größer als 65535 werden. Einen größeren Wert
kannst du versuchen reinzuschreiben, aber da werden dann einfach ein
paar Bits oben abgeschnitten. Das ist ungefähr so, als ob du in einen
10-Liter-Eimer 35 Liter Wasser reinschüttest.
> Auf der Internetseite steht, dass man in einem solchen Fall einen> sogenannten Prescaler verwenden soll. Ich habe jedoch leider nicht> verstanden, was das genau sein soll.
Der Prescaler teilt den Takt vom Timer runter, so daß dieser langsam
genug ist, damit der Eimer nicht überläuft.
> Doch ich habe so das Gefühl, dass dies nicht die Ursache des Problems> ist.
Und wie kommst du darauf?
Vielen Dank schon mal für eure starke Mithilfe!
Ich habe gerade das Programm von dir ausprobiert, Thomas. Das
funktioniert schon deutlich besser. Das Problem ist hier nur, dass das
Intervall der beiden Punkte zwischen denen sich der Servo hin- und
herbewegt, man sieht somit, dass sich das Servohorn nur um wenige Grad
bewegt. Selbst wenn ich das Intervall im Programm auf
1
OCR1A=2000;
2
_delay_ms(2000);
3
OCR1A=1000;
4
_delay_ms(2000);
vergrößere, ändert sich das Verhaltensmuster des Servos nicht.
Aufällig ist jedoch bei dem Programm noch, dass die Bewegung zur einen
Seite hin sehr ruckhaft und schnell, während die Bewegung zur anderen
Seite sehr langsam ( obwohl es sich wie gesagt nur um wenige Grad
handelt) ausgeführt wird. Weiß jemand, woran das liegen kann?
Mike A. schrieb:> Dazu kannst du z.B. ein kleines Blinkprogramm für eine LED> schreiben, so dass du per Augenmaß prüfen kannst, ob der Prozessor mit> dem von dir angenommenen Takt läuft.
Das werde ich morgen dann mal machen und weiter berichten.
Rolf Magnus schrieb:>> Doch ich habe so das Gefühl, dass dies nicht die Ursache des Problems>> ist.>> Und wie kommst du darauf?
Weil ich bereits andere Beispielprogramme ausprobiert habe, die
teilweise für einen 12 oder 16MHz Quarz bestimmt sind und der Servo dort
das selbe gemacht hat. Deswegen hatte ich das als Ursache schon
ausgeschlossen, aber ich kann mich auch irren.
Thomas Messmer schrieb:> am besten nochmal im Forum> das hier> http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR>> und das hier http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM> durchlesen.
Das mach ich morgen dann auch noch mal.
Viele Grüße, Marcel
Na, der Timer hat doch nur 8 Register. :-)
Die PWM für den Servo braucht so 20ms Perioden-Dauer.
Unterer Anschlag sind so 1ms, Mitte so 1,5ms und oben so 2ms.
12 MHz Takt = 83,33ns pro Zyklus
20ms / 83,33ns = 240000 -> zuviel
Prescaler = 8 -> 1,5MHz -> 666,67ns -> 30000 -> okay
1ms / 666,67ns = 1500
2ms / 666,67ns = 3000
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
int main(void)
6
{
7
DDRD = (1<<PD5); // Servo 1 an PD5, Servo 2 an PD4
8
TCCR1A = (1<<WGM11) | (1<<COM1A1);
9
ICR1 = 30000; // Top-Wert
10
OCR1A = 1500;
11
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11);
12
13
while(1)
14
{
15
OCR1A = 1500;
16
_delay_ms(1000);
17
OCR1A = 3000;
18
_delay_ms(1000);
19
}
20
}
Sieht doch fast genauso aus.
Geändert habe ich den Output-Mode für den Pin, den Prescaler, die Werte
für ICR1 und OCR1A, die Art wie die Register geschriebn werden und die
Reihenfolge in der die Register beschrieben werden.
Der Zähler läuft nämlich los sobald der Prescaler eingestellt ist,
sobald der Zähler Takt hat, das sollte man also immer als letztes
machen.
Und wenn man das jetzt vergleicht, das ist im Effekt exakt das gleiche
was Thomas Messmer schon geschrieben hat, nur weniger kompliziert.
Okay, jetzt weiß ich echt nicht mehr weiter :(
@Rudolph: Mit deinem Programm macht der Servo das selbe, wie bei dem
Programm von Thomas Messmer. Er bewegt sich nur jeweils in einem sehr
kleinen Winkel.
Das merkwürdige dabei ist jedoch, dass wenn ich die Endlosschleife leer
lasse und dem OCR1A nur in dem Hauptprogrammteil einen Wert zuweise,
dann fährt der Servo auch zu diesem Punkt hin. Damit habe ich
herausgefunden, dass die linke Grenze des Servos bei OCR1A=1000 und die
rechte Grenze bei OCR1A=2000 erreicht ist. Wenn ich nun jedoch mit
diesem Werte in der Endlosschleife weiter arbeiten will, und der Servo
zwischen diesen beiden Punkten "wandern" soll, dann fährt er zur Mitte
und macht genau dasselbe wie bei deinem Programm und bewegt sich wieder
nur ein paar Grad weiter und dann wieder zurück.
Sind die 12MHz überhaupt definiert damit das delay() funktioniert?
Das sollte aber eine Compiler-Warnung geben.
Genauso wie eine falsche Optimierungs-Stufe.
Bei 12MHz sind 1000 = 0,66ms und 2000 = 1,33ms, das passt so garnicht zu
einem Servo.
Hmm, bei 8MHz mit dem Prescaler von 8 sind 1000 genau 1ms und 2000 genau
2ms.
Dein Quarz scheint überhaupt nicht aktiviert zu sein.