Temperaturmessung mit PT100 und MAX31865

In dieses Forum gehören all deine Fragen rund um die Elektrotechnik und im Speziellen zum Bereich der Mikrocontrollertechnik.

Temperaturmessung mit PT100 und MAX31865

#1

Ungelesener Beitrag emy » 1. Apr 2019, 15:33

Hallo an alle,

ich bin nicht nur neu hier, sondern auch absoluter Anfänger was die Programmierung eines Mikrocontrollers angeht.

Ziel ist es, eine Temperatur mit Hilfe eines PT100 und eines MAX31865 RTD-to-Digital Converter zu messen (Masterarbeit). Ich habe bereits die Entwicklungsumgebung, passenden Compiler und den Pickit 3, sowie MCC-Software, die ja einiges erleichtern soll. Ich nutze einen PIC24FJ256DA206.

Ich habe mir bereits mit einem Oszilloskop ein paar Nullen und Einsen an einem Pin anzeigen lassen, die Kommunikation funktioniert also.

Nun fehlt es mir aber an Erfahrung und ich weiß nicht so recht wie ich anfangen soll. Vielleicht hat ja jemand Erfahrung mit einem RTD-to-Digital-Converter?
Im Netz habe ich tatsächlich Codes für mein Bauteil gefunden, die mir im Verständnis schon ein bisschen helfen konnten: https://www.mikrocontroller.net/attachm ... ght/218763 und https://www.mikrocontroller.net/attachm ... ght/219344
Was ich breits gemacht habe: nicht viel :D, ich habe eine SPI Schnittstelle in der MCC ausgewählt und im Pin Manager meine Pins für Clock SDI und SDO festgelegt. Der Chip Select Pin ist ein normaler GPIO. Ich habe auch angefangen die Register zu definieren.

Die nächsten Schritte wären jetzt verschiedene Funktionen für das Schreiben und Lesen der Register und das Berechnen und Ausgeben der Temperatur. Habt ihr das ein paar Tips wie ich den Anfang in das Programm finde oder vielleicht sogar Beispiele?

Als Anfänger bedanke ich mich schon einmal für die Geduld.

Re: Temperaturmessung mit PT100 und MAX31865

#2

Ungelesener Beitrag Nico » 1. Apr 2019, 20:21

Hi @emy,

willkommen bei uns im Forum.

Die grundsätzliche Funktion des MAX hast du ja offenbar bereits verstanden. Für den Anfang wäre es sicherlich nicht verkehrt, den 1-Shot Modus zu nutzen. Sprich, der Chip macht nichts, solange du ihn nicht dazu aufforderst. Zu Beginn einer neuen Messung, schreibst in das Configuration Register mit 80h als Adresse. Im selben Zyklus (CS low) sendest du im Anschluss den Wert, den du in das Register schreiben möchtest. Sobald du den Chip wieder deselektierst (CS wieder high), beginnt der Chip die Messung. Hier musst du aufpassen, dass der Chip zuvor nicht direkt im Bias off mode war, andernfalls sind die Kondensatoren ggf. noch nicht vollständig auf den Messwert geladen.

Aber bevor du soweit bist, musst du natürlich erstmal ein entsprechendes Grundgerüst für deinen Controller, den PIC, haben. Wenn du jetzt schon mit dem Code Configurator angefangen hast, spricht grundsätzlich auch nichts dagegen, diesen weiter als Hilfe zu nutzen. Ein erster Wichtiger Punkt ist die Konfiguration des Chips zu setzen (Takt, Reset ..). Ggf. hast du das auch schon erledigt?

