Pages: 1 2 [3] 4   Go Down
Author Topic: Pt100 e Smartec UTI  (Read 4200 times)
0 Members and 1 Guest are viewing this topic.
Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

vorrei fare qualche cosa del genere partendo dalla formula base RT = R0(1 + AT + BT² + C(T-100)T³), vediamo cosa riesco a combinare smiley-grin
Logged

Gianfranco

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10113
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

uhmm se vuoi una tale precisione io partirei da un termometro con già tale precisione, lo userei come riferimento per un range di misure molto più puntuali, e poi disegnerei il grafico della resistenza in funzione della temperatura. Poi dal grafico ricaverei (con non poca fatica) una funzione.

In generale, una volta che hai il grafico, testare formule come RT = R0(1 + AT + BT² + C(T-100)T³) è poco più difficile che inserire la formula in un foglio excel e vedere i valori ricavati al variare di R quanto sballano rispetto ai valori reali.
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Avessi avuto lo strumento richiesto per fare il tuo esperimento lo avrei già usato, mi sarei segnato i valori grado per grado smiley-grin
Logged

Gianfranco

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ecco un pò di codice:

Code:
#include <stdio.h>
#include "pins_arduino.h"
#include <LiquidCrystal.h>

#define UTI_PIN 5
#define UTI_RESISTANCE_REF 1000

float TempStorage[20] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};  //Contiene le ultime 20 rilevazioni
float Media = 0.0; //Contiene il valore della temperatura media
int MediaCount = 0; //Contatore che permette il calcolo della media solo dopo aver riempito completamente l'array
int ArrayMax = 19; // Dimensione massima array
int CurPos = 0; //Contiene la posizione corrente nell'array

LiquidCrystal lcd(12, 11, 6, 4, 3, 2);
unsigned long samplingMillis, printMillis;
int samplingTime = 500; //In ms, frequenza di campionamento
int printTime = 1000; //in ms, frequenza di stampa dei dati

void setup()
{
  Serial.begin(9600);
  pinMode(UTI_PIN, INPUT);
  Serial.print("Avvio PT100");
  Serial.print("\n");
  lcd.begin(16, 2);
  lcd.print("PT100");
  CurPos=-1; //Inizializzo la posizione nell'array
  delay(3000);
}

int ReadUTI(uint8_t pin, float * temp,int refRes) //Ottimizzato per PT100 4 fili - Modalità 5 (4 fasi)
{
    int state = HIGH;
    int i,startindex=-1;
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    uint8_t stateMask = (state ? bit : 0);
    unsigned long width[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
    float nOff=0,nAB=0,nCD=0,nBC=0,nDF=0;
       
    while ( (*portInputRegister(port) & bit) != stateMask)
        ;
   
    for(i=0;i<10;i++) {
      while ( (*portInputRegister(port) & bit) == stateMask)
          width[i]++;
      while ( (*portInputRegister(port) & bit) != stateMask)
          width[i]++;
    }
    for(i=1;i<10;i++) {
      if(i<6) {
        if(width[i]<width[i+2]&&width[i]<width[i+3]&&width[i]<width[i+4]&&width[i+1]<width[i+2]&&width[i+1]<width[i+3]&&width[i+1]<width[i+4]) {
          startindex=i;
          i=10;
        }
      }
    }
    if(startindex!=-1) {
      nOff=width[startindex]+width[startindex+1];
      nAB=width[startindex+2];
      nCD=width[startindex+3];
      nBC=width[startindex+4];

      *temp=((nCD-nOff)/(nAB-nOff))*refRes;
     
      return 1;
    }
    else {
      return 0;
    }
}

void readTemp()
{
  float temp;
  if(ReadUTI(UTI_PIN,&temp,UTI_RESISTANCE_REF)) {
      float TempNorm = 2.596415876*temp-264.95648; //Formula ricavata dalla calibrazione a 0 e 100 °C
     
      if (CurPos<ArrayMax){CurPos++;} else { CurPos=0; } //Gestisce la posizione del cursore all'interno dell'array
      TempStorage[CurPos]=TempNorm; //Registra la temperatura all'interno dell'array
     
      if (MediaCount<23) {MediaCount++;} //Calcola la media solo se l'array è stato riempito completamente
      else {
        Media =0.0;
        for (int i=0;i<=ArrayMax;i++) { Media = Media + TempStorage[i];}
        Media = Media / (ArrayMax+1);
      }
  }
    else {
      printTempError(); //Se l'UTI non riceve alcuna temperatura, restituisce errore
    }
}

void printTempError()
{
  Serial.print("Not Found");
  Serial.print("\n");
  lcd.setCursor(0, 1);
  lcd.print("NotFound");
}

void printTempMedia()
{
  if (MediaCount < 23) { //Stampa la media solo se l'array è completamente pieno
    Serial.print("Inizializzazione Sensore (");
    Serial.print(CurPos);
    Serial.print(")");
    Serial.print("\n");
    lcd.setCursor(0, 1);
    lcd.print("Init");
  } else {
    Serial.print(Media);
    Serial.print("\n");
    lcd.setCursor(0, 1);
    lcd.print(Media);
  }
}

void loop()

  if ((millis()- samplingMillis) > samplingTime) {
    samplingMillis = millis();
    readTemp();
  }
  if ((millis()- printMillis) > printTime) {
    printMillis = millis();
    printTempMedia();
  }
« Last Edit: November 16, 2012, 05:06:11 pm by GianfrancoPa » Logged

Gianfranco

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Al fine di poter trovare questa famosa formula magica, perfetta, di conversione, mi son messo un pochettino a giocare con Excel. Prego tutti voi di verificare che i miei ragionamenti sono esatti!!!

La formula base, per una PT100, che restituisce il valore della resistenza è la seguente:

1) Rt = R0*(1 + A*t + B*t^2 + C*(t-100)*t^3)

