Hallo an Alle!
da ich ja in letzter Zeit ein bisschen am experimentieren bin habe ich jetzt versucht ein altes Modellbauservo durch einen ATMega16 steuern zu lassen. Leider reagiert das Servo überhauptnicht (ist aber getestet. Mit der RC-Fernbedinung und dem normalen Empfänger funktioniert es).
Zur kurzen Erklärung:
Das Servo hat seine eigene Stromversorgung mittels Batterieblock. Der Controller wird durch den Programmer mit Strom versorgt.
Ich habe das Signalkabel (die Gelbe Leitung) durchgeschnitten und an PD5 (OC1A) verstöpselt.
jetzt habe ich folgenden Code in C geschrieben aber wie gesagt es reagiert nicht:
Wenn ich den Wert für OCR1A = (uint16_t)1000; nun auf OCR1A = (uint16_t)2000; endere sollte eigentlich das Servo zum neuen Ausschlag fahren und dann da auch bleiben... ich finde den Fehler aber nicht.Code:#include <avr/io.h> #include <util/delay.h> int main(void) { DDRD = (1 << DDD5); // OC1A als Ausgang DDRB= (1<<PB0); ICR1 = (uint16_t)19999; // TOP => 50 Hz OCR1A = (uint16_t)1000; // Vergleichswert einstellen (hier quasi minimaler Ausschlag) TCCR1A |= (1 << COM1A1); // non-inverting mode fuer Pin OC1A TCCR1A |= (1 << WGM11) ; // Fast PWM Mode 14 Teil A TCCR1B |= (1 << CS11); // Prescaler: 1/8 while (1) // endlos { PORTB^=(1<<PB0); //Blinkt nur als visualisierung das überhaupt was tut _delay_ms(100); } return 0; }
Vielen Dank schon mal
Gruß
Jeti
Ich habe dabei 2 Varianten Probiert. Zuerst habe ich die Masse für das Servo von der Batterie geholt. Das hat nicht funktioniert aber das servo hat wenigstens noch "gezuckt" wenn man das Signalkabel vom PD5 abgestöpselt hat. Dann habe ich die Masse vom 7805 auf dem Board abgezwackt... Das hat aber auch nicht funktioniert und das servo zuckt nicht mal mehr.
Die Masse der Batterie muss mit der Masse des Atmel's verbunden sein. Diese gemeinsamme Masse ist dann auch die Masse für das Servo. Nur die + Leitungen müssen getrennt bleiben.
Guck mal hier da ist ein Schaltplan mit 2 Servos. Achte mal auf die Spannungsversorgung des Atmels und der Servos. Da sieht man ganz gut wie das verdrahtet sein sollte.
Unser Sommer ist ein grün angestrichener Winter. Das einzige reife Obst, das wir haben, sind gebratene Äpfel. [Heinrich Heine]
also... ich habe jetzt:
-Die Masse der Batterie mit der Masse des Servos verbunden.
-Die Masse des Boards ebenfalls mit der Masse der Batterie verbunden.
-Der Programmer versorgt immer noch das Board
-Der Akku ist mit seinen 6V an das Servo angeschlossen
-Die Signalleitung des Servos liegt immer noch an PD5
aber Leider habe ich immer noch keinen Erfolg...
- - - Aktualisiert - - -
Also einen Fehler habe ich gefunden. Mir ist eine Lötstelle am Kabel für das Servo wohl gebrochen. Seit ich diese jetzt wieder gerichtet habe hat sich der Fehler deutlich geändert. Das Servo läuft jetzt immer eine Position an, nämlich ganz links... aber eine Änderung von OCR1A führt es immer noch nicht aus.
Hast du einen normalen RC Empfänger? Dann teste mal ob das Servo noch lebt. Ich habe die Erfahrung gemacht, das die Logikelektronik von Servos recht empfindlich ist. Passt z.B. die Signal Frequenz nicht, kann das schon reichen und das Servo ist tot.
Ok hat sich etwas überschnitten.
Ich denke dein Code passt nicht. So ganz weiss ich jetzt aber auch nicht was falsch ist.
Unser Sommer ist ein grün angestrichener Winter. Das einzige reife Obst, das wir haben, sind gebratene Äpfel. [Heinrich Heine]
die On-Board Frequenz meines Mega16 müsste doch 8kHz sein oder? wenn ich dann einen Takt von 50Hz brauche darf ich den 16 bit Timer nur bis 19999 zählen lassen wenn mein Prescaler bei 8 liegt... oder sehe ich da was falsch. Und wenn ich nun das Servo auf Mittelstellung stellen will dann müsste ich doch sagen 19999/20*1,5 also ungefähr 1500... Dann schwankt der Wert für OCR1A zwischen 1000 und 2000... in Momenten wie diesen hätte ich gerne ein Oszilloskop...
Hoffentlich liegt das Ziel auch am Weg
..................................................................Der Weg zu einigen meiner Konstruktionen
Ähm für die Timer berechnung musst du schon die Prozessorfrequenz nehmen. Also z.B. 8MHz.
Gib mal hier deine gewünschten Daten ein:
http://www.dieelektronikerseite.de/T...er-Rechner.htm
Pass aber mit deinem Servo auf. Klemm es erst an wenn du dir sicher bist, das alles richtig ist. Ich tu mich mit den Timern auch immer schwer.
Meine Methode:
Timer einstellen z.B. auf 20ms. Dann in der Interruptroutine einen Counter hochzählen lassen bis 50 (= 1s) und dann eine Led Togglen. Wenn die dann im 1s Takt blinkt ist das schonmal gut. So ermittel ich das experimentell. Mein Logikanalyzer ist aber schon so gut wie bestellt. Die Teile gibt es fürn 10er in China. Da kann man nicht viel verkehrt machen.
Unser Sommer ist ein grün angestrichener Winter. Das einzige reife Obst, das wir haben, sind gebratene Äpfel. [Heinrich Heine]
Erst einmal herzlichen Dank schon einmal für die Hilfe!
Ich habe meine Frequenz jetzt auf den externen quarz gelegt, dann kann ich mir sicher sein das der Mega16 die 8MHz verwendet.
Außerdem habe ich im Datenblatt den Timer jetzt (denke ich) richtig auf den Mode 14 gelegt. Ich habe auch einmal die Routine mit den Interrupts versucht einzubauen um zu schauen ob die LED Blinkt. Da ich aber wie gesagt recht frisch in der Materie bin habe ich so einige Schwierigkeiten damit bekommen. Der Code sieht nun aus wie folgt:
Ich glaube das mir mein Interrupt den Zähler n jedesmal wieder neu mit 0 beschreibt. Ich weiß aber auch noch nicht wirklich wie ich das verhindern kann. DanielSan kannst du mir da einen Tipp geben?Code:#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> int n=0; ISR (TIMER1_OVF_vect) { n++; if (n>=50) { PORTB^=(1<<PB0); n=0; } } int main(void) { DDRD = (1 << DDD5); // OC1A als Ausgang DDRB= (1<<PB0); ICR1 = (uint16_t)19999; // TOP => 50 Hz OCR1A = (uint16_t)1500; // Vergleichswert einstellen TCCR1A |= (1 << COM1A1); // non-inverting mode fuer Pin OC1A TCCR1A |= (1 << WGM11); // Fast PWM Mode 14 Teil A TCCR1B |=(1 << WGM13)|(1 << WGM12) ; // Fast PWM Mode 14 Teil A TCCR1B |= (1 << CS11); // Prescaler: 1/8 while (1); }
---------------------------------------
Ich habe noch einmal ein paar Änderungen vorgenommen zum einen habe ich n jetzt global definiert damit es sie nicht bei jedem Interrupt überschreibt. Blinken tut meine LED deswegen trotzdem nicht. Und ich habe denke ich noch mal einen Fehler beim Mode gefunden und behoben. Jetzt zuckt das servo immerhin schon mal rythmisch... aber mehr auch nicht
Geändert von Jeti (04.04.2013 um 12:31 Uhr) Grund: Code Angepasst und Variable global definiert
Lesezeichen