Hallo,
wie die Überschrift schon sagt, möchte ich Servomotoren (hier PortA,
konkret an PA7, PA0-3 sind LEDS) an meinem ATmega32 mit 16MHz Quarz über
Timer0 steuern. (hfuse=c9, lfuse=9f)
Dafür habe ich folgende Überlegung angestellt:
16.000.000 mit Prescaler 1/64 macht 250.000 Ticks pro Sekunde, das wären
250 Ticks pro ms. Das wäre ja fast genau das was ich brauche (mein Servo
braucht anscheinend eher 0,8ms als 1ms für einen Vollausschlag). Also
fluchs noch Compare so gesetzt, dass es nur noch einen Tick machen muss,
und dann sollte das ja eigentlich klappen...
--- tuts aber net, und ich steh einfach aufm Schlauch was da schuld dran
sein mag ---
... die LEDs flackern so, dass mans noch gut mit dem Auge sehen kann,
somit denke ich, dass ich wohl in meiner Berechnung einen Fehler drinen
habe, und alles viel zu langsam läuft.
Grüße Uli
PS: Der Servo geht auf Linksanschlag.
PPS: Ich weiß, das CTC hier eventuell etwas ungünstig gewählt ist, aber
da ich dies bisher noch nie genutzt habe, und eventuell noch genauere
Feineinstellungen vornehmen will, halte ich das für am geeignetsten.
1 | #define F_CPU 16000000L
|
2 |
|
3 | #include <avr/io.h>
|
4 | #include <avr/interrupt.h>
|
5 |
|
6 | volatile unsigned long t0_clk;
|
7 | volatile unsigned long servo1;
|
8 |
|
9 | SIGNAL( TIMER0_COMP_vect ) {
|
10 | t0_clk++;
|
11 | if( t0_clk == 5000 ) t0_clk = 0; //alle 20ms
|
12 | if( t0_clk == 0 ) PORTA |= 0xFF; //setze Servopin(s) auf an
|
13 | if( t0_clk == servo1 ) PORTA &= 0x00; //Servowinkel erricht
|
14 | }
|
15 |
|
16 | void servoGrad(int grad) { //von -60 bis 60;
|
17 | if ((grad >= -60) && (grad <= 60)) {
|
18 | servo1 = 375+((250/120)*grad);
|
19 | }
|
20 | }
|
21 |
|
22 | int main()
|
23 | {
|
24 | DDRA = 0xFF; //Ausgänge (LEDS und Servo hängen dran)
|
25 | PORTA = 0x01; //Start-LED einschalten, rest ausschalten
|
26 |
|
27 |
|
28 | TCNT0 = 0x00; // Timer auf 0 Setzen
|
29 |
|
30 | TCCR0 = ( 0 << CS02 ) | ( 1 << CS01 ) | ( 1 << CS00 ); /* Prescaler: 1 / 64 */
|
31 | TCCR0 |= ( 1 << WGM01 ) | ( 0 << WGM00 ); /* CTC-Modus ein */
|
32 | TCCR0 |= ( 1 << COM01 ); /* Clear OC0 on compare */
|
33 |
|
34 | OCR0 = 0x01; //Immer wenns 1 wird
|
35 | TIMSK = ( 1 << OCIE0 ); /* Compare Match einschalten */
|
36 |
|
37 | t0_clk = 0;
|
38 |
|
39 | servo1 = 300;
|
40 |
|
41 | sei(); /* Interrupts anschalten */
|
42 |
|
43 | while( 1 ) {
|
44 | }
|
45 | }
|