Supponendo di avere una PT100 ed un circuito che rispondano perfettamente a questa formula, andiamo avanti. Ho realizzato con excel una lista di valori derivati dalla suddetta formula, ed ho ricavato il seguente grafico:



Poi ho invertito x e y ed ho ottenuto il seguente grafico:



Al che ho fatto sviluppare a Excel la relativa formula:

2) t = 4E-13*Rt^6 - 2E-10*Rt^5 + 7E-08*Rt^4 - 2E-05*Rt^3 + 0,0038*Rt^2 + 2,1705*Rt - 241,09

Ho ridato quindi in pasto ad excel i dati ottenuti dalla formula 1) ed ho ottenuto un valore simile a quello iniziale. Ho quindi creato una lista degli scarti di cui ho fatto il grafico:



Ancora una volta il buon Excel ha fatto il lavoraccio:

3) y = -8E-05x2 - 0,0086x - 0,6422

Questa nuova formula corregge l'errore della 2)

In pratica, dopo tutto questo trambusto ottengo che la somma delle formule 2) e 3) danno un risultato compatibile con la formula generale 1) che è si lineare, con le dovute approssimazioni! Come vi sembra? Ho sprecato tempo??

Tutto questo mi è utile perchè, dando per scontata la correttezza di quanto fatto, ho notato che la mia configurazione pt100 + circuito, risponde alla legge generale delle PT100 (formula 1)) con un offset di 2,047 Ohm. Sapendo ciò posso facilmente adattare le formule 2) e 3) al mio caso... che ne pensate?
Logged

Gianfranco

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 415
Posts: 11993
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

penso con terrore a cosa potrai essere capace di fare quando realizzerai il primo circuito con due sonde PT100 per rilevare il range di variazione smiley-yell
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non sapevo di incutere tanto timore smiley-grin
Logged

Gianfranco

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10113
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ah, quindi hai preso la fomrula che usi - la formula vera = formula dell'errore, ma non vedo come ti possa aiutare la cosa, puoi usare direttamente la formula vera e bon. il problema quì è capire se la formula vera è abbastanza veritiera per la precisione che vuoi ottenere, no?
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

La formula vera (1) è quella che ho trovato in rete, tra le specifiche della resistenze al platino. Non posso usarla direttamente perchè restituisce la Resistenza in funzione della temperatura, mentre io ho bisogno di conoscere la temperatura in funzione della resistenza. Per tale ragione ho utilizzato Excel per trovarmi la formula inversa (2), soltanto che, vuoi per le approssimazioni, vuoi per la (forse) poca affidabilità di excel, produce un errore che in ogni caso ho calcolato e quindi eliminato aggiungendo un secondo passaggio (funzione 3).

In ogni caso ancora non posso utilizzare questa funzione perchè è ideale, ovvero non tiene conto delle imprecisioni che produce il mio hardware, che, se non ho fatto troppi errori, aggiunge 2ohm rispetto ai valori "ideali", per cui non ho 100 ohm a 0°C bensì 102 ohm; non ho 138,5 ohm a 100°C bensì 140,5ohm.

Perchè sto insistendo con la formula ideale? Mi è stato già consigliato di realizzare una semplice funzione partendo dai due punti di riferimento, cosa che ho fatto. Purtroppo questa funzione approssima il dato finale. Perchè? Leggendo in rete si trova che per ogni °C la resistenza subisce una variazione di 0,385 ohm. Purtroppo si tratta di un valore medio, perchè a 0°C la variazione è di 0,3909 ohm, mentre a 100°C è di 0,3793 ohm.

