Hallo, ich habe hier meine ISR, die ich zum empfangen von messwerten verwende, ich habe einen algorithmus eingebaut, um das "digitale Rauschen", mit dem meine Nachricht verseucht ist, herauszufiltern. Wenn die Filterung abgeschlossen ist sollen die Messwerte im EEPROM abgespeichert werden. Anbei ist mein derzeitiger Code ich hoffe ihr könnt mir helfen mfg int us_start_bed = 0; int us_mess_start = 0; int us_dp_zaehler = 0; int us_zaehler = 0; int us_endzaehler = 0; int us_mitlauf=0; int us_i = 0; int mw = 0; int us_messwert_counter_bit = 0; char receive_char_fsk; #if defined (_AVR_ATmega644P_) #if RCV_FSK ISR (USART_RX1) { #if USE_FSKP /* Die Messwerte müssen aus dem Rauschen herausgefiltert, dies wird durch mehrere If schleifen durchgeführt. Möglicherweise später durch eine gemeinsame Switch Anweisung,defines um die Int in bit umzuwandlen Übermittelte Nachricht ..........:wert1*wert2*wertn########### */ // usart_write_char(UDR1); us_mitlauf++; if(UDR1 == '.' && us_mitlauf <10) { us_zaehler++; us_mitlauf = 0; if(us_zaehler == 7) { us_zaehler = 0; us_start_bed = 1; //Startbedingung erfüllt DEBUG1("Start\n"); } } if(us_mess_start == 1) { if(UDR1 == '*'){ mw++; if(mw==2) { us_mess_start =0; } } else { rcf[us_messwert_counter_bit] = UDR1; us_messwert_counter_bit++; if(us_messwert_counter_bit == 2) { usart_write("%c%c:", rcf[0], rcf[1]); us_messwert_counter_bit = 0; us_mess_start = 0; } } if(UDR1 == '#') { us_endzaehler++; if(us_endzaehler == 5) { us_endzaehler = 0; us_mess_start = 0; us_start_bed = 0; DEBUG1("Ende\n"); usart_write("%c.%c.%c.%c\r\n", rcf[0], rcf[1], rcf[2], rcf[3]); /*nun müssen die erhaltenen Werte in dem EEPROm geschrieben werden for (unsigned char count = 0; count<4; count++) { eeprom_busy_wait (); eeprom_write_byte((unsigned char *)(WERT_EEPROM_STORE + count),rcf[count]); }*/ } } } if(us_start_bed == 1) { if(UDR1 == ':') { us_mess_start = 1; } } return; #endif }
Was ist jetzt deine Frage? Du darfst UDR1 nur einmal in der ISR lesen! Auszug Datenblatt Mega16 (ist bei dir aber sicher auch nicht anders <quote> A second Buffer Register has been added. The two Buffer Registers operate as a circular FIFO buffer. Therefore the UDR must only be read once for each incoming data! More important is the fact that the Error Flags (FE and DOR) and the 9th data bit (RXB8) are buffered with the data in the receive buffer. Therefore the status bits must always be read before the UDR Register is read. Otherwise the error status will be lost since the buffer state is lost. </quote> Das zurücksenden von Charactern in der Empfangs-ISR mag gerade noch angehen (wenn dort ein Ringbuffer sitzt, der die Zeichen zwischendurch aufnimmt, ist das auf jeden Fall ok) aber das Speichern im EEPROM geht gar nicht. Dauert einfach zu lange.
> Die Messwerte müssen aus dem Rauschen herausgefiltert, dies > wird durch mehrere If schleifen durchgeführt. Ein if ist keine Schleife!
1 | us_mitlauf++; |
2 | if(UDR1 == '.' && us_mitlauf <10) |
3 | |
4 | {
|
5 | us_zaehler++; |
6 | us_mitlauf = 0; |
7 | if(us_zaehler == 7) |
8 | {
|
9 | us_zaehler = 0; |
10 | us_start_bed = 1; //Startbedingung erfüllt |
11 | DEBUG1("Start\n"); |
12 | }
|
13 | }
|
Selten eine so komplizierte Art gesehen um 70 aufeinanderfolgende '.' abzuzählen. Und dann sind auch noch alle Variablen int, also 16 Bit. Und du fragst ernsthaft um Optimierungen an? Räum doch bitte erst mal den Code auf! Und zwar so, dass man auch ohne ständiges Hin und Herscrollen verfolgen kann, wie du dir die Absicherung gegen zufälliges Auslösen durch Leitungsrauschen vorstellst. Und wenn du schon dabei bist: optisch ansprechendes, konsistentes Einrücken ist kein Selbstzweck oder Schnickschnack.
Christoph K. schrieb: > ich zähle 7 Punkte..... > Das solltest du gleich mal als Indiz werten, dass dein Code nicht wirklich gut nachvollziehbar ist. > wie bekomme ich dann die werte ins EEPROM? Im main in der Hauptschleife. So wie man das üblicherweise macht. Die ISR wertet (im Rahmen ihrer zeitlichen Möglichkeiten) die auslösende Bedingung aus und hinterlässt der Hauptschleife ein Flag, dass Arbeit vorliegt.
Christoph K. schrieb: > ich zähle 7 Punkte..... > Wenn ich das richtig im Kopf dechiffriere, dann liegt die Startbedingung dann vor, wenn in 70 Zeichen 7 mal das Zeichen '.' war und die einzelnen '.' nicht weiter als 10 Zeichen voneinander entfernt sind. Was passiert eigentlich, wenn diese Bedinung nicht zutrifft? Nur mal angenommen us_mitlauf wird größer als 10. Dann dauert es ~65530 Zeichen, bis us_mitlauf überläuft und jemals wieder eine Chance hat <10 zu sein, damit die Triggerung erfolgen kann.
Wie kann es eigentlich sein, dass sich hier
> Übermittelte Nachricht ..........:wert1*wert2*wertn###########
zwischen den einzelnen Zeichen, irgendwelche Zeichen durch Rauschen
einschleichen? Sollte es nicht eher so sein, dass diese Zeichen
tatsächlich ohne Unterbrechung vom Sender daherkommen?
(Denn woher weißt du, dass sich nicht auch zwischen den Bytes für die
Werte ein paar Rauschbytes eingeschlichen haben und du daher etwas
völlig Falsches für die Werte nimmst)
Karl heinz Buchegger schrieb: > > Du darfst UDR1 nur einmal in der ISR lesen! > > Auszug Datenblatt Mega16 (ist bei dir aber sicher auch nicht anders > > <quote> > A second Buffer Register has been added. The two Buffer Registers > operate as a circular FIFO buffer. Therefore the UDR must only be > read once for each incoming data! Hallo, na da haben wir doch schon eine mögliche Quelle des "Rauschens". Also ich würde hier erstmal die normale Funktion, so wie in den Applikationsschriften oder im Datenblatt vorgesehen, sicherstellen und dann ermitteln, ob wirklich ein Rauschen vorliegt. Gruß, Michael
Michael Appelt schrieb:
> na da haben wir doch schon eine mögliche Quelle des "Rauschens".
Wenn ich das richtig in Erinnerung habe und den TO richtig zuordne, dann
beschäftigt er sich mit einer Datenübermittlung über Funk, wobei die
Funkstrecke nur dann 'steht' wenn der Sender sendet. In den Sendepausen
empfängt der Empfänger alles mögliche und gibt das auch aus.
Meiner Meinung nach sollte man da ansetzen und erst mal aus dem
Empfänger herauskitzeln, ob ein Signal vorliegt, welches stark genug
ist. Dann auf jeden Fall die Statusbits der UART auswerten und dann
würde ich nicht lange fackeln und jedes Zeichen einfach in eine
etntsprechend lange Queue schreiben. Einfach hinten drann, wobei die
ältesten Zeichen vorne raus fallen. Noch ein Check, ob in der Queue das
Muster
"..........:" {abwechselnd Byte und *} "###########"
Karl heinz Buchegger schrieb: > Wie kann es eigentlich sein, dass sich hier > >> Übermittelte Nachricht ..........:wert1*wert2*wertn########### > > zwischen den einzelnen Zeichen, irgendwelche Zeichen durch Rauschen > einschleichen? Sollte es nicht eher so sein, dass diese Zeichen > tatsächlich ohne Unterbrechung vom Sender daherkommen? > (Denn woher weißt du, dass sich nicht auch zwischen den Bytes für die > Werte ein paar Rauschbytes eingeschlichen haben und du daher etwas > völlig Falsches für die Werte nimmst) ja aber davor und danach schlecht sich rauschen ein, weil 1.)das funkmodul bei fehlendem eingangssignal ein schwankendes ausgangssignal ausgibt 2.)der avr dieses signal als eine zufällige anordnung von ASCI zeichen anzeigt die Punkte sind dazu da um sicherzustellen, dass jetzt die richtige nachricht folgt
Karl heinz Buchegger schrieb: > Meiner Meinung nach sollte man da ansetzen und erst mal aus dem > Empfänger herauskitzeln, ob ein Signal vorliegt, welches stark genug > ist. Dann auf jeden Fall die Statusbits der UART auswerten und dann > würde ich nicht lange fackeln und jedes Zeichen einfach in eine > etntsprechend lange Queue schreiben. Einfach hinten drann, wobei die > ältesten Zeichen vorne raus fallen. Noch ein Check, ob in der Queue das > Muster > > "..........:" {abwechselnd Byte und *} "###########" und wie macht man das jetzt praktisch?
Christoph K. schrieb: > Karl heinz Buchegger schrieb: >> Meiner Meinung nach sollte man da ansetzen und erst mal aus dem >> Empfänger herauskitzeln, ob ein Signal vorliegt, welches stark genug >> ist. Dann auf jeden Fall die Statusbits der UART auswerten und dann >> würde ich nicht lange fackeln und jedes Zeichen einfach in eine >> etntsprechend lange Queue schreiben. Einfach hinten drann, wobei die >> ältesten Zeichen vorne raus fallen. Noch ein Check, ob in der Queue das >> Muster >> >> "..........:" {abwechselnd Byte und *} "###########" > > und wie macht man das jetzt praktisch? Hast du immer die gleiche Anzahl an Datenbytes, bzw. kannst du das sicherstellen, dass das so ist (Dummy Bytes einfügen) (Dann vereinfacht sich das Mustersuchen)
Karl heinz Buchegger schrieb: > Hast du immer die gleiche Anzahl an Datenbytes, bzw. kannst du das > sicherstellen, dass das so ist (Dummy Bytes einfügen) > (Dann vereinfacht sich das Mustersuchen) ja ich habe immer Werte von 0 bis 40,
Christoph K. schrieb: > Karl heinz Buchegger schrieb: >> Hast du immer die gleiche Anzahl an Datenbytes, bzw. kannst du das >> sicherstellen, dass das so ist (Dummy Bytes einfügen) >> (Dann vereinfacht sich das Mustersuchen) > > ja ich habe immer Werte von 0 bis 40, Also 40 Bytes maximal. Du kommen also dahinter noch 11 mal #, macht 51 und davor noch 7 mal ., macht 58 und der :, macht 59 also unsigned char ReceiveBuffer[59] beim Empfang eines neuen Zeichens, werden die Zeichen 1 bis 58 um 1 Stelle nach vor gerückt, das neue Zeichen an die Position 58. Und dann fang ich von hinten an. Sind die Zeichen 58 bis 58-11 alle '#' Wenn nein, kann es schon mal keine gültige Message sein Dann weiter nach vorne gehen und das jeweils übernächste Byte betrachten, dass muss sein * '*' in dem Fall gehts weiter mit dem übernächsten Vorgänger * '.' die Präambel ist erreicht. Abtesten ob die 6 Zeichen davor ebenfalls '.' sind. Wenn ja: die ganze Nachricht ist gültig * irgendwas anderes: keine gültige Nachricht. Ist die ganze Nachricht gültig, kennt man dann auch gleich die Positionen, an denen die Nutzbytes stehen. Der ganze Abtest-Mechanismus erfolgt bei jedem Zeichen. Da man bei jedem Zeichen ein wenig Zeit hat, bis das nächste eintrudelt, denke ich sollte das schnell genug gehen. Stell es dir einfach so vor: Du hast einen Papierstreifen. Immer wenn ein Zeichen eintrudelt schreibst du es auf den Papierstreifen. Über dem Streifen liegt ein Fenster, welches dir genau die letzten 59 empfangenen Zeichen zeigt. Und dann schaust du dir sichtbaren Zeichen im Fenster an und entscheidest, ob das was du siehst, gültig ist. Du fängst dabei hinten (rechts im Fenster) an, mit der Kontrolle, weil deine Anzahl Nutzbytes nicht immer gleich lang ist. Alternativ könnte man auch eine Statemachine aufsetzen, die bei jedem einlangenden Zeichen dieses anhand des Zustands klassifiziert und gegebenenfalls den Zustandswechsel in einen anderen Zustand durchführt. Das geht sicherlich schneller, ist aber mit mehr Code verbunden.
wenn ich richtig verstanden habe, dann muss ich warten biss der buffer voll ist, dann mit einem Muster den Inhalt überprüfen und dann die Messwerte herausnehmen?
ReceiveBuffer[us_mitlauf] = UDR1; us_mitlauf++; if(ReceiveBuffer[us_mitlauf] = muster[us_mitlauf])richtig++; if((mitlauf=20)&&(richtig<7)mitlauf=0; hallo, ich habe jetzt diese ISR geschrieben, und wollte fragen, ob ich auf dem richtigen weg bin. Stimmen 7 Werte des Buffers mit dem Muster überein, so wird der Buffer vollgemacht und dieser dann verwendet
Du solltest erstmal ne Präambel senden, damit sich die UART synchronisieren kann, sonst kommt immer nur Müll raus. Und damit das Synchronisieren klappt muß die Praämbel aus Bytes bestehen, die nur eine 1-0 Flanke haben, also 0x00, 0x80, 0xC0, 0xE0, ... 0xFF. Sonst kann es passieren, daß die UART die falsche Flanke als Startbit erkennt. Peter
Mein Tip Programmiere die wesentlichen Teile erst mal auf dem PC aus. Dort hast du bessere Debugmöglichkeiten. Wenn du auf dem PC mit einem von dir vorgefertigtem Array soweit bist, dass deine Erkennung sauber funktioniert, ist es banal den Code dann ins AVR Programm zu übernehmen. if(ReceiveBuffer[us_mitlauf] = muster[us_mitlauf]) Ich denke nicht, dass du hier eine Zuweisung willst. -> Code auf dem PC vorbereiten, debuggen und erst dann übernehmen.
Karl heinz Buchegger schrieb:
> Ich denke nicht, dass du hier eine Zuweisung willst.
will ich auch nicht ;)
der verstand war nur schneller als die finger
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.