Hallo,
ich habe ein Problem.Ich muss einen PT100 Auswerten. Um das ganze
abzukürzen erklär ich kurz was mein Problem ist. Ich habe die Formel des
PT100 auf T umgestellt. Mittels Referenzspannungsquelle möchte ich bei
Änderung der SPannung eine Temperaturänderung simulieren. Ich habe mir
vom ADC eine Wert ausgeben lassen bei verschiedenen Spannungen. DIesen
Wert muss ich nun in meine Umgestellte Formel einsetzen. Dabei krie ich
Utopische Werte für die Temperatur raus. Ich weiss wo der Fehjler ist,
krieg ihn aber nicht behoben. Ich muss den vom ADC umgewandelten Wert
mit einem Korrekturfaktor multiplizieren. WIe bekomme ich diesen
Korrekturfaktor raus? Oder wie kann ich diesen ermitteln.
Vielen dank im voraus für die hilfe.
Wie sieht die Bitfolge vom ADC denn aus, die du da kriegst? Du kannst
diese nicht einfach als Integer oder Float interpretieren und dann ein
"V" dahintersetzen um die Spannung zu bekommen; wie man diese Bitfolge
in eine Spannung umrechnet steht im Datenblatt vom uC. i.d.R. muss man
sowas machen wie "als signed short interpretieren, mit dem Messbereich
multiplizieren und dann durch die Anzahl der Schritte teilen" oder so.
Die Bitfolge kenn ich noch nicht.
Wie kann ich mir dirse anzeigen lassen?
Kann ich nicht auch in einer Tabelle den Wiederstandswert bei bestimmten
Temperaturen raussuchen und mir den Faktor den ich brauche errechnen?
ich habe nur 8 verschiedene Spannungswerte. Oder würde das nicht gehen.
Ich muss den PT100 nehmen. Anbei das Programm was ich bis jetzt
habe.´Vielleicht ist auch bei der Formel noch ein Fehler. Die
Deklaration hab ich mal weg gelassen.
void main(void)
{
for(;;)
{
ptrADC = adc084s021_open(DRV_ADC084S021_1); //Treiber ADC laden
ptrPRTIO = ioport_open(DRV_IOPORT_1); //Treiber PRTIO laden
Wert = adc084s021_read(ptrADC, 0); //ADC auslesen
ioport_set_value(ptrPRTIO, 1, Wert); //ADC Wert auf LEDs
anzeigen
U = Wert*Korrekturfaktor;
R = U/I;
T1=-(A/2*B)-sqrt((pow((A),2))/(4/(pow((B),2)))-(1/B)+(R/C+B));
T2=-(A/2*B)-sqrt((pow((A),2))/(4*(pow((B),2)))-(1/B)+(R/C*B));
}
}
Poste doch bitte mal den Code und nicht so ein verkrüppeltes Zeug. Wir
können schon C lesen, das brauchst du nicht zu vereinfachen. [code]-Tags
und Einrückung helfen auch.
Was macht "adc084s021_read"? Die Definition dieser Funktion wäre auch
nützlich.
Also die Funktion read soll mir die umgewandelten werte ausgeben. Hat
auch funktioniert.
ich schicke mal das was ich soweit als programm habe.
#include <drv_ioport.h> //Treiber für LED
#include <drv_adc084s021.h> //Treiber für ADC
#include <string.h>
#include <devices.h>
#include <math.h>
adc084s021_t*ptrADC;
ioport_t*ptrPRTIO;
int Wert;
const double B = -5.775e-07; //Wert in °C
const double A = 3.9083e-03; //Wert in °C
const double C = 100; //Widerstand bei 0°C in [Ohm]
const double I = 0.001; // Strom in [A]
double R, P, Q, T1, T2, U;
void main(void)
{
for(;;)
{
ptrADC = adc084s021_open(DRV_ADC084S021_1); //Treiber ADC laden
ptrPRTIO = ioport_open(DRV_IOPORT_1); //Treiber PRTIO laden
Wert = adc084s021_read(ptrADC, 0); //ADC auslesen
ioport_set_value(ptrPRTIO, 1, Wert); //ADC Wert auf LEDs
anzeigen
U = Wert*0.01;
R = U/I;
T1=-(A/2*B)-sqrt((pow((A),2))/(4/(pow((B),2)))-(1/B)+(R/C+B));
T2=-(A/2*B)-sqrt((pow((A),2))/(4*(pow((B),2)))-(1/B)+(R/C*B));
}
}
Bist du sicher, dass die Umrechnung der Spannung so passt, also ist das
U korrekt?
Wo kommen diese 100µA, die du da einsetzt? Auch B und A kommen mir
irgendwie komisch vor, was soll das sein? Die sind ja beide quasi 0.
also A und B sind konstanten des PT100. C ist der Wiederstand bei 0°C.
Der Wert ist z.B bei 0,5V referenzspannung umgewandelt 38. DIesen muss
ich jetzt mit dem korrekturfaktor multiplizieren. Dieser stellt noch die
0,01 dar und sollten nur zur überprüfung der umgestellten funktion nach
t dienen. Den korrekturfaktor gilt es zu ermitteln.der fehlt mir
Sorry, ich verstehe wirklich nicht, was du sagst.
Aus dem Thead-Titel lese ich, dass es ein Problem mit dem Auslesen der
Spannung vom ADC gibt. Ist das der Fall, oder nicht? Falls das das
Problem ist, ist ja die Berechnung der Temperatur aus dieser Spannung
erstmal irrelevant, oder?
Gruß,
Sven
Du willst also wissen, wie du den Integer-Wert vom ADC in eine Spannung
umrechnest, richtig?
Dazu rate ich, mal in's Datenblatt zu schauen, da steht das sicherlich
drin. Wie gesagt: in der Regel muss man einfach mit
<Messbereich>/<Samplezahl> multiplizieren oder so ähnlich.
also ich habe mich belesen. Da wurde gesagt, das ich die spannung
folgendermaßen ermitteln kann:
Uin= ADCwert*Referenzspannung/2^bitbreite.
die Bitbreite ist bei dem ADC 8
als Beispiel:
Uin= 38*0,5V/256=0,072.
ist der Ansatz richtug oder ist das absoluter blödsinn?
Ja, das sieht so aus, wie ich es erwarten würde. Du skalierst quasi den
alten Wertebereich von 0 bis 255 um auf 0 bis <V_max>.
Sollte also passen. Vorsichtig sein muss man noch beim Vorzeichen des
Ganzen, manchmal ist das MSB (das erste bit) das Vorzeichen. Je nach dem
halt, ob der ADC negative Spannungen misst oder nicht.
Grüße,
Sven
ich habe das jetzt einmal durchgerechnet und komme auf werte die nicht
passen können.einmal im 2stelligen minusbereich und einmal im 4stelligen
plusbereich.
Dann stimmt die annahme noch nicht
Na gut, das ist jetzt ja ein neues Problem.
Über die Formel für die Temperatur weiß ich jetzt konkret nix, aber wie
gesagt, so wie das da steht sieht es total falsch aus. A/2*B ist
ungefähr 1e-10 -- davon irgendwas abzuziehen ist sicher nicht korrekt.
Grüße,
Sven
habe mit einer anderen formel per hand gerechnet.
p=A/B
q=(1-(R/Ro)/B
T1= -p/2+sqrt(p/2)^2-q
t2 das selbe nur vor der wurzel steht -
also eine normale pq formel. Die werte stimmen nicht
Gruß
MG
Also ich hab keine Lust, mir jetzt selber diese Formel zu suchen...
entweder du beschreibst das etwas klarer, oder du musst halt auf jemand
anderen warten, der dir hilft. ;)
Schätze mal, das Er die Formelmäßige Herleitung á la:
http://de.wikipedia.org/wiki/Pt100 oder so meint.
Damit ihr über das Gleiche diskutieren könnt sollte von Euch beiden
schon die gleiche "Formulierung" benutzt werden.
Man kann die Koeffizienten ja auch x, y, z nennen und sich dann darüber
streiten wer denn wer ist.
Also spendier' Sven die vollständigen Formeln mit den Bezeichnungen der
Koeffizienten und was Du sonst noch hast. Alternativ reicht auch ein
Link.
Sven B. schrieb:> Du willst also wissen, wie du den Integer-Wert vom ADC in eine Spannung> umrechnest, richtig?
Ich behaupte: Nein!
Eigentlich will MG aus dem ADC-Wert die Temperatur berechnen. Nur klappt
das mit der Algebra noch nicht so richtig: wie setzt man 2 Formeln
ineinander ein?
BTW: weil die Frage nichts mit FPGA zu tun hat, verschiebe ich den
Thread mal ins richtige Forum.
Ich glaube du machst dir das Leben zu schwer. Es stimmt zwar das dein
Temperatursensor dir einen Widerstand in Abhängigkeit zur Temperatur
gibt aber als Folge bekommst du doch nur eine Spannung am ADC welche
einer Temperatur entspricht.
Also, angenommen eine Temperatur von 37 Grad Celsius gibt dir einen ADC
Wert von 3025 (bei einem 12 BIT Wandler) und bei 1 Grad Celsius bekommst
du z.B. einen ADC Wert von 2920 dann kannst du eine einfache Gleichung
aufstellen.
1
// ADC Werte bei 1 Grad / 37 Grad
2
#define AdcRawHigh 3025
3
#define AdcRawLow 2920
4
#define DeltaRaw (AdcRawHigh - AdcRawLow)
5
6
// Skalierung Temperatur in Celsius
7
#define RefValHigh 370.0 // Ausgabewert für AdcRawHigh = 37 Grad Celsius
8
#define RefValLow 10.0 // Ausgabewert für AdcRawLow = 1 ""
9
#define Scale 65536 // zur Basis 2^16
10
#define DeltaOut (RefValHigh - RefValLow)
11
12
// Berechnung der ADC Korrekturwerte mittels Referenzpunkte
Lothar Miller schrieb:> Sven B. schrieb:>> Du willst also wissen, wie du den Integer-Wert vom ADC in eine Spannung>> umrechnest, richtig?> Ich behaupte: Nein!> Eigentlich will MG aus dem ADC-Wert die Temperatur berechnen.
Klar, im Endeffekt schon, aber schon die Umrechnung von der Spannung war
falsch ;)
also die umstellung der Formel ist nicht das problem. Wenn ich mal aus
der PT100 Tabelle werte nehme und in die nach T umgestellte Formel
einsetze und das per hand ausrechen komm ich auch den Richtigen Wert.
Ich beschreibe mal was ich gemacht habe.
ich habe eine Konstantstromquelle mit I=1mA. Die Spannung habe ich über
eine Referenzspannung in 0,5V schritten von 0V bis 3V auf den ADC
gegeben und mit mit Wert = adc084s021_read(ptrADC, 0); folgende
Werte auslesen lassen;
Uref=0V --> ADC Wert=0
Uref=0,5V --> ADC Wert=38
Uref=1V --> ADC Wert=77
Uref=1,5V --> ADC Wert=116
Uref=2V --> ADC Wert=154
Uref=2,5V --> ADC Wert=193
Uref=3V --> ADC Wert=232
Die Konstanten sind folgender Maßen deklariert:
const double B = -5.775e-07;
const double A = 3.9083e-03;
const double C = 100;
const double I = 0.001;
mit U= Wert*Korrekturfaktor wollte ich mir mit R=U/I den
Widerstandswert ausrechten und dann in die nach T umgestellte formel für
den PT100 einsetzen und mit eine Temperatur ausrechnen lassen.
Bei sagen wir mal 50°C liegt mein optimum. ich habe eine Hysterese von
+- 10°C ausgewählt. Das heisst ich möchte, das wenn T unter 40°C ist
sollen LEDs aufleuchten. Das gleiche wenn T größer als 60°C ist. Nun
kriege ich aber nur Utopische Werte für die Temperatur raus. Dabei ist
eigentlich egal ob ich einen PT100 habe oder nicht. Wollte es halt mit
diesem Simulieren. Es soll laut aufgabe mit einem Widerstandstermometer
realisiert werden.
Vielleicht gibt es ja eine einfachere Lösung
ja hab es durchgerechnet.habe folgende Formel:
Konstanten:
A= 3,9083+10^-3
B=-5,775+10^-7
mit
p=A/B
q=(1-(R/Ro)/B
und dann in PQ-Formel eingesetzt
T1= -p/2+sqrt(p/2)^2-q
T2= -p/2-sqrt(p/2)^2-q
5+10^-7 ist auch Quatsch, das bedeutet nämlich 5,00000001. Was du meinst
ist entweder 5e-7 oder 5*10^-7, das ist nämlich 0.00000005.
Aber, funktioniert die neue Formel denn jetzt?
sollte auch ein * sein. Hast recht. Also die formel geht. Aber nur wenn
ich werte aus einer PT100 Tabelle nehme. Wenn ich die vom ADC nehme dann
nicht
das stimmen die temperturen nicht. Was an dem Korrekturfaktor liegt
denke ich .
>> Vielleicht gibt es ja eine einfachere Lösung
Die habe ich dir gezeigt! Kannst du mal eine Temperatur zu ADC Value
Zuordnung machen ? dann bist du schon am Ziel.
Arc Net schrieb:> Das kann nicht stimmen...> p ist immer negativ und sqrt(p/2) liefert keine komplexe Zahl zurück
und
T1=-(A/2*B)-sqrt((pow((A),2))/(4/(pow((B),2)))-(1/B)+(R/C+B));
T2=-(A/2*B)-sqrt((pow((A),2))/(4*(pow((B),2)))-(1/B)+(R/C*B));
liefern definitiv nicht die richtigen Werte zurück
@ Arc Net
ich verwende diese formel
Konstanten:
A= 3,9083+10^-3
B=-5,775+10^-7
mit
p=A/B
q=(1-(R/Ro)/B
und dann in PQ-Formel eingesetzt
T1= -p/2+sqrt(p/2)^2-q
T2= -p/2-sqrt(p/2)^2-q
>> die Temperatur ist doch das was ich brauche. wie soll ich die denn>> zuordnen?
OK, geh mal zu deinem Kühlschrank und hol nen paar Eiswürfel. Die legst
du auf deinen Sensor und liest den ADC Wert ab.
Dann klemmst du dir den Sensor unter den Arm und wir nehmen mal an das
du kein Fieber hast, also ca 37 Grad und dann bitte den ADC Wert.
Dann nimmst du die Formel von oben und setzt das Ergebnis ein, fertig
ist das Ding.
Dann schauen wir weiter. Glaub mir, du willst gar keinen Widerstand,
Spannung oder Strom wissen.
MG schrieb:> @ Arc Net> ich verwende diese formel>> Konstanten:> A= 3,9083+10^-3> B=-5,775+10^-7>> mit> p=A/B>> q=(1-(R/Ro)/B> und dann in PQ-Formel eingesetzt> T1= -p/2+sqrt(p/2)^2-q> T2= -p/2-sqrt(p/2)^2-q
p = A / B = 3.9083e-03 / 5.775e-07 = -6767.6190476...
R0 * (1 + a * t + b * t^2) = R
R0 + R0 a t + R0 b t^2 = R
R0 b t^2 + R0 a t + R0 - R = 0
und jetzt das ganze durch (R0 * b) ...
dann wären p und q ...
habe mal zur überprüfung das Programm zur umgestellten PT100 formel
geschrieben und die werte stimmen mit denen aus der PT100 Tabelle
überein:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main()
{
const double B = -5.775E-07;
const double A = 3.9083E-03;
double Ro = 100;
double R = 138.505;
double p,q,T1,T2;
p = (A/B);
q = ((1-(R/Ro))/B);
T1= (-p/2)+sqrt((pow(p/2,2))-q);
T2= (-p/2)-sqrt((pow(p/2,2))-q);
printf("Ergebnis p: %lf\n", p);
printf("Ergebnis q: %lf\n", q);
printf("Ergebnis T1: %lf\n", T1);
printf("Ergebnis T2: %lf\n", T2);
system("Pause");
return 0;
}
also stimmt die umstellung der Formel schon mal
als erstes muss ich sagen das ich noch keinen Sensor habe. ich wollte es
über die spannung machen. Ich kann mir aber einen PT100 simulator von
Burster besorgen. Kann ich das dann so machen, dass ich dort
verschiedene Temperaturen einstelle und mir davon jeweils den ADC wert
auslesen lasse und mit diesem dann weiter rechne? Diesen wert muss ich
ja dann auch wieder in einen Widerstandswert umrechnen oder?
MG schrieb:> int main()>> {>> const double B = -5.775E-07;> const double A = 3.9083E-03;> double Ro = 100;> double R = 138.505;> double p,q,T1,T2;>> p = (A/B);> q = ((1-(R/Ro))/B);>> T1= (-p/2)+sqrt((pow(p/2,2))-q);> T2= (-p/2)-sqrt((pow(p/2,2))-q);> printf("Ergebnis p: %lf\n", p);> printf("Ergebnis q: %lf\n", q);> printf("Ergebnis T1: %lf\n", T1);> printf("Ergebnis T2: %lf\n", T2);> system("Pause");> return 0;> }>> also stimmt die umstellung der Formel schon mal
das passt (T2)
der Rest wird einfach: Wenn es dieser
http://www.ti.com/lit/ds/symlink/adc084s021.pdf AD-Wandler ist, ist die
Versorgungsspannung zugleich die Referenzspannung. VA = VREF d.h. der
Wert, den der ADC liefert ist
Code = VIN / VREF * 256
>> Diesen wert muss ich ja dann auch wieder in einen Widerstandswert>> umrechnen oder?
Nein!, schau es dir doch mal an. Du hast 2 ADC Werte und 2 Temperaturen
die man den Werten zuordnen kann. Wenn du dann auch noch nen Simulator
hast umso besser.
2 Wertepaare und oben gezeigter Weg ist alles was du brauchst. Du
skalierst dann nur den Eingangswert auf einen Ausgangswert, simple
Algebra.
Da sich dein Sensor (Widerstand) linear verhält ergeben sich die
Zwischenwerte.
http://de.wikipedia.org/wiki/Lineare_RegressionBeitrag "kalibrierung - Linearisierung"
Bernd N schrieb:>>> Diesen wert muss ich ja dann auch wieder in einen Widerstandswert>>> umrechnen oder?>> Nein!, schau es dir doch mal an. Du hast 2 ADC Werte und 2 Temperaturen> die man den Werten zuordnen kann. Wenn du dann auch noch nen Simulator> hast umso besser.>> 2 Wertepaare und oben gezeigter Weg ist alles was du brauchst. Du> skalierst dann nur den Eingangswert auf einen Ausgangswert, simple> Algebra.>> Da sich dein Sensor (Widerstand) linear verhält ergeben sich die> Zwischenwerte.>> http://de.wikipedia.org/wiki/Lineare_Regression>> Beitrag "kalibrierung - Linearisierung"
Ja, könnte man hier machen, hilft aber auch nicht viel wenn es
tatsächlich der genannte ADC ist und mit nur 1 mA Strom gemessen wird.
Ist VREF = 5V dann wären 0°C 100 Ohm * 1 mA = 100 mV und der ADC sollte
~5 liefern, bei 20 °C wären es 107.8 Ohm * 1 mA = 107.8 mV und der ADC
sollte auch etwas um die ~5.5 liefern, bei 40 °C ~5.9...
könntest du bitte diese formel:
Code = VIN / VREF * 256
näher beschreiben.
256 ergibt sich aus 2^bitzahl, die ist bei diesem 8.
Vref ist die von mir eingestellte Spannung an der
Referenzspannungsquelle. Z.B. 3V. Was ist VIN und der Code?
Annahme VCC = 3.3V dann gilt Auflösung = 3.3V/256=0,012890625 Volt,
deine VREF ADC=3.3V. Die Schrittweite (Auflösung) ist somit bekannt.
Annahme ADCIN = 35 (der Wert kann ja max. nur 0-255 sein)
Umrechnung, UADCVolt=35*0,012890625=0,451171875 Volt
Aber wir wollen das Rechnen mit float vermeiden. Du kannst genauso gut
ADCIN * VREF / ADCauflösung rechnen.
35*3.3 / 256 = 0,451171875 Volt jetzt noch float heraus
35*3300 / 256 = 451 (mV) und damit hast du dein Ergebnis, das Komma
setzt du dann einfach in der Ausgabe Routine statisch.
Auch wenn du noch keinen Sensor hast so kannst du doch die
Eingangsspannung messen. Denke das war gemeint.
Ich glaub ich habs. hab jedenfalls gute werte für die Temperatur raus.
Hab hierzu das C programm geschrieben:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main()
{
const double B = -5.775E-07;
const double A = 3.9083E-03;
double Ro = 100;
double I = 0.001;
double p,q,T1,T2,Uadc, R;
double Aufl = (3.3/256);
double ADC = 10;
Uadc = ADC*Aufl;
R = (Uadc/I);
p = (A/B);
q = ((1-(R/Ro))/B);
T1= (-p/2)+sqrt((pow(p/2,2))-q);
T2= (-p/2)-sqrt((pow(p/2,2))-q);
printf("Ergebnis Aufl = %f \n", Aufl);
printf("Ergebnis Uadc= %f\n", Uadc);
printf("Ergebnis R= %f \n", R);
printf("Ergebnis p= %f \n", p);
printf("Ergebnis q= %f \n", q);
printf("Ergebnis T1= %f \n", T1);
printf("Ergebnis T2= %f \n", T2);
if (T2>=60)
{
printf("Heizung auschalten \n", T2);
}
else
{
if(T2<=40)
{
printf("Heizung einschalten \n", T2);
}
}
system("Pause");
return 0;
}
Wenn ihr wisst wie ich noch etwas vereinfachen kann dann immer her mit
den vorschlägen. Und besten dank an alle beteildigten für die hilfe