Forum: Mikrocontroller und Digitale Elektronik Berechnung mit ADC-wert mißlingt


von Mathias (Gast)


Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

Mathias schrieb:

> Woran kann das liegen?

Daran, dass 1000/8184 null ist.

von Urgs (Gast)


Lesenswert?

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 .

von Stefan E. (sternst)


Lesenswert?

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?

von Urgs (Gast)


Lesenswert?

>Oder war das jetzt irgendwie ironisch von dir gemeint?

War die Frage jetzt irgendwie ironisch von dir gemeint?

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


Lesenswert?

>> 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);

von Karl H. (kbuchegg)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

Hey,

hast du deine Variable in deinem Programm richtig initalisiert?
Mit int oder uint_8 ....

Vielleicht liegt es daran

von chridre (Gast)


Lesenswert?

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

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


Lesenswert?

> Deklariere deine Variable als float oder double.
Ja, klar. Und dann wundere dich, warum das Flash voll ist und das 
Berechnen solange dauert...

von Urgs (Gast)


Lesenswert?

@ Karl heinz Buchegger

Noch mehr Ironie?
Dafür wäre es ein bischen lang.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Urgs (Gast)


Lesenswert?

@ Karl Heinz

Nun mal langsam mit den jungen Pferden.

Ich glaube Du hast mich falsch verstanden.

Du wirst mir in letzter Zeit unsympathisch.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Urgs (Gast)


Lesenswert?

Auch recht.

von Mathias (Gast)


Lesenswert?

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 ;(

von Falk B. (falk)


Lesenswert?


von eProfi (Gast)


Lesenswert?

> 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.

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


Lesenswert?

> 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 ;-)

von RetterDerMathematik (Gast)


Lesenswert?

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"

von :::: (Gast)


Lesenswert?

Ein Tiefpass ist resourcenschonender wie eine Mittelung und gibt jedes 
Mal ein Resultat. Man kann auch mach exponentiellem Mittel suchen 
lassen.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

...resourcenschonender als eine Mittelung...

von Dieter S. (accutron)


Lesenswert?

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

von Reinhard R. (reirawb)


Lesenswert?

> 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

von Richard U. (ronw)


Lesenswert?

:::: schrieb:
> Ein Tiefpass ist resourcenschonender wie eine Mittelung und ...

Eine Mittelwertbildung über mehrere Werte ist nichts anderes als ein 
Tiefpass.

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.