Hi Hannes!
Vielen Dank für deine schnelle Antwort!
Werde versuchen das ganze umzusetzen und mich dann nochmal melden!
MfG
Lichti01
Hi Hannes!
Vielen Dank für deine schnelle Antwort!
Werde versuchen das ganze umzusetzen und mich dann nochmal melden!
MfG
Lichti01
So habe nun den ganzen Tag getüftelt hänge aber immer noch fest.
Hier mal mein bisheriger Code:
Leider bekomme ich bei der Zeile "//Zählerstand auslesen und in Variable schreiben" noch den Fehler angezeigt: "lvalue required as left operand of assignment".Code:#define F_CPU 1200000UL //Taktfrequenz CPU 1,2MHz #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <stdio.h> //LED-Ports #define LED1 1 #define LED2 2 #define LED3 3 #define LED4 4 #define C 0 //Variable für Zählerstand int main(void) { DDRB = 0b00011110; //Eingänge und Ausgänge definieren PORTB = 0b00000001; //Pullups setzen //Einstellungen für PCINT MCUCR = (1<<ISC00); //Jede logische Änderung an INT0 erzeugt eine Interrupt-Anforderung GIMSK = (1<<PCIE); //PCINT aktivieren PCMSK = (1<<PCINT0); //PCINT0 Eingang wird genutzt //Einstellungen Timer / PWM TCCR0A = ((1<<WGM00) | (1<<WGM01)); //FastPWM (Top=0xFF Update of OCRx at = TOP TOV Flag Set on = MAX) TCCR0B = ((1<<CS00) | (1<<CS01)); //Prescaler clk/64 (zählt in ca. 0,002s bis 219) sei(); //globale Interrupts aktivieren while(1) { if(C >= 100) { PORTB |= ((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4)); } else if (C <=100) { PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4)); } } } ISR(PCINT0_vect) { if(PINB & (1<<PB0)) //erkennung steigender Flanke { TCNT0 = 0; } else //sonst { C = TCNT0; //Zählerstand auslesen und in variable schreiben } }
Über Hilfe wäre ich wieder dankbar.
Was natürlich auch gut zu wissen wäre ist, ob der Code ansonsten für mein Vorhaben richtig umgesetzt ist.
LG
Lichti01
Du hast glaube ich C nicht richtig verstanden. Ein define ist dafür da bestimmte Werte einem Namen zu geben, als Beispiel z.b. Pi, das ist immer 3,1415. Jetzt kannst du in dem Programm jedes mal 3,1415 hinschreiben oder zuerst mit define definieren und anschließend nur mehr mit dem definierten Label (Pi) arbeiten. Bei den Leds hast du es richtig verwendet, bei der Zählervariable allerdings falsch, dort musst du schreiben wie groß der wert sein kann (signed bzw unsigned, char, int float,...). https://www.mikrocontroller.net/arti...R-GCC-Tutorial dort bei ganzzahlige datentypen (integer). Zuerst musst du wissen wie weit der TCNT zählen kann (beim längsten Impuls, also 2ms) und dementsprechend den Typ wählen (vermutlich unsigned char bzw unsigned int).
MfG Hannes
Ja da habe ich wohl etwas falsch verstanden!
Habe nun meinen Code geändert. Im Testlauf habe ich mit einem Zweiten µC die PWM vom Empfänger simuliert und es funktioniert auch soweit.
Die Tage geht es dann an den Test mit einem RC-Empfänger. Hoffe das das dann auch so reibungslos funktioniert wie mit dem zweiten µC.
An dieser Stelle möchte ich mich bei dir auch noch für deine Hilfe bedanken! Finde es klasse, dass du mir nicht einfach den Code präsentiert hast. Somit habe ich doch einiges gelernt!
Gruß
Lichti01
so nun habe ich den code mit verschiedenen Empfängern erfolglos getestet.
Was ist falsch?
Habe schon mit den Einstellungen am Sender gespielt hab verschiedene Prescaler / Integer ausprobiert. Was kann ich noch machen?Code:#define F_CPU 1200000UL //Taktfrequenz CPU 1,2MHz #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <stdio.h> //LED-Ports #define LED1 1 #define LED2 2 #define LED3 3 #define LED4 4 uint16_t C; //Integer einfügen und Variable für Zählerstand festlegen int main(void) { DDRB = 0b00011110; //Eingänge und Ausgänge definieren PORTB = 0b00000000; //Pullups setzen //Einstellungen für PCINT MCUCR = (1<<ISC00); //Jede logische Änderung an INT0 erzeugt eine Interrupt-Anforderung GIMSK = (1<<PCIE); //PCINT aktivieren PCMSK = (1<<PCINT0); //PCINT0 Eingang wird genutzt //Einstellungen Timer / PWM TCCR0A = ((1<<WGM00) | (1<<WGM01)); //FastPWM (Top=0xFF Update of OCRx at = TOP TOV Flag Set on = MAX) TCCR0B = (1<<CS01); //Prescaler clk/8 sei(); //globale Interrupts aktivieren while(1) { if (C < 80) { PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4)); sei(); } else if((C > 80) & (C < 190)) { PORTB &= ~((1<<LED2) | (1<<LED4)); PORTB |= (1<<LED1); PORTB &= ~(1<<LED3); _delay_ms(500); PORTB |= (1<<LED3); PORTB &= ~(1<<LED1); sei(); _delay_ms(500); } else if (C > 190) { PORTB |= ((1<<LED2) | (1<<LED4)); PORTB |= (1<<LED1); PORTB &= ~(1<<LED3); _delay_ms(500); PORTB |= (1<<LED3); PORTB &= ~(1<<LED1); sei(); _delay_ms(500); } } } ISR(PCINT0_vect) { if(PINB & (1<<PB0)) //erkennung steigender Flanke { TCNT0 = 0; } else //ansonsten { C = TCNT0; //Zählerstand auslesen und in variable schreiben cli(); } }
Gruß
Lichti01
Servus,
du hast die PWM simuliert, und es hat funktioniert. Da würde ich das Simulierte Signal und das Signal vom RC Empfänger vergleichen. Entweder mit einem Oszilloskop, oder als ich das noch nicht hatte, ging das mit einem Freeware Softwareoszi für den PC sehr gut.
IMHO ist es sinnlos, im Code herum zu rühren, wenn man nicht weiss, was die Hardware macht. Auf Dauer ist das fürchterlich ineffizient.
Warum schreibst du PORTB = 0b00000000; ? Portb ist beim einschalten automatisch 0x00 (steht im DB).
Warum konfigurierst du 2 Interrupts, das ist vermutlich auch der Fehler. Du konfigurierst einmal INT0 und PCINT0, INT0 ist PB1 und PCINT0 ist PB0. Du reagierst aber nur auf den PCINT, ich vermute das du den Empfänger auf PB1 (INT0) angeschlossen hast. Eigentlich sollte es aber Warnungen geben wenn du es kompilierst. Warum schaltest du eigentlich die Interruptfreigabe aus?
MfG Hannes
okay ich werf fragen hinterher, wozu einen WaveForm Modus?
lass TCCR0A einfach auf initial Zustand! Normaler Zählmodus, kein PWM das ist nutzlos!Code://Einstellungen Timer / PWM TCCR0A = ((1<<WGM00) | (1<<WGM01)); //FastPWM (Top=0xFF Update of OCRx at = TOP TOV Flag Set on = MAX) TCCR0B = (1<<CS01); //Prescaler clk/8
1.2MHz / 8 = 150kHz -> 8bit = 265 counts -> 1/150kHz * 256 = 1.70666 mS
sollte alos für den maximal möglichen 1.5mS Puls reichen
du initialisierst den Timer OHNE clockselect, du lässt CS einfach komtplett weg! Damit steht dein Timer!
in der ISR, bei steigender Flanke, startest du den timer indem du die CS01 setzt
bei fallender Flanke stoppst du den timer, indem du die CS Bits weider auf 0 setzt, prüfst du zuerst das TIFR Register ob das Overflow Bit gesetzt ist, löschst es (eine 1 auf das bit schreiben, keine 0) und verwirfst die Messung (Die High Phase war offensichtlich länger als 1.7mS)
wenn das OVF Flag nicht gesetzt ist schreibst du den TCNT wert auf und verarbeitest die gemessenen zeit und setzt TCNT wieder auf 0
so sparst du sogar in den low phasen noch strom weil dein timer nciht die ganze zeit sinnlos mitrennt
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
Lesezeichen