Qui trovi una tabella dei valori ricavati partendo dalla formula base: http://www.sevimpianti.it/tabella_pt100.htm

L'ideale sarebbe, come consigliato da tutti quanti, avere uno strumento già tarato su cui tarare il mio. Purtroppo non dispongo uno strumento simile, per cui devo accontentarmi dei punti di fusione ed ebollizione!
Logged

Gianfranco

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In ogni caso, paranoie a parte, ecco lo schema:



Uploaded with ImageShack.us

PS: ho apportato una correzione allo schema


Rispetto allo schema presente nel topic http://arduino.cc/forum/index.php/topic,17349.0.html, ho modificato la RBias che ho portato a 2.2K e il pin 6 (SEL 3) che da GND ho portato a +5V in modo da poter usare la Modalità 5 dell'integrato, come specificato nel datasheet per l'utilizzo di una PT100 a 4 vie. Ovviamente il codice che ho riportato qualche post fa è stato modificato adeguatamente.
« Last Edit: November 27, 2012, 09:04:47 am by GianfrancoPa » Logged

Gianfranco

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ecco il board:



Allego pure i file di Eagle


Ricordo che questo è lo schema per utilizzare una PT100 a quattro fili, nella modalità 5 indicata nel datasheet.

* Schematic.brd (56.95 KB - downloaded 9 times.)
* Schematic.pro (0.98 KB - downloaded 6 times.)
* Schematic.sch (178.89 KB - downloaded 25 times.)
« Last Edit: November 28, 2012, 04:57:49 am by GianfrancoPa » Logged

Gianfranco

0
Offline Offline
Newbie
*
Karma: 0
Posts: 44
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In ogni caso, paranoie a parte, ecco lo schema:



Uploaded with ImageShack.us

PS: ho apportato una correzione allo schema


Rispetto allo schema presente nel topic http://arduino.cc/forum/index.php/topic,17349.0.html, ho modificato la RBias che ho portato a 2.2K e il pin 6 (SEL 3) che da GND ho portato a +5V in modo da poter usare la Modalità 5 dell'integrato, come specificato nel datasheet per l'utilizzo di una PT100 a 4 vie. Ovviamente il codice che ho riportato qualche post fa è stato modificato adeguatamente.

rref non dovrebbe essere 100ohm per le pt100?

edit: ah no, come non detto smiley-grin . Comunque sto provando il tuo codice e il tuo schema (ho uno uti smartec anche io), ma mi stampa valori di resistenza intorno a 8500..C'è qualcosa che non mi torna smiley cosa potrebbe essere?

ri-edit: come non detto. penso che sto usando il vecchio codice con il nuovo schema smiley-grin potresti postare anche il nuovo codice?
« Last Edit: December 02, 2012, 06:04:58 am by sollazzo » Logged

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ottimo!! Qualcuno con cui confrontarmi è splendido!!

Allora, il tuo risultato è molto strano! La tua pt1000 è a 4 fili?? come li hai collegati i fili nel pinheader JP1? supponendo che i tuoi 4 fili siano in due coppie di colori, rosso e bianco come nel mio caso, devi mettere quelli bianchi nei pin 1-2, e quelli rossi nei pin 3-4. Ovviamente va bene anche il contrario smiley-wink
Logged

Gianfranco

Palermo
Offline Offline
God Member
*****
Karma: 2
Posts: 745
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In ogni caso prova questo codice se puoi, ho portato il campionamento a 20 secondi ed immagazzino ogni volta il valore della resistenza e non della temperatura:

Code:
#include <stdio.h>
#include "pins_arduino.h"
#include <LiquidCrystal.h>

#define UTI_PIN 5
#define UTI_RESISTANCE_REF 1000

double TempStorage[40];  //Contiene le rilevazioni
int ArrayMax = 39; // Dimensione massima array: dimensione TempStorage - 1
double Media = 0.0; //Contiene il valore della temperatura media
int MediaCount = 0; //Contatore che permette il calcolo della media solo dopo aver riempito completamente l'array
int CurPos = 0; //Contiene la posizione corrente nell'array

LiquidCrystal lcd(12, 11, 6, 4, 3, 2);
unsigned long samplingMillis, printMillis;
int samplingTime = 500; //In ms, frequenza di campionamento
int printTime = 1000; //in ms, frequenza di stampa dei dati

void setup()
{
  Serial.begin(9600);
  pinMode(UTI_PIN, INPUT);
  Serial.print("Avvio PT100");
  Serial.print("\n");
  lcd.begin(16, 2);
  lcd.print("PT100");
  CurPos=-1; //Inizializzo la posizione nell'array
  for (int i=0;i<= ArrayMax;i++) { //Inizializzo array a zero
    TempStorage[i] = 0.0;
  }
  delay(3000);
}

