Hallo, wer kann mir helfen? Hab folgendes Problem: Ich möchte den Wert des A/D-Wandlers in eine Temperatur 12,34 wandeln. Bei einem ADC_WERT von 0x07FF sollte das Ergebnis 0x22 , 0x4F = 34,79 sein. Heraus bekomme ich aber 0x22 , 0xE8 = 34,23. Wo liegt mein Fehler ? int32_t t; int8_t x,z = 0; t = ADC_WERT [ADC_CANNEL]; t = t / 5; t = t - 84; t = t * 100; x = t / 934; ADC_TEMP [z] = x; t = t % 934; x = t; ADC_TEMP [z + 1] = x;
>in eine Temperatur 12,34 wandeln >Wo liegt mein Fehler ? >sollte das Ergebnis 0x22 , 0x4F = 34,79 sein ^^^^^ da! Du wolltest 12,34 als Ergebnis haben, nicht 34,79! Das folgende Programm läuft einwandfrei: int32_t t; int8_t x,z = 0; t = ADC_WERT [ADC_CANNEL]; t = t / 5; t = t - 84; t = t * (84-7*12); x = t + 12; ADC_TEMP [z] = x; t = t + 22; x = t; ADC_TEMP [z + 1] = x;
Also 12,34 sollte nur ein Beispiel sein, 2 Stellen vor dem Komma und 2 danach. Der Ganzzahlige Wert der Rechnung stimmt immer nur der Divisions Rest nicht. Da mache ich irgendwo einen Fehler. Ich erhalte 0xE8 als Divisions Rest und das sind Dezimal 232. Der Fehler legt in der Umrechnung, aber wo? Wie rechne ich es richtig um?
>Bei einem ADC_WERT von 0x07FF sollte das Ergebnis 0x22 , 0x4F = 34,79 sein.
Du bist echt etwas -sagen wir mal- beschränkt, wenn du meinst, dass das
irgendeine sinnvolle Information darstellt zusammen mit deinem
sogenannten Programm, zu dem du nicht einmal angibst, welche Sprache das
darstellen soll geschweige denn, auf welchem Supercomputer das Programm
läuft.
Alles, was ich dir sagen kann, ist, dass du mit einer if-Abfrage für den
Fall, daß der ADC_WERT 0x07FF beträgt, das Ergebnis auf 0x22 , 0x4F
setzen kannst (was immer das bedeuten mag). Für jeden weiteren ADC_WERT
hast du rein gar keine Information gegeben, wie das Ergebnis aussehen
KÖNNTE, wenn denn richtig gerechnet wird.
Du bist der typische Anfänger, der sich in das hoffentlich bald
eingerichtete Anfängerforum verziehen sollte, da du nicht in der Lage
bist, Fragen zu stellen, die ein µC-Experte beantworten könnte.
Peter
Ich sach mal, den Beitrag hätte sich "Peter (Gast)" sparen können. Der ist mir schon öfter unangenehm aufgefallen. @Bernd, wenn Du 2 Nachkommastellen haben willst, muß der Wert das 100-fache sein und dann: vorkomma = x / 100; nachkomma = x % 100; (gilt aber nur für positive Zahlen) Peter P.S.: Bei der Ausgabe der Nachkommastellen nicht die führende Null unterdrücken !
Bernd, nette Kopfnuss! Auf deine Faktoren (5, 84 und 934) und die Rechenoperationen ( - ) komme ich nicht. Aber ich habe ein nettes Tutorial zum Ganzzahlrechnen hier gefunden: http://www.avr-asm-tutorial.net/avr_de/rechnen/fpconv.html Der (Gleitkomma-)Dreisatz Temperatur_1 = Messwert * 34,79 / 0x7FF kann so umgeformt werden. Statt mit 34.79 rechnet man mit dem Hundertfachen und ist dann schon teilweise ganzzahlig. Man muss aber später das Komma richtig setzen bzw. ... bis gleich ;-) Temperatur_2 = Messwert * 3479 / 2047 Malnehmen mit 3479 wäre noch OK, aber durch 2047 teilen ist eine kniffelige Sache, die man verbessern sollte. Mit 2048 malgenommen ist der Bruch 3479*2048/2047 = 3480,699... und das ist aufgerundet 3481. Nicht vergessen durch die 2048 wieder zu teilen. Temperatur_3 = Messwert * 3481 / 2048 Jetzt kann man statt durch die "krumme" 2047 durch eine Potenz von 2 teilen. Das kann der µC sehr gut durch Shiften erledigen. Ein Beispiel: Messwert = 2047 Temperatur_1 = 34,79(00) Temperatur_2 = 3479(,00) Temperatur_3 = 3479(,30) d.h. +0,0086% Fehler Und jetzt die Multiplikation * 100 vom Anfang beachten. Vorkomma = Temperatur_3 / 100 Nachkomma = Temperatur_3 % 100
Vielen Dank für euer Kopfzerbrechen, wir reden aber aneinander vorbei. Daher gehe ich mal davon das meine Frage schlecht gestellt war. Ich möchte aus einem ADC_WERT von 84 => 0°C bis 1018 => 100°C die Temperatur mit 2 Vorkomma und 2 Nachkomma Stellen berechnen. t = ADC_WERT [ADC_CANNEL]; t = t / 5; // Ich mache 5 Messungen und addiere sie, daher teile ich erst einmal durch 5 t = t - 84; // ADC_WERT 84 => 0°C, dann 84 Abziehen (Offset) t = t * 100; x = t / 934; // ADC_WERT 100°C => 1018 – 84 = 934, also durch 934 teilen ADC_TEMP [z] = x; // Vorkommastellen speichern t = t % 934; // Hier sollten die Nachkommastellen rauskommen x = t; ADC_TEMP [z + 1] = x; Die Aufteilung in die ganzen Einzelschritte hab ich nur gemacht um meinen Fehler besser einkreisen zu können. Das Problem liegt nur an der Zeile „ t = t % 934; “ Mit dem Taschenrechner erhalte ich als Nachkomma Stellen 0x4F = 79, mein Programm bekommt aber als Ergebnis 0xE8 = 232 heraus.
Wenn ich diese Zeile weglasse, kommt bei der Division durch 934 ein wert kleiner 0 heraus. Ich hab diese Berechnung schon in einem anderen Programm, in Assembler verwendet aber ohne Nachkomma und wollte dort halt auch nur mit ganzen Zahlen rechnen.
Bernd wrote: > Die Aufteilung in die ganzen Einzelschritte hab ich nur gemacht um > meinen Fehler besser einkreisen zu können. Das Problem liegt nur an der > Zeile „ t = t % 934; “ Mit dem Taschenrechner erhalte ich als Nachkomma > Stellen 0x4F = 79, mein Programm bekommt aber als Ergebnis 0xE8 = 232 > heraus. Warum liest Du nicht einfach mal die Antworten ? Es ist völlig egal, was bei „ t = t % 934; “ rauskommt, es ist in jedem Fall Mumpitz. Es kommt irgend ne Zahl von 0..933 raus und keine Dezimalstellen. Und in ein Byte paßt es auch nicht. Nochmal: Wenn Du Dezimalstellen willst, mußt Du durch die entsprechende Zenerpotenz teilen, also /100 und %100 für 2 Dezimalstellen. Und bei Integerrechnung gilt immer, erst alle Multiplikation, dann die Divisionen (Überlauf beachten !). Was Du einmal an Stellen wegdividiert hast, kannst Du nicht mehr wieder hervorzaubern. Peter
Hallo Peter Dannegger, hab die Antworten schon gelesen, villeicht nicht alles verstanden. Hab's jetzt so gemacht: t = ADC_WERT [ADC_CANNEL]; t = t / 5; t = t - 84; t = t * 10000; t = t / 934; x = t / 100; ADC_TEMP [z] = x; x = t % 100; ADC_TEMP [z + 1] = x; und es funktioniert. Sorry noch mal Peter Dannegger hab's nicht so mit Komplizierter rechnerei und bin villeicht auch manchmal etwas schwer von begriff. Noch mal vielen Dank für die Hilfe und Denkanstösse.
Hallo! An deiner Stelle würde ich die Mathematik noch etwas vereinfachen: > t = t / 5; > t = t - 84; > t = t * 10000; > t = t / 934; in:
1 | t -= 420; // 84*5 |
2 | t = (t * 137) / 64; // 137/64 = 2.14 = 10000/934/5 (zumindest etwa) |
Falls die Genauigkeit nicht reicht z.B. (t*8771)/2^12 rechenen. Dabei aber bitte immer unbedingt Überläufe überprüfen! Viel Erfolg! Grüße Christian
Hoppla, erst denken, dann posten! :-( Vergesse bitte ganz schnell die Rechnung oben. So geht's besser:
1 | t = (t * 137) / 64; |
2 | t -= 899; // 84*10000/934 |
Grüße, Christian
Heute ist einfach nicht mein Tag :-( Beide Lösungen funktionieren, da es ja nur eine lineare Rechnung ist. Meine erste Rechnung ist sogar etwas genauer.
>Beide Lösungen funktionieren, da es ja nur eine lineare Rechnung ist. Quatsch. Gar nix linear. Er scheint integer-Variablen zu verwenden, und (int)(x/const) ist stark nichtlinear. >Meine erste Rechnung ist sogar etwas genauer. Genau das ist euer Problem. Berndt gibt zu, daß er dumm wie Brot ist, Christian hat nie heute seinen Tag, der eine will keine genaue Rechung, der andere kapierts halt nicht.
Hallo Zusammen, ich habe gerade mal nichts zu diesem Thema zu sagen, aber ich finde es erschreckend wie agressiv hier die "Anfänger" angegriffen werden. Wobei "Bernd (Gast)" noch nicht einmal ein Anfänger sein muss... ich finde so ein Forum ist da um solche Fragen zu klären und nicht um sich beschimpfen zu lassen!? Kann man nicht die IP-Adresse desjenigen sperren lassen??? Denn, wenn ich das so nachvollziehe heißt "Peter (Gast)" jetzt "u-C (Gast)".... aber die IP wird die gleiche sein!! Dieser "Experte" scheint sich nicht im klaren zu sein, dass man seine IP nachverfolgen und ihn anzeigen kann. Sowas halte ich schon für einen Persönlichkeitsangriff.... Vorstrafen zeichnen sich bei keinem Arbeitgeber gut aus!! Ich kann solche Leute auf den Tot nicht leiden!! Gruß
Genauer als:
1 | uint16_t C = (uint16_t)(((t-420)*1000UL)/467); |
wird es nunmal nicht. Das da die Integerrechnung zusätzliche Fehler verursacht, ist halt so. Wobei ich bei einer Eigenbautemperaturmessung die zweite Nachkommastelle sowieso als reines Zufallsprodukt ansehen würde, aber das ist ein anderes Thema... Oliver
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.