Hallo, ich möchte eine Korrekturfunktion erstellen, womit ich bestimmte Variablenwerte korrigieren kann, also Anhand von: a = Korrekturfunktion(variable b); Das Problem ist, dass ich die "Korrekturfunktion" nicht habe, sondern nur eine Tabelle mit bestimmten diskreten Werten. Das könnte ich mit IF oder SWITCH Abfragen machen, wäre aber sehr aufwendig und ich kann nur die Werte zuweisen, die in der Tabelle stehen, nicht Werte die zwischen den Tabellenwerten liegen. Jetzt die Frage, gibt es eine Möglichkeit aus den Tabellenwerten eine Funktion zu erstellen? Stellt gcc gewisse Funktionen bereit, die einem die Korrekturfunktionen erleichtern? Vielleicht über arrays oder ähnliches?
Mit dem GCC selbst hat das nichts zu tun. Die Frage ist ja auch, wie du die Approximation durchführen willst: lineare Interpolation zwischen den Stützstellen, Polynom n-ten Grades, das durch alle n+1 Stützstellen durchgeht, Polynom m-ten Grades mit m < n+1 und geringstem quadratischen Fehler zu allen Stützstellen? Für all diese Dinge hat die Mathematik Lösungen parat. Die musst du in irgendein Programm gießen (das kann ein GCC sein, dass kann eine Scriptsprache sein wie Perl oder Python, das kann ein Mathematikprogramm sein), und das lässt du dann deine Tabelle berechnen.
Am Einfachsten (und meistens auch ausreichend) ist wohl lineare Interpolation Mach dir ne Tabelle, welche soritert ist, dann läust die Tabelle durch, schaust wann du zum ersten mal größer oder gleich dem Wert im Array bist. (bei größeren Tabellen kann man auch binäre Suche verwenden) Wenn du die Stelle gefunden hast, dann bist zwischen 2 Stützsstellen. Dann musst noch das Verhältnis ausrechen zwischen den 2 Stützsstellen und auf die andere Spalte anwenden. Hab hier mal ein Beispiel wie ich die Werte von einen Temp-Fühler vom ADC auf °C umrechne
1 | int __attribute__ ((progmem)) adc_table [20*2] = { |
2 | -999, 0, |
3 | -350, 64, |
4 | -200, 129, |
5 | -100, 171, |
6 | 00, 213, |
7 | 150, 273, |
8 | 250, 312, |
9 | 350, 351, |
10 | 450, 389, |
11 | 600, 444, |
12 | 750, 497, |
13 | 900, 549, |
14 | 1050, 600, |
15 | 1200, 649, |
16 | 1500, 743, |
17 | 1800, 833, |
18 | 2100, 917, |
19 | 2300, 972, |
20 | 2490, 1021, |
21 | 3000, 1023 }; |
22 | |
23 | int adc_getTemp(int adc) { |
24 | unsigned char i; |
25 | int x1,x2,t1,t2; |
26 | for (i = 1; i < 19; i++) { |
27 | if (PRG_RDInt(&adc_table[i*2+1]) >= adc) break; |
28 | }
|
29 | x1 = PRG_RDInt(&adc_table[i*2-1]); |
30 | x2 = PRG_RDInt(&adc_table[i*2+1]); |
31 | t1 = PRG_RDInt(&adc_table[i*2-2]); |
32 | t2 = PRG_RDInt(&adc_table[i*2]); |
33 | |
34 | |
35 | return ((adc-x1) * (t2-t1)) / (x2-x1) + t1; |
36 | }
|
>Jetzt die Frage, gibt es eine Möglichkeit aus den Tabellenwerten eine >Funktion zu erstellen? Stellt gcc gewisse Funktionen bereit, die einem >die Korrekturfunktionen erleichtern? Vielleicht über arrays oder >ähnliches? GCC ist nur ein C-Compiler. Du brauchst ein Programm zur Datenverarbeitung/analyse. Versuchs mal mit Excel, das kann AFAIK lineare Regression sowie quadratische Interpolation. MfG Falk
ich seh grad dass der code noch für ne alte gcc-Version ist. Besser man verwendet anstatt PRG_RDint pgm_... aber das wirst schon selber heraus finden ;-)
Das steuert genau in die Richtung wo ich hin möchte. Es wäre schon eine Hilfe, wenn man aus den einfachen Tabellenwerten mit Hilfe eines Programms irgendwie eine Mathemantische Funktion erstellen könnte. Die dazwischenliegenden Werte würde ausreichen linear zu interpolieren oder sonstwie anzunähern. Leider habe ich nichts passendes gefunden. Ich werde mal versuchen über eine Switch Anweisung das abzudecken, die dazwischenliegenden Werte einfach zu berechnen.
interpolationsformel von Lagrange oder Newton. gibt natürlich noch andere verfahren um eine funktion aus stützstellen zu erhalten. ein matheprogramm ist da definitiv zu empfehlen, ansonsten kann es passieren dass du ewig rechnest. pumpkin
Danke Leute! ich versuche mal den Lösungsansatz von Roland umzusetzen. Danach melde ich mich wieder zu Wort.
OpenOfficeCalc legt immerhin eine Gerade durch die Tabellenwerte, als erster Anhaltspunkt welche Kurvenform geeignet wäre. Durch Logarithmieren der Tabellenwerte kann man auch Geraden in "halblogaritmischen" Diagrammen zeichnen lassen. "lineare Regression sowie quadratische Interpolation" hab ich in der OpenOffice-Hilfefunktion nicht gefunden, aber vielleicht nur die falschen Suchbegriffe benutzt.
edit: aber um deine zwischenwerte linear zu interpolieren reicht eine kleine funktion. etwa so: nehme den nächst kleineren und den nächst größeren. größerer - kleinerer = deltaY. dein deltaX (also x beim größeren - x beim kleineren) ist vermutlich immer gleich. somit kannst du die steigung zwischen den beiden punkten ausrechnen (deltaY/deltaX = dY/dX). dann nimmst du dein aktuellen X wert und ziehst das X des kleineren ab und multiplizierst das ergebniss mit dem dY/dX. kleineren Y-wert hinzuaddiert, fertig. pseudocode also: ( (( Y[größer] - Y[kleiner] )/( X[größer] - X[kleiner] )) * ( X[aktuell] - X[kleiner] ) ) + Y[kleiner] pumpkin
Ich glaube mich zu erinnern, dass es da auch was passendes in Matlab gab. Hab das Prog aber leider nicht zur Hand.
>> Das steuert genau in die Richtung wo ich hin möchte. Es wäre schon eine >> Hilfe, wenn man aus den einfachen Tabellenwerten mit Hilfe eines >> Programms irgendwie eine Mathemantische Funktion erstellen könnte. Die >> dazwischenliegenden Werte würde ausreichen linear zu interpolieren oder >> sonstwie anzunähern. Leider habe ich nichts passendes gefunden. was willst du eigentlich? eine mathematische funktion? lineare interpolation zwischen den werten? wenn du eine stetige funktion willst, bekommst du ein polynom x-ten grades, wobei x+1 die anzahl deiner stützstellen ist (wie Jörg schon schrieb). das auf einem µC ist zwar machbar aber nicht empfehlenswert. soll es denn überhaupt für einen µC sein? pumpkin
Eine Funktion wäre am genauesten. Aber ich habe ca. 45 Stützstellen, diese in ein Polynom zu gießen wäre glaube ich zu aufwendig. Habe von der MAthe nicht so die Ahnung, aber müsste man dann nicht vorher ein Gleichungssystem mit 44 unbekannten lösen? Ich habe jetzt eine einfache Funktion gemacht, die auf nem Atmega laufen soll. Tabellenwerte vergleichen und dann lineare Interpolation anwenden und so den zugehörigen Wert approximieren. Die Genauigkeit ist da ausreichend für meine Zwecke. Eine exakte Funktion mit 44 Polynomen wäre Seitens der Implementation zu aufwendig und (für mich) zu schwierig.
Hallo, Du solltest die Interpolation bereits explizit vorziehen und nicht die Stützstellen, sondern die Steigung und den Achsabschnitt vorgeben. Dann gibt es weniger zu rechnen.
@Mister mit Kanister >Eine Funktion wäre am genauesten. Aber ich habe ca. 45 Stützstellen, >diese in ein Polynom zu gießen wäre glaube ich zu aufwendig. Habe von Wieso, das macht das Programm für dich. >der MAthe nicht so die Ahnung, aber müsste man dann nicht vorher ein >Gleichungssystem mit 44 unbekannten lösen? Nur wenn du ein Polynom 44. Grades haben willst. Aber meist tuts eins dritten Grades. Aber auch das rechnet dir das richtige Programm automatisch aus. >Ich habe jetzt eine einfache Funktion gemacht, die auf nem Atmega laufen >soll. Tabellenwerte vergleichen und dann lineare Interpolation anwenden >und so den zugehörigen Wert approximieren. Die Genauigkeit ist da >ausreichend für meine Zwecke. Problem gelöst. >Eine exakte Funktion mit 44 Polynomen wäre Seitens der Implementation zu >aufwendig und (für mich) zu schwierig. Braucht keiner, siehe oben. MFG Falk
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.