Hi, vielleicht kann mir jemand weiterhelfen. habe schon etliche Beiträge zu diesem Thema gelesen, aber keiner hat mir so richtig Antwort auf meine Frage gegeben. Außerdem versuche ich mein nachgelesenes Wissen für andere nochmal kompakt zussammenzufassen. Ich habe einen einen ADC der mir ratiometrisch den Widerstand eines Platin 1000 widerstandes berechnet. Der ADC hat eine Auflösung von 15Bit, sprich sein maximalwert ist 32768. Wenn ich einen 2kOhm Widerstand als Refernz dranhänge folgt daraus, dass er bei 0°C(PT1000) als ADC wert 32768/2 = 16384 hat. Bei 100°C liefert er dann 1385,06ohm/2000ohm * 32768 = 22693. Das ist auch der Messbereich der für mich interessant ist. Jetzt habe ich also 22963-16384 = 6309 Werte die meinen Bereich von 0 bis 100°C widerspiegeln. So wie es verstanden habe, gibt es jetzt 3 Varianten das ganze zu realisieren. 1. LookUp Table Variante 1: Man schreibt in eine LUT für alle 6309 Werte jeweils, welcher Temperatur sie entsprechen. D.h 100C° = LUT[6309] bzw LUT[ADCwert- 16384] Das ist sehr schnell verbraucht aber 6309 * 2Byte. Also circa 12kb Flash Wenn man z.B. 100,05°C also 10005 speichert. Die Auflösung soll 0,05°C betragen. 2. LookUp Table Variante 2: Man macht die LUT anders herum. D.h ADCWert = LUT[56,05°C]. Jetzt macht man eine binäre Suche guckt welcher Wert des Wandlers am nächsten zu einer ADC Stiufe ist, die über die LUT erreichbar ist. Vorteil ist, dass jeder TempWert einmal abgebildet ist, aber die binäre Suche länger dauert und dann muss man die Adresse der LUT noch in einen Temeratur umrechnen. 3. Einfach linearisieren oder Van Dusysen Formel benutzen. Bei der Linearisierung muss dann folgendes Berechnet werden Temp = m*ADCWert- b; b und m sind mit zwei Werten einfach zu bestimmen. Allerdings schrevke ich da von der Floating Point Multiplikation doch schon sehr zurück. Was meint ihr dazu? Das Problem ist das halt parrallel noch ein Webserver betrieben werden soll und ein PI Regler und ich Angst habe, dass gerade die 3. Variante sehr viel Rechenleistung verbraucht. Wenn man die erste Variante benutzt, muss ja zur Anzeige der Int Wert noch in einen Ascii Wert umgerechnet werden. Braucht sowas viel Zeit? Oder sollte man lieber direkt als Ascii speichern? Das benötigt dann aber 4 Bytes pro ADC Stufe... Vielen Dank für eure Hilfe...
Florian_unbekannto schrieb: > Was meint ihr dazu? Das Problem ist das halt parrallel noch ein > Webserver betrieben werden soll und ein PI Regler und ich Angst habe, > dass gerade die 3. Variante sehr viel Rechenleistung verbraucht. > Wenn man die erste Variante benutzt, muss ja zur Anzeige der Int Wert > noch in einen Ascii Wert umgerechnet werden. Braucht sowas viel Zeit? Nein Generell denke ich, dass du zuviel Schiss vor Berechnungen hast. So ein µC ist zwar kein Desktop-System mit ein paar GigaHerz aber ein paar 1000 mal pro Sekunde kann der schon durch die Berechnung durchhacheln. Zumal ja Temperaturmessungen im Normalfall nicht wirklich zeitkritisch sind und sich Temperaturen eigentlich nicht besonders schnell ändern. D.h. zum Beispiel, dass wenn du vom ADC denselben Wert kriegst wie bei der Messung zuvor, dann kannst du dem µC die komplette Berechnung sparen, weil du weißt das da nichts anderes als zuvor rauskommen wird. PS: 0.05° was misst du und wie gut ist der Klimaschrank, in dem der Sensor sitzt? 0.05°C sind praktisch nie sinnvoll. Wenn da jemand in 3 Meter Entfernung am Sensor vorbeigeht, ändert sich die Temperatur durch den Luftzug schon um mehr.
Üblich wäre lineare Interpolation (also 3. erster Fall) oder lineare Interpolation durch mehr Stützwerte, sagen wir 10, was nicht weniger aufwändig als 3. ist. Bei hohen Genauigkeitsanforderungen auch Van Dusen Formel, dann muss man eben mit der Rechenzeit leben, Temperaturen ändern sich ja eher langsam, man hat also Zeit, die muss man nur verteilen.
Ok, erstmal herzlichen Dank für die Antworten. @Karl Heinz. Der Sensor liegt an einem Rohr. Das Sytem hat also eine recht hohe Wärmekapazität. Wenn das zu fein ist gehen auch 0,1C. Das wollte ich einfach mal ausprobieren...Ist das erste mal, dass ich sowas mache. Die Angst vor der Rechenzeit habe ich, da ich gelesen habe, dass mit so einem Webserver( bzw muss der eigentlich erstmal nur ein Socket bereitstellen) steht noch nicht fest, der XMEGA schon sehr ausgelastet ist. Hab mal einen Regler gebaut, der lief allerdings auch schneeler durch als 1/sek, da hat diese floating Rechnerrei das ganze Dingen lahmgelegt. Die LUT haltet ihr nicht für gut? Ist ein XMEGA 128. Also genug Speicher hat der allemal... Speicherung dann direkt in ASCII oder also double?
Florian_unbekannto schrieb: > da hat diese floating Rechnerrei das ganze Dingen > lahmgelegt. die Frage ist wozu man floating braucht? Man kann in in 1/10 Grad rechnen und int verwenden.
das wäre cool! kannst du mir kurz erklären wie du das meinst anhand meines Beispiels von onben?
Ich bau Temperatur Regler mit einem Mega32, rechne mit Float fuer das Benutzerinterface, mit integern fuer den Regelalgorithmus, update 3 mal pro Sekunde und kommuniziere noch nebenbei. Ich rechne mit 0.01 Kelvin Aufloesung in Integern. Das waeren dann +-320 Grad Bereich fuer einen 16bit integer. Ich rechne den Algorithmus aber mit Longint, 32bit. Der Regler sollte mindestens die 10fache Aufloesung wie spezifiziert rechnen. Und dann ist noch Einiges an Luft
Florian_unbekannto schrieb: > Die LUT haltet ihr nicht für gut? Ist ein XMEGA 128. Warum nicht? Es muss ja nicht für jeden ADC-Wert ein Eintrag in der LUT vorhanden sein, sondern bspw. nur jeder zweite oder vierte Wert. Die Zwischenwerte lassen sich dann mit Additionen und Shifts berechnen.
Florian_unbekannto schrieb: > Ich habe einen einen ADC der mir ratiometrisch den Widerstand eines > Platin 1000 widerstandes berechnet. Huch?! Seit wann berechnet ein ADC irgendwas? > Jetzt habe ich also 22963-16384 = 6309 Werte die meinen Bereich von 0 > bis 100°C widerspiegeln. > 1. LookUp Table Variante 1: Die schnellste Variante, aber platzraubend. > 2. LookUp Table Variante 2: Reiner Blödsinn. > 3. Einfach linearisieren oder Van Dusysen Formel benutzen. > Temp = m*ADCWert- b; b und m sind mit zwei Werten einfach zu bestimmen. > Allerdings schrevke ich da von der Floating Point Multiplikation doch > schon sehr zurück. Zu recht. Sowas rechnet man natürlich als Festkomma. Im konkreten Fall paßt das sehr gut, weil m irgendwas bei 1,x sein muß und 7 Nachkommabits gebraucht werden, um nix von der Genauigkeit zu verlieren, m paßt also ideal in ein Byte rein, ein Bit vorm'm Komma, 7 dahinter. Der Meßwert ist in zwei Bytes. Du machst also eine 8x16Bit unsigned integer-Multiplikation, shiftest das 3-Byte-Ergebnis ein Bit nach links und wirfst das unterste Byte dann wech. In den oberen zwei Byte steht dein Ergebnis. Da brauchst du bloß noch b aufzuaddieren. Manchmal ist es auch sinnvoller, die den konstanten Teil schon vor der Multiplikation zu behandeln, aber im konkreten Fall ist's egal. Das ist die platzsparendste Variante und bei genauerer Betrachtung des Gesamtkontextes ist sie nicht mal viel langsamer als die mit der LUT. Jedenfalls auf'm AVR und in Assembler wäre das der Fall.
also bei mir kommt für m = 0.015199878... raus. mach ich irgendwas falsch? Weil du meinst mitr 1,x??
habe mich jetzt mal hieran orientiert: http://www.mikrocontroller.net/articles/Festkommaarithmetik Demnach müsst ich meine (ADC werte -16384)*1585 rechnen. Dann habe ich ein gutes Ergebnis. Muss nur noch die restlichen 4 Stellen verwerfen. Das sollte jedoch machbar sein. Wäre das okay? Oder besser Teilen durch 10000? Wie lange dauert denn so eine 16*16Bit operation?
Hi, so kleines update... habe mal gerade auf meinem avr simulator in studio 6 32bit*32bit = 32bit ausgeführt. Das soll nur 12 Takte benötigen und ist damit viermal schneller als mit mehreren Bitshifts und dann aufaddieren... Kann das sein? So schnell kann das doch garnicht sein oder?
Ich glaube, die Anzahl der Takte hängt von den Werten ab, die da multipliziert werden. Das ist keine Konstante. Ich hab' da noch eine Idee zur Beschleunigung: Man könnte sich eine Lookup Tabelle anlegen, in der die letzten 10 Berechnungsergebnisse abgelegt werden, sozusagen als cache.
(ADC werte -16384)*1585
1 | x = ADC; |
2 | ADC -= 16384; |
3 | |
4 | tmp = ADC << 10;// * 1024 |
5 | tmp+= ADC << 9; // * 512 ( * 1536 ) |
6 | tmp+= ADC << 5; // * 32 ( * 1568 ) |
7 | tmp+= ADC << 4; // * 16 ( * 1584 ) |
8 | tmp+= ADC; // * 1 ( * 1585 ) |
keine ahnung ob die interne mulitplikation es auch so macht.
Peter, genausao habe ich es gemacht und das hat ungefähr viermal so lange gebraucht..Ich denke mal der Compiler wird so schlau sein, das mindestens genauso gut zu machen...oder? Nur kamen mir 12 Takte sau kurz vor. Vorallem weil einen Appnote von atmel 121 Takte braucht
aaaah, habe gerade noch einen Appnote gefunden.. Die 201. Die benutzt die Hardware-Multiplikation. Da sind 17 Taktzyklen angegeben. Also passt das doch sehr gut. Braucht man sich also nicht so große Gedanken machen. Das verwirft natürlich auch meine LookUpTaable, bei 12 Taktzyklen brauch man garnicht drüber reden:-) Hatte ich niemals so schnell erwartet...
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.