Forum: Mikrocontroller und Digitale Elektronik ATMega und die Mathematik.


von Markus (Gast)


Lesenswert?

Hallo,
im Rahmen eines 12-bit Labornetzteils, bin ich dabei die 
Temperaturmessung zu implementieren.

Zu dem poste ich mal meine entworfene Funktion:

uint16_t meastemperatur(){

tmpspg=GetADC(2);//funktioniert
tmpspg=(double)tmpspg*(5.0/1024.0);//funktioniert
Rntc=(double)((1.0/1000.0)*(5.0-tmpspg)/((tmpspg/22000.0)));//funktionie 
rt
measuretemperatur=(double)(1/(A+(B*log(Rntc/Ref)) 
+(C*pow((log(Rntc/Ref)),2))+(D*pow((log(Rntc/Ref)),3))));//hier ist der 
Fehler!!!

return measuretemperatur;
}

//sorry irgendwie krieg ich die Einrückungen hier nicht richtig hin...

Ich hab die Variablen alle als double (ausser measuretemperatur dort 
sollte uint16_t reichen) deklariert, trotzdem kommt in der Anzeige immer 
"0".
Das Forum hab ich diesbezüglich auch schon durchsucht, allerdings konnte 
ich nicht wirklich Hilfe finden.
Würde mich freuen, wenn jemand einen Fehler in der Formel 
measuretemperatur findet.
Math.h is included

Danke

von Lukas K. (carrotindustries)


Lesenswert?

1
uint16_t meastemperatur(){
2
3
  tmpspg=GetADC(2);//funktioniert
4
  tmpspg=(double)tmpspg*(5.0/1024.0);//funktioniert
5
  Rntc=(double)((1.0/1000.0)*(5.0-tmpspg)/((tmpspg/22000.0)));//funktioniert
6
  measuretemperatur=(double)(1/(A+(B*log(Rntc/Ref))+(C*pow((log(Rntc/Ref)),2))
7
    +(D*pow((log(Rntc/Ref)),3))));//hier ist der Fehler!!!
8
9
  return measuretemperatur;
10
}

Du willst mit measuretemperatur ein Double zurückgeben, meastemperatur 
ist aber als uint16_t deklariert, das kann schonmal nicht gut gehen.
Außderdem ist Fließkommaarithmetik auf dem AVR nicht so der Hit, siehe 
Festkommaarithmetik Womöglich lassen sich deine Logarithmen und 
Potenzen auch hinreichend genau durch eine ganzrationale Funktion 
beschreiben, kannst du mal die Werte der Konstanten posten?

von holger (Gast)


Lesenswert?

measuretemperatur=(double)(1.0/(A+(B*log(Rntc/Ref))+(C*pow((log(Rntc/Ref 
)),2))
    +(D*pow((log(Rntc/Ref)),3))));//hier ist der Fehler!!!

von Markus (Gast)


Lesenswert?

Hallo, Danke für Eure schnellen Antworten.

Hier meine Konstanten:

const double A=3.354016;
const double B=2.993410;
const double C=2.13513E-06;
const double D=-8.05672;
const double Ref=22;
uint32_t Rntc;

Danke Holger, da ist mein Fehler....nur wo da...

von holger (Gast)


Lesenswert?

>Danke Holger, da ist mein Fehler....nur wo da...

1/...   !=   1.0/...

von Karl H. (kbuchegg)


Lesenswert?

> measuretemperatur=(double)(1/(A+(B*log(Rntc/Ref))
+(C*pow((log(Rntc/Ref)),2))+(D*pow((log(Rntc/Ref)),3))));//hier ist der
Fehler!!!


Brich den Ausdruck in Einzelteile auf. SOlche Monsterausdrücke haben 
hauptsächlich eines: Man vertippt sich ständig und auch die Gefahr, dass 
man sich mit den Klammern vertut, steigt enorm an.
1
  double logValue = log( Rntc / Ref );
2
  double logValue2 = logValue * logValue;   // Quadrat davon, pow( x, 2 )
3
  double logValue3 = logValue2 * logValue;  // Dritte Potenz, pow( x, 3 )
4
5
  measuretemperatur = 1.0 / ( A + B * logValue + C * logValue2 + D * logValue3 );

Nebeneffekt: Durch den Wegfall der pow() Funktion ist es ausserdem auch 
noch schneller berechnet.

