Hallo! ich habe vor, 30 int werte zu speichern. den neuesten Wert speichere ich mir an stelle 0 in einem array. die anderen schiebe ich durch. Die Stellen [0] und [1] sind od, leider erhalte ich immer die gleichen Werte für die anderen Stellen. meine Befüllung: for(int i = 29; i >= 1 ;i--) { fifo_buffer[i] = fifo_buffer[i-1]; } fifo_buffer[0] = act_value;
Im geposteten Minimalauschnnit ist nichts falsch (ausser das du deinem AVR unnötig Arbeit machst, indem du i als int definierst, ein uint8_t hätte es auch getan) Das Problem liegt wieder mal in den nicht geposteten Codeteilen.
> die anderen schiebe ich durch. Das ist der falsche Ansatz für einen Fifo, weil die Verwaltung unglaublich viel Rechenleistung verbraucht. In einem FIFO wandert nicht der Inhalt, sondern nur die Schreib- und Lese-Zeiger: http://www.lothar-miller.de/s9y/categories/51-Fifo
Die anzahl der Werte soll evlt. ncoh erweitert werden auf eine Zahl, für die ich auf jeden fall einen int, evtl. einen unsigned int benötige. Werde ich alles zur einfacheren Bedienung Definen... hier mal eine Datei im Anhang, an der man den Timerinterrupt und die aufgerufene fifo_handler funktion sieht.
oliver schrieb: > Die anzahl der Werte soll evlt. ncoh erweitert werden auf eine Zahl, für > die ich auf jeden fall einen int, evtl. einen unsigned int benötige. OK. Gerade dann solltest du den FiFo auf jeden Fall auf einen Ringbuffer umstellen. void fill_fifo( int value_dB, int *fifo_buffer) { for(int i = 29; i >= 1 ;i--) { fifo_buffer[i] = fifo_buffer[i-1]; _delay_ms(50); } 30 mal 50 Millisekunden, macht 1500 Millisekunden. Und das bei einer ISR die alle 1000 Millisekunden aufgerufen werden soll. Das kann nicht gut gehen. Aber abgesehen davon: Du machst viel zu viel in deiner ISR! Und dann noch dazu alles elends langsame Dinge! So wirst du das Timing in deinem Programm nie unter Kontrolle kriegen Aber zurück zum Problem. Woher weißt du, dass nur die ersten beiden Werte im FiFo stimmen? Ich sehe nirgends etwas, was dir diesen Umstand verraten könnte.
dieser Umstand wird gesehen in meiner Ausgabe, die ich in meiner fill_fifo funktion mache. Dort gebe ich das array komplett aus. Die zeitliche Verzögerung war nur eine Idee. Ich habe es sogar mit einer Puffervariablen versucht. den wert in einem einzelnen int gespeichert, dann an eine andere stelle wieder eingetragen. Ich weiß nicht, wo mein fehler ist...
oliver schrieb: > dieser Umstand wird gesehen in meiner Ausgabe, die ich in meiner > fill_fifo funktion mache. Hmm. Und wieso kann ich dann selbiges nicht auch sehen, wenn ich mir deine Funktion anschaue und analysiere? > Dort gebe ich das array komplett aus. Wo? Wie? Mit welchen Formatierungen? Kann es sein, dass in der Ausgabe ein Fehler war? Frageb über Fragen. > Die zeitliche Verzögerung war nur eine Idee. :-) War mir schon klar. Aber Tatsache ist, dass du wirklich viel zu viel in deiner ISR machst. Und dann auch noch auf die umständlichst mögliche Art und Weise. Was du da machst ist Beschäftigungstherapie für deinen µC. Ach ja. Eines wollte ich noch sagen. Mit dem langen String bei der Ausgabe kommst du bedenklich nahe an die Grenze von 32 Charactern für s ran. Nur mal so als Zwischeneinwand. > Ich weiß nicht, wo mein fehler ist... Du musst vor allen Dingen aufhören uns immer nur winzige Codeausschnitte zu zeigen. Auch wenn hier keiner wirklich glücklich damit ist, es hilft nichts: Der komplette Code muss her. So wie er ist. So wie du ihn laufen lässt, damit du den Fehler siehst. Alles andere ist: sich selbst und uns anlügen. Es ist sinnlos, wenn wir hier Fehler in Code suchen, der so nie läuft, oder wenn wir Fehler suchen, die durch die Interaktion des Codes mit anderen Codeteilen entstehen. So ist das nun mal bei globalen Variablen: Auch Codeteile, die scheinbar nichts damit zu tun haben, können über die globalen Variablen interagieren. Und sei es nur, weil dort irgendwo ein Array überlaufen wird.
Karl heinz Buchegger schrieb: > Ach ja. > Eines wollte ich noch sagen. > Mit dem langen String bei der Ausgabe kommst du bedenklich nahe an die > Grenze von 32 Charactern für s ran. > Nur mal so als Zwischeneinwand. Bei einem Blick auf dein zwischenzeitlich geposteten Screenshot würde ich sogar sagen: Du bist drüber. Weit drüber. Und da das fifo_buffer Array ein daran benachbartes Array ist ....
Karl heinz Buchegger schrieb: > Hmm. > Und wieso kann ich dann selbiges nicht auch sehen, wenn ich mir deine > Funktion anschaue und analysiere? Das hier nehme ich übrigens zurück. Hab die Stelle mitlerweile gefunden
besten Dank für eure Stellungnahmen. im Prinzip habe ich nur vor, in regelmaßigem(also timerinterruptgesteuertem) Intvervall den ADC eine Messung machen zu lassen. Dessen Ergebnis möchte ich in einem Array speichern. evlt werden es 300 sekunden mit 300 Werten. Also jede sekunde eine Messung. Wenn ich im Interrupt den ganzen Code nicht ausführen darf, kann ich dann den Code in mein main schreiben, wo ich in meiner for(;;) ein vom Interrupt gesetztes flag abfrage und darauf hin funktionen wie read_adc, fill_fifo usw ausführe? Rechenintensität sollte doch so nicht abnehmen, macht nur die ISR selbst kleiner und beendet sich schneller. Dann wird der code zwar außerhalb der ISR ausgef. jedoch ist die rechenzeit die gleiche !?! Danke für weitere Ratschläge!
> jedoch ist die rechenzeit die gleiche !?!
Klar, aber mal angenommen, du hast jetzt noch einen RS232-Empfang am
Laufen. Dann könnte bei der Verwaltung des Puffers in der ISR einfach
ein RS232-Interrupt verschlampt werden. Deshalb Interrupts kurz und
knackig.
Hallo So könntest du deinen Buffer machen, spart Zeit: #define BUFFER_SIZE 30 #define BUFFER_SUCCESS 0x00 #define BUFFER_OVERFLOW 0x01 #define BUFFER_EMPTY 0x02 int buffer[BUFFER_SIZE]; int bufferDataPoitner=0; unsigned char fillBuffer(int value) { if(bufferDataPointer>=BUFFER_SIZE-1) { return BUFFER_OVERFLOW; } buffer[bufferDataPointer]=newValue; bufferDataPointer++; return BUFFER_SUCCESS; } unsigned char getBufferVal(int *value) { if(bufferDataPointer<0) { return BUFFER_EMPTY; } *value=buffer[bufferDataPointer]; bufferDataPointer--; return BUFFER_SUCCESS; } lg
oliver schrieb: > Danke für weitere Ratschläge! sieh dir mal folgende Version an (Warnung: ungetesteter Code, direkt im Forum eingetippt)
1 | #define NR_VALUES 30
|
2 | |
3 | uint32_t avgSum; |
4 | uint16_t adcBuffer[ NR_VALUES ]; |
5 | uint16_t actAdcNr; |
6 | float avg; |
7 | |
8 | void fillBuffer( uint16_t nextVal ) |
9 | {
|
10 | adcActNr++; |
11 | if( adcActNr == NR_VALUES ) |
12 | adcActNr = 0; |
13 | |
14 | avgSum -= adcBuffer[ actAdcNr ]; |
15 | adcBuffer[ actAdcNr ] = nextVal; |
16 | avgSum += nextVal; |
17 | |
18 | avg = avgSum / (double)NR_VALUES; |
19 | |
20 | #ifdef CHECK_VALUES
|
21 | // zu Kontrollzwecken
|
22 | over_threshold = 0; |
23 | for( uint16_t = 0; i < NR_VALUES; ++i ) |
24 | {
|
25 | uint16_t j = i + actAdcNr; |
26 | if( j >= NR_VALUES ) |
27 | j -= NR_VALUES; |
28 | |
29 | if( adcBuffer[j] > THRESHOLD_VALUE ) |
30 | over_threshold++; |
31 | sprintf( s, "%02d: buffer[%02d]: %3d\r\n", i, j, adcBuffer[j] ); |
32 | uputs( s ); |
33 | }
|
34 | uputs( "\r\n" ); |
35 | sprintf( s, "avg: %f\r\n" , avg ); |
36 | uputs( s ); |
37 | sprintf( s, "over_threshold: %d\r\n", over_threshold ); |
38 | uputs( s ); |
39 | #endif
|
40 | }
|
Die Messwerte werden ganz einfach reihum im Array abgelegt. Dadurch, dass ich weiß, wo der letzte Wert abgelegt wurde (actAdcNr), weiß ich klarerweise auch, welches der älteste Wert im Buffer ist, er muss an der nächsten Stelle stehen. Also keine Angst, wenn das logisch 0-te Element nicht auch am Index 0 gespeichert ist. Das ist kein allzugrosses Problem, wie man in der Ausgabeschleife sieht. Schau dir auch an, wie ich die ganze Summiererei für die Mittelwertberechnung durch Einführen einer weiteren Variablen vereinfacht habe. Ich hebe mir einfach die Summe der Werte auf. Kommt ein neuer dazu, dann wird der älteste aus der Summe rausgerechnet, dafür kommt dann der neue dazu. Und schon habe ich wieder die aktuelle Summe, ohne alle Messwerte aufsummieren zu müssen.
> Ich hebe mir einfach die Summe der Werte auf. Kommt ein neuer dazu, > dann wird der älteste aus der Summe rausgerechnet, dafür kommt > dann der neue dazu. Für eine einfache Mittelwertbildung wäre mir schon der Speicher für die letzten 300 Elemente zu schade. Da würde ich einfach ein RC-Glied nachbilden: http://www.lothar-miller.de/s9y/categories/21-Filter
Gibts ne Gegenüberstellung der Rechnezeiten bei dem System, wo ich das Array einzeln weiterschiebe und dem Buffer von euch? Mich würde die Laufzeit interessieren, bei nem buffer von sagen wir 300 Werten mit Durchschnittswertbildung. Bin auf Antwort gespannt.
oliver schrieb: > Gibts ne Gegenüberstellung der Rechnezeiten bei dem System, wo ich das > Array einzeln weiterschiebe und dem Buffer von euch? > > Mich würde die Laufzeit interessieren, bei nem buffer von sagen wir 300 > Werten mit Durchschnittswertbildung. > > Bin auf Antwort gespannt. Schreib ein Testprogramm mit der einen Systematik. Lade es in den Simulator und lass dir die Taktzyklen für einen von dir gewählten Testfall ausgeben. Dann dasselbe noch einmal für die andere Systematik. Dann weißt du es genau.
meinst du den Simulator von AVRStudio? Den kenne ich bisher noch nicht, sollte ich mir aber mal ansehen. Bisher habe ich geflasht, weil den MK2 kann man bequem stecken lassen auf dem entwicklungsboard.
oliver schrieb: > meinst du den Simulator von AVRStudio? > Den kenne ich bisher noch nicht, sollte ich mir aber mal ansehen. Solltest du. Der hat einen wunderbaren Zyklencounter eingebaut, bei dem er dir genau sagt, wieviele Taktzyklen von einem Breakpoint zum nächsten vergangen sind.
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.