Hallo,
ich hoffe jemand kann mir helfen.
Ich verwende den ADC eines Atmega32 um eine Stromstärke (4-20mA) über
einen Widerstand zumessen. (Imax = 20mA, mit R=250 Ohm --> Vmax=5V; ARef
= AVCC)
Die ADC-Messung klappt schon, auch die Ausgabe auf einer
7-Segmentanzeige.
nun möcht ich den eingelesen ADC-Wert noch umrechnen. 4mA ensprechen
0kg; 20mA entsprechen 1000kg. Der Bereich dazwischen ist linear.
Daher habe ich folgende Formel entwickelt, um das Offset auszugleichen:
u32 ADU; //Mittelwert von 4 ADC-Wandlungen
u32 kg;
kg = ((1000/8184)*(ADU*10-2046)); //Faktor 10, damit ich nicht mit 818,4
und 204,6 rechnen muss
Wenn ich nun das Programm durch den AVR Simulator jage, stimmt der Wert
in ADU, aber "kg" bleibt immer 0 ...
Woran kann das liegen?
Vielen Dank schonmal für eure Hilfe
Mathias
Das glaube ich nicht. Dann wäre ja die ganze Herleitung Formel,
einschliess der AD-Werte für 0 und 20kg bzw. 4mA und 20mA falsch?
Uuups. Da gab es ja garkeine Herleitung.
Aber abgesehen davon ist 1000/8184 doch
0,12218963831867057673509286412512 .
Urgs schrieb:
> Aber abgesehen davon ist 1000/8184 doch> 0,12218963831867057673509286412512 .
Es ist eine Integer-Berechnung, und damit ist 1000/8184 = 0.
Oder war das jetzt irgendwie ironisch von dir gemeint?
>> 0,12218963831867057673509286412512 .> Oder war das jetzt irgendwie ironisch von dir gemeint?
bis 0,12218963831867 wäre es noch als normale, durchaus übliche Antwort
durchgegangen.
Ab 057673509286412512 wirds dann ironisch ;-)
> kg = ((1000/8184)*(ADU*10-2046));
Besser so:
kg = ((1000*ADU*10-2046000)/8184);
Urgs schrieb:
> Das glaube ich nicht.
Solltest du aber
> Dann wäre ja die ganze Herleitung Formel,
Herleitung und Formel sind Mathematik.
Es ist ein Fehler zu glauben, dass Arithmetik in einem Computer exakt
gleich funktioniert wie in der Mathematik. In Mathe gibt es keine
Datentypen, in C aber schon. Und der Compiler benutzt die Datentypen der
beteiligten Operanden um zu entscheiden, wie eine Operation durchgeführt
wird.
Bei dir ist alles int. Daher wird auch int gerechnet.
So wie in der Grundschule: 17 Äpfel durch 3 Kinder macht 5 Äpfel pro
Kind und 2 bleiben Rest
1000 durch 8184 macht 0 mal und 1000 bleiben Rest
int kennt nur ganze Zahlen und keine fließkomma ;)
also wenn du eine Rechnung hast bei der irgend was raus kommt wie
0,9018239083
so wird alles hinter dem Komma abgeschnitten.
Deklariere deine Variable als float oder double. Dann klappt es auch mit
Kommazahlen.
mfg
chridre
Urgs schrieb:
> @ Karl heinz Buchegger>> Noch mehr Ironie?
Die Ironie besteht darin, dass du von C keine Ahnung hast, dich hier
aber als der große Macker aufspielst.
chridre schrieb:
> Deklariere deine Variable als float oder double. Dann klappt es auch mit> Kommazahlen.
Mann kann aber auch Gehirnschmalz anstelle von Testosteron einsetzen :-)
Gleichungen kann man umstellen.
Oft kann man sie so umstellen, dass die potentiell gefährlichen
Operationen wie Division, bei denen etwas verlorengeht (nämlich die
Nachkommastellen), erst ganz zum Schluss ausgeführt werden. Bin ich
sowieso nur am ganzzahligen Ergebnis interessiert, so habe ich gegenüber
der float/double Variante meistens keinen Nachteil, habe aber den
Vorteil dass die Berechnung 30 mal so schnell durchrechnet und 40 mal
weniger Flash belegt.
Urgs schrieb:
> @ Karl Heinz> Ich glaube Du hast mich falsch verstanden.
Dann drück dich normal aus, dann gibt es auch keine Missverständnisse.
> Du wirst mir in letzter Zeit unsympathisch.
Auch recht.
Danke, an alle, dir mir die Augen geöffnet haben, besonders an Lothar.
Funktioniert nun (zumindest im Simulator), wie gewollt...
P.S.. Ich wollte hier keinen Streit auslösen ;(
> u32 ADU; //Mittelwert von 4 ADC-Wandlungen
u32 ist überflüssig (wenn der ADC-Wert rechtsbündig ausgegeben wird).
u16 ADCsum; /Summe von 4 Wandlungen (können auch mehr (8..64) sein)
u16 kg;
Wenn Du statt des Mittelwertes die Summe von 4 Wandlungen verwendest
und das in der nachfolgenden Berechnung berücksichtigst, hast Du weniger
zu rechnen und mehr Genauigkeit.
Ich würde auch nicht dividieren, sondern mit dem Kehrwert
multiplizieren, geht viel schneller.
Eigentlich müsste man auch noch aufrunden:
//bei Summe von 4 Wandlungen
#define ADCsummeVon4mA (4*1024/5) //819,2
#define Aufrunden (32768/20024) //1
kg = (ADCsumme + Aufrunden - ADCsummeVon4mA) * 20024UL / 65536UL;
Probe:
4*1023 muss 1000 ergeben:
(4*1023 +1 -819)*20024/65536=1000,3445
//bei Summe von 16 Wandlungen
#define ADCsummeVon4mA (1+16*1024/5) //3276,8 --> 3277
#define Aufrunden (32768/5005) //6
kg = (ADCsumme + Aufrunden - ADCsummeVon4mA) * 5005UL / 65536UL;
Probe:
(16*1023+ 6-3277)*5005/65536=1000,2210
Genaugenommen müsste man so rechnen:
65536*1000/4/1024/0,8=20000
(4096-819)*20000/65536=1000,06103515625
Da aber der ADC nicht 1024 ausgeben kann, hilft man dem Wert etwas auf
die Sprünge, indem man mit 20024 multipliziert.
Merke:
Der Rechner rechnet viel lieber mit Vielfachen von 2 als mit Vielfachen
von 10.
> Merke: Der Rechner rechnet viel lieber mit Vielfachen von 2 als mit> Vielfachen von 10.
Jedes Vielfache von 10 ist zugleich ein Vielfaches von 2 :-o
2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22....
Korrekt hieße das
Merke: Der Rechner rechnet viel schneller mit Potenzen von 2 als mit
Potenzen von 10.
BTW:
> ... Der Rechner rechnet viel lieber ...
"Lieb" ist dem Rechner gar nichts,
dem ist vollkommen egal, womit oder was er rechnet ;-)
eheheh nicht die mathematik verteufeln, sehr wohl hat auch die
Mathematik für das Problem einen logischen Weg! Wenn er nämlich mit Int
rechnet ist er nicht im Raum von |R sondern im Raum von Z! und somit
gibt es dort keine Zahl 0,.... und das Problem ist auch in der
Mathematik gelöst! In der Natur kommt es nur sehr oft vor das Gerechnet
wird ohne zu wissen was man tut (z.B. in welchen Raum man sich bewegt
...) und schwup die wup hat man shcon das falsche ergebnis... (schönste
beispiele sind komplizierteste gleichungen wie durch x dividiert wird
und nicht ausgeschlossen wird das x null werden kann somit die
umstellung nicht exakt ist, räume verlassen werden (imaginäre zahlen)
etc. etc. und die Leute wundern sich warum es nicht klappt (bsp.
(-1)^1/3 bzw. die dritte wurzel aus -1. die die nicht nachdenken sagen
es gibt nur eine lösung nämlich -1, das ist aber falsch es gibt exakt 3
lösungen! (-1, 0.5(-1+i*sqrt(3)), 0.5(-1-i*sqrt(3))) zugegeben ich habs
auch in der schule nicht besser gelernt aber in studium sind mir dann
die augen aufgegangen und ich überleg nun des öftern mal wenn ich einen
mist raus bekomme aus formel ob ich mir nicht hilfe bei der mathematik
holen kann ;) )
so nun: "hoch die mathematik"
Die Anfangsgleichung kann vereinfacht werden zu:
Y = (X * 1250)/1023 - 250
Die Multiplikation und Division erfordern aber immer noch 32 Bit (bzw.
24 Bit).
Wichtig ist dabei zu beachten, dass es für kleine X auch zu Unterläufen
kommen kann (die abzufangen sind).
Gruß
Dieter
> Y = (X * 1250)/1023 - 250
Bei moderater Verschlechterung der Genauigkeit kann ich
(programmtechnisch gesehen) noch weiter vereinfachen:
Y = (X * 1251)/1024 - 250
10 Bit Schieben^^^^
aber bei einem Wertebereich von 0...1000 und dem auswertbaren
ADC-Bereich von 204 (4mA) bis 1023 = 820 Schritte wird das
ganze sowieso nur ein Schätzeisen :-)
^^^^^^^^^^^
Das soll jetzt keine Abwertung des Projetes sein. Wahrscheinlich reicht
dem OP die Auflösung.
Reinhard
:::: schrieb:
> Ein Tiefpass ist resourcenschonender wie eine Mittelung und ...
Eine Mittelwertbildung über mehrere Werte ist nichts anderes als ein
Tiefpass.