Hallo, Ich möchte die Werte dich erzeuge mit dem Poti speichern und auf dem Display darstellen. Mit diesem Programm habe kann ich die Werte erzeugen und mit dem Poti am Mikrocontroller kann ich die Werte ändern. int adcresult; ADMUX = channel; ADCSR = (ADCSR | 0b00000111); ADCSR = ADCSR & ~(1<<ADFR); ADCSR = ADCSR | (1<<ADEN); ADCSR = ADCSR | (1<<ADSC); while(ADCSR & (1<<ADSC)); adcresult = ADCL; adcresult = adcresult | (ADCH<<8); return(adcresult); Jetzt möchte ich die Werte die erzeugt werden zwischenspeichern in einem Array. So das ich später darauf zugreifen kann. Wie kann ich das am einfachsten machen? für Tipps oder Lösungen wäre ich sehr dankbar. Danke Lg
Hallo 1. Wieviele Werte willst Du speichern? 2. Wie oft soll gespeichert werden (zeitlich oder nach festgelegter Wertänderung)? Zum Speichern mit array - am sinnvollsten wäre wohl ein Ringpuffer (der älteste Wert wird überschrieben)...
Hallo danke für deine Antwort. 1.) Ich möchte 100 einzelne Werte Speichern. Beim erreichen diesen Wertes, sollen die ersten Werte wieder überspringen werden. 2.) nach festgelegter Wert Änderung. Also ich bekomme ja vom ADC konstant Werte, den zeitlichen Abstand weiß ich nicht. Der Ringpuffer hört sich sehr gut an, da der älteste Wert überschrieben Wird. Mir fällt jetzt aber keine Funktion ein, wo bei jeder Wertänderung ein Wert in den Array gespeichert wird. Vllt. kannst du mir mehr davon erzählen Danke
Stefan M. schrieb: > Mir fällt jetzt aber keine Funktion ein, wo bei jeder Wertänderung > ein Wert in den Array gespeichert wird. if (wert != alter_wert) speichere alter_wert = wert ; Stefan M. schrieb: > adcresult = ADCL; > adcresult = adcresult | (ADCH<<8); Warum nicht adcresult = ADC; oder gleich return (ADC); ganz ohne die Variable 'adcresult'.
Stefan M. schrieb: > wo bei jeder Wertänderung Dabei solltest du berücksichtigen, dass du dazu noch etwas Datenaufbereitung brauchst. Nur ein ein Vergleich "letzter Wert mit aktuellem Wert" ist blöd: das niederstwertige Bit kann immer togglen, außerdem musst du mit Rauschen und Störungen rechnen. Also brauchst du ein Filter und/oder einen Schwellwert.
Jetzt wo ihr es sagt, den alten Wert mit dem neuen Wert zu vergleichen ist doch nicht so ideal, da ich hier tatsächlich Rauschen haben und die Werte auch trotzdem speichern will, wenn sich der Wert nicht ändert. Die Werte kommen ja vom Adc Clock mit einer bestimmten Frequenz und wenn ich den Poti nicht drehe ändert sich der Wert auch nicht. Heißt das dann doch das ich die Werte zeitlich speichern muss oder wie läuft das genau ab?
Ich wette die nächste Frage wird sein, "Wie kann ich wert aus Ringpuffer auslesen?". Beschreibe mal dein Problem, anstatt deine Lösung zu beschreiben. Was willst du machen?
:
Bearbeitet durch User
Hallo Die Funktion eines Ringpuffers ist Dir klar, nehme ich an (ein Element zeigt auf das nächste..) Du musst also einen Ringpuffer mit 100 Elementen anlegen mittels einer Struktur:
1 | #define NUMMER 100
|
2 | |
3 | struct Element { |
4 | uint8_t zaehl; /* Nummer des Elements */ |
5 | int adc_wert; /* hier wird der ADC-Wert gespeichert*/ |
6 | struct Element *next; /* Pointer auf sich selbst...*/ |
7 | };
|
8 | |
9 | typedef struct Element element; |
10 | |
11 | /*dann den Puffer erzeugen mit:*/
|
12 | |
13 | /* - - - hier werden NUMMER Elemente des Ringpuffers erzeugt - - - */
|
14 | element *ring_erz(element *root) { |
15 | element *New; |
16 | uint8_t nummer; |
17 | uint8_t i; |
18 | |
19 | nummer = 0; |
20 | for(i = 0; i < NUMMER; i++) { |
21 | New = (element *)malloc(sizeof(element)*1); |
22 | nummer++; |
23 | New->zaehl = nummer; /* "0" => leer!! */ |
24 | if(root == NULL) { |
25 | New->next = New; /* zeigt auf sich selbst, wenn es noch kein Element gibt */ |
26 | root = New; |
27 | } else { |
28 | New->next = root->next; /* New->next zeigt dahin, wohin root->next zeigt */ |
29 | root->next = New; /* root-> next zeigt auf das neue Element */ |
30 | }
|
31 | }
|
32 | return(New); |
33 | }
|
in der main:
1 | element *rptr = NULL; |
2 | rptr = ring_erz(rptr); /* erzeugen des RingPuffers */ |
und dann den ADC Wert in die Array-Zelle schreiben und den "Schreibzeiger um 1 weiterzaehlen... mfg Heiner
>Die Funktion eines Ringpuffers ist Dir klar, nehme ich an (ein Element >zeigt auf das nächste..) Das erwartest du von jemand der auf ein Array nicht "zugreifen" kann? Ich glaub das geht schief.
Stefan M. schrieb: > Jetzt wo ihr es sagt, den alten Wert mit dem neuen Wert zu vergleichen > ist doch nicht so ideal, da ich hier tatsächlich Rauschen haben und die > Werte auch trotzdem speichern will, wenn sich der Wert nicht ändert. Einen hast du ja schon gespeichert, nur die Folgewerte, die (fast) gleich sind, sollen dann nicht gespeichert werden. Du kannst ja z.B. vier Messungen nacheinander machen, die Werte addieren, +2 zum Runden und durch 4 wieder teilen. Das ist schon mal ein einfaches Filter. Dann kann man in vielen µCs noch den ADC-Power-Down verwenden, um Eigenstörungen zu reduzieren. Man kann auch auf eine Änderung < epsilon abfragen und wenn wahr, das als 'gleich' ansehen. Das ergibt allerdings eine reduzierte Auflösung. Lass einfach ein wenig Phantasie walten und überlege, welche Werteänderungen tatsächlich relevant sind und welche durch Rauschen verursacht wurden ...
Egonwalter M. schrieb: > Die Funktion eines Ringpuffers ist Dir klar, Ich mache meine Ringpuffer immer wesentlich einfacher. Auf die Stelle des Schreibzeigers schreiben, increment Zeiger, bei Überlauf wieder auf Null setzen. Der Schreibzeiger ist einfach ein uint8_t (bei 100 Werten). Sind zwei, drei Zeilen Code.
HildeK schrieb: > Egonwalter M. schrieb: >> Die Funktion eines Ringpuffers ist Dir klar, > > Ich mache meine Ringpuffer immer wesentlich einfacher. > Auf die Stelle des Schreibzeigers schreiben, increment Zeiger, bei > Überlauf wieder auf Null setzen. Der Schreibzeiger ist einfach ein > uint8_t (bei 100 Werten). > Sind zwei, drei Zeilen Code. Hmmm.... Ja und? Mein Schreibzeiger zahl ist auch ein uint8_t ... Zeig' doch mal Deinen Code ;-)) edit: Eigentlich benötigt man die Variable "zahl" in der Struktur nicht (verkettete Liste, die einen Ring bildet; der Strukturpointer next zeigt auf das nächste Element)
:
Bearbeitet durch User
Hallo Stefan M Am einfachsten dürfte es dennoch sein, wenn Du einen INT-Array mit 100 Werten definierst, z.B int adc_val[100] und diesen dann mit den ADC Werten füllst - wenn der ADC Wert eine von Dir definierte Grenze überschritten hat, speicherst Du den Wert im Array: adc_val[0] = gemessener ADC Wert, dann zählst Du den Array-Index um 1 weiter usw...; wenn Du beim max. Array-Index (99!!!) bist, fängst Du wieder bei 0 an. Ganz einfach; ebenso geht das Auslesen Achja wenn Du den ADC Wert speicherst - das muss eine atomare Operation sein, kann sonst durch Interrupt verfälscht werden ...
:
Bearbeitet durch User
Egonwalter M. schrieb: > Zeig' doch mal Deinen Code ;-))
1 | temp[i] = adc_value; // Wert in Ringpuffer merken |
2 | i = (i+1)%BUF_LEN; |
BUF_LEN ist die Dimension vom Array 'temp'.
HildeK schrieb: > Egonwalter M. schrieb: >> Zeig' doch mal Deinen Code ;-)) >
1 | > temp[i] = adc_value; // Wert in Ringpuffer merken |
2 | > i = (i+1)%BUF_LEN; |
3 | >
|
> BUF_LEN ist die Dimension vom Array 'temp'.
1 | if((++i) == BUF_LEN)i = 0; |
würde genauso gehen - viele Wege führen nach Rom
Egonwalter M. schrieb: > würde genauso gehen - viele Wege führen nach Rom Ja, und je nach Compiler gibt das sogar effizienter compilierten Code. Der Modulooperator muss nämlich mehr können und auch noch was anderes und legt den Code dafür an, auch wenn er in dem Kontext nicht gebraucht wird. Aber er ist sehr anschaulich. Selbst das hier ist schneller als '%':
1 | // am verständlichsten (und das wären dann mit der Ringpufferzuweisung drei Zeile:
|
2 | i++; |
3 | if (i==BUFF_LEN) i=0; |
4 | |
5 | // oder auch:
|
6 | i++; |
7 | i = (i == BUFF_LEN ) ? 0 : i; |
Ja, viele Wege führen nach Rom. Und auch aus Verständnisgründen habe ich die Increments immer gerne extra. Ein einigermaßen guter Compiler macht das selbe daraus. Nur deiner oben schien mir etwas ausufernd. Vielleicht habe ich auch einfach andere beabsichtigte Funktionen in deinem Code nicht verstanden 😀
HildeK schrieb: > Nur deiner oben schien mir etwas ausufernd. Vielleicht habe ich auch > einfach andere beabsichtigte Funktionen in deinem Code nicht verstanden > 😀 Ja, der oben aufgeführte Code mit der Struktur und dem Ringpuffer anlegen ist für die Zwecke des TO "over the top" und für den TO eh' nicht zielführend (besser Array anlegen usw).
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.