Wenn diese grundsätzlichen "Säulen" stehen, kannst du entsprechende SPI Funktionen schreiben. Dabei gehst du von "unten" nach "oben" vor. Soll heißen, dass du zu aller erst eine Funktion schreibst (vielleicht auch via MCC), die dein SPI Interface entsprechend initialisiert. Im Anschluss schreibst du eine Funktion, die ein einzelnes Byte über den Bus sendet und parallel liest. Die Funktion kannst du erweitern um mehrere Bytes zu schreiben/lesen. Dies ist die Treiber-Ebene. Darüber setzt du die Library-Ebene, die bereits etwas abstrahiert arbeitet und Funktionen für den MAX Chip bereitstellt, z.B. start_measurement(): Die Funktion nutzt dann entsprechende "tiefere" Funktionen, die Bytes auf dem SPI Interface schreiben/lesen.

Je nachdem wie die Darstellung der Messwerte realisiert werden soll, ist hier evtl. noch vorher eine Entsprechende Programmierung notwendig (Display) um das Entwickeln etwas angenehmer zu gestalten. Sprich wenn z.B. ein LCD zur Anzeige genutzt werden soll, stell zunächst sicher, dass du fehlerfrei z.B. auf Knopfdruck einen 16 Bit Hexadezimalwert darstellen kannst (z.B. 0x137F). So wird die Programmierung des MAX später etwas komfortabler, da du Werte nicht immer mit dem PICKit auslesen musst.

Idealerweise lieferst du noch etwas mehr Informationen (Schaltplan, bereits geschriebener Code).

Viele Grüße
Nico

Re: Temperaturmessung mit PT100 und MAX31865

#3

Ungelesener Beitrag emy » 1. Apr 2019, 21:58

Vielen Dank für deine Antwort, Nico.

Meine Schaltung wird leider geopfert, das heißt sie wird die hohen Temperaturen nicht überstehen, sondern sendet so lange wie möglich die Temperaturwerte an einen Emfänger. Die Messung muss beginnen, sobald die Spannungsversorgung (Batterien) angeschlossen werden (ist das überhaupt möglich?). Und es wird dort kein Computer mehr in der Nähe geben, um die Messungen zu starten. Daher kann der 1-Shot Modus nicht genutzt werden oder? :)
Demnach gibt es auch kein Display, sondern die Messwerte sollten kontinuierlich mit Hilfe eines Transceivers gesendet werden, der ersteinmal außer Acht gelassen werden soll (er ist auch noch nicht auf der Platine), da ersteinmal der MAX mit dem Mikrocontroller funktionieren soll. So viel noch einmal zum Zweck meines ganzen Vorhabens.

Ein Bild meiner Schaltung füge ich morgen hinzu.
Wie das Lesen und Schreiben in die Register generell funktionieren müsste, hoffe ich bereits zu wissen. Schwierigkeiten macht die Umsetzung in C. Beispielsweise eine Write-Funktion, wie ich sie im Beispiel gefunden habe:

Code: Alles auswählen

void Write(byte w_addr, byte data) {
digitalWrite(CS_Pin, LOW);
SPI.transfer(w_addr);
SPI.transfer(data);
digitalWrite(CS_Pin, High);
}
hier ist klar, dass das natürlich von den Befehlen her nicht passt. Das so aber hinzubekommen bereitet mir Schwierigkeiten, oder ich bin zu blöd zu googlen...

Für die grundsätzlichen "Säulen" dachte ich dass die Grundeinstellungen schon nicht ganz verkehrt sind, bei meinem Pic sind es jetzt zum Beispiel 8 MHz.

Viele Grüße

Re: Temperaturmessung mit PT100 und MAX31865

#4

Ungelesener Beitrag emy » 2. Apr 2019, 10:28

Hier nochmal der Ausschnitt der Schaltung MAX und Mikrocontroller. Transceiver und Beschleunigungssensor sind nicht mit enthalten.
Dateianhänge
Schaltung.png

Re: Temperaturmessung mit PT100 und MAX31865

#5

Ungelesener Beitrag Sven » 2. Apr 2019, 11:11

emy hat geschrieben:
1. Apr 2019, 21:58
Meine Schaltung wird leider geopfert, das heißt sie wird die hohen Temperaturen nicht überstehen, sondern sendet so lange wie möglich die Temperaturwerte an einen Emfänger.
Du meinst hiermit aber hoffentlich nur den PT Widerstand?

