ich habe ein kleines Programm geschrieben, welches über zwei taster ganz
simpel einen servo einmal nach links und einmal nach rechts ausschlagen
läßt. das nacch links ausschlagen funktioniert auch soweit. (ich hatte
in einem beitrag gelesen, das 2ms voller ausschlag zur einen und 1ms
voller ausschlag zur anderen seite ist.) nach rechts jedoch bleibt er
ungefär in mittelstellung stehen. kein problem dachte ich mir,
verringerst du die zeit unter ein ms. hier trat folgendes problem auf.
bei 0 ms verzögerung drehte sich der servo hin und her, als ich wenn ich
anstatt der funktion _delay _ms(); _delay_us(); nehme mechert avr studio
rum. er will die ganze zeit neu kompilieren und so. diese funktion
benötige ich aber spätestenz, wenn ich zwischenstellen zwischen
ausschlag rechts und ausschlag links haben möchte.
hier erstmal mein code:
1
#define __OPTIMIZE__ // Code Optimieren für richtige verzögerungszeit
2
3
#define F_CPU 8000000
4
5
6
#include<avr/io.h>
7
#include<util/delay.h>
8
9
10
int8_tflag;
11
12
13
voidleft(){// Funktion linksdrehung
14
15
_delay_ms(20);
16
17
PORTB|=(1<<0);/* setzt Bit 0 an PortC auf 1 */
18
19
_delay_ms(2);
20
21
PORTB&=~(1<<0);/* loescht Bit 0 an PortC */
22
23
_delay_ms(20);
24
25
PORTB|=(1<<0);/* setzt Bit 0 an PortC auf 1 */
26
27
_delay_ms(2);
28
29
PORTB&=~(1<<0);/* loescht Bit 0 an PortC */
30
31
}
32
33
voidright(){// funktion rechtsdrehung
34
35
_delay_ms(20);
36
37
PORTB|=(1<<0);/* setzt Bit 0 an PortC auf 1 */
38
39
_delay_us(1000);// 1 ms warten für rechtsdrehung
40
41
PORTB&=~(1<<0);/* loescht Bit 0 an PortC */
42
43
_delay_ms(20);
44
45
PORTB|=(1<<0);/* setzt Bit 0 an PortC auf 1 */
46
47
_delay_us(1000);// 1 ms warten für rechtsdrehung
48
49
PORTB&=~(1<<0);/* loescht Bit 0 an PortC */
50
51
}
52
53
54
55
intmain(){
56
57
58
59
60
DDRB=0xff;
61
DDRD=0x00;
62
63
while(1==1){
64
65
while(!(PIND&(1<<0))){// bit 1 wird abgefragt gesezt (Taster abfragen)
66
_delay_ms(100);
67
68
left();//(links drehen)
69
70
}
71
72
73
while(!(PIND&(1<<1))){// bit 2 wird abgefragt gesezt (Taster abfragen)
74
_delay_ms(100);
75
76
right();//(rechts drehen)
77
78
}
79
80
81
82
83
}
84
85
86
}
hier die Fehlermeldung:
avr-gcc.exe -mmcu=atmega8515 -Wall -gdwarf-2 -O0 -MD -MP -MT servo.o
-MF dep/servo.o.d -c ../servo.c
c:/winavr-20071221/bin/../avr/include/util/delay.h: In function 'right':
c:/winavr-20071221/bin/../avr/include/util/delay.h:143: sorry,
unimplemented: inlining failed in call to '_delay_ms': function not
considered for inlining
c:/winavr-20071221/bin/../avr/include/util/delay.h:116: sorry,
unimplemented: called from here
c:/winavr-20071221/bin/../avr/include/util/delay.h:143: sorry,
unimplemented: inlining failed in call to '_delay_ms': function not
considered for inlining
c:/winavr-20071221/bin/../avr/include/util/delay.h:116: sorry,
unimplemented: called from here
ich benutze das stk500 mit einem 8515 und programmiere in c.
Mach ich villeicht bei der PWM was falsch???
Die Delay-Funktion (kann auch ein Makro sein...) hat einen möglichen
Wertebereich, der von der Taktfrequenz abhängt.
Möglicherweise hängt dein Problem damit zusammen.
Das vermute ich aber auch nur. Mit der Funktion habe ich noch nie
gearbeitet, da es meiner Meinung nach einfacher ist, einen Timer
entsprechend zu konfigurieren.
Hallo,
ich baue auch gerade eine Servosteuerung.
Die PWM muß aber eine Periode von 20ms und ein Pulsbreite von 1 bzw. 2
ms haben. Also _delay_ms(100) kann nicht funktionieren.
Gruß
Olaf
STK500-Besitzer wrote:
>>Die PWM muß aber eine Periode von 20ms und ein Pulsbreite von 1 bzw. 2>>ms haben.>> Nee, muß sie nicht!
Stimmt... Es schadet aber trotzdem nicht, so zu tun, als käme der Impuls
aus einem handelsüblichen RC-Empfänger.
-------------
Und lasst den Blödsinn mit den Warteschleifen, das bisschen
Servo-Impulstelegramm erzeugt ein AVR ganz nebenbei in einer
State-machine im Timer-Interrupt, wobei nur wenige Prozent
Rechenleistung beansprucht werden. Der Mainloop steht also weiterhin
fast die gesamte Rechenleistung zur Verfügung.
...
Sönke Paschko wrote:
> gibts dazu ne gute anleitung oder ein tutorial, weil ich weder mit> timern noch mit externen interrupts bei einem avr gearbeitet habe.
Ist das jetzt Dein Ernst???
Im oben genannten Link wird der Programmablauf mit normalem Deutschen
Text beschrieben. Der beiliegende Quelltext ist sehr üppig kommentiert,
den versteht man auch ohne fundierte ASM-Kenntnisse. Ein Blick ins
Datenblatt des AVRs ist allerdings nötig, denn wenn man die Architektur
des verwendeten Controllers nicht kennt, kann man auch das beste
Programm oder Tutorial nicht verstehen.
...
Um zwei Servos an den OC1A und OC1B Pins eines Tiny 2313 zu betreiben
reicht schon eine Handvoll Codezeilen:
1
// Servo Frame-Time:
2
#define FRAME_TIME 20 // msec
3
4
// init timer 1:
5
ICR1=FRAME_TIME*1000;// PWM cycle time in usec
6
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);// OC1A/B clr on match, set on TOP
7
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS11);// TOP = ICR1, clk = sysclk/8 (->1us)
8
TCNT1=0;// reset Timer
9
10
OCR1A=1000;// set Servo 1 to 1ms-position
11
OCR1B=2000;// set Servo 1 to 2ms-position
Durch die Verwendung der Output-Compare-Funktion des 16bit-Timers 1
bleiben die Servos gesteuert, ohne dass der Prozessor auch nur einen
einzigen Befehl dazu abarbeiten müsste. Er muss lediglich die
OCR-Register passend beschreiben, wenn die Servos bewegt werden sollen.
Gruß,
Peter
so damit hast du jezt den timer gestartet oder was???
was ist OCR1A?
was ist OCR1b?
wan wird ein Pin für pwm beschrieben, oder muss ich das selbst machen
wenn ja wann?
zum Datenplatt, im datenblatt steht nur, das man einen prescaler
benutzen kann, jedoch weder wie man ihn benutzt noch wie man den timer
initialisiert.
> so damit hast du jezt den timer gestartet oder was???
Mal nebenbei: Wenn Du hilfreiche Antworten haben willst, darfst Du auch
gerne einen Tick freundlicher sein. Danke.
Zum Timer: Guck Dir mal im Datenblatt den Teil vom Timer 1 an, speziell
den "Fast PWM Mode". Dort steht genau beschrieben, wie die Ausgangspinne
OC1A und OC1B gesteuert werden.
Der Timer selbst läuft immer zwischen Null und einer Obergrenze. Hat er
die erreicht, fängt er wieder bei Null an. Bei meiner Konfiguration gibt
ICR1 die Obergrenze vor, welche ich auf 20000 gesetzt habe. Programmiert
man jetzt noch den Vorteiler auf 8, so rennt der Timer bei einem 8MHz
Quartz in 1us-Schritten von Null bis 20ms, was genau der
RC-Wiederholungsrate entspricht.
Die Compare Register steuern die Ausgangspins: Beim Sprung des Timers
auf Null werden sie gesetzt, überschreitet der Timers die Werte in
OCR1A/OCR1B, wird der entsprechende Pin auf low gesetzt. Du musst halt
nur in OCR1A/OCR1B eine Zahl zwischen 1000 und 2000 eintragen, das gibt
dann die gewünschten 1...2ms Pulsbreite mit 20ms Abstand.
Ach ja, die Pins OC1A und OC1B müssen unbedingt als Ausgänge gesetzt
sein.
Gruß,
Peter
danke, ich meinte das nicht böse oben,dein text ist echt super so hab
ichs verstanden.
einen nachteil hat das doch aber weil oc1a an ein pin gekoppelt ist und
sich damit also nur ein servo steuern läßt. kann man das nicht so lösen,
das eine Interruptrutine aufgerufen wird, die dann die Pins steuert,
sodass auch mehrere Pins geschaltet werden können?
Ja, und mit OC1B steuerst Du ein zweites Servo. Wenn's mehr sein soll,
brauchst Du entweder einen AVR mit mehr 16-Bit PWMs oder eine
Softwarelösung. Du hattest aber in Deinem Initialposting auch nur von
einem Servo geschrieben.
Gruß,
Peter
> DDRB = (1 << PB1 );> DDRB = (1 << PB2 );
Demnach ist nur noch PB2 ein Ausgang.
Schreib es lieber so:
DDRB = (1 << PB1 ) | (1 << PB2 );
>Kannst du mit nem Osziloskop mal gucken, ob die Pulsweiten stimmen? bzw.>ob überhaupt was rauskommt
Einfacher: Häng eine LED an einen Port und lass sie im Sekundentakt
blinken.
Das kleine Hemdentaschenmultimeter von Pollin Best.Nr. 830 096 zum Preis
von 12,95 EUR hat unter Anderem auch einen Frequenzmessbereich mit dem
man die Periodendauer messen kann. Dieser lässt sich auf Tastgradmessung
umschalten, was das Messen der relativen Impulsbreite ermöglicht. Bei
einem Servoimpuls von 1.0 bis 2,0 ms im Abstand von 20 ms sind das 5 bis
10 % Tastgrad.
Ich möchte weder gegen ein Oszilloskop diskutieren, noch Werbung für
Pollin machen, aber die Anschaffung dieses kleinen schnuckligen
Mini-Multimeters sollte auch als sparsamer Bastler drin sein. Das
amortisiert sich schnell.
...
stimmt, mein multimeter hat auch duty cicle messung und frequenzmessung,
funktioniert super, hab die werte gerade nachgerechnet, stimmt fast 100%
genau