Hallo zusammen,
ich wollte nun mal testen, ob ich es schaffe mit einem AVR einen Servo
zu steuern.
Der Servo besitzt eine eigene Spannungsversorgung und ist mit der
Steuersignalleitung und GND mit einem ATmega8 verbunden.
Der ATmega8 arbeitet mit 12MHz.
Wenn ich den Servo mit Spannung versorge bewegt er sich ein Stück vor.
Durch das jetzige Programm passiert nichts, wenn ich eine Taste drucke,
um die Servoposition zu ändern. Ich weiß, dass die Tasten nicht
entprellt sind, aber das ist ja so nur zum testen ;-)
Ich hatte mit einem etwas anderen Programm den Servo so, dass ich ihn
einmal per Taste bewegen konnte und dann stürzte der AVR ab, weil ich
keinen Prescaler genutzt habe und der Timerwert größer als 16 bit wurde.
Das ist zumindest meine Vermutung ;-)
Hat jemand eine Idee, was falsch ist?
Ein Oszi habe ich leider nicht zur Verfügung, sonst hätte ich mal
geschaut, wie mein Signal aussieht.
Danke :-)
1
#include<avr/io.h>
2
3
4
intmain(){
5
intServoPos;
6
DDRB|=(1<<DDB1);// PB1 (=OC1A) als Ausgang
7
PORTB|=(1<<PD0)|(1<<PD1)|(1<<PD2);// PullUp für Taster an PD0,1,2
8
TCCR1A|=(1<<COM1A1)|(1<<WGM11)|(1<<WGM10);// Ausgang OC1A bei 0 setzen und bei OCR1A loeschen
9
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS11);// Waveform Generation Mode: Fast PWM it OCR1A als Top, Timer mit CPU-CLK // Prescaler auf 8
10
OCR1A=29999;// alle 20 ms
11
12
while(1){// Endlosschleife
13
OCR1B=ServoPos;
14
if(!(PIND&(1<<PIND0))){ServoPos=1500};//entspricht 1 ms
15
if(!(PIND&(1<<PIND1))){ServoPos=2250};//entspricht 1,5 ms
16
if(!(PIND&(1<<PIND2))){ServoPos=3000};}//entspricht 2 ms
R. B. schrieb:> Ein Oszi habe ich leider nicht zur Verfügung, sonst hätte ich mal> geschaut, wie mein Signal aussieht.
Aber einen Simulator hast du doch - oder welche Entwicklungsumgebung
benutzt du?
Hallo,
ich habe mich gestern auch damit beschäftigt. Ich glaube dein fPWM
benutzt das falsche Register.
Anstatt OCR1A = 29999; versuch mal
1
ICR1=29999;
zu verwenden.
Weil OCR1 das ist ja der compare Wert bei dem die Flanke auf 0 gehen
soll, ICR ist TOP, also da wo der Zähler wieder auf 0 geht.
Hm, bissel schlecht erklärt, aber ich denke somit sollte es gehen, die
Hintergründe und richtige Bezeichnungen kann ja eventuell noch mal ein
Profi hier erklären.
Lieben Gruß,
ps
Wolfgang schrieb:> R. B. schrieb:>> Ein Oszi habe ich leider nicht zur Verfügung, sonst hätte ich mal>> geschaut, wie mein Signal aussieht.>> Aber einen Simulator hast du doch - oder welche Entwicklungsumgebung> benutzt du?
Ich habe keinen Simulator, da ich Visual Studio mit AVR GCC nutze.
Zugegeben, ein Simulator wäre nicht verkehrt ;)
Peter Shaw schrieb:> Anstatt OCR1A = 29999; versuch mal> ICR1=29999;>> zu verwenden.> Weil OCR1 das ist ja der compare Wert bei dem die Flanke auf 0 gehen> soll, ICR ist TOP, also da wo der Zähler wieder auf 0 geht.
Ich habe gerade mal einen Blick ins Datenblatt geworfen und ich denke du
hast recht, dass ich ICR1 nehmen muss. (Ist mein Erstkontakt mit PWM und
alles noch nicht so 100 % verstanden ;) )
Leider ändert sich nichts.
Der Servo mag noch immer nicht.
Ok, ich habe jetzt nochmal alles mit dem Datenblatt vom Meg8 verglichen
und festgestellt, dass WGM10, wenn ich ICR1 als Top nehmen möchte 0 sein
muss.
Den Servo habe ich mal testweise an den Pin vom genutzten Quarz gehalten
und da bewegt er sich munter in alle Richtungen wild hin und her. Am
Servo scheint es also nicht zu liegen.
Mein Programm sieht jetzt so aus:
1
#include<avr/io.h>
2
3
4
intmain(){
5
intServoPos;
6
DDRB|=(1<<DDB1);// PB1 (=OC1A) als Ausgang
7
PORTB|=(1<<PD0)|(1<<PD1)|(1<<PD2);// PullUp für Taster an PD0,1,2
8
TCCR1A|=(1<<COM1A1)|(1<<WGM11);// Ausgang OC1A bei 0 setzen und bei ICR1 loeschen
9
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS11);//Fast PWM it ICR1 als Top // Prescaler auf 8
10
ICR1=29999;// alle 20ms
11
12
while(1){// Endlosschleife
13
OCR1B=ServoPos;// Impulslaenge 1,5ms bei 12 MHZ und Prescaler 8 = 18000
14
if(!(PIND&(1<<PIND0))){ServoPos=1500};
15
if(!(PIND&(1<<PIND1))){ServoPos=2250};
16
if(!(PIND&(1<<PIND2))){ServoPos=3000};}
17
}
Leider funktioniert nach wie vor nichts und mir fällt leider momentan
nichts mehr ein.
Hat jemand eine Idee?
Danke :-)
Spess53 schrieb:> Hi>>>PORTB|= (1<<PD0) | (1<<PD1) | (1<<PD2); // PullUp für Taster an PD0,1,2>> Soll das so sein?>> MfG Spess
Hi, jepp, weil die Taster als ActiveLow angeschlossen sind.
Ich habe eben mal die Taster durch eine Schleife ersetzt, die die Werte
für die Servoposition ändert.
Bringt aber leider nichts.
Ich bin mir nun auch unsicher, ob OCR1A oder B der Ausgang sein muss und
steig langsam nicht mehr durch.
Ich habe aber beides getestet und den Servo umgesteckt sowie OCR1B auch
als Ausgang definiert. Trotzdem keine Reaktion!
Lediglich bein Reset des AVRs bewegt sich der Servo kurz gegen den
Uhrzeigersinn :-(
Georg G. schrieb:> Erklär uns doch, warum du PortB mit Bitwerten für PortD initialisierst> um dann PortD zu nutzen.
Danke für den Hinweis.
Den Fehler habe ich ständig überlesen! ;-)
Funktionierten tut es nach der Fehlerkorrektur leider noch immer nicht
:-(
Spess53 schrieb:> Hi>>>Funktionierten tut es nach der Fehlerkorrektur leider noch immer nicht>> Aber hoffentlich PortB in PortD geändert.>> MfG Spess
Jepp und ich habe nun auch den Fehler gefunden.
Aber den verrate ich lieber nicht ^^
Es lag am Compiler ;)
Danke :-)