Hallo Leute, ich möchte mehrere Signale von einem Graupner Empfänger mit AVR einlesen auswerten und mischen. Die Suche habe ich bemüht aber leider nichts brauchbares gefunden, es existieren zwar zig Themen zum Thema "Servo ansteuern" aber nichts zu der Auswertung von Signalen. Möchte mit einem Atmega 32 die Signale auswerten, versuche in C zu programmieren. Also meine Idee war folgende: Ich wollte die externen Interrupts benutzen, es wären die Pins INT0, INT1, INT2. 1) Am Anfang den Interrupt Initialisieren für die Positive Flanke 2) Positive Flanke aufgetreten--->Initialisieren für die Negative Flanke 3) Zeit zählen die vergeht bis wieder ein Interrupt auftritt(jetzt für die Negative Flanke) 4) Negative Flanke aufgetreten--->Initialisieren für die Positive Flanke usw Das ganze funz aber nicht, es geht zwar wenn ich mit einem Draht die Flanken simuliere aber nicht wenn der Empfänger am µC hängt. Hat einer vielleicht eine andere Idee? wo liegt mein Fehler? Welche Möglichkeiten gibt es noch?
>wo liegt mein Fehler?
Entweder in der Hardware, der Software oder in beiden...
Zeig dein Programm, und man kann dir (besser) helfen.
http://www.hanneslux.de/avr/mobau/index.html Nicht der letzte Schrei, aber brauchbar und ausbaufähig... ...
Hallo, ich habe es so gemacht. ATmega8, 16mHz,ein Kanal wird mit einem Ext.Int ausgewertet. #include <avr/io.h> #include <avr/interrupt.h> volatile uint8_t Pulsdauer = 0; void (steigende_Flanke)(void); void (fallende_Flanke)(void); SIGNAL(SIG_INTERRUPT0) { if( MCUCR == 0x03) // Testen auf steigende Flanke { steigende_Flanke(); return; } if( MCUCR == 0x02 ) // Testen auf fallende Flanke { fallende_Flanke(); return; } } void (steigende_Flanke)(void) { TCNT0 = 0; // Timer Reset TCCR0 = _BV (CS02); // Timer2 1/256 MCU start MCUCR = 0x02; // INT0 fallende Flanke } void (fallende_Flanke)(void) { TCCR0 = 0x00; // Timer2 Stoppen Pulsdauer = TCNT0; // Timer Wert = Pulsdauer MCUCR = 0x03; // INT0 auf steigende Flanke } int main(void) { //PD2 Int0 für RC Signal PORTD = 0x04; // Pull up on PD2 DDRD = 0xFB; // PD2 in Rest out //Int0 steigende Flanke / INT0 enable MCUCR = _BV (ISC01) | _BV (ISC00); GICR = _BV (INT0); sei(); for(;;) { if (Pulsdauer < 68){"mach was"} else if (Pulsdauer >= 68 && Pulsdauer < 85){"mach was anderes"} else if (Pulsdauer >= 85 && Pulsdauer < 110){"mach was anderes"} else if (Pulsdauer >= 110 && Pulsdauer < 150){"mach was anderes"} } } Gruß Toby
Hallo nochmal, du kannst natürlich auch mit dem RC Summensignal mehrere Kanäle auswerten. Das habe ich mal hier gemacht, siehe Anhang. Die LCD Routine habe ich nicht mit angehangen, es geht ja ums Auswerten des Signals. Gruß Toby
Danke erstmal für die Antworten und Beispiele. Hier ist mein Code, etwas primitiv aber na ja: #include <avr/interrupt.h> #include <avr/io.h> #include "usart.h" #include "lcd.h" volatile int eins=1 ; // Wenn die Variable eins 1 ist, wird für negative // Flanke initialisiert volatile int zeit_ein; //Wenn die Variable zeit_ein 1 ist läuft die Zeit volatile int wert; //Pulsbreite //---------------------------------------------------------------------- ------ //INT1 Interrupt ISR (INT1_vect) { if(eins==1) { wert=0; zeit_ein=1; MCUCR|= (1<<ISC11); GICR |= (1<<INT1); eins=0; } else { zeit_ein=0; MCUCR|= (1<<ISC10 | 1<<ISC11); GICR |= (1<<INT1); eins=1; } } //---------------------------------------------------------------------- -------- int main (void) { //-----Allgemeine Initialisierung----------------------- //Initialisierung externe Interrupt MCUCR|= (1<<ISC10 | 1<<ISC11); GICR |= (1<<INT1); LCD_Init(); LCD_Clear(); sei(); //------Allgemeine Initialisierung ende -------------------- while(1) { if(zeit_ein == 1) { wert=wert+1; } LCD_Print(0,0," %i %i ",wert,zeit_ein); LCD_Print(1,0," "); LCD_Print(2,0," "); LCD_Print(3,0," "); } } @Tobias du benutzt da den Timer, wie ist es aber wenn ich mehrere Kanäle auswerten will?
1 | if(eins==1) |
2 | {
|
3 | wert=0; |
4 | zeit_ein=1; |
5 | MCUCR|= (1<<ISC11); |
6 | GICR |= (1<<INT1); |
7 | eins=0; |
8 | }
|
9 | |
10 | else
|
11 | {
|
12 | zeit_ein=0; |
13 | MCUCR|= (1<<ISC10 | 1<<ISC11); |
14 | GICR |= (1<<INT1); |
15 | eins=1; |
16 | }
|
17 | }
|
Soll wohl deine Flankendetektierungsumschaltung sein. Allerdings wird die immer auf die gleiche Flanke reagieren. Du mußt das entsprechende Bit löschen "... &= ~ ...". Dann schaltest du auch die Flanken um.
Hallo, eigentlich müssten die Empfängerausgänge nacheinander angesteuert werden, da der Empfänger nur das PPM Signal in die Entsprechenden Kanäle umwandelt. Also müsste eine Auswertung von 2 Kanälen mit 2 Ext.Ints gehen. Siehe hier: http://www.mftech.de/ppm.htm Alle 22,5 ms bekommt der dementsprechende Kanal seine Pulslänge. Gruß Toby
Ja hast eigentlich recht, die Signale kommen ja nach einander. Ich probiere was aus vielleicht klappt es ja
Kann mir einer sagen was das für ein Fehler ist? Compiling: main.c avr-gcc -c -mmcu=atmega32 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst -std=gnu99 main.c -o main.o main.c: In function '__vector_1': main.c:84: warning: 'main' is normally a non-static function main.c:180: error: expected declaration or statement at end of input make.exe: *** [main.o] Error 1 Der zeigt auf die Geschweiften Klammern von "main" Ich weis aber nicht was da falsch sein soll.
Ich habs, es fehlte nur eine Klammer. Und die Auswertung läuft auch, Super. Ich danke euch.
Hi, ich habe lange gewartet mit dem Posten hier, aber scheinbar komme ich nicht drum herum (leider). Zu meinem Problemchen: Ich versuche ähnliches (Empfänger Signal von nem Servo auslesen) mit einem Attiny2313 aber komme nun schon seit 5 Tagen und etlichen Stunden testerei nicht mehr weiter. Ich habe viel selbst rumprobiert, mir auch mal nen Source, der eigentlich für den Atmega8 waren angeguckt und meinen danach umgeschrieben, aber leider klappt alles nicht! Vielleicht könnte mir jemand mit mehr Erfahrung (stehe noch relativ am Anfang) einen Tip geben. Als Info: Den Interrupt habe ich getestet, reagiert auf steigende und sinkende Flanken. Der Overflow von INT0 geht auch. Der Timer wird mit nem Prescale von 64 gestartet (was eigentlich nicht sein muss) und wenn meine Berechnungen stimmen sollte bei einem Maximal Ausschlag (~2ms) knappe 250 rauskommen. Stimmt das so? Den Divider habe habe ich weggefused. Und sonst die Standardfuses gelassen (Int. RC Osc. 4 MHz; Start-up time: 14 CK + 65 ms) Um den Code (solange er noch nicht funktioniert) möglichst schmal zu halten schalte ich nur Komplett den PORTB an, mehr nicht. Ich habe den Code mal ein bisschen dokumentiert.
1 | #define F_CPU 4000000;
|
2 | #include <inttypes.h> |
3 | #include <avr/io.h> |
4 | #include <avr/interrupt.h> |
5 | |
6 | uint16_t value; |
7 | |
8 | int main (void) |
9 | {
|
10 | |
11 | DDRB = 255; // portb as output |
12 | PORTB = 0; // portb to 0 |
13 | |
14 | DDRD = 0; // portd as input |
15 | PORTD = 0; // portd to 0 |
16 | |
17 | PCMSK |= (1<<PIND2); // Pin 6 (PD2) als Interrupt setzen |
18 | MCUCR = 1; // External Interrupt on PinChange |
19 | GIMSK |= (1<<INT0); |
20 | |
21 | TCNT1 = 0; |
22 | |
23 | TIMSK |= (1<<TOIE1); // 16-Bit Timer Overflow-Interrupt an |
24 | TCCR1A = 0; // 16-Bit Normal Mode |
25 | TCCR1B = 0; // stop 16-Bit Timer |
26 | |
27 | sei(); // Interrupts an. |
28 | |
29 | |
30 | |
31 | while(1) |
32 | {
|
33 | if (value > 200) |
34 | {
|
35 | PORTB = 255; |
36 | }
|
37 | else
|
38 | {
|
39 | PORTB = 0; |
40 | }
|
41 | }
|
42 | }
|
43 | |
44 | ISR(TIMER1_OVF_vect) |
45 | {
|
46 | |
47 | }
|
48 | |
49 | ISR (INT0_vect) |
50 | {
|
51 | if ((PIND & 4)==4) // HIGH! |
52 | {
|
53 | TCCR1B = 0; |
54 | TCNT1 = 0; |
55 | TCCR1B = 3; // Starten mit Prescaler: 4mhz / 64 > 2ms = 125 Takte |
56 | |
57 | }
|
58 | else
|
59 | {
|
60 | value = TCNT1; |
61 | TCCR1B = 0; |
62 | }
|
63 | }
|
Kann mir vielleicht jemand sagen, warum die LED nur wie blöde flackert? Ich hatte schon alle Möglichkeiten mit dem Timer durch, am Ende habe ich ihn einfach erst gestartet, als ne hohe Flanke kam. Bin für jeden Tip Dankbar
Mach dein "value" noch volatile! Hat der Attiny2313 keine InputCapture-Unit? Damit mache ich solche Sachen immer...
Hi, das mit Volatile muss ich mal ausprobieren. Mit der InputCapture-Unit muss ich mal nachsehen, damit habe ich noch nichts gemacht, werde ich mir aber heute Abend mal ansehen. Ich habe den Teil mit dem "Value" aus einem anderen Beispiel übernommen, bei dem es mit einem Atmega8 so ähnlich funktioniert hat. Ich dachte, wenn ich das erstmal relativ simpel halte kann ich das Programm nach und nach ausbauen, wenn ich weiß dass es grundsätzlich so funktioniert Bei dem ganzen Aufbau ist es in erster Linie nicht so wichtig, ob die Werte genau sind, ich will darüber nur eine Beleuchtung über einen freien Kanal an meiner Fernsteuerung einschalten/ausschalten. Was ich vergessen habe, an Portb hängt beim Testaufbau nur eine LED. Was mich gewundert hat war, dass die LED an Portb immer geflackert hat, unabhängig davon, was ich an der Fernsteuerung gemacht habe. Die Leitungen habe ich alle schon durchgemessen, das Signal kommt genau so, wie es sein soll und die richtige Leitung habe ich auch an PD2 angeschlossen. Viele Grüße Pendler
Ich habs letztens hinbekommen, war nur ein dummer Fehler. Die GND Brücke zwischen den beiden Stromversorgungen war nicht korrekt. Tja, so einfach gehts!
Hallo Leute, ich muss wie "GEA (Gast)" die Empfänger Signale auslesen und auswerten aber komme leider nicht weit... Meine Aufgabe ist mit Atmega32 und AVR die Signale zu lesen und Sie auswerten. Die Programmierung muss über C laufen... Habt Ihr vielleicht für mich fertig Programmierte Programme welche ich einfach übernehmen kann? ich hab leider nicht viel Zeit da ich neben bei auf meine Studium Konzentrieren muss:( viele grüße
Hallo, musste auch ein ähnliches Problem lösen, allerdings hatte ich keinen freien Interrupt mehr und habe das Ganze dann etwas schmutziger per Busy-Wait gelöst. Funktioniert auch und hat für mich den Vorteil, dass ich mehr Kanäle als freie Interrupt Leitungen vorhanden sind mit einem AVR auslesen kann.
1 | /*! Einlesen von RC-Signalen
|
2 | * Schmutzig per Busy Loop, dafür Interrupt unabhängig
|
3 | */
|
4 | |
5 | #include <avr/io.h> |
6 | #include <util/delay.h> |
7 | #include <avr/pgmspace.h> |
8 | #include <stdarg.h> |
9 | #include <string.h> |
10 | #include <stdlib.h> |
11 | |
12 | #define F_CPU 16000000
|
13 | |
14 | |
15 | uint16_t Pulsdauer; |
16 | uint16_t ReadChannel (void); |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | //###################################################################################
|
23 | /* Hauptprogramm */
|
24 | int main(void) |
25 | //###################################################################################
|
26 | {
|
27 | |
28 | char debtext [10]; |
29 | |
30 | |
31 | // RC Signal Init
|
32 | DDRD &= ~(1 << PD3); //PD3 auf Input |
33 | PORTD |= (1 <<PD3); //pullup auf PD3 |
34 | // Ende Init RC Signal
|
35 | |
36 | for(;;) // loop forever |
37 | {
|
38 | //DEBUG Output
|
39 | Pulsdauer=ReadChannel(); |
40 | itoa(Pulsdauer, debtext, 10); |
41 | puts("Pulsdauer Debug: "); |
42 | |
43 | puts(debtext); |
44 | puts("\r\n"); |
45 | |
46 | }
|
47 | |
48 | uint16_t ReadChannel (void) |
49 | {
|
50 | uint16_t i; |
51 | i=2000; //Wert Initialisieren um einen positiven Wert als Ausgabe zu erzeugen |
52 | while (!(PIND & (1<<PD3))){asm volatile ("nop");} |
53 | while (PIND & (1<<PD3)){asm volatile ("nop");} |
54 | while (!(PIND & (1<<PD3))){i--; _delay_us(10);} |
55 | return (i); |
56 | |
57 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.