von Karl H. (kbuchegg)


Lesenswert?

> uint32_t Rntc;

Wozu dann die ganzen double Rechnereien, wenn du in Rntc dann sowieso 
wieder alles wegwirfst?
An dieser Stelle ist das kontraproduktiv.
Das Ergebnis der Berechnung

   (double)((1.0/1000.0)*(5.0-tmpspg)/((tmpspg/22000.0)));

muss erst mühsam in einen uint32_t gewandelt werden, nur um dann in der 
nächsten Berechnung wieder auf einen double konvertiert zu werden. Nette 
Beschäftigungstherapie für den µC.

von Markus (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wozu dann die ganzen double Rechnereien, wenn du in Rntc dann sowieso
>
> wieder alles wegwirfst?

Ich brauche nur einen Temperaturwert, der muß nicht mal genau sein, nur 
dass ein Transistor im Überlastfall abgeschalten wird, daher weg mit den 
Genauigkeiten.

Karl Heinz Buchegger schrieb:
> Nebeneffekt: Durch den Wegfall der pow() Funktion ist es ausserdem auch
>
> noch schneller berechnet.

Najaaa, die pow Funktion soll nicht wegfallen, da lt. Datenblatt man mit 
x log (...) + y log²(...) + y log³ (...) rechnen soll.

holger schrieb:
> 1/...   !=   1.0/...

...das ist eine Idee, ich schliesse daraus, dass man das bei jedem 
Zahlenwert, den man eingibt, tun muss?

Die double Berechnungen und Ausgaben als uint-Werte klappte bei anderen 
Funktionen gut.

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:

> Karl Heinz Buchegger schrieb:
>> Nebeneffekt: Durch den Wegfall der pow() Funktion ist es ausserdem auch
>>
>> noch schneller berechnet.
>
> Najaaa, die pow Funktion soll nicht wegfallen,

doch, soll sie.
Denn ein Quadrat kann man auch einfacher berechnen als mit pow(x,2). Und 
eine 3.te Potenz kann man einfacher berechnen als mit pow(x,3)

> da lt. Datenblatt man mit
> x log (...) + y log²(...) + y log³ (...) rechnen soll.

Und was denkst du ergibt   x * x ?
Und was ergibt x*x*x

von Lukas K. (carrotindustries)


Lesenswert?

Markus schrieb:
> Ich brauche nur einen Temperaturwert, der muß nicht mal genau sein, nur
> dass ein Transistor im Überlastfall abgeschalten wird, daher weg mit den
> Genauigkeiten.

Ach, dann spare dir die ganzen Rechnereien und rechne von Hand bzw. mit 
dem Präprozessor den ADC-Wert aus, bei dem's zu warm wird.

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:

> holger schrieb:
>> 1/...   !=   1.0/...
>
> ...das ist eine Idee,

grundsätzlich ja, in deinem Fall nein

> ich schliesse daraus, dass man das bei jedem
> Zahlenwert, den man eingibt, tun muss?

http://www.mikrocontroller.net/articles/FAQ#Datentypen_in_Operationen

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
> Karl Heinz Buchegger schrieb:
>> Wozu dann die ganzen double Rechnereien, wenn du in Rntc dann sowieso
>>
>> wieder alles wegwirfst?
>
> Ich brauche nur einen Temperaturwert, der muß nicht mal genau sein, nur
> dass ein Transistor im Überlastfall abgeschalten wird, daher weg mit den
> Genauigkeiten.

Wozu dann die ganze Rechnerei eines Polynoms 3.ten Grades, wenn es eine 
Näherung auch tut.

Bist du sicher, dass du dich hier

const double A=3.354016;
const double B=2.993410;
const double C=2.13513E-06;
const double D=-8.05672;

beim D nicht mit dem Exponenten vertan hast? Ist der Sensor wirklich so 
nichtlinear?

von Markus (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Bist du sicher, dass du dich hier
>
>
>
> const double A=3.354016;
>
> const double B=2.993410;
>
> const double C=2.13513E-06;
>
> const double D=-8.05672;
>
>
>
> beim D nicht mit dem Exponenten vertan hast? Ist der Sensor wirklich so
>
> nichtlinear?

...soweit steht es im Datenblatt, wahrscheinlich fehlt da etwas in 
diesem Datenblatt, da bei allen Typen, die eine Stelle weniger haben 
steht ...E-07, bei 2 oder drei Typen steht nur ...E also wusste ich auch 
nicht was los ist und dachte mir , dass ich das Ergebnis schon rauskrieg 
:-)
Studieren heisst ja auch rumprobieren...

von Floh (Gast)


Lesenswert?

Markus schrieb:
> Ich brauche nur einen Temperaturwert, der muß nicht mal genau sein, nur
> dass ein Transistor im Überlastfall abgeschalten wird, daher weg mit den
> Genauigkeiten.

Mein Vorschlag:

const int schwelle = 150;  //Wert ist zu ermitteln
...
if(GetADC(2) > Schwelle)
  abschalten();
:-)

