Korrekturfaktor ADC 084s021

Gast #3076847
Lesenswert?

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.
#3077010
Lesenswert?

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.
Gast #3077172
Lesenswert?

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


  }
}
Gast #3077221
Lesenswert?

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


  }
}
Gast #3077240
Lesenswert?

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
#3077263
Lesenswert?

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
#3077326
Lesenswert?

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.
Gast #3077450
Lesenswert?

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?
#3077472
Lesenswert?

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
Gast #3077726
Lesenswert?

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.
Moderator (Firma: Titel) Persönliche Seite #3077905
Lesenswert?

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.
Gast #3078077
Lesenswert?

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
13
#define Slope     (DeltaOut / DeltaRaw)                           // ADC Steigung
14
#define zeroPoint (RefValLow - AdcRawLow * Slope)
15
#define Offset    (int32_t) (zeroPoint * Scale)                   // ADC Offset Fehler zur Basis 2^16
16
#define Factor    (int32_t) (Slope * Scale)                       // ADC Faktor zur Basis 2^16
Damit sind dann alle Fehler raus und deine Zahlenwerte sind sogar zur 
Basis 2 erweitert um float zu vermeiden.

Dein Rückgabewert sieht dann so aus
1
return ((((ADCValue) * Factor) + Offset) >> 16);
Eine einfache schiebe Operation.

Du denkst zu kompliziert und rechnest erst Spannung  Strom  Widerstand 
/ Temperatur. Das brauchst du nicht.
Gast #3078496
Lesenswert?

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
Gast #3078608
Lesenswert?

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 .
Gast #3078742
Lesenswert?

>> 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.
#3078744
Lesenswert?

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 ...
Gast #3078751
Lesenswert?

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
Gast #3078783
Lesenswert?

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?
#3078790
Lesenswert?

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
Gast #3078800
Lesenswert?

>> 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"
#3078806
Lesenswert?

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...
Gast #3079254
Lesenswert?

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?
Gast #3079370
Lesenswert?

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.
Gast #3079580
Lesenswert?

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
#3079608
Lesenswert?

Du hast gefragt, also...
1
> #include <stdio.h>
2
#include <math.h>
3
#include <stdlib.h>
4

5
int main()
6
 
7
 {
8
 // wie wäre es mit weniger schrecklichen Variablennamen
9
 const double B = -5.775E-07;
10
 const double A = 3.9083E-03;
11
 double Ro = 100; // const
12
 double I = 0.001; // const
13
 double p,q,T1,T2,Uadc, R; // richtige Leerzeichen, initialisieren!
14
 double Aufl = (3.3/256); // const
15
 double ADC = 10; // const
16
 
17
   Uadc = ADC*Aufl;
18
   R = (Uadc/I); // was sollen die Klammern?
19
   p = (A/B); // dito
20
   q = ((1-(R/Ro))/B); // dito; Leerzeichen!
21
 
22
  T1= (-p/2)+sqrt((pow(p/2,2))-q); // Leerzeichen!
23
  T2= (-p/2)-sqrt((pow(p/2,2))-q); // ^
24
  printf("Ergebnis Aufl = %f \n", Aufl);
25
  printf("Ergebnis Uadc= %f\n", Uadc);
26
  printf("Ergebnis R= %f \n", R);
27
  printf("Ergebnis p= %f \n", p);
28
  printf("Ergebnis q= %f \n", q);
29
  printf("Ergebnis T1= %f \n", T1);
30
  printf("Ergebnis T2= %f \n", T2);
31
  // urgh, zwei Leerzeichen Einrückung vor der Klammer und eines danach?
32
  // wer denkt sich denn sowas aus? ;)
33
   if (T2>=60)
34
    {
35
     printf("Heizung auschalten \n", T2); // printf mit Argument, aber hne format-string?
36
    }
37
   else // else if (...)
38
     {
39
      if(T2<=40)
40
       {
41
        printf("Heizung einschalten \n", T2); // s.o.
42
       }
43
     }
44
   system("Pause"); // ersetzen durch cin.get();
45
   return 0;
46
 }

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren