ich habe ein eigentlich ganz einfaches Problem, stehe aber gerade massiv auf der Leitung.
Folgendes: ich lese Analogdaten von einem ADC ein. Auf Grund der externen Beschaltung nutzt der mögliche Eingangsspannungsbereich nicht den maximal möglichen ADC-Wertebereich aus. Also würde ich die real gemessenen Daten gerne auf den tatsächlichen Wertebereich skalieren.
Es sieht also so aus:
0V Eingangsspannung ergeben real einen Wert von 193
2,5V Eingangsspannung erbenen real einen Wert von 2221
5V Eingangsspannung ergeben real einen Wert von 4072
Das würde ich jetzt gerne so skalieren, dass der komplette bereich von 0 (0V) bis 4095 (5V) genutzt wird.
Bisher war mein Ansatz, 193 vom DAC-Wert abzuziehen (Offset von 0V) und mit 1.051064 zu multiplizieren (Skalierungsfaktor, der sich aus 4096/(4072-193) ergibt).
Allerdings funktioniert das nicht, da dieser Weg bei 2,5V Eingangsspannung nicht 2048 ergibt, sondern 2132. Wo ist mein Denkfehler? Wie berechne ich das richtig?
0V Eingangsspannung ergeben real einen Wert von 193
2,5V Eingangsspannung ergeben real einen Wert von 2221
5V Eingangsspannung ergeben real einen Wert von 4072
Bei einer linearen Messung müsste 2,5V den Wert 1940 ergeben. Lass mich raten, geht es um einen ESP8266 oder ESP32?
Nach Deinen Berichten ist der AD Aufbau und die Referenzmessung total vermurkst, dass kriegste auch nicht mehr per Software nutzbar zurecht skaliert.
Du hast einen 12 bit AD-Wandler, dann sollte die Messgenauigkeit der Referenzmessung auch in diesem Bereich liegen. Also brauchste nicht die Werte bei 0 2,5 und 5 sondern bei 0,000V 2,500 V und 5,000 V. Bringt dein Referenzmessgerät überhaupt diese Anzeigegenauigkeit?
Und dann sollten beim 0.000V aka "Analogeingang mit GND verbunden" höchstens das einzeln niederwertigste Bit wackeln, bei dir sind es aber gleich die unteren 8 bit.
Das schaut dann schon mal nicht nach einem Offset-fehler sondern nach kompletten Murks aus. Das kann vom fehFer beim Auslesen des AD-Wandlers, falsche Decodierung und stark verrauschter Versorgungs- resp. Ref.-spannung alles sein.
Bring erst die Messungen bei 0.000V und Eingang gegen GND schaltungstechnisch sauber auf "000000000000" .
Wie stellst du eigentlich die 0V ein, etwa Analogeingang offen lassen ?
OK, da hier mal wieder großkotzig von Murks die Rede ist: nein, es ist kein Murks.
Der tatsächliche Analogwert liegt weit außerhalb des Eingangsspannungsbereiches des ADC, weswegen das mit einem Spannungsteiler angepasst wurde.
Tatsächlich sind die Eingangsspannungswerte (Sollwerte):
Minimum ca. 0,156V
Mittelwert ca. 1,79V
Maximum ca 3,28V
Warum nicht 0V und 3,3V? Um Bauteiltoleranzen im Spannungsteiler aufzufangen. Entsprechend ergibt sich der relativ hohe Offset beim Minimalwert. Das ist also kein Murks, sondern gewollt.
OK, da hier mal wieder großkotzig von Murks die Rede ist: nein, es ist
kein Murks.
Naja Auskotzen kann man nur was man einem in den Mund gelegt wird.
Und in den seltesten Fällen ist der Autor geeignet die Qualität seines eigenen Werkes objektiv einzuschätzen. Das "sich selbst auf die Schulter klopfen" liegt in der Natur jedes Menschen.
Der tatsächliche Analogwert liegt weit außerhalb des
Eingangsspannungsbereiches des ADC, weswegen das mit einem
Spannungsteiler angepasst wurde.
Ich nehme an, der Spannungsteiler ist aus gewöhnlichen Widerständen mit Toleranz 1% aufgebaut? Das kann man machen, bei einen AD-Wandler mit 12 bit verschenkt man aber reichlich Genauigkeit. Widerstände verändern auch bei Erwärmung ihren Widerstandswert, ein Temp.-kompensierte Messverstärker resp. Abschwächer wäre hier besser für höchste Gebauigkeit.
Tatsächlich sind die Eingangsspannungswerte (Sollwerte):
Und in den seltesten Fällen ist der Autor geeignet die Qualität seines
eigenen Werkes objektiv einzuschätzen.
Noch viel weniger ist jemand dazu geeignet, der nicht bekannte technische Details durch übergroßes Ego ersetzt. Also diese armen Würstchen, die nur in der Anonymität des Internet glauben, irgendwas zu sein oder zu können, dort um so aggressiver und großmäuliger auftreten und im wahren Leben absolut nichts auf die Reihe kriegen.
Ende der Diskussion mit dir, bye und ein schönes Leben noch!
Noch viel weniger ist jemand dazu geeignet, der nicht bekannte
technische Details durch übergroßes Ego ersetzt.
Die meisten Leser hier gehen optimistischerweise davon aus, dass der
Threadstarter alle für seine Frage relevanten Details offenlegt und
diese auch korrekt sind. Ist dies nicht der Fall, muss er sich eben
kritische Bemerkungen gefallen lassen.
Die meisten Leser hier gehen optimistischerweise davon aus, dass der
Threadstarter alle für seine Frage relevanten Details offenlegt und
diese auch korrekt sind.
Und manche prüfen eben, ob die genannten Werte plausibel sind und das sind sie eben nicht. Also meckert man genau das an. Und gibt auch Hinweise für die Korrektur (Messschaltung, Genauigkeit Anzeige)
Ist dies nicht der Fall, muss er sich eben
kritische Bemerkungen gefallen lassen.
Und unmittelbar nach der kritischen Bewmerkung hat der Threadstarter
den Makel fehlender und grob ungenauer Angaben behoben. Also was gibts da zu meckern?
Weiterer Tipp: intern könnte man den eingehenden Messwert zuerst auf die Toleranzen der Messstrecke runterskallieren, also grob bei den 12 Bit Wandler und 1% Bauteiltoleranzen die unteren 4 bit "wegwerfen". Dann kann man die weitere Rechnung auf den Eingengsbereich mit einer kleinen LookUp-table erschlagen. Natürlich ist das dann nur ca. 0.05V (1% auf 5V) genau. Mehr ist aber bei Spannungsteiler aus der Bastelkiste nicht drin.
Die meisten Leser hier gehen optimistischerweise davon aus, dass der
Threadstarter alle für seine Frage relevanten Details offenlegt und
diese auch korrekt sind.
OK, meine Frage war aber nicht "Ist meine Schaltung korrekt" oder "funktioniert mein ADC wie er soll", sondern wie berechne ich diese Werte korrekt.
Und es besteht auch ein großer Unterschied zwischen "kritischer Bemerkung" und unhöflichem, großkotzigen Rumpampen, bei dem man ganz deutlich merkt, dass es gar nicht darum geht, eine Antwort zu geben, sondern einfach mal darzustellen, wie toll man selber ist und wie dumm und Sch*** alle anderen sind. Das ist kein zivilisierter Umgangston, das ist einfach nur allerunterste Schiene. Und solche Leute und Ihre Pseudo-Antworten können mir persönlich komplett gestohlen bleiben.
Noch viel weniger ist jemand dazu geeignet, der nicht bekannte
technische Details durch übergroßes Ego ersetzt. Also diese armen
Würstchen, die nur in der Anonymität des Internet glauben, irgendwas zu
sein oder zu können, dort um so aggressiver und großmäuliger auftreten
und im wahren Leben absolut nichts auf die Reihe kriegen.
Es zeigt sich ziemlich klar hier wieder dass der Spruch
"Wie man in den Wald hineinruft, so schallt es heraus"
zutrifft.
2.5 V ist der arithmetische Mittelwert von 0 V und 5 V, aber 2221 ist nicht der arithmetische Mittelwert von 193 und 4072, denn dieser ergibt sich zu (193 + 4072)/2 = 2132.5. Die Funktion A(U) mit A = ADC-Output und U = Eingangsspannung ist also nicht linear. Dafür muss es irgendeinen Grund geben, der sich aus Deiner Schaltung ergibt. Diesen Grund gilt es zu identifizieren und daraus die entsprechende Mathematik abzuleiten, um so zu wissen, welche Art von Nichtlinearität vorliegt. Mit dieser Information kannst Du dann darauf...
Und es besteht auch ein großer Unterschied zwischen "kritischer
Bemerkung" und unhöflichem, großkotzigen Rumpampen,
Unhöflich ist es falsche Angaben zu machen wenn man von anderen Hilfe will. Während 2,5V tatsächlich die Hälfte von 5.0V ist, ist (1.79-0.16)V weit weg von der Hälfte von (3.28-0.16)V.
Stimmt, Dreisatz ist Inhalt des Matheunterricht in der sechsten Klasse, Geradengleichung der achten Klasse.
Auf Grund der externen Beschaltung nutzt der mögliche
Eingangsspannungsbereich nicht den maximal möglichen ADC-Wertebereich
aus. Also würde ich die real gemessenen Daten gerne auf den
tatsächlichen Wertebereich skalieren.
Ja und?
Was soll die Rumrechnerei - außer zusätzlichem Rechenaufwand - bringen.
Die Daten werden dadurch nicht besser.
Außerdem wäre auch noch zu klären, was genau Du damit meinst:
Das würde ich jetzt gerne so skalieren, dass der komplette bereich von 0
(0V) bis 4095 (5V) genutzt wird.
Das finde ich nämlich alles andere als eindeutig. Heißt das, Du suchst eine Funktion f mit der Eigenschaft f(192) = 0 und f(2221) = 2048 und f(4072) = 4095? Wenn ja: Wozu? Was soll f können, was eine Funktion g mit der Eigenschaft g(192) = 0 und g(2221) = 2.5 und g(4072) = 5 nicht kann?
Dann hoffe ich mal, daß Dein Taschenrechner auf nur 'integer' einzustellen ist.
Kleine Notiz: 'float/double' und Divisionen nutze ich sogar in ISRs ;-)
Was soll die Rumrechnerei - außer zusätzlichem Rechenaufwand - bringen.
Die Daten werden dadurch nicht besser.
Aber die Skalierbarkeit zur Laufzeit. Offsets und Faktoren lassen sich anpassen und im EEPROM abspeichern. Aber wer es lieber mag, nimmt eben Trimmpotis.
Anstelle der umstrittenen Bewertungsfunktion plädiere ich für einen intelligenten Filter, der emotional gefärbte Beiträge und grob beleidigendes Vokabular ausblendet oder erst gar nicht annimmt.
Wenn man schon beleidigen will, dann doch bitte elegant! Oder ist Deutsch derart hinterwäldlerisch?
Kleine Notiz: 'float/double' und Divisionen nutze ich sogar in ISRs ;-)
Recht so!
Ich glaube das war irgendwann zwischen 1880 und 1905, da hat mal jemand postuliert das float Operation schlimmster Teufelskram sind.
Weiter darüber nachgedacht haben danach nur sehr wenige und so werden den Kindern am Kaminfeuer noch heute die alten Geschichten erzählt.
Ungeachtet der Tatsache das diese Operationen eher im µs denn im ms Bereich angesiedelt sind.
Ich glaube das war irgendwann zwischen 1880 und 1905, da hat mal jemand
postuliert das float Operation schlimmster Teufelskram sind.
Hmm, manchmal schon. Ist mir erst heute passiert zwar nicht im µC sondern im Excel. Kann einem aber so ähnlich auch im µC auf die Füße fallen.
156,22€ Einnahmen, 156,22€ Aussgaben, Differenz ist ungleich Null!?
Hatte extra eine Formel genutzt um auf Nulldiffernz zu prüfen.
Hhmm, Excel Doof?, Ich doof?
Bei 156,20€ statt 156,22 gehts aber? Was ist hier los?
Ein Vergleich von Floats kann auch schief gehen, wenn die Differnz sehr sehr klein ist. Hätte nicht gedacht das beim addieren von vielleicht 5 Beträgen bereits Rundungsfehler im Float auftreten. Ist aber so.
Hätte nicht gedacht das beim addieren von vielleicht 5 Beträgen bereits
Rundungsfehler im Float auftreten. Ist aber so.
Die Rundungsfehler entstehen schon, wenn deine reellen Zahlen aus dem Dezimalsystem in Float (aka. Fixkommazahlen mit variabler Kommaposition im Binärformat) gewandelt werden.
Meine maximale Zykluszeit ohne die Double Berechnung: 80 us
Mit 1000 Berechnung Double: 161 us
Wenn dein Compiler über ein Minimum an Optimierung verfügt, hat er erkannt, dass a und b durch die Schleife nicht beeinflusst werden und hat die Operation aus der Schleife heraus genommen.
Um wirklich zu wissen, was er rechnet, guckst du besser in den erzeugten Assemblercode.
156,22€ Einnahmen, 156,22€ Aussgaben, Differenz ist ungleich Null!?
Man vergleicht Fließkommazahlen niemals auf Gleichheit. <-PUNKT
(Außer man weiß zu 100% das der Nachkommaanteil aus 1/2^n Komponenten zusammen setzbar ist.)
Wobei N besser nicht die gewählte Präzision (Mantisse) sprengt.
Alle anderen vergleichen auf Ähnlichkeit innerhalb einer gegebenen Varianz.
Meine maximale Zykluszeit ohne die Double Berechnung:
Hab's früher™ mal mit einem Kinder-AVR™ ausgiebig getestet und meine mich zu erinnern das man dort mit maximal ~ 500CPU-Zyklen (zumeist deutlich weniger) rechnen musste.
Das kann man dann geschmeidig für die jeweilige CPU-Taktfrequenz umrechnen und stellt fest das selbst Kinder-AVRs™ Hunderte bis Tausende FLOPS können.
Ich glaube das war irgendwann zwischen 1880 und 1905
Gestern hier im Forum veröffentlicht:
OCR0A = (262L * delta) >> 9;
Was immer der Autor damit gemeint hat: Es ist wohl eine Art Religion,
die nur Angehörige der Sekte als heilsbringend betrachten.
Tja, wenn man nichts kapiert, muss es dumm sein, gelle.
Wenn man aber zu doof oder zu faul zum Lesen des Kommentars ist, ist Hopfen und Malz verloren. Andere Leute haben Festkommaarithmetik verstanden und wenden sie erfolgreich an. Du gehörst nicht dazu.
Tja, wenn man nichts kapiert, muss es dumm sein, gelle.
Falk, du hast schon in der Vergangenheit in hinreichendem Maße bewiesen, das du eine besondere Befähigung hast blöde Kommentare abzugeben. Du musst es nicht ständig aufs Neue beweisen.
Es gibt nur selten einen wirklich guten Grund sich mit Festkommaarithmetik herum zu schlagen. Ja, es gibt sie manchmal. MANCHMAL.
Zumeist sind die Kommentare eine blinde Trotzreaktion ohne die echten Fakten zu kennen.
Tja, wenn man nichts kapiert, muss es dumm sein, gelle.
Falk, du hast schon in der Vergangenheit in hinreichendem Maße bewiesen,
das du eine besondere Befähigung hast blöde Kommentare abzugeben. Du
musst es nicht ständig aufs Neue beweisen.
Wie man in den Wald hinein ruft, so schallt es heraus. Und in besonderen Wäldern noch viel lauter!
Es gibt nur selten einen wirklich guten Grund sich mit
Festkommaarithmetik herum zu schlagen. Ja, es gibt sie manchmal.
MANCHMAL.
Ich behaupte das Gegenteil! Die meisten Anwendungen kommen problemlos damit aus. Eben WEIL der Dynamikbereich von Festkomma NICHT gebraucht wird! Solche ADC und andere Sensorgeschichten sind sowas!
Zumeist sind die Kommentare eine blinde Trotzreaktion ohne die echten
Fakten zu kennen.
und mache dabei nicht den Fehler, direkt ins OCRxx-Register zu schreiben, sondern die Ausgabe zu invertieren. Bei '0' soll ja auch '0' am Ausgang erscheinen ;-)
Ich behaupte das Gegenteil! Die meisten Anwendungen kommen problemlos
damit aus.
Ja selbstverständlich Falk.
Es ist unbedingt darauf zu achten das vom verfügbaren Flashspeicher nach Fertigstellung des Programms noch 95% frei bleiben.
Ebenso muss sichergestellt werden, das die CPU mindestens zu 95% im Idle herum eiert. Weil man nur dann ein echt sparsamer Profi ist.
Ich behaupte das Gegenteil! Die meisten Anwendungen kommen problemlos
damit aus.
Ja selbstverständlich Falk.
Na immerhin.
Es ist unbedingt darauf zu achten das vom verfügbaren Flashspeicher
nach Fertigstellung des Programms noch 95% frei bleiben.
Ebenso muss sichergestellt werden, das die CPU mindestens zu 95% im Idle
herum eiert. Weil man nur dann ein echt sparsamer Profi ist.
Die meisten "Profis" sind faul und verschwenderisch und das was sie am besten können ist Jammern über fehlende Resourcen, sei es Speicher oder CPU-Leistung.
156,22€ Einnahmen, 156,22€ Aussgaben, Differenz ist ungleich Null!?
Kann aber nur passieren, wenn einer von beiden oder beide berechnete Werte sind. Also nur äuserlich gleich aussehen, aber in FP-Representation doch leicht unterschiedlich sind.
Allerdings funktioniert das nicht, da dieser Weg bei 2,5V
Eingangsspannung nicht 2048 ergibt, sondern 2132. Wo ist mein
Denkfehler? Wie berechne ich das richtig?
Wie schon mehrfach bis zu Erbrechen klargestellt wurde, Deine Werte bilden eine nichtlineare Funktion, d.h. die Geradengleichung kann darauf nicht angewendet werden.
Du solltest also erstmal die Fehlerquelle ermitteln.
Ein gerne gemachter Fehler ist, daß R2R-OPVs eben nicht R2R sind, sondern auch einen Totbereich haben. Nur ist der kleiner, als bei herkömmlichen OPVs (etwa 50mV >GND bzw. <VCC).
Messungen nahe 0V sind daher stark fehlerbehaftet. Ich speise daher einen kleinen Offsetstrom in den Eingang mit ein.
Wie schon mehrfach bis zu Erbrechen klargestellt wurde, Deine Werte
bilden eine nichtlineare Funktion, d.h. die Geradengleichung kann darauf
nicht angewendet werden.
mit Offsetbetrachtung (b) aber meist ausreichend genau.
Die Geradengleichung heisst ja nicht umsonst y = m * x + b
Wie schon mehrfach bis zu Erbrechen klargestellt wurde, Deine Werte
bilden eine nichtlineare Funktion, d.h. die Geradengleichung kann darauf
nicht angewendet werden.
Du solltest also erstmal die Fehlerquelle ermitteln.
Das hat er, der TO hat (auf drängende Nachfrage) auch drei (tatsächlich ermittelte) Paare Analog|Digital genannt, die auf einer Geraden liegen: Beitrag "Re: ADC-Wert skalieren"
#1 0,156 -> 193
#2 1,79 -> 2221 (denn nent der TO aber Mittelwert statt Mittenwert)
#3 3,28 -> 4072
Und das will der TO durch etwas was er "Skalierung" nennt, dahingehend verbogen haben, das es "erscheint" wie:
#1* 0,00 -> 0
#2* 2,50 -> 2048
#3* 5,00 -> 4095
Mit dem Vorschlag, das (wie beliebig andere Zuordnungen eingelesener Wert -> verarbeiteter Wert) über eine LookUp-Table zu realisieren weiß der TO wohl nichts anzufangen. Nicht bekannt ist, wie mit Werten kleiner 0.156 und größer 3,28 zu verfahren ist.
Ich denke ja, weil ">" das Gegenteil von "<=" ist. Ganz unabhängig
davon, wie exakt die hart codierten Zahlenwerte als Float/Double
darstellbar sind.
Wobei man gerade bei gemischten Operationen float/double auch aufpassen muss.
So sind bei float x1 = sqrt(2) und double x2 = sqrt(2) die beiden resultierenden Werte NICHT gleich.
Obwohl sie bei einem einfachen printf (ohne Präzisionseinstellungen) als gleich dargestellt werden.
Ein Vergleich von Floats kann auch schief gehen, wenn die Differnz sehr
sehr klein ist.
"Sehr, sehr klein" schlägt bereits beim Kontoauszug der Bank zu, wenn man versucht, den mit 32-Bit Float aufzuaddieren, jedenfalls wenn der Kontostand nicht sehr, sehr klein ist.
Da hat man gerade einmal 23 Bit zur Verfügung.
Gestern hier im Forum veröffentlicht:
OCR0A = (262L * delta) >> 9;
Was immer der Autor damit gemeint hat
Das ist doch so offensichtlich, dass man das sogar stinkbesoffen sofort lesen kann.
Da steht ganz klar:
OCR0A = 0.51171875 * delta;
Bloß eben so ausgedrückt, dass der strunzdoofe Compiler daraus für die behinderte CPU ein sehr viel schnelleres und sehr viel kleineres Stück Code produzieren kann.
Im Übrigen könnte man dieselbe Optimierung auch so erreichen, dass sogar der Faktor direkt im Quelltext lesbar ist und auch, was die Sache macht:
Da sollte bei einem modernen Compiler zumindest in etwa dasselbe rauskommen, wie bei der Originalschreibweise. Also etwas, was sehr viel schneller und sehr viel kleiner ist als das Machwerk mit float auf demselben Target, die eben keine FPU hat.
OK, meine Frage war aber nicht "Ist meine Schaltung korrekt" oder
"funktioniert mein ADC wie er soll", sondern wie berechne ich diese
Werte korrekt.
Und es besteht auch ein großer Unterschied zwischen "kritischer
Bemerkung" und unhöflichem, großkotzigen Rumpampen,
Jajaja, ich bereue zutiefst, das ich versucht habe einen Sinn in Deinen fehlerhaften Angaben zu finden und dir mögliche Fehlerquellen genannt zu haben. Es kann nach dem GIGO-Prinzip eben keine korrekte Berechnung aus frei erfundenen Zahlen geben. https://de.wikipedia.org/wiki/Garbage_In,_Garbage_Out
Aus welchen Werten ist der Spannungsteiler zusammengesetzt
und in welchem Prozessor ist der ADC?
Wahrscheinlich in dem selben wie dort: Beitrag "STM32F4 - Audioausgabe realisieren?"
STM32F4 - selbst der kleinste hat genug Speicher für mehrere LUT's
Die Fakten ergeben sich aus dem Vergleich der account-namen und dem vertrauen das hinter den jeweiligen accounts die selbe person steckt.
Und dem kompletten Ignorieren des Bewertungssystems hier, in dem die inhaltsbesten beiträge gern mit der negativsten bewertung abgestraft werden. Halt wie bei den drei Affen "Nichts hören, nichts sehen, nichts ..." https://de.wikipedia.org/wiki/Drei_Affen
Echt?!?
Ich hätte gedacht, damit ist gemeint, wie ich es lese.
Hat >> 9 eine höhere Wertung, also wird VOR der Klammer ausgewertet?!?
Ist das wieder so ein C Ding oder ist das überall so?
Oder wie ist das zu verstehen?
262L bedeutet doch 262 als Long Wert?
Ob S. schrieb im Beitrag #7541415:
Mi N. schrieb:
Gestern hier im Forum veröffentlicht:
OCR0A = (262L * delta) >> 9;
Was immer der Autor damit gemeint hat
Das ist doch so offensichtlich, dass man das sogar stinkbesoffen sofort
lesen kann.
Hat >> 9 eine höhere Wertung, also wird VOR der Klammer ausgewertet?!?
Ist das wieder so ein C Ding oder ist das überall so?
Oder wie ist das zu verstehen?
Nein, keine Sorge. Die Klammern funktionieren in C so, wie man es nach dem Mathe Unterricht in der Schule erwartet.
262L bedeutet doch 262 als Long Wert?
Ja
Das macht er, damit die Multiplikation von 262·delta keinen Überlauf ergibt.
Ohne das "L" wären beide Operanden der Multiplikation 16 Bit Integer, deswegen würde der Compiler Code generieren, der als Ergebnis 16 Bit Integer produziert. Bei einem delta > 125 würde das nicht ausreichen.
Hat >> 9 eine höhere Wertung, also wird VOR der Klammer ausgewertet?!?
Ist das wieder so ein C Ding oder ist das überall so?
Oder wie ist das zu verstehen?
Nein, keine Sorge. Die Klammern funktionieren in C so, wie man es nach
dem Mathe Unterricht in der Schule erwartet.
Auch bei der Code Optimierung?
Da ja zwei der drei Faktoren Konstanten sind, wäre es schon Sinnvoll beim Kompilieren den Faktor 1/512 (aka ">> 9") in die Klammer zu ziehen, statt während der Laufzeit immer das Gleiche zu prozessiren.
Selbstverständlich, sonst wäre ein eine Code-Zerstörung.#
Gerade diese "Code-Zerstörung" resp. -aufweichung ist ja der Zweck einer Optimierung.
Da ja zwei der drei Faktoren Konstanten sind, wäre es schon Sinnvoll
beim Kompilieren den Faktor 1/512 (aka ">> 9") in die Klammer zu ziehen
Wäre es nicht, weil 1/512 = 0 ist und dann das Ergebnis auch 0 wäre.
Nein, der Faktor 1/512 ist nicht Null, genausowenig wie 1+1 gleich 3 ist.
Aber natürlich stimmt es, das die Zahlenrepresentationen mancher elektronischer Rechenknechte und deren Programmiersprachen die Gesetze der Mathematik (scheinbar) außer Kraft setzen resp. (unbekümmert) ignorieren.
Das ist doch so offensichtlich, dass man das sogar stinkbesoffen sofort
lesen kann.
Anders herum wird ein Schuh draus: man muß stinkbesoffen sein, um solchen Code ertragen zu können. Strunzdoof ist nicht der Compiler, sondern der Programmierer.
Hört denn dieser Kinderkram mit den vermeintlichen Optimierungen nie auf? Zum Schluß wird noch nach einem Verfahren gesucht, damit 10/3 genau 3 ergibt, um in seiner bescheiden kleinen Welt glücklich zu werden :-(
Aber gut, jeder so wie er kann.
Zum Schluß wird noch nach einem Verfahren gesucht, damit 10/3 genau
3 ergibt
Das Verfahren ist alt, lernt jeder in der zweiten(?) Klasse. Nennt sich Ganzzahlendivision mit Rest.
Und ist auf den mir bekannten Prozessoren das was beim normalen DIV Befehl rauskommt.
Nach dem also geklärt ist, dass man heute neben Festkomma auch float im µC rechnen lassen kann, hier meine Antwort auf die Frage des Threadstarters zur BERECHNUNG seines offensichtlich mehr oder weniger nichtlinearen Messproblems.
Eine Anpassung an eine Skalierungskurve zweiter Ordnung könnte in diesem Fall eher hilfreich sein als ein linearer Dreisatz: Zielwert = k0 + k1 * ADC + k2 * ADC*ADC, wobei k0 ,k1 ,k2 aus 3 (einmalig kalibrierten) Stützstellen-Wertepaaren ermittelt werden. Z.B. bei 1V, 2,5V und 4V (und dazu die jeweiligen ADC-Werte). Dann ließe sich auch die 12 Bit-Auflösung des ADC trotz des Impedanz-Dilemmas besser nutzen. Es käme nur auf eine sorgfältige einmalige Messung an. Die Berechnung der Konstanten k0-k2 erfolgt dann bekanntermaßen nach Newton. Hier ein Programmierbeispiel für die Berechnung der Konstanten zur Laufzeit aus einem bewährten Turbo-Pascal Programm von 2005 (x0/Y0-Wertepaar, a0 entspricht obigen k0 usw.):
Leider nein und inkonsequent umgesetzt, denn es geht natürlich frei von
Grundrechenarten.
1
OCR0A=((delta<<8|(delta<<1|delta)<<1))>>9;
Leider falsch. Das Ergebnis Deiner falschen Shift-Orgie ist nämlich ein uint16_t.
um 9 Bit nach rechts geschiftet bleiben nur 7 Bit übrig. Daneben müssen die Teilergebnisse addiert und nicht verordert werden.
Na geht's noch?
Das würde ja bedeuten, dem Compiler eine temporäre Typanpassung zuzumuten.
Gans schlecht programmiert - besser gegessen.
Wie gesagt: Kinderkram.
So sind bei float x1 = sqrt(2) und double x2 = sqrt(2) die beiden
resultierenden Werte NICHT gleich.
Was für eine Überraschung.
Wenn du von einer unendlich langen Zahl willkürlich unterschiedlich viele Stelle abschneidest, kannst du nicht erwarten, dass der Unterschied zwischen deinen beiden Abschnitten zufällig vollständig aus Nullen besteht, kann manchmal klappen, aber bei 29 Bit ist das doch eher unwahrscheinlich, wenn es sich nicht um binär glatte Zahlen handelt.
Kann man bitte mal nen Schaltplanauszug bekommen, dass man weis, wo da welcher Spannungsteiler wie verschaltet wurde. Wird ja hinzubekommen sein, sich dem Wusch des TO wenigstens ansatzweise nähern zu können. Ist ja keine Raketenwissenschaft, sondern Irgendwas mit "Kirchoff und Ohm" und wer da noch so seine Finger mit im Spiel hatte, damals(tm).
Vielleicht reicht es ja schon, das Impedanzniveau der Gesamtschaltung um den Faktor zehn zu verringern.
Ist ja nicht teil der Frage.
Er fragt ja nach einer Softwarelösung der IST Situation
Das er an der HArdware was ändern könnte, wusste er bzw weiß er,ja jetzt auch.
Völlig unabhängig davon finde ich aber eine Lösung für so ein Problem wie es gegeben ist auch interessanter, was den Lerneffekt angeht.
Spricht Mehrpunktkalibration, oder mit Tabelle Arbeiten etc pp
Es ist ja ok, den Themenstarter auf etwas hinzuweisen, aber seine Frage lautet ja anders und nicht was ist an der HArdware falsch und sollte geändert werden.
Kenne ich leider von meinen Themen auch, dass es dann so verläuft...
Kann man bitte mal nen Schaltplanauszug bekommen, dass man weis,
wo da
welcher Spannungsteiler wie verschaltet wurde. Wird ja hinzubekommen
sein, sich dem Wusch des TO wenigstens ansatzweise nähern zu können. Ist
ja keine Raketenwissenschaft, sondern Irgendwas mit "Kirchoff und Ohm"
und wer da noch so seine Finger mit im Spiel hatte, damals(tm).
Vielleicht reicht es ja schon, das Impedanzniveau der Gesamtschaltung um
den Faktor zehn zu verringern.
Wenn du den Rest gelesen und verstanden hättest, dann nicht.
Ich schrieb - EXPLIZIT - das ein casual printf zwei gleiche Werte anzeigt obwohl ein Vergleich der Werte kein True ergibt.
Ich schrieb - EXPLIZIT - das ein casual printf zwei gleiche Werte
anzeigt obwohl ein Vergleich der Werte kein True ergibt.
Wenn du über printf vergleichen willst (gleiche Ausgabe), musst du sicher stellen, dass dein casual printf mehr Stellen darstellt, als deine Zahl benutzt und nicht gar noch eine implizite Typumwandlung mit Stellenverlust dazwischen schalten.
Kenne ich leider von meinen Themen auch, dass es dann so verläuft...
jaja, aber das liegt auch immer an denen, die alles (T)OT machen, indem sie z.B. über SW diskutieren :-)
Und hier lohnt schon auch ein Hinweis an den TO, dass man das hätte googeln können. Wie man Widerstände und deren Abweichungen wegbekommt, ist ja easy.
Wenn du über printf vergleichen willst (gleiche Ausgabe), musst du
sicher stellen, dass dein casual printf mehr Stellen darstellt, als
deine Zahl benutzt und nicht gar noch eine implizite Typumwandlung mit
Stellenverlust dazwischen schalten.
Ernsthaft? Ich meine, ERNSTHAFT?
All das habe ich bereits früher ausführlich geschrieben.
Aber wir können's ja gerne immer wieder falsch und/oder unvollständig zitiert wiederholen.
Nebenbei sind das alles Informationen für Anfänger, wie in der Threaderöffnung unschwer zu sehen ist.
Ich glaube nicht das jemand der eine 32bit Folge mit dem Stift auf dem Papier in einen Float Wert gemäß IEEE754 umwandeln kann in diese Fallen stolpert.
Genaugenommen ist der "nackte" (32 bit) Integer ein fixpoint mit 0 Nachkommastellen also 32b.0b . Es ist ein Leichtes, die 12 bit des ADC hier so auf die 32 bit zu "skalieren" das man damit bespielsweise 16b.16b oder 22b.10b Fixpoint ausführen kann.
Und in solchen Fixpoint-darstellung ist die Zahl "1/512" eben nicht gleich 0. Man kann auch in manchen Programmiersprachen Operatoren wie '+' überladen, das auf den ersten Blick kein Unterschied zwischen der Darstellung 32b.0b und 22b.10b Rechnung erkennbar ist. Manche nennen diese triviale Grunderkenntniss aus der Numerik nicht Fixpoint, manche sprechen lediglich "von der richtigen Skalierung an der richtigen Stelle und Rundungsfehler durch unterschlagenen Nachkommastellen zu vermeiden".
Braucht bei arithmetischer Mittelung, Filterung und Statistik allenthalben.
Gerade diese "Code-Zerstörung" resp. -aufweichung ist ja der Zweck einer
Optimierung.
Sag mal, liest du auch manchmal was du schreibst?
Und - viel wichtiger - kannst du das ertragen ohne vor Schmerzen zu
schreien?
Eher ist es die Frage, ob Du nicht fähig oder nicht willens bist, die Posts die Andere verfasst haben zu verstehen!
Natürlich verändert eine Optimierung wie "Dead Code Elimination" den Code, insbesonders wenn sie wegen einem vergessen "volatile" unerwartet aktiv ist. Ebenso wirft die Optimierung "Loop unrooling" Code-teile wie den Loop-Header und pointer-Rechnung aus den Programm. Optimierende register-Allokierung wandelt langsames Speicher-lesen/schreiben in schnelles Register-umladen um, ...
Es ist ja ok, den Themenstarter auf etwas hinzuweisen, aber seine Frage
lautet ja anders und nicht was ist an der HArdware falsch und sollte
geändert werden.
Es ist nicht "nur" ok, es ist notwendig den Threadstarter unmissverständlich daraufhinzuweisen das er offensichtlich grob falsche Messwerte bearbeitet. Andernfalls setz man sich dem Vorwurf aus, ihn "sehendes Auge ins Messer laufen zu lassen".
Man kann einen defekten AD-Wandler, also einer mit massiven Grundrauschen, Offset-Fehler und Nichtlinearitäten nicht "gesund" programmieren. Das der AD-Wandler eigentlich ganz passable arbeitet, aber die "Messwerte" wie "bei 0 Volt Digitalwert '000011000001' " vom TO 'erlogen' wurden, das es so ausschaut als wäre der ADC defekt, ist dann eine ganz andere Geschichte ...
Gerade diese "Code-Zerstörung" resp. -aufweichung ist ja der Zweck einer
Optimierung.
Der Code wird ganz sicher nicht zerstört und auch nicht aufgeweicht - was auch immer diese hochgradig seltsamen Beschreibungen auch aussagen sollen.
Bei einer Code Optimierung wird in einer Art und Weise Maschinencode generiert, das der ursprüngliche Zweck und die ursprüngliche Funktion zu 100% erhalten bleiben. Wäre das nicht der Fall sein - und man beachte bitte den Konjunktiv - dann wäre es »Code-Zerstörung« und der Compiler somit reparaturbedürftig.
Nicht beachtet wird jedoch die Geschwindigkeit oder Größe des erzeugten Code. Darüber wird keinerlei Aussage getroffen oder Annahme gemacht, bzw. das ist abhängig von den Optimierungseinstellungen.
Gerade diese "Code-Zerstörung" resp. -aufweichung ist ja der Zweck einer
Optimierung.
Der Code wird ganz sicher nicht zerstört und auch nicht aufgeweicht -
was auch immer diese hochgradig seltsamen Beschreibungen auch aussagen
sollen.
Bei einer Code Optimierung wird in einer Art und Weise Maschinencode
generiert, das der ursprüngliche Zweck und die ursprüngliche Funktion zu
100% erhalten bleiben. Wäre das nicht der Fall sein - und man beachte
bitte den Konjunktiv - dann wäre es »Code-Zerstörung« und der Compiler
somit reparaturbedürftig.
Mglw. meinen wir das Gleiche, wobei der eine drastische Wortwahl benutzt. Auch macht es den Disput nicht einfacher, wenn ohne Unterscheidung von "Code" gesprochen wird unabhängig davon ob damit Opimierungs-Imput (bspw. Hochsprachen-Code) oder Optimierungs-Output (Kompilat, Maschinencode) gemeint ist.
Optimierung heisst eben Aufwandsverminderung, also beispielsweise weniger Zeit aufwenden, weniger Speicher benutzen. Und das schliesst eben auch den Fall ein, das der eigentliche Zweck "umformuliert" wird. Wie bei der Codeoptimierung, bei der eben eine Zählschleife als (dummer) Delay-ersatz rausfliegt, weil eben der gezählte Wert nie benutzt wird.
Oder beim loop-unrolling fällt bspw das incrementweg, der for () Teil exestiert schlicht nicht, kann auch bei Reverse compilieren im Instruction code nicht aufgefunden werden. Das wäre dann m.M.n. "zerstörter Code". Das kann dann beim debugging für verwunderung sorgen, wenn man beispielsweise auf das increment eines registerwertes wartet.
Und natürlich kann auch etwas "kaputt optimiert" werden, das sehe ich nicht vorrangig als Compilerfehler, sondern eher Fehler des Compiler-nutzers. Dann hat er eben ein Stück Code vom Compiler automatisch optimieren lassen, das nicht "verändert" werden darf. Also eine Form von "zu Tode gespart" resp. "an falschen Ende gespart".
Bei einer Code Optimierung wird in einer Art und Weise Maschinencode
generiert,
Widerspruch! Die Compiler zerpflücken heute in der Regel in einer Vorphase der Übersetzung des Codes selbigen so, dass er compiler-kompatibel wird, zur Aufgabe passt und die Vorgaben des Entwicklers berücksichtig, oftmals auch die des Herstellers.
Bei Funktionsaufrufen wird z.B. die Stacktiefe mitprotokolliert, die erzeugt wird um sicherzustellen, dass die Resourcen die eingestellt und verfügbar sind, auch reichen.
Beim Inlinnig wird geprüft, ob die zeitlichen Randbedingungen noch passen, wenn z.B. eine LIB als Datei ausgelagert ist, deren Funktionsteile nachgeladen werden müssen und gegengerechnet, ob der Mehr-Code, der durch Einkopieren erzeugt wird, noch in das spätere Flash passt - früher wurde sogar noch geprüft, ob der Compiler wegen der RAM-Beschränkungen die eine oder andere Stategie fahren darf - um nichts überlaufen zu lassen (ist heute natürlich weg)
Funktionsaufrufe aus lib-spezifischen API-calls werden dahingehend erweitert oder gestripped, daß die herstellereigenen Implementierungen direkt verwendet werden können, damit nicht ausgedehnter Code erzeugt und übersetzt werden muss, sondern bereits linkerfähiger Code in einer von mehreren vorbereiteten Übersetzungen verwendet werden kann - um a ) schneller zu werden, b) Knowhow zu schützen, weil so kein lesbarer C-Code vorliegen muss
weiters wegen Funktionsaufrufe so gestaltet, dass die MPS-fähig werden, also Zugriff auf Resourcen erlangen können, die mehrfach genutzt werden, bzw die in den LIBs vorbereiteten Funktionen dafür werden aktiviert - oder auch weggelassen, wenn es ein Single Core System ist.
Kurz: dein Problem hat nichts mit dem Compiler zu tun, auch wenn du dort den Schuldigen suchst.
Du solltest einfach mal deine Kennlinie aufzeichnen. Hilfreich wäre dann auch, ein paar mehr Stützpunkte der Kennlinie zu haben, wenn du schon erkennst, dass sie nicht linear ist.
Und natürlich kann auch etwas "kaputt optimiert" werden, das sehe ich
nicht vorrangig als Compilerfehler, sondern eher Fehler des
Compiler-nutzers
Klaus, ich finde du hast eine enorm erfrischende Art, jegliche
Produktfehler als durch den Kunden verursacht anzusehen!
Es ist eher so, dass sich der Anwender aus Faulheit oder seinem "Gefühl heraus" implizit auf etwas verlässt, was nirgends so dokumentiert ist. Derjenige, der die Doku zur Sprache gelesen hat, weil er dafür einen Compiler schreiben musste, nimmt auf solche faulen Kameraden und irgendwelche Gefühle natürlich keine Rücksicht.
Und natürlich kann auch etwas "kaputt optimiert" werden, das sehe ich
nicht vorrangig als Compilerfehler, sondern eher Fehler des
Compiler-nutzers
Klaus, ich finde du hast eine enorm erfrischende Art, jegliche
Produktfehler als durch den Kunden verursacht anzusehen!
Es ist eher so, dass sich der Anwender aus Faulheit oder seinem "Gefühl
heraus" implizit auf etwas verlässt, was nirgends so dokumentiert ist.
Derjenige, der die Doku zur Sprache gelesen hat, weil er dafür einen
Compiler schreiben musste, nimmt auf solche faulen Kameraden und
irgendwelche Gefühle natürlich keine Rücksicht.
Wenn halt jemand das richtige Werkzeug an der falschen Stelle/zum falschen Zweck verwendet, dann liegt das Problem eben nicht beim "Werkzeugmacher". Oder wie der Engländer kalauert: "a fool with a tool is still a fool"
Außerdem ist es meiner Erfahrung nach produktiver und führt schneller zu Erfolg wenn man die Verbesserungs/Lösungsmöglichkeiten wie bspw. Auswahl des passenden tools oder Produktes selbst in der Hand hat, als das man versucht den Hersteller zur Änderung an seinem Produkt zu bewegen.
Hinweis: die neuere Form ist "polynominal"...
"This forms part of the old polynomial API. Since version 1.4, the new polynomial API defined in numpy.polynomial is preferred. A summary of the differences can be found in the transition guide"
[https://numpy.org/doc/stable/reference/generated/numpy.polyfit.html]
Kannst du die Werte nicht mit noch etwas mehr gewürfelten
Nachkommastellen angeben? ;-)
Hätte ich gekonnt, hatte aber bequemerweise einfach die Ausgabe des Programmes wenige Zeilen darüber genommen. Hat auch gar nicht weh getan. Vor allem ändert es absolut gar nichts an der Ausführungsgeschwindigkeit.
Zunächst überflüssig erscheinende Genauigkeit wird im Bedarfsfall automagisch verworfen.
Man könnte also die Ausgabe sowohl für ›float‹ als auch für ›double‹ verwenden.
Interessanter Nebeneffekt: Man kann Micropython sowohl mit ›float‹ als auch mit ›double‹ Genauigkeit kompilieren.
Gerüchteweise soll es auch in anderen Programmiersprachen funktionieren.
Zunächst überflüssig erscheinende Genauigkeit wird im Bedarfsfall
automagisch verworfen.
Das, was du da präsentierst, ist keine Genauigkeit, sondern weitgehend sinnloser Zahlensalat.
Die Eingangsdaten haben, so wie der TO es schreibt, gerade einmal eine Genauigkeit von bestenfalls zwei gültigen Stellen. Damit kann das Ergebnis bei gerade einmal drei Messpunkten nicht plötzlich wesentlich besser werden.
Bitte beschreibe den entstandenen Schaden wenn man die Werte aus der
vorangegangenen Rechnung einfach übernimmt…
Füllen von Papier/Bildschirm mit sinnfreiem und eine nicht vorhandene Genauigkeit vorgaukelnden Zahlensalat, den vielleicht auch noch Leute lesen und fälschlicherweise für bare Münze nehmen.
Zahlensalat, den vielleicht auch noch Leute
lesen und fälschlicherweise für bare Münze nehmen.
das ist doch deren Problem, wer es nicht lernen will!
Ich nehme auch gerne Rechenergebnisse C & P wird eh vom Preprozessor ausgerechnet, sind also nur ein paar Byte im Quellcode, da muss man hier nicht die Riesenkeule schwingen.
Das, was du da präsentierst, ist keine Genauigkeit, sondern weitgehend
sinnloser Zahlensalat.
Die drei Zahlenwerte sind genau in dem Sinne, dass sie bei der
Verrechnung mit den (relativ ungenauen) Messwerten keine weitere
Ungenauigkeit hinzufügen.
Die Eingangsdaten haben, so wie der TO es schreibt, gerade einmal eine
Genauigkeit von bestenfalls zwei gültigen Stellen.
Wenn der Fehler der Eingangsdaten bei 1% liegt und die Koeffizienten
durch die von dir vorgeschlagene Rundung ebenfalls mit einem Fehler von
1% beaufschlagt werden, wächst der Fehler des Ergebnisses unnötigerweise
von 1% auf 2%. Das will man natürlich nicht.
Es ist deswegen generell ratsam, bei einer Berechnung sämtliche
Operanden mit der jeweils maximal verfügbaren Genauigkeit einzusetzen.
Die Rundung auf eine vernünftige Stellenzahl sollte immer erst beim
Endergebnis vorgenommen werden. Da ist sie aus den von dir genannten
Gründen auch sinnvoll.
Die drei Zahlenwerte sind genau in dem Sinne, dass sie bei der
Verrechnung mit den (relativ ungenauen) Messwerten keine weitere
Ungenauigkeit hinzufügen.
so kann man es auch ausdrücken, man nimmt was man hat.
Die drei Zahlenwerte sind genau in dem Sinne, dass sie bei der
Verrechnung mit den (relativ ungenauen) Messwerten keine weitere
Ungenauigkeit hinzufügen.
Dafür hätte auch die Angabe der Werte mit um 10 Stellen reduzierter Auflösung mehr als gereicht.
"keine weitere" ist genauso unsinnig wie "bestmöglich" und relativ in Bezug auf die Qualität der Ausgangsdaten.
Ich wundere mich immer mehr, mit welcher Borniertheit hier dieser bedeutungslose Zahlensalat verteidigt wird, der jeglicher Grundlage entbehrt.
Gedankenlos werden Ziffern nachgeplappert, die ein Algorithmus unter Annahme eines durch nichts begründeten Modellansatzes ausspuckt.
Und wenn die nächste Sprache/Compiler Zahlenformate mit noch höherer Auflösung unterstützt, kommen eben noch 20 Ziffern dazu und werden als goldene Wahrheit verkauft ...
Ich wundere mich immer mehr, mit welcher Borniertheit hier dieser
bedeutungslose Zahlensalat verteidigt wird, der jeglicher Grundlage
entbehrt.
Naja, ich wundere mich mit welcher Borniertheit hier gegen diese Lösung vorgegangen wird.
Wäre es nicht zielführender gewesen, wenn es dich schon so sehr stört, wenn du eine alternative Lösung angeboten hättest statt raus zu plärren "Bäh, das ist aber Scheiße.". Immerhin ist der "Zahlensalat" nachvollziehbar wo er her kommt (und deshalb auch verständlich dass er verteidigt wird), dass dir das aber egal ist macht die Sache nicht besser.
Was ich im Grunde sagen will: Wer so viel Gegenwind erfährt wie du sollte sich fragen ob er nicht doch auf dem falschen Kurs ist. ;)
Immerhin ist der "Zahlensalat" nachvollziehbar wo er her kommt
In der Technik gibt man zu Messwerten gewöhnlich einen Fehler an, der sich über weitere Berechnungen fortpflanzt.
Woher weiß der Polynomfitter, dass der Zusammenhang polynomisch mit 2ter Ordnung ist. Könnte nicht genauso gut bei einem ansonsten linearen Zusammenhang beim oberen Wert ein Sättigungsverhalten in Erscheinung treten, dass den unteren Bereich überhaupt nicht betrifft.
Wenigstens ein paar mehr Messwerte sollte man hinzuziehen.
Wenigstens ein paar mehr Messwerte sollte man hinzuziehen.
Dem bin ich ja grundsätzlich nicht abgeneigt, ich kann deinen Standpunkt durchaus nachvollziehen. Die Frage ist aber halt auch wie der Standpunkt vorgetragen wird ;)
Die jetzige Lösung bezieht sich auf drei Messpunkte und das nur deshalb weil der TE bisher nur drei Messpunkt angegeben hat. Sprich: Genauer kann es zum jetzigen Standpunkt nicht werden. Und wenn ich sehe wie sich der TE bisher verhalten hat wird es, denke ich mir, auch nicht mehr Messpunkte geben.
Norbert hat seine Lösung incl. Lösungsweg präsentiert. Jetzt liegt es am TE ob er diese Lösung verwendet, die er ja auch mit beliebig mehr Messpunkten füttern kann um die Genauigkeit zu vergrößern ;)