int ReadUTI(uint8_t pin, double * temp,int refRes) //Ottimizzato per PT100 4 fili - Modalità 5 (4 fasi)
{
    int state = HIGH;
    int i,startindex=-1;
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    uint8_t stateMask = (state ? bit : 0);
    unsigned long width[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
    double nOff=0,nAB=0,nCD=0,nBC=0,nDF=0;
       
    while ( (*portInputRegister(port) & bit) != stateMask)
        ;
   
    for(i=0;i<10;i++) {
      while ( (*portInputRegister(port) & bit) == stateMask)
          width[i]++;
      while ( (*portInputRegister(port) & bit) != stateMask)
          width[i]++;
    }
    for(i=1;i<10;i++) {
      if(i<6) {
        if(width[i]<width[i+2]&&width[i]<width[i+3]&&width[i]<width[i+4]&&width[i+1]<width[i+2]&&width[i+1]<width[i+3]&&width[i+1]<width[i+4]) {
          startindex=i;
          i=10;
        }
      }
    }
    if(startindex!=-1) {
      nOff=width[startindex]+width[startindex+1];
      nAB=width[startindex+2];
      nCD=width[startindex+3];
      nBC=width[startindex+4];

      *temp=((nCD-nOff)/(nAB-nOff))*refRes;
     
      return 1;
    }
    else {
      return 0;
    }
}

void readTemp()
{
  double temp;
  if(ReadUTI(UTI_PIN,&temp,UTI_RESISTANCE_REF)) {
      if (CurPos<ArrayMax){CurPos++;} else { CurPos=0; } //Gestisce la posizione del cursore all'interno dell'array
      TempStorage[CurPos]=temp; //Registra la temperatura all'interno dell'array
     
      if (MediaCount<(ArrayMax+4)) {MediaCount++;} //Calcola la media solo se l'array è stato riempito completamente
      else {
        Media =0.0;
        for (int i=0;i<=ArrayMax;i++) { Media = Media + TempStorage[i];}
        Media = Media / (ArrayMax+1);
      }
  }
    else {
      printTempError(); //Se l'UTI non riceve alcuna temperatura, restituisce errore
    }
}

void printTempError()
{
  Serial.print("Not Found");
  Serial.print("\n");
  lcd.setCursor(0, 1);
  lcd.print("NotFound");
}

void printTempMedia()
{
  if (MediaCount < (ArrayMax+4)) { //Stampa la media solo se l'array è completamente pieno
    Serial.print("Inizializzazione Sensore: ");
    Serial.print(CurPos);
    Serial.print("\n");
    lcd.setCursor(0, 1);
    lcd.print("Init");
  } else {
    //double TempNorm = 2.596415876*Media-264.95648; //Formula ricavata dalla calibrazione a 0 e 100 °C
    double TempNorm = 2.624704336*Media-266.3919005;
    //double TempNorm = (0.0000000000004 * pow(Media,6)) - (0.0000000002 * pow(Media,5)) + (0.00000007 * pow(Media,4)) - (0.00002 * pow(Media,3)) + (0.0038 * pow(Media,2)) + (2.1705 * Media) - 241.09;
    //TempNorm = TempNorm - ((-0.00008 * pow(TempNorm,2)) + (-0.0086 * TempNorm) - 0.6422);
    Serial.print(TempNorm);
    Serial.print(" - ");
    Serial.print(Media);
    Serial.print("\n");
    lcd.begin(16, 2);
    lcd.print(Media);
    lcd.setCursor(0, 1);
    lcd.print(TempNorm);
  }
}

void loop()

  if ((millis()- samplingMillis) > samplingTime) {
    samplingMillis = millis();
    readTemp();
  }
  if ((millis()- printMillis) > printTime) {
    printMillis = millis();
    printTempMedia();
  }
}
Logged

Gianfranco

0
Offline Offline
Newbie
*
Karma: 0
Posts: 44
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

esatto ho pt100 a 4 fili(colori diversi, bianco-blu-maroone-nero).

il bianco blu dovrebbe essere il rosso e marrone nero il bianco.


ho collegato come hai detto te e ricaricato il codice. adesso come resistenza mi rileva sempre 0  smiley-cry

Il circuito l'ho appena controllato e dovrebbe essere giusto

edit: temo che ho sbagliato i colori: il bianco dovrebbe andare col nero e il marrone con il blu. ora riprovo a vedere se cambia
« Last Edit: December 02, 2012, 08:46:33 am by sollazzo » Logged

Pages: 1 2 [3] 4   Go Up
Jump to: