Forum: Compiler & IDEs Wertebereich skalieren und Offset ausgleichen


von Z.B. Max Z. (oapc)


Lesenswert?

So, nach dem meine vorherige Frage in einen Bereich verschoben wurde, 
der mit dem Thema gar nichts zu tun hat und dort dementsprechend auch 
nicht verstanden wurde, versuche ich, das Problem mal anders 
darzustellen.

Es geht mir hier um eine rein mathematische Fragestellung und 
dementsprechend auch um eine rein mathematische Lösung für exakt dieses 
Problem.
Eigentlich kann die Lösung nicht so kompliziert sein, allerdings stehe 
ich gerade komplett auf dem Schlauch:

Ich habe einen Wertebereich (der als linear anzunehmen ist) mit 
Messwerten, bei denen ich real folgende Werte habe:

- Minimalwert ist 193
- Mittelwert ist 2221
- Maximalwert ist 4070

Der interne Wertebereich, den ich zur Verfügung habe, geht von 0 bis 
4095.

Jetzt würde ich die realen Werte gerne so skalieren, dass sie einerseits 
den internen Wertebereich so gut wie möglich ausnutzen (bis ganz nach 0 
wird es auf Grund des hohen realen Minimalwertes wohl nicht gehen 
können!?), andererseits der Mittlerwert bei exakt 2048 liegt.

Heißt, ich muss einen Skalierungsfaktor und einen Offset ermitteln, der 
diese Bedingungen erfüllt und mit denen ich jeden anderen, realen 
Messwert im Bereich 193..4070 auf eben den internen Wert im Bereich von 
0..4095 konvertieren kann. Rechenleistung ist dabei kein Problem, 
Fließpunktzahlen sind vorhanden.

Wie kriege ich hier einen passenden Offset und Faktor ermittelt?

von Bernd N. (_bn_)


Lesenswert?

Arbeite doch mal die Antworten durch die du schon bekommen hast.

Beitrag "ADC-Wert skalieren"

Eine andere Möglichkeit wäre eine LUT, siehe...
https://blog.stratifylabs.dev/device/2013-10-03-ADC-Thermistor-Circuit-and-Lookup-Table/

von Andreas M. (amesser)


Lesenswert?

Z.B. Max Z. schrieb:
> Wie kriege ich hier einen passenden Offset und Faktor ermittelt?

Mit Schulmathematik 7. Klasse.

von Andreas M. (amesser)


Lesenswert?

Z.B. Max Z. schrieb:
> Ich habe einen Wertebereich (der als linear anzunehmen ist) mit
> Messwerten, bei denen ich real folgende Werte habe:
>
> - Minimalwert ist 193
> - Mittelwert ist 2221
> - Maximalwert ist 4070

Da ist nix linear. Wenn es linear wäre, wäre der Mittelwert 2131.

: Bearbeitet durch User
von Foobar (asdfasd)


Lesenswert?

Wie schon geschrieben wurde, die Werte:
1
   0: 193
2
 0.5: 2221
3
   1: 4070
sind nicht linear.  Sie entsprächen z.B. dem Polynom:
1
  193 +4235*x -358*x*x

Mittels Polynominterpolation[1] kann man ein Polynom berechnen, das dein 
gewünschtes mapping erzeugt:
1
 -184.15408271593785 + 0.9493263981267704*x + 0.000025076857834335404*x*x
liefert für:
1
 193: 0
2
2221: 2048
3
4070: 4095

Ich bezweifel aber, dass das das ist, was du suchst ...



[1] https://de.wikipedia.org/wiki/Polynominterpolation

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

Z.B. Max Z. schrieb:
> Offset und Faktor

Offset und Faktor sind Begriffe, die auf ein lineares Gleichungssystem 
a*x+b hindeuten, mit a als Faktor und b als Offset.

Deine Vorgabewerte liegen aber nicht auf einer Linie, sie lassen sich 
also durch ein lineares Gleichungssystem nicht abbilden.

Insofern:

Z.B. Max Z. schrieb:
> Wie kriege ich hier einen passenden Offset und Faktor ermittelt?

Gar nicht.

LG, Sebastian

von Daniel A. (daniel-a)


Lesenswert?

Z.B. Max Z. schrieb:
> Heißt, ich muss einen Skalierungsfaktor und einen Offset ermitteln, der
> diese Bedingungen erfüllt und mit denen ich jeden anderen, realen
> Messwert im Bereich 193..4070 auf eben den internen Wert im Bereich von
> 0..4095 konvertieren kann. Rechenleistung ist dabei kein Problem,
> Fließpunktzahlen sind vorhanden.
1
uint16_t normalize_value(uint16_t min, uint16_t max, uint16_t value, uint16_t new_max){
2
  return (uint32_t)(value-min)*new_max/(max-min);
3
}

normalize_value(193, 4070, 193, 4095)  -> 0 (0%)
normalize_value(193, 4070, 2221, 4095) -> 2142 (~52%)
normalize_value(193, 4070, 4070, 4095) -> 4095 (100%)