Re: Temperaturmessung mit PT100 und MAX31865

#6

Ungelesener Beitrag emy » 2. Apr 2019, 11:19

Sven hat geschrieben:
2. Apr 2019, 11:11
Du meinst hiermit aber hoffentlich nur den PT Widerstand?
Nein leider alles. Es wird eine Sonde entwickelt, die in pyroklastische Ströme geworfen wird und von dort aus die Temperatur sendet. Demnach wird alles, Gehäuse, Elektronik und Sensor geopfert.

Re: Temperaturmessung mit PT100 und MAX31865

#7

Ungelesener Beitrag Sven » 2. Apr 2019, 11:42

Sicherlich bist du an gewisse Geheimhaltung gebunden .. mich würde interessieren, wie die Messdaten letztendlich gesendet werden insbesondere über welches Medium. Im Klartext sollen die Messdaten gefunkt werden? Ist das überhaupt möglich aus so einer Wolke (pyroklastische Ströme sind doch sowas wie Glutwolken bei Vulkanen, oder?)?

Re: Temperaturmessung mit PT100 und MAX31865

#8

Ungelesener Beitrag emy » 2. Apr 2019, 12:13

Ja so in etwa. Mit einem Transceiver und Monopolantenne. Medium kann man schlecht definieren. Die pyroklastischen Ströme sind ja noch nicht ganz genau erforscht, eben wegen der extremen Umgebung. Es wird ein erster Prototyp gebaut, wo genau diese ganzen Sachen getestet und geklärt werden sollen.

Re: Temperaturmessung mit PT100 und MAX31865

#9

Ungelesener Beitrag Nico » 2. Apr 2019, 13:53

Meine Schaltung wird leider geopfert, das heißt sie wird die hohen Temperaturen nicht überstehen, sondern sendet so lange wie möglich die Temperaturwerte an einen Emfänger. Die Messung muss beginnen, sobald die Spannungsversorgung (Batterien) angeschlossen werden (ist das überhaupt möglich?).
Na klar, das ist kein Problem.
Und es wird dort kein Computer mehr in der Nähe geben, um die Messungen zu starten. Daher kann der 1-Shot Modus nicht genutzt werden oder? :)
Ich meinte damit, den 1-Shot Modus für die ersten Versuche zu nutzen. Quasi das Grundgerüst samt Konvertierung (sofern diese überhaupt notwendig, da Daten ja sowieso ohne Anzeige weitergegeben werden) mit diesem Modus aufsetzen. Ist so ggf etwas einfacher. Wenn dann hinterher die gesamte Strecke funktioniert, kann man ja immer noch den Modus wechseln (also dann für den richtigen Einsatz).
Das so aber hinzubekommen bereitet mir Schwierigkeiten, oder ich bin zu blöd zu googlen.
Ja gut, ein fertiges Programm wirst du kaum finden ;-) aber das ist dir sicher klar. Ich melde mich heute Abend nochmal mit einer kleinen Starthilfe, die dir hoffentlich hilft in die Programmierung einzusteigen.
Für die grundsätzlichen "Säulen" dachte ich dass die Grundeinstellungen schon nicht ganz verkehrt sind, bei meinem Pic sind es jetzt zum Beispiel 8 MHz.
Bei dem bisschen und 8 MHz langweilt sich der Controller zu Tode ;-) also die 8 MHz sollten dicke ausreichen.

Bis später

Re: Temperaturmessung mit PT100 und MAX31865

#10

Ungelesener Beitrag Nico » 2. Apr 2019, 19:53

