...oder mal die Suchfunktion bemühen...
OK,
dann solltest du auch so intelligent sein, und dir die Handhabung von Timern und Interrupts ansehen.
grüsse,
vohopri
...oder mal die Suchfunktion bemühen...
![]()
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
stimmt, ich schau mir mal des an, was in RN-Wissen steht.
Hey Hoh, letz program
Ich hab jetz mal folgenden Code ausprobiert:
der hat funktioniert, nachedm ich servopos als integer deklariert hab.Code:#define SERVOPIN 7 #define SERVOPORT PORTD #define DDRSERVO DDRD volatile unsigned char servopos; void servo_init() { TIMSK|=(1<<OCIE2); TCCR2 |= (1<<WGM21) | (1<<CS20); //Prescale=1, CTC mode OCR2 = F_CPU/100000; //alle 10µS ein IRQ DDRSERVO|=(1<<SERVOPIN); }; ISR(TIMER2_COMP_vect) { static int count; if(count>servopos)SERVOPORT&=~(1<<SERVOPIN); else SERVOPORT|=(1<<SERVOPIN); if(count<2000+servopos)count++; else count=0; };
der folgende code für zwei Servos funktioniert aber nicht so richtig:
wenn ich im Interrupt den Teil für den ersten Servo auskommentier läuft der erste, wenn ich den zweiten auskommentier läuft der zweite.Code:#define SERVOPIN_LEFT (1<<PA1) #define SERVOPIN_RIGHT (1<<PA2) #define SERVOPORT PORTA #define DDRSERVO DDRA #define LEFT_SERVO 450 #define RIGHT_SERVO 420 volatile unsigned int servopos_left; volatile unsigned int servopos_right; void servo_init() { TIMSK |= (1<<OCIE2); TCCR2 |= (1<<WGM21) | (1<<CS20); //Prescale=1, CTC mode OCR2 = F_CPU/100000; //alle 10µS ein IRQ }; ISR(TIMER2_COMP_vect) { static int count_left; static int count_right; if(count_left > servopos_left) SERVOPORT &= ~SERVOPIN_LEFT; else SERVOPORT |= SERVOPIN_LEFT; if(count_left < 2000 + servopos_left) count_left++; else count_left=0; if(count_right > servopos_right) SERVOPORT &= ~SERVOPIN_RIGHT; else SERVOPORT |= SERVOPIN_RIGHT; if(count_right < 2000 + servopos_right) count_right++; else count_right=0; };
Aber beide gleichzeitig laufen nicht.
Ach ja, ich hab ne main-schleife:
Code:int main(void) { DDRA = 255; servo_init(); servopos_left = 500; servopos_right = 370; sei(); while(1) { } while(1); return 0; }
Hey Hoh, letz program
Weiß irgendwer, wo der Fehler in meinem Programcode liegt?
Hey Hoh, letz program
Mach die Servo-Ansteuerung lieber über hardware-PWM an den Pins OC1a und OC2.
Lied dir dazu im Datenblatt des Controllers den Artikel "Timer/counter" (oder so ähnlich) durch, dann brauchst du nicht mal Interrupts.
Ich würde Fast-PWM empfehlen (ich finde, das kann man am schönsten einstellen.
Grüße, Yaro
ah, danke, ich werds ausprobieren
Hey Hoh, letz program
Ok, ich hab jetz mal nen Code erstell:
Code:DDRD |= (1<<PD4) | (1<<PD5); TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<COM1A0) | (1<<COM1B0)| (1<<WGM12) | (1<<WGM11) | (1<<WGM10); TCCR1B |= (1<<CS11);
Hey Hoh, letz program
Ok, ich hab jetz mal nen Code erstell:
Jetzt weiß ich bloß nicht, wie ich OCR1A und OCR1B einstellen muss.Code:DDRD |= (1<<PD4) | (1<<PD5); TCCR1A |= (1<<COM1A1)|(1<<COM1B1)|(1<<COM1A0)|(1<<COM1B0)|(1<<WGM12)|(1<<WGM11)|(1<<WGM10); TCCR1B |= (1<<CS11);
Hey Hoh, letz program
Hallo
Deine ISR von oben sollte besser so aussehen:
Mit dem "count=1" kann man mit servopos=0 den Impuls ganz ausschalten.Code:ISR(TIMER2_COMP_vect) { static int count; if(count > servopos_left) SERVOPORT &= ~SERVOPIN_LEFT; else SERVOPORT |= SERVOPIN_LEFT; if(count > servopos_right) SERVOPORT &= ~SERVOPIN_RIGHT; else SERVOPORT |= SERVOPIN_RIGHT; if(count < (2000) count++; else count=1; };
Trotzdem stimmt etwas mit dem Takt nicht denn die Werte für die Servopositionen sind viel zu hoch:
Bei einem 10µs-Interrupt wären das 5ms oder 3,7ms! Und 2000 als count-Wert würden auch keine 20ms ergeben. Deshalb reicht dir auch das char für servopos nicht aus.servopos_left = 500;
servopos_right = 370;
Sollen wir nun das Datenblatt wälzen um das Setup des Timers zu kontrollieren? Je nach Timer-Mode und Taktfrequenz/Prescaler werden OCR1A und OCR1B eingestellt. Bei nur zwei Servos erscheint mir die Verwendung der ISR-Lösung einfacher.Code:TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<COM1A0) | (1<<COM1B0)| (1<<WGM12) | (1<<WGM11) | (1<<WGM10); TCCR1B |= (1<<CS11);
Gruß
mic
![]()
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Lesezeichen