Hallo Leute ich habe mir eine Schaltung mit Funkmodulen (Sender /Empfänger) aufgebaut. Der eine Controller (ATTINY2313) sendet lustig vor sich hin. Mein Empfänger der ATMEGA 128 Empfängt auch... Jetzt das Problem: Wenn der ATTINY nix sendet habe ich störsignale welches mir beim Empfangen der Daten probleme macht.. Habt ihr ne Idee für einen Filter oder soo. Oder wie macht ihr das mit dem Empfangen. Ich mache das im Moment über den IPC PIN messe zeit und Pegel und danach wird das Manchester wieder decodiert. ??? Kann mir einer Helfen ?
Tja, Andreas, Du: "Wenn der ATTINY nix sendet habe ich störsignale welches mir beim Empfangen der Daten probleme macht" Willkommen in der Welt der drahtlosen Kommunikation. Im Leerlauf hast Du im Wesentlichen folgende Störquellen: 1. Das Rauschen des Empfängers. 2. Einstrahlungen von anderen Nutzern des Frequenzbandes und von Störquellen (z.B. Oberwellen der Taktfrequenz Deines Atmega128). Die üblichen Gegenmaßnahmen, die mit einem simplen Funkmodul machbar sein könnten: 1. Frequenzselektiv - je schmalbandiger die Antenne und Vorfilter, desto weniger Störsignale. 2. Pegelselektiv - der Empfänger tastet erst ab einem minimalen Empfangspegel auf. Hilft gegen Rauschen und schwache Störer. 3. Winkelselektiv - Richtantenne. Je schmaler das Diagramm und auf den Sender ausgerichtet, desto weniger Störsignale. (Die Polarisation vernachlässige ich.) 4. Zeitselektiv: Der Sender sendet zu vereinbarten Zeitpunkten. Er sendet beispielsweise alle 10 Sekunden entweder, daß er eigentlich nicht zu senden hat, oder daß nun eine Nachricht folgt. Vorteil: Der Empfänger braucht nur den vereinbarten Zeitpunkten auf Empfang zu gehen, hat nur dann Störungen abzuarbeiten, und kann sich in Sendepausen wichtigeren Aufgaben zuwenden. Hallo Freunde, was gibt's noch? Ciao Wolfgang Horn
Wenn du die Zeit misst, filterst du dann schon zu kleine und große Impulsbreiten raus? Dann hast du schon mal die ständigen Nadelimpulse draußen. Desweiteren am Anfang ein Präambel senden, also z.B. 7 Byte "10101010", damit sich der Empfänger "einschwingt" und dann ein Startbyte, z.B. "10101011". Danach kannst du ja dann suchen (Stichwort: Ringspeicher, FiFo), zudem noch prüfen, ob vorher die Präambelbytes gesendet wurden und dann erst die folgenden Daten einlesen. Somit läßt du nur deinen Datenstrom durch. Empfehlenswert wäre noch ein CRC-Block zur Fehlererkennung oder sogar Hamming-Code für Fehlerkorrektur.
Damit kann ich nicht so richtig was anfangen : 1. Frequenzselektiv - je schmalbandiger die Antenne und Vorfilter, desto weniger Störsignale. 2. Pegelselektiv - der Empfänger tastet erst ab einem minimalen Empfangspegel auf. Hilft gegen Rauschen und schwache Störer. Ringspeicher hört sich gut an...den pegel bei Flankenwechsel reinshifen und gucken wann mein Startwert drinsteht ? ist das so richtig ?
Ich hab' als Präambel 3ms lang 0x55 (0b10101010) gesendet, danach 2x 0xFF, während dem 2. 0xFF lässt sich dann ganz easy der USART zuschalten (Startbit ist low). Nach empfangenem Datenpaket (mit CRC16) schalte ich den USART wieder ab. Funktioniert sehr zuverlässig.
Genau, Interrupt bei Flankenwechsel, Zeitdiffernez prüfen und dann Pegel abfragen, somit hast du gleich den Manchester decodiert (da ja fallende oder steigende Flanke detektiert werden muss) und Bit weiterschieben. Warum is der Manchester dann ein Problem?
Hallo Sonic kannst du mir mal deinen Code Zeigen ???? Irgendwie versteh ich da nicht wie du den manchester drin hast ?
Welchen meinst du? die CRC-Berechnung oder die Impulsauswertung? Häng' dir mal die Impulsauswertung im INT0 dran, bezieht sich auf 38400 Baud, Präambel: 3ms 0x55 und 2x 0xFF. /*********************************************************************** ****************/ /*** Externer Interrupt 0 (falling edge) ***********************************************/ SIGNAL (SIG_INTERRUPT0) // carrier-detect { GICR &= ~(1<<INT0); // INT0 disabled GIFR |= (1<<INT0); // INT0-Flag löschen rx_cnt = 0; // Empfangsbytezähler löschen _delay_ms(2); // 2ms Pause Data = UDR; // Flag löschen unsigned char c = 0; Rep_Strt: SREG |= (1<<SREG_I); // Globalen Interrupt freigeben while (!(PIND &(1<<RX_PIN))) TCNT0 = 0; while ((PIND &(1<<RX_PIN))) // auf 0xFF warten (234µs 'High') Temp = TCNT0; if ((Temp >= 210)&&(Temp <=222)) { _delay_us(50); // 50µs Pause (bis Mitte 2. 0xFF-Byte) UCSRB |= (1<<RXEN); // RX freigeben return; } else { if (c >= 60) { PORTD &= ~(1<<RX_EN)&~(1<<TXD); // RX enabled GIFR |= (1<<INT0); // INT0-Flag löschen GICR |= (1<<INT0); // INT0 enabled return; } c++; goto Rep_Strt; // weiter auf Startbyte warten } }
bin mal gerade was am zusammenbasteln (proggen) meist du das könnt efunktionieren ??? schau mal ISR(SIG_INPUT_CAPTURE1) { TCNT1= 0x00; if( ICR1 < TIMEOUT) { level = ((PIND & 0x10)>>4); // 0x10 -> PIN D4 if(ICR1 < TWO_VALUES)// EIN BIT { manchester_bits = manchester_bits >> 1; // 1x das lsb rausschiften manchester_bits.bit_16 = level; // neues msb reinkopieren } else // ZWEI BITS { manchester_bits = manchester_bits >> 1; // 2x das lsb rausschiften manchester_bits.bit_16 = level; // neues msb reinkopieren manchester_bits = manchester_bits >> 1; manchester_bits.bit_16 = level; } } else // vom Timeout { //Abbrechen bitcount = 0; } }
Der Input-Capture misst die Periodendauer, also entweder den Abstand der high- oder lowflanken, je nach Einstellung. Müsste also funktionieren. Nur das Ende der Rechteckspannung zu erkenn stelle ich mir schwieriger vor. In meinem Code sind auch unfeine Geschichten drin (Warteschleife, Goto), also nicht so kritisch sein! Ich habe am Transceivermodul einen Carrier-detect-Ausgang, der wird bei erkanntem Trägersignal low (bei mir INT0), deshalb ist das Ganze etwas einfacher auszuwerten.
ich invertiere jetzt den Flankentrigger d.h. ich bekomme jeden Pinchange einen INT
Das geht aber nicht mit dem Input-Capture, da musst du einen 'normalen' Interrupt (1 oder 2) nehmen. Miss doch einfach nur die Impulse und zähle sie (bei korrekter Breite) mit INT0 oder INT1 'any edge' getriggert, nach dem letzten Impuls (Ende Präambel) weißt du dass Daten folgen. Ist glaub' ich weniger Aufwand.
das habe ich aber schon mal ausprobiert... mit einem Testsignal hat das toggeln aber geklappt.... hier mein Code muss ich morgen mal testen : ISR(SIG_INPUT_CAPTURE1) { TCNT1= 0x00; // Timerregister zurücksetzen TCCR1B ^= _BV(ICES1); // Triggerflanke invertieren if( ICR1 < TIMEOUT) { // Ringbuffer start level = ((PIND & 0x10)>>4); // 0x10 -> PIN D4 pegel einlesen if(ICR1 < TWO_VALUES)// EIN BIT { bits.bitfield = bits.bitfield >> 1; // lsb rausschiften bits.bit_16 = level; // neues msb reinkopieren if(raster_aktiv) // bitcounter erst hochzählen wenn das protokoll mit der Startkennung "eingerastet" ist bitcount ++; } else // ZWEI BITS { bits.bitfield = bits.bitfield >> 1; // 2x das lsb rausschiften bits.bit_16 = level; // neues msb reinkopieren if(raster_aktiv) // bitcounter erst hochzählen wenn das Protokoll mit der Startkennung "eingerastet" ist bitcount ++; bits.bitfield = bits.bitfield >> 1; bits.bit_16 = level; if(raster_aktiv) bitcount ++; } if(bits.bitfield == START ) // aktiviere Raster { raster_aktiv = 1; } // Ringbuffer stop // Manchester decodieren d.h. jedes 2te Bit in ein Byte zusammenführen if( raster_aktiv ) { if(bitcount >= 16) { byte = ((bits.bit_1<<1)|(bits.bit_3<<2)|(bits.bit_5<<3)|(bits.bit_7<<4)|(bits.b it_9<<5)|(bits.bit_11<<6)|(bits.bit_13<<7)|(bits.bit_15<<8)); bitcount = 0; } } if(bits.bitfield == ENDE ) // deaktiviere Raster { raster_aktiv = 0; bitcount = 0 ; flag_send_data = 1; TCCR1B &= ~(1<<ICES1); //auf fallende Flanke init. } } else // timeout { //Abbrechen bitcount = 0; raster_aktiv = 0; TCCR1B &= ~(1<<ICES1); //auf fallende Flanke init. } }
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.