Also hier nun mal ein Beispiel, wie man den Aufbau gestalten könnte. Ich mache es in der Regel so, dass ich die Konfiguration (#pragma Anweisungen), die Grundinitialisierung sowie die Endlosschleife in die main.c Datei lege. Das sieht dann so oder so ähnlich aus:

main.c

Code: Alles auswählen

// description of file, project, license

// some include files
#include <xc.h>
#include <stdint.h>
#include <maxrtd.h>

// configuration
#pragma ...

void main (void)
{
   // some initialisation here
   init_pic();
   init_spi();
   // ...
   
   while(1)
   {
      // processing of arising tasks
   }
}
Der Prozessor startet in der main() Funktion und würde dann erstmal damit beginnen grundlegende Einstellungen wie GPIOs, Timer, Interrupts und weitere Dinge zu initialisieren (z.B. auch eine SPI Schnittstelle). Im Anschluss läuft der Controller üblicherweise in die Endlosschleife (siehe while(1) aus der er nur noch über besondere Ereignisse, wie etwa einem Reset, rauskommt. Innerhalb der Schleife werden in der Regel anfallende Aufgaben erledigt, die bspw. über entsprechende Flags signalisiert werden. Diese Flags werden meist über Interrupts gesetzt. So könnte man später auch ein neues Messergebnis des ADCs erkennen und dann entsprechend über SPI vom Chip abrufen. Aber eins nach dem anderen. Für die ersten Gehversuche reicht es auch erstmal völlig aus mittels Polling (= ständiges manuelles prüfen) nach neu verfügbaren Messungen zu prüfen. Daher auch der Vorschlag mit dem 1-Shot Modus. Eine erste Variante könnte daher wie folgt aussehen:

Code: Alles auswählen

void main (void)
{
   uint16_t val;
	
    // ...
	
   while(1)
   {
      // start a new measurement (e.g. via 1-Shot)
      maxRTD_request_new_meas_1s();
      
      // wait as long as DRDY is high
      while(DRDY);
      
      // read the measurement result
      val = maxRTD_read_res();
      
      // ...
   }
}
Ich würde dir gerne ans Herz legen, Funktionen systematisch zu gruppieren und Module anzulegen (siehe auch Modularisierung). Das wird dir ungemein helfen die Übersicht zu behalten (auch wenn ein Projekt keine 10.000 Zeilen Code hat ist es immer anzuraten seinen Code sauber zu strukturieren. Auch in Bezug auf spätere Wartbarkeit ist dies von entschiedener Bedeutung. Also wir möchten eine saubere Struktur in unserem Projekt, also legen wir Module an (wobei ein Modul hier einfach eine weitere C-Datei samt ggf. H-Datei ist).

In der main.c habe ich schon mal demonstrativ die maxrtd.h Datei eingebunden (siehe #include "maxrtd.h"). Sprich alle Funktionen, die im Zusammenhang mit dem MAX Chip stehen, werden in der Datei maxrtd.c gebündelt. Hier ein Beispiel, wie diese Datei in etwa aussehen könnte:

maxrtd.c:

Code: Alles auswählen

#include <stdint.h>
#include <stddef.h>
#include "maxrtd.h"
#include "spi.h"

/**
 * \brief	A little description what this function will do.
 */
void maxRTD_request_new_meas_1s (void)
{
   uint8_t buf[2];
   
   buf[0] = 0x80; // config write address
   buf[1] = 0bA2; // start a new 1-shot measurement
   
   // transfer two bytes (storred in buf)
   spi_transfer(buf, NULL, 2);
}

/**
 * \brief	Read the latest result.
 *
 * \return	The 15 bit result
 */
uint16_t maxRTD_read_res (void)
{
   uint8_t buf[3];
   
   buf[0] = 0x10; // read address of RTDs MSB
   
   spi_transfer(buf,buf,3);
   
   return ((buf[0] << 8) | buf[1]);
}
So würde man immer weiter vorgehen. In der Regel fängt man dabei "unten" an zu programmieren. Sprich die eigentlichen Treiber programmieren um zum Beispiel die SPI Schnittstelle des PIC ordnungsgemäß nutzen zu können. Anschließend eine Ebene weiter oben, die Funktionen für den MAX und so weiter.

Demnach könnten die Funktionen für das SPI Interface in der spi.c Datei gesammelt sein:

spi.c:

Code: Alles auswählen

#include <xc.h>
#include <stdint.h>
#include <stddef.h>

void spi_init (void)
{
   // initialize the spi interface with mode, frequency...
}

void spi_transfer (uint8_t *pWrBuf, uint8_t pRdBuf, uint8_t len)
{
   while(len)
   {
      if(pWrBuf != NULL)
      {
         pWrBuf++;
      }
      
      if(pRdBuf != NULL)
      {
         pRdBuf++;
      }
      
      // start the spi write
      // read the spi input byte
      
      len--;
   }
}
Wichtig: Die gezeigten Beispiele sind wirklich nur Anregungen und kein funktionierender Programmcode!
Ich hoffe die Beispiele helfen ein bisschen als Gedankenanstoß :-)

Viele Grüße
Nico

Re: Temperaturmessung mit PT100 und MAX31865

#11

Ungelesener Beitrag emy » 2. Apr 2019, 21:38

Ich danke dir jetzt schon einmal für deine Hilfe und Bemühungen. Ich werde mich da einmal durchhangeln und werde schon einmal meine ersten Versuche starten.

Bestimmt komme ich noch einmal drauf zurück, wenn ich vor konkreteren Problemen stehe.

Vielen Dank und liebe Grüße!

Re: Temperaturmessung mit PT100 und MAX31865

#12

Ungelesener Beitrag emy » 10. Apr 2019, 15:44

Ich nochmal...

Ich bin in der Lage das korrekte Byte zu dem korrekten Pin zu schreiben. Ein kleiner Fortschritt :)

Jetzt geht es darum, aus dem MSB und LSB Register zu lesen. In diesen Registern wird soweit ich das verstanden habe, das Verhältnis vom RTD Widerstand und dem Referenzwiderstand angegeben. Nun habe ich das kleine Verständnisproblem vom Einlesen. Es ist ja wahrscheinlich so, dass man die beiden Bytes bitweise von links nach rechts, angefangen mit dem MSB Register, einliest oder? Dieser ADC-Code wird dann für die Berechnung vom Widerstand verwendet: R_RTD=(ADC-Code * R_Ref)/2^15. Muss so dann die Temperatur extra berechnet werden? Mit der Callendar-Van Dusen Gleichung? Problem derzeit ist gerade eigentlich das Einlesen der beiden Bytes... Zuerst MSB Register Adresse, dann bitweises einlesen und dann LSB Regsiter Adresse und das gleiche noch einmal?

Danke schon einmal :)
Viele Grüße

Re: Temperaturmessung mit PT100 und MAX31865

#13

Ungelesener Beitrag Nico » 11. Apr 2019, 13:06

[..] Es ist ja wahrscheinlich so, dass man die beiden Bytes bitweise von links nach rechts [..] einliest oder? [..]
Ja, siehe auch "Figure 1. Timing Diagram: SPI Read Data Transfer" im Datenblatt des MAX31865.
[..] angefangen mit dem MSB Register [..]
Wenn du beginnend mit der Adresse des MSB zwei Bytes liest, sprich 01h als Kommando nutzt und dann zwei Bytes liest, dann wirst du zuerst das MSB Register und anschließend das LSB Register lesen, ja.
[..] Dieser ADC-Code wird dann für die Berechnung vom Widerstand verwendet: R_RTD=(ADC-Code * R_Ref)/2^15. Muss so dann die Temperatur extra berechnet werden? [..]
Ja die Temperatur muss berechnet werden, Den Widerstandswert hast du ja bereits. Nicht vergessen den ADC-Wert um eine Stelle nach rechts zu shiften um das fault Bit zu streichen.
[..] Mit der Callendar-Van Dusen Gleichung? [..]
Entweder so oder schneller allerdings deutlich speicherintensiver mit Hilfe einer LUT (look up table).
[..] Problem derzeit ist gerade eigentlich das Einlesen der beiden Bytes... Zuerst MSB Register Adresse, dann bitweises einlesen und dann LSB Regsiter Adresse und das gleiche noch einmal? [..]
Das Vorgehen hierzu ist im Datenblatt auf Seite 5 in Figure 1. Timing Diagram: SPI Read Data Transfer dargestellt. Zum Lesen eines Registers aktivierst du den Chip zunächst mit seinem Chip Select signal (low aktiv) und sendest dann die Adresse des Registers bei dem du mit dem Lesen beginnen möchtest. Wichtig beim Senden der Register-Adresse das Bit 7 nicht setzen, da der Chip sonst einen Schreib-Packet erwartet (siehe Table 1. Register Addresses and POR State).

Direkt im Anschluss (selber CS low Zyklus), kannst du "beliebig" viele Register hintereinander weg lesen (du liest also zwei mal, denn du möchtest ja RTD MSBs und RTD LSBs haben).

Gruß Nico

Re: Temperaturmessung mit PT100 und MAX31865

#14

Ungelesener Beitrag pic18 » 11. Apr 2019, 20:55

Callendar-Van Dusen Gleichung
Ich habe die ganze Zeit gerätselt. Wie man den Widerstandswert nach Temperaturwert umrechnet. Da es keine Gerade ist. Jetzt bin ich ein Stück schlauer.
Ich frage mich gerade wie man so eine komplexe Formel mit einem Pic berechnen kann?
https://de-de.wika.de/upload/DS_IN0029_de_de_59666.pdf

Re: Temperaturmessung mit PT100 und MAX31865

#15

Ungelesener Beitrag Nico » 12. Apr 2019, 06:54

Es kommt darauf an wie genau man die Temperatur braucht. Wenn man beispielsweise mit -1,75°C Ungenauigkeit bei -100°C und -1,4°C bei +100°C leben kann, wird es mit der folgenden Gleichung (siehe Linearizing Temperature Data im Datenblatt) deutlich einfacher:

Code: Alles auswählen

Temperature (°C) = (ADC code / 32) - 256
Ansonsten gibt es hier eine schöne Application note, die sich genau mit diesem Thema auseinander setzt. Die AN trennt den Temperaturbereich in >=0°C und <0°C. Die mathematische Betrachtung im Bereich >=0°C ist vergleichsweise einfach:

Code: Alles auswählen

T_rtd(r) = [ Z1 + sqrt(Z2+Z3*r) ] / Z4
Hierbei sind die Z Faktoren jeweils Konstanten (siehe Application Note). Wenn das Ergebnis ergibt, dass die Temperatur <0°C ist, muss mit einer Polynom 3. Grades approximiert werden (auch in der AN gezeigt).

Wie gesagt letztendlich hat man folgende Möglichkeiten:
  • Approximation mit Polynom 2. bzw. 3. Grades
  • Tabelle (LUT)
  • Approximation mit Hilfe einer Geraden
Version (1) ist nicht 100% genau aber schon nah dran. Sie braucht relativ wenig speicher, geht aber auf Kosten der Komplexität. Bei Version (2) dreht sich de Spieß. Je nachdem wie fein man die Schrittweite gliedert wird natürlich der Speicherbedarf sehr groß. Dafür ist die Variante jedoch unschlagbar schnell und zudem auch sehr genau. Ein Kompromiss zwischen Schnelligkeit und Genauigkeit liefert Version (3). Diese Variante ist natürlich längst nicht so genau wie (1) oder (2), dafür jedoch deutlich schneller als (1) und gleichzeitig wesentlich schonender in Bezug auf Speicher als (3).

Wie man sieht hat man also mal wieder die Qual der Wahl.

PS: Eine Umsetzung der in der Application Note getrennten Betrachtung (<0°C oder >=0°C) findest du als C-Beispielcode hier.

Viele Grüße
Nico

Antworten