...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...
Bild hier
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
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Lesezeichen