von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

Lesenswert?

Datenblatt genau lesen (s. Anhang).

Edit1:

Irgendwas stimmt im Datenblatt aber trotzdem nicht: Die Einheit aller
vier Koeffizienten sollte K¯¹ sein. Wenn dies der einzige Fehler ist,
sollte das Ergebnis aber trotzdem stimmen.

Edit2:

Wenn Rref=R25=22Ω ist, ist lt. Datenblatt der B25/85-Wert 3136K und
nicht 3390K. Die Koeffizienten sollten dann nach obiger Tabelle

  A1=3.354016e-3
  B1=3.243880e-4
  C1=2.658012e-6
  D1=-2.70156e-7

sein.

von Markus (Gast)


Lesenswert?

...so ich bins wieder, als erst einmal Danke an Euch alle,
die Hinweise mit den Größenordnungen und die Aufspaltung in Einzelne 
Terme haben es letztlich gebracht.
Es kommen zwar ca. 25 Grad zu wenig raus aber das krieg ich schon 
umgerechnet.

Der interne AD-Wandler oder der Vorwiderstand von 22K zu einem 68K-NTC 
werden wohl nun die Ursache für die Abweichung sein,
aber das rechne ich schon irgendwie raus.

MFG

von Yalu X. (yalu) (Moderator)


Lesenswert?

Markus schrieb:
> Es kommen zwar ca. 25 Grad zu wenig raus aber das krieg ich schon
> umgerechnet.

Dann ist da noch irgendwo ein grober Denkfehler drin.

> Der interne AD-Wandler oder der Vorwiderstand von 22K zu einem 68K-NTC
> werden wohl nun die Ursache für die Abweichung sein,

Das glaube ich nicht. Der ADC ist wahrscheinlich genauer als der NTC und
22kΩ vor einem 68kΩ-NTC klingen auch nicht abwegig.

> aber das rechne ich schon irgendwie raus.

"Irgendwie" hat irgendwie immer ein ungewisses Ergebnis. Und irgendwie
habe ich das unbestimmte Gefühl, dass du noch nicht ganz verstanden
hast, wie man den NTC richtig anwendet ;-)

Wenn du mir folgende Fragen beantwortest, zeige ich dir, wie du systema-
tisch zum Ziel kommst:

1. Um welchen Typ von NTC handelt es sich genau? Wenn es der ist, den
   ich vermute, kommt er von Vishay/BCcomponents und hat eine Typbe-
   zeichnung der Form "2322 640 nnnn", wobei jedes n für eine Ziffer
   steht. Wenn du den genauen Typ kennst, weiter mit (5).

2. Welchen R25-Widerstand hat der NTC? Sind die 68kΩ aus deinem letzen
   Beitrag sicher oder nur vermutet? Wenn du dir 200%ig sicher bist,
   weiter mit (5).

3. Hat der NTC Farbringe? Die o.g. Serie hat bspw. vier davon. Welches
   sind deren Farben, von unten nach oben? Wenn der NTC mindestens drei
   Farbringe hat, weiter mit (5).

4. Miss den Widerstand bei Zimmertemperatur in ausgebautem Zustand mit
   einem Ohmmeter und gleichzeitig die Umgebungstemperatur mit einem
   ordentlichen Thermometer. Fass dabei den NTC mindestens 1 Minute vor
   der Messung nicht mit den Fingern an, damit er nicht zusätzlich er-
   wärmt wird. Wie hoch ist der Wider- stand und die Temperatur?

5. Wie ist der NTC geschaltet? Wenn ich dich richtig verstanden habe
   liegt er in Reihe zu einem Vorwiderstand an 5V. Wenn das stimmt:
   Welcher der beiden Widerstände liegt an 5V und welcher an Masse?

