Nochmal eine andere Frage: Um Strom zu sparen und da der Servo nicht permanent mit Kraft die Stellung halten muss, wollte ich den jetzt ohne Timer versorgen. Und zwar über eine ganz einfache Funktion, die in einer Schleife 30 mal erst für 1-2ms ein High am Port ausgibt, gefolgt von 15ms Low. (Die Länge des High-Zustandes bestimmt die Position und da sich der Servo scheinbar nur in den kurzen 15ms lang bewegt und in der Zeit keine 180° schafft, mach ich es 30 mal).
Meine Frage bezieht sich auf den Typ der Zählvariablen in der Schleife für die 1-2ms Wartezeit.
Um RAM zu sparen wollte ich nämlich eine 8bit statt einer 16bit Variablen benutzen, aber leider funktioniert das nicht.
Die anderen, betroffenen Variablen (i in der main und time als Parameter) sind auch nur 8bit groß.Code:#define F_CPU 1000000UL #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> volatile uint8_t OCR0Adirection=0, OCR0Avalue=1; //0->OCR0A raufzählen 1-> OCR0A runterzählen ISR(TIMER0_COMPA_vect){ if(OCR0Adirection==0){ OCR0Avalue += 1; if(OCR0Avalue==254) OCR0Adirection=1; }else { OCR0Avalue -= 1; if(OCR0Avalue==1) OCR0Adirection=0; } OCR0A = OCR0Avalue; } void moveServo(uint8_t time){ cli(); PORTB |= (1<<PB4);//Servo Stromversorgung an uint8_t i=0; uint16_t j=0; //<-----Diese Stelle ist gemeint-----> for(;i<50;i++){//es wird ein paar mal der folgende drehbefehl durchgegeben PORTD |= (1<<PD5);//servo-takt-pin an for(j=0;j<time;j++){//eine ganz bestimmte zeit lang an lassen (1-2ms) _delay_us(1);} PORTD &= ~(1<<PD5);//dann wieder aus _delay_ms(15);//und bis zum nächsten warten (10-20ms) } PORTB &= ~(1<<PB4);//Servo Stromversorgung aus sei(); } int main (void) { TCCR0A = (1 << COM0A1) | (1 << COM0A0) | (1 << WGM00) | (1 << WGM01); //TCCR0B = (1 << CS00);//no Prescaler //TCCR0B = (1 << CS01);//Prescaler CPU/8 TCCR0B = (1 << CS00) | (1 << CS01);//Prescaler CPU/64 //TCCR0B = (1 << CS02);//Prescaler CPU/256 //TCCR0B = (1 << CS00) | (1 << CS02);//Prescaler CPU/1024 OCR0A = 1; //Startwert, pendelt dann zwischen 0..255 DDRB = (1 << PB2); //pin PB2 auf Ausgang (das ist OC0A) //blinkende led PB4, PD5, PA0 DDRB |= (1 << PB4);//Strom für Servo DDRD |= (1 << PD5);//OC0B (Servo) DDRA |= (1 << PA0); //ISRs für OCR0A Compare Match TIMSK = (1 << OCIE0A); sei(); uint8_t i; while(1){ if(OCR0Avalue==20) { i=70; moveServo(i); } if(OCR0Avalue==240) { i=170; moveServo(i); } if(OCR0Avalue==128) { i=250; moveServo(i); } } }
D.h. wenn ich die Zählvariable j auch nur 8bit groß mache, müsste es doch alles glatt laufen (einen Überlauf kanns nicht geben). Aber trotzdem scheint die Schleife mit (uint8_t jschon ganz früh abzubrechen, denn der Servo dreht sich bis zum Anschlag in die Richtung der kurzen Impulsdauern. Mit uint16_t j; gehts komischerweise.







Zitieren

Lesezeichen