PS: Wenn ungenaue floats erlaubt sind, normalisiere ich gerne auf 0..1. 
Also "(double)(value-min)/(max-min)". Dass kann man dann einfach mit 
4095 multiplizieren, und schon geht's von 0..4095. Und wenn man mehrere 
Werte im Bereich 0..1 hat, kann man die auch multiplizieren usw., und 
hat wieder einen Wert von 0..1. Es wird alles einfacher, sobald man 
merkt, das 100% = 100/100 = 1 ist.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Z.B. Max Z. schrieb:
> Ich habe einen Wertebereich (der als linear anzunehmen ist)

Wenn Du die 3 Werte in ein Koordinatensystem einträgst, wirst Du sehen, 
dass Du da keine Gerade durchziehen kannst. Der Wertebereich ist daher 
nicht linear.

> Wie kriege ich hier einen passenden Offset und Faktor ermittelt?

Wenn Du einen Deiner 3 Punkte ignorierst, ist das einfach:

Geradengleichung ist:
1
y = a * x + b

Bestimmung von Steigung a:
1
a=(y2–y1)/(x2–x1)

Fehlt nur noch der y-Achsenabschnitt b:
1
b = y - a * x
Konkret für Punkt (x1,y1):
1
b = y1 - a * x1

Das ganze klappt aber nur mit 2 Punkten. Wenn der Wertebereich 
tatsächlich linear wäre, dann könntest Du einen der 3 Punkte ignorieren. 
Geht aber nicht, da die 3 Punkte nicht auf einer Geraden liegen. Egal, 
welche zwei Punkte Du von den dreien auswählst, wirst Du jedesmal eine 
andere Geradengleichung erhalten - eben weil sie nicht auf einer Geraden 
liegen.

Egal, wie oft Du für das Thema einen neuen Thread öffnest, wirst Du 
keine zufriedenstellende Lösung erhalten. Das liegt daran, dass Deine 
Annahme, der Wertebereich sei linear, für die angegebenen Punkte einfach 
falsch ist.

Also: Entweder sind die 3 Punkte (damit Deine Messung) falsch oder Deine 
Annahme ist falsch. Dieser Widerspruch ist durch wiederholte Fragen 
einfach nicht auflösbar.

Tipp:

Ziehe eine Gerade durch den minimalen und den mittleren Punkt. Ziehe 
eine zweite Gerade durch den mittleren Punkt zum maximalen Punkt. Wende 
darauf die obigen Formeln an. Dann erhältst Du zwei Geradengleichungen. 
Mit der ersten Geradengleichung kannst Du dann Punkt zwischen Min und 
Mittel extrapolieren, mit der zweiten Geradengleichung die Punkte 
zwischen Mittel und Max. Immerhin ist das einfacher als mit Polynomen 
herumrechnen zu müssen. Die Genauigkeit wird vielleicht Deinen 
Ansprüchen nicht genügen. Das ist aber Dein Problem.

Alternativ könntest Du Deine Messwerte anzweifeln und da nochmal neu 
ansetzen.

: Bearbeitet durch Moderator
von Sebastian W. (wangnick)


Lesenswert?

Sebastian W. schrieb:
> Gar nicht.

Was du allerdings machen könntest, wäre aus den drei Meßpunkten eine 
Gerade zu berechnen, die die Summe der Fehlerquadrate minimiert. Das 
geht recht einfach in Excel. Trage deine drei Punkte ein, erstelle 
daraus einen xy-Graphen, und wähle dann "lineare Interpolation" und 
"Formel einblenden". Dann zeigt Excel dir Offset und Faktor einer 
"besten" Annäherung.

LG, Sebastian

: Bearbeitet durch User
von Toxy T. (toxy_t)


Angehängte Dateien:

Lesenswert?

Z.B. Max Z. schrieb:
> für exakt dieses
> Problem.
Ich gehe von einem linearen System aus.
Hier ne Opamp Loesung (Levelshifting) mit Gleichung.
siehe Anhang

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Z.B. Max Z. schrieb:
> So, nach dem meine vorherige Frage
Die da im 
Beitrag "ADC-Wert skalieren"


> in einen Bereich verschoben wurde,
> der mit dem Thema gar nichts zu tun hat
Du siehst das aus einer seltsamen Sicht, denn deine Aufgabe hat mit der 
verwendeten Toolchain überhaupt nichts zu tun.

Wenn dir "uC und Digitaltechnik" irrigerweise falsch vorkommt, dann nimm 
wenigstens "Signalverarbeitung".

Z.B. Max Z. schrieb:
> folgende Werte habe:
>
> Minimalwert ist 193
> Mittelwert ist 2221
> Maximalwert ist 4070
>
> Der interne Wertebereich, den ich zur Verfügung habe, geht von 0 bis
> 4095.
> Jetzt würde ich die realen Werte gerne so skalieren, dass sie einerseits
> den internen Wertebereich so gut wie möglich ausnutzen (bis ganz nach 0
> wird es auf Grund des hohen realen Minimalwertes wohl nicht gehen
> können!?), andererseits der Mittlerwert bei exakt 2048 liegt.
Weil das offenbar sehr viel mit "ich will unbedingt!" zu tun hat, würde 
ich die Eingangswerte mit zwei(!) unabhängigen(!) Geraden so skalieren, 
dass 193..2220 auf 0..2047 sowie der Bereich 2221..4070 auf 2048..4095 
abgebildet werden. Brute Force at its best.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Z.B. Max Z. schrieb:
> Es geht mir hier um eine rein mathematische Fragestellung und
> dementsprechend auch um eine rein mathematische Lösung für exakt dieses
> Problem.