6. Welchen Temperaturbereich (Minimum, Maximum) möchtest du messen?
   Davon hängt die richtige Wahl des Vorwiderstands (oder ggf. einer
   geeigneten Verstärkerschaltung) ab.

7. Wie hoch ist die Referenzspannung des A/D-Umsetzers?

8. Welche Genauigkeit und welche Auflösung in K soll die Messung haben?

Nur wenn du zielgerichtet vorgehst, hat die von dir programmierte kom-
plizierte Formel einen Sinn. Wenn man du eine der vielen Einflussgrößen
außer Acht lässt oder dabei von falschen Annahmen ausgehst, wird das
Ergebnis ungenau, und es ist schade um die Rechenzeit, die diese Formel
verschlingt.

von Lukas K. (carrotindustries)


Lesenswert?

Markus schrieb:
> Ich brauche nur einen Temperaturwert, der muß nicht mal genau sein, nur
> dass ein Transistor im Überlastfall abgeschalten wird, daher weg mit den
> Genauigkeiten.
Also nur <> kritische temperatur
Yalu X. schrieb:
>[...]
> Nur wenn du zielgerichtet vorgehst, hat die von dir programmierte kom-
> plizierte Formel einen Sinn. Wenn man du eine der vielen Einflussgrößen
> außer Acht lässt oder dabei von falschen Annahmen ausgehst, wird das
> Ergebnis ungenau, und es ist schade um die Rechenzeit, die diese Formel
> verschlingt.

Wozu das ganze? Mit nem Fön oder wie auch immer den NTC erwärmen, 
Thermometer dranhalten, Spannung messen, in ADC-Wert umrechnen, fertig.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Luk4s K. schrieb:
> Wozu das ganze? Mit nem Fön oder wie auch immer den NTC erwärmen,
> Thermometer dranhalten, Spannung messen, in ADC-Wert umrechnen, fertig.

Ja klar, das geht auch. Nur ist dann die Diskussion um Monsterformel im
Eröffnungsbeitrag mit den auf 7 Stellen genauen Koeffizienten für die
Katz.

Luk4s K. schrieb:
> Markus schrieb:
>> Ich brauche nur einen Temperaturwert, der muß nicht mal genau sein, nur
>> dass ein Transistor im Überlastfall abgeschalten wird, daher weg mit den
>> Genauigkeiten.

Huch, das habe ich völlig übersehen :)

Dann genügt ja ein simpler Schwellwert, und es muss praktisch gar nichts
gerechnet werden. Dafür ist aber so ein "Accuracy Line"-NTC eigentlich
viel zu schade ;-)

von Anja (Gast)


Lesenswert?

Markus schrieb:
> Ich brauche nur einen Temperaturwert, der muß nicht mal genau sein, nur
> dass ein Transistor im Überlastfall abgeschalten wird, daher weg mit den
> Genauigkeiten.

Wenn Du den Vorwiderstand = dem NTC-Widerstandswert deiner 
Schaltschwelle machst kannst Du davon ausgehen daß die Kennlinie in 
einem Bereich +/-15 Grad um die Schaltschwelle halbwegs linear ist 
(Linearitätsfehler ca 0,3 Grad). Gleichzeitig hast Du bei dieser 
Dimensionierung die maximale Empfindlichkeit.

Da reicht dann ein wenig 3-Satz und 32Bit Integer-Arithmetik.

Gruß Anja

von Karl H. (kbuchegg)


Lesenswert?

Yalu X. schrieb:

> Dann genügt ja ein simpler Schwellwert, und es muss praktisch gar nichts
> gerechnet werden.


Und wie soll dann der Flash voll werden?
So lagen wenigstens die Floating Point Routinen da drinnen und der µC 
hatte was zu tun. :-)

von Lukas K. (carrotindustries)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Yalu X. schrieb:
>
>> Dann genügt ja ein simpler Schwellwert, und es muss praktisch gar nichts
>> gerechnet werden.
>
>
> Und wie soll dann der Flash voll werden?
> So lagen wenigstens die Floating Point Routinen da drinnen und der µC
> hatte was zu tun. :-)
Ich gehe mal davon aus, dass das Netzgerät nen alphanum. LC-Display 
bekommt
Wie wär's mit div Hilfetexten und Serviceanleitungen, die Beschreiben, 
was bei zu warmem Transistor zu unternehmen ist? ;)

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.