Rein mathematisch hast du erstmal 3 Gleichungen fuer 3 Punkte in deinem 
Bereich. Daraus kannst du dir 3 Unbekannte errechnen - das gibt eine 
quadratische Funktion (Polynom 2.Kajuete). Die wurde dir schon 
vorexerziert und geht exakt durch die 3 gegebenen Punkte.
Du kannst aber auch hergehen und sagen: Ich will da mit Gewalt eine 
Gerade, also ein Polynom 1.Kajuete, durchlegen - dann hast du 2 
Moeglichkeiten:

1.) Du laesst aus deinen 3 Gleichungen fuer 3 Punkte einfach mal eine 
Gleichung weg, evtl. die, wo du spaeter Abweichungen am besten 
tolerieren kannst. Dann berechnest du die Gerade fuer diesen Fall und 
lebst mit der Abweichung, die du dann fuer die weggelassene Gleichung 
hast.

2.) Du hast ein ueberbestimmtes Gleichungssystem, da kannst du in deinem 
Fall eine Gleichung fuer eine Gerade berechnen, bei der der Fehler, also 
die (Quadrate der) Abweichung zur quadratischen Funktion minimal wird.
Dann geht deine Gerade aber wahrscheinlich durch keinen der gegebenen 
Punkte genau, sondern halt nur so ungefaehr. Aber das beste Ungefaehr, 
was du kriegen kannst.

recht viel mehr wird das Problem wohl nicht hergeben, vermute ich mal.

Gruss
WK

von Michael B. (laberkopp)


Lesenswert?

Z.B. Max Z. schrieb:
> Wie kriege ich hier einen passenden Offset und Faktor ermittelt?

Grundschulmathematik ?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> würde ich die Eingangswerte mit zwei(!) unabhängigen(!) Geraden so
> skalieren, dass 193..2220 auf 0..2047 sowie der Bereich 2221..4070 auf
> 2048..4095 abgebildet werden. Brute Force at its best.
Das geht übrigens etwa so:
1
if (x<2221) y =  ((x-193L )*((2047L*63356L)/(2221-193))) /63356L;
2
else        y = (((x-2221L)*((2047L*63356L)/(4070-2221)))/63356L)+2048L;
- https://onlinegdb.com/QgrRrlJ3K

Oder wer es lieber auf float will, weil ihm die Rechenzeit egal ist:
1
if (x < 2221)   y = (long) ((x - 193.0) *2047.0 / (2221.0-193.0));
2
else            y = (long) ((x - 2221.0)*2047.0 / (4070.0-2221.0) + 2048);
- https://onlinegdb.com/6t2xId8kd

von Rainer W. (rawi)


Lesenswert?

Z.B. Max Z. schrieb:
> Eigentlich kann die Lösung nicht so kompliziert sein, allerdings stehe
> ich gerade komplett auf dem Schlauch

Ich finde es immer wieder erstaunlich, dass genau die Leute, die es 
selber nicht hinbekommen, sich oft anmaßen, den Kompliziertheitsgrad 
einer Lösung als "nicht so kompliziert" beurteilen zu können.

Und nein, es ist in der Tat nicht sonderlich kompliziert.

Z.B. Max Z. schrieb:
> Ich habe einen Wertebereich (der als linear anzunehmen ist) mit
> Messwerten, bei denen ich real folgende Werte habe:
>
> - Minimalwert ist 193
> - Mittelwert ist 2221
> - Maximalwert ist 4070

Was ist ein "linearer Wertebereich"?
Bevor du mit solchen Begriffen um dich wirfst, solltest du wenigstens 
ein ganz klein wenig verstehen, wovon du sprichst. Der Mittelwert hängt 
von der Verteilung deiner Messwerte ab und ist eine statistische Größe. 
Woraus ist deine 2221 gemittelt? Falls es die Mitte zwischen Minimal- 
und Maximalwert sein soll, hast du einen NICHTlinearen Zusammenhang. 
Dein Annahme wäre dann falsch. Eine andere Möglichkeit ist, dass deine 
Messwerte fehlerbehaftet sind und den funktionalen Zusammenhang nur 
innerhalb eines gewissen Fehlerbandes darstellen. Eine weitere 
Möglichkeit ist, dass der Zusammenhang nichtlinear ist, du das Verhalten 
aber nur an diesen drei Punkten kennst und damit eine Parabel die rein 
mathematische Lösung für dein Problem wäre. Oder du beharrst auf 
"Linear" und betrachtest den Zusammenhang als abschnittsweise linear, 
wie von Lother vorgeschlagen, darfst dich dann aber nicht über den Knick 
beim mittleren Wert wundern.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.