Temperaturmessung mit PT100 und MAX31865

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

Re: Temperaturmessung mit PT100 und MAX31865

#31

Ungelesener Beitrag emy » 18. Apr 2019, 14:24

Hast du dir nach dem Auslesen des MAX mal die 15 Bit angesehen?
Ja, 2 Bytes voller Nullen …
Und kannst du vielleicht mal einen Screenshot von der Kommunikation zum MAX zeigen? Idealerweise die Config sowie das Auslesen.
Von was genau soll ich einen Screenshot machen? Das "output" des progamms ist recht unspektakulär, oder was meinst du genau?

Viele Grüße

Re: Temperaturmessung mit PT100 und MAX31865

#32

Ungelesener Beitrag Nico » 18. Apr 2019, 14:29

Dann würde ich behaupten, dass bei der Übertragung noch irgendwas nicht stimmt, denn das wirklich alles Null ist, glaube ich nicht.
Von was genau soll ich einen Screenshot machen?
Von den gemessenen Signalen (SPI Kommunikation) zwischen dem PIC und dem MAX, also Chip Select, Clock und 2x Daten.

Re: Temperaturmessung mit PT100 und MAX31865

#33

Ungelesener Beitrag emy » 18. Apr 2019, 15:01

Es ist leider kein Screenshot, sondern ein Foto, weil das Ding alt ist....
von oben nach unten: Clock, SDO, CS, SDI.
IMG_20190418_145615.jpg

Re: Temperaturmessung mit PT100 und MAX31865

#34

Ungelesener Beitrag Nico » 18. Apr 2019, 15:21

Mh .. damit kann ich nicht so viel anfangen, da CS hier ja immer low zu sein scheint. Bitte setzt mal einen Breakpoint vor dem Konfigurieren des MAX und dann wieder vor dem Anfordern des Ergebnisses. So dass man auch vernünftig die zwei Zugriffe sieht.

Die Frequenz von SCLK liegt bei ~7..8kHz sofern ich mich nicht verlesen habe?

Re: Temperaturmessung mit PT100 und MAX31865

#35

Ungelesener Beitrag emy » 18. Apr 2019, 15:43

Ja die Frequenz von SCLK liegt bei 7,8 kHz.

Auf Kanal 1 wird gesendet, sobald das Senden beginnt, geht CS auf LOW. Es wird 1000 0000 1100 0010 gesendet, danach gibt es einen kurzen PEAK bei CS und dann wird die Adresse für das Lesen und zweimal 0x00 gesendet über SDO 0000 0001 0000 0000 0000 0000. Daraufhin hat CS wieder eine positive Flanke, das ist doch richtig so oder nicht? Im Kanal 7 hat SDI jedoch fast nur einen Pegel von 1. Einen Breakpoint kann ich mit dem Ding nicht darstellen, dafür bin ich nicht schnell genug :D

Re: Temperaturmessung mit PT100 und MAX31865

#36

Ungelesener Beitrag Nico » 18. Apr 2019, 15:58

von oben nach unten: Clock, SDO, CS, SDI
An welchem Kanal liegt was an?
Im Kanal 7 hat SDI..
Ich dachte von oben nach unten?

Sag mal genau auf welchem Kanal was anliegt.

Re: Temperaturmessung mit PT100 und MAX31865

#37

Ungelesener Beitrag emy » 18. Apr 2019, 16:02

  • Kanal 0: Clock
  • Kanal 1: SDO
  • Kanal 5: CS
  • Kanal 7: SDI
Ja, ich meinte von oben nach unten, wo etwas zu sehen ist. So ist es jetzt richtig.
Ich werde jetzt leider aus der Uni geworfen, weil alle Feierabend haben :D

Ich hoffe aber, dass ich das Problem auch zu Hause lösen kann, hab da allerdings kein Oszi usw. Platine ist aber eingesteckt.

Re: Temperaturmessung mit PT100 und MAX31865

#38

Ungelesener Beitrag Nico » 18. Apr 2019, 16:35

Also deine Funktion maxRTD_request_new_meas() brauchst du nur einmalig aufzurufen, du arbeitest ja nun im Automatic Mode, da du das Bit 6 im Config Register setzt. Der Chip wird also automatisch messen. Du musst das Config-Register nicht erneut zu beschreiben.

Mit anderen Worten:
  • Der Funktionsname maxRTD_request_new_meas() passt nicht :-D (besser wäre z.B. maxRTD_set_config()) und
  • der Aufruf muss vor die Endlosschleife.
In der Endlosschleife kannst du nun nicht einfach wild drauf los lesen (vom MAX). Stattdessen musst du schon darauf warten, dass der MAX dir signalisiert, dass ein neues Messergebnis vorliegt. Also in der Endlosschleife musst du warten bis DRDY auf low geht. Erst dann kannst du das Ergebnis auslesen. Durch das Auslesen geht DRDY automatisch wieder zurück auf high und du kannst erneut warten..

Und was du auch noch einbauen solltest um folgendes zu berücksichtigen:

The MAX31865 automatically accommodates either clock polarity by sampling SCLK when CS becomes active to determine the polarity of the inactive clock.

Sobald du CS auf low ziehst, prüft der Chip den Pegel auf der Clock Leitung um zu prüfen welcher Pegel im low Zustand auf Clock anliegt. Somit weiß er, welcher SPI Modus (1 oder 3) genutzt wird. Daher würde ich vorschlagen in spi_transfer() eine kurze Wartezeit von vielleicht einem Clock Takt einzubauen bevor du den Clock auf low ziehst.

Re: Temperaturmessung mit PT100 und MAX31865

#39

Ungelesener Beitrag emy » 18. Apr 2019, 20:10

Du hast Recht, das macht Sinn. Hatte ich sogar ganz am Anfang mal.
Nach wieder einigen Stunden herumprobieren, bin ich nicht viel weiter. Die Veränderungen haben keinen Einfluss auf das Ergebnis.
Derzeit bin ich bei diesem Code:

Code: Alles auswählen

void spi_transfer (uint8_t *pWr, uint8_t *pRd, uint8_t len){
           uint8_t i; 
           __delay32(150);
           SCLK = 0;
           
           if (pWr == NULL) return;
           
           while (len){
               for (i=0; i<8; i++){
                    SDO = ((*pWr) & (0x80 >> i)) ? 1 : 0;
                   __delay32(100);
                   SCLK ^= 1;
                   
                   if (pRd) {
                       if (SDI){
                           *pRd |= (0x80 >> i);
                       }
                       else {
                           *pRd &= ~(0x80 >> i);
                       }
                      
                   }
                __delay32(100);
                SCLK ^=1;    
               }
               pWr++;
               if (pRd) pRd++;
               
               len--;
           }
           SCLK = 1;
        
        }

Code: Alles auswählen

void maxRTD_set_config(void)
    {
        uint8_t buf[2];
        
        buf[0] = 0x80;
        buf[1] = 0xC2;
        
        CS_MAX = 0;
        spi_transfer(buf, NULL, 2);
        CS_MAX = 1;
    }

    uint16_t maxRTD_read_res (void)
    {
        uint8_t buf[3];
        
        buf[0] = 0x01;
        buf[1] = 0x00;
        buf[2] = 0x00;
        
        CS_MAX = 0;
        spi_transfer(buf, buf, 3);
        CS_MAX = 1;
        
        return ((buf[1] << 7) | (buf[2] >> 1));
    }

Code: Alles auswählen

int main(void)
{
    // initialize the device
    SYSTEM_Initialize();
    
    uint16_t adccode;
    double temp;
    int i = 0;
    
    maxRTD_set_config();
     
    while (1)

        while(DRDY);
        adccode = maxRTD_read_res();
         
         i++;
        temp = (double) (adccode / 32.0) - 256;

Die 15 Bit sind bei i=2 alle 0 und bei i=3 01111111 11111111 und bleiben es auch bei jedem weiteren Durchgang. Macht also immer noch keinen Sinn.

Code: Alles auswählen

*pRd |= (0x80 >> i);
müsste nicht aber beim bitweisen ODER immer nur 1en entstehen so wie bei mir zur Zeit?

Re: Temperaturmessung mit PT100 und MAX31865

#40

Ungelesener Beitrag Nico » 19. Apr 2019, 10:12

Je nachdem was auf SDI (vom PIC) empfangen wird, werden die Bits in pRd gesetzt (ODER) oder gelöscht (UND):

Code: Alles auswählen

if (SDI){
   *pRd |= (0x80 >> i);
} else {
   *pRd &= ~(0x80 >> i);
}
Da du es bisher nicht gezeigt hast: Was genau steckt hinter SCLK, SDO, SDI, CS_MAX und sind diese korrekt konfiguriert (Eingang/Ausgang)? Außerdem kommt man häufig auch mal durcheinander beim Anschluss von SDI und SDO. Beim MAX31865 muss sein SDI GPIO mit dem SDO vom PIC (bei dir ist das jetzt der GPIO RD2) verbunden werden. Also der SDI vom MAX ist nicht der SDI vom PIC :-) Das hast du hoffentlich richtig :-) und glaub es oder glaub es nicht, sowas wird unglaublich häufig verdreht (genau wie RX/TX bei UART - denn hier kommt auch nicht TX an TX sondern RX an TX und umgekehrt).

Und des Weiteren: Ist der GPIO an den du DRDY angeschlossen hast (also RC13 korrekt als digitaler Eingang konfiguriert?

Gruß Nico

Re: Temperaturmessung mit PT100 und MAX31865

#41

Ungelesener Beitrag emy » 19. Apr 2019, 13:41

Code: Alles auswählen

#define CS_MAX	_RC14	// Chip Select am Pin 48 
#define SCLK	_RF3	// Clock am Pin 33
#define SDI	_RD2	// SDI Controller, SDO MAX
#define SDO	_RD1	// SDO Controller, SDI MAX
#define DRDY	_RC13	// DRDY Pin 
Das sind die Pins, die ich für die Übertragung nutze. Also eigentlich müsste das so richtig sein.
Dateianhänge
pin.jpg

Re: Temperaturmessung mit PT100 und MAX31865

#42

Ungelesener Beitrag Nico » 20. Apr 2019, 09:52

Okay, dann würde ich sagen sind die GPIOs soweit in Ordnung. RD2 scheint bei deinem PIC tatsächlich auch keine Analogfunktion zu besitzen, so dass man hier auch nicht ins Fettnäpfchen treten könnte. Jetzt mit den letzten Änderungen wäre es interessant nochmal einen Messung zu sehen um zu prüfen ob das Einlesen der Bits auch wirklich korrekt funktioniert.

Hier nochmal die spi_transfer() Funktion etwas umgeschrieben / vereinfacht. Des Weiteren würde ich den Chip Select hier tatsächlich ruhig in die Funktion mit rein nehmen. So bist du immer auf der sicheren Seite, dass der MAX den SPI Modus korrekt erkennt (Zustand vom Clock, wenn CS aktiv wird). Könnte man später auch wieder ändern aber erstmal ist es so einfacher Fehlerquellen auszuschließen.

Das funktioniert so natürlich nur, wenn an dem SPI Bus bloß der eine Teilnehmer ist :-)

Code: Alles auswählen

void spi_transfer (uint8_t *pBuf, uint8_t len)
{
	int8_t i; 
	
	// ensure clock is high when CS becomes active
	SCLK = 1;
	CS_MAX = 0;

	if(pBuf == NULL) return;

	while(len) {
		for (i=7; i>=0; i--) {
			__delay32(100);
			SCLK ^= 1;
		
			SDO = ((*pBuf) & (1<<i)) ? 1 : 0;
			__delay32(100);
			SCLK ^= 1;

			if(SDI) {
				*pBuf |= (1<<i);
			}
			else {
				*pBuf &= ~(1<<i);
			}
		}
		
		pBuf++;
		len--;
	}
	
	CS_MAX = 1;
}
Im Wesentlichen habe ich den zweiten Pointer zum Lesen entfernt (war sowieso der selbe). Das vereinfacht den Aufruf der Funktion. Wenn du die gelesenen Daten nicht brauchst, liest du sie halt einfach nicht aus, fertig. Dann habe ich die for Schleife noch "umgedreht". Also sie läuft jetzt rückwärts von 7 bis 0 statt wie vorher von 0 bis 7. Das vereinfacht etwas die Schreibweise zum Setzen/Löschen der Bits.

Ich denke jetzt muss man wirklich mal eine neue Messung machen um zu sehen, ob das was auf dem Bus passiert auch wirklich zu den Bits/Bytes passt, die geschrieben und gelesen werden. Also genieß die Sonne ein bisschen oder fahr heute in die Uni und miss mal fix ;-)

Gruß Nico

Re: Temperaturmessung mit PT100 und MAX31865

#43

Ungelesener Beitrag emy » 23. Apr 2019, 11:29

Leider hatte ich deinen Beitrag zu spät gelesen, sodass ich erst heute zum Messen kam:
Mit den Codes

Code: Alles auswählen

void spi_transfer (uint8_t *pBuf, uint8_t len)
    {
        int8_t i;
        
        SCLK = 1;
        CS_MAX = 0;
        
        if(pBuf == 0) return;
        
        while(len) {
            for (i=7; i>=0; i--) {
                __delay32(100);
                SCLK ^= 1;
                
                SDO = ((*pBuf) & (1<<i)) ? 1 : 0;
                __delay32(100);
                SCLK ^= 1;
                
                if (SDI) {
                    *pBuf |= (1<<i);
                }
                else {
                    *pBuf &= ~(1<<i);
                }
                
            }
            pBuf++;
            len--;
        }
        CS_MAX = 1;
    }

Code: Alles auswählen

void maxRTD_set_config(void)
    {
        uint8_t buf[2];
        
        buf[0] = 0x80;
        buf[1] = 0xC2;
        
        spi_transfer(buf, 2);
    }
    
    uint16_t maxRTD_read_res(void)
    {
        uint8_t buf[3];
        
        buf[0] = 0x01;
        buf[1] = 0x00;
        buf[2] = 0x00;
        
        spi_transfer(buf, 3);
        
        return ((buf[1] << 7) | (buf[2] >> 1));
    }

Code: Alles auswählen

int main(void)
{
    // initialize the device
    SYSTEM_Initialize();
    
    uint16_t adccode;
    int i = 0;
    double temp;

    while (1)
    {
        maxRTD_set_config();
//        while(DRDY);
//        adccode = maxRTD_read_res();
//        
//        i++;
//        
//        temp = (double) (adccode / 32.0) - 256;
    }

    return 1;
}
habe ich zunächst erst einmal das beschreiben des Konfigurationsregisters kontrolliert, deswegen ist der Aufruf der Funktion auch in der while Schleife, um es besser sichtbar zu machen (Bild: schreiben)
  • Kanal 0: Chip Select
  • Kanal 1: Clock
  • Kanal 3: SDI
  • Kanal 4: SDO
Wenn ich jetzt in der main folgenden Code habe

Code: Alles auswählen

int main(void)
{
    // initialize the device
    SYSTEM_Initialize();
    
    uint16_t adccode;
    int i = 0;
    double temp;
    
    maxRTD_set_config();

    while (1)
    {
        while(DRDY);
        adccode = maxRTD_read_res();
        i++;
        temp = (double) (adccode / 32.0) - 256;
    }

    return 1;
}
Dann sind lediglich Chip Select und Clock durchgehend auf 1, der Rest 0. Daraufhin habe ich dann

Code: Alles auswählen

while(DRDY);
auskommentiert und das Ergebnis ist in Bild "lesen" zu sehen.
Dateianhänge
lesen.jpg
schreiben.jpg

Re: Temperaturmessung mit PT100 und MAX31865

#44

Ungelesener Beitrag emy » 23. Apr 2019, 13:22

Mir ist jetzt aufgefallen, dass jedes Bit mit einer fallenden Flanke von Clock zeitgleich angezeigt wurde, da nach Abbildung 7 des Datenblatts ein Bit mit jeder positiven Flanke von Clock gesendet wird, habe ich das jetzt noch einmal umgedreht. Keine Ahnung, ob das einen Unterschied macht.

Außerdem habe ich jetzt den ADC Code nicht um eine Stelle nach rechts geshiftet, da mir aufm Oszi eine 1 bei SDI aufgefallen ist. So war es jetzt auch, mein ADC Code zeigt jetzt 0000 0001 an (mit deinem neusten spi_Transfer).
Jetzt komme ich um eine Fehlerauswertung via Code nicht vorbei, oder?

Mir ist auch aufgefallen, dass die positive Flanke von Clock und das Bit auf SDO um ca 8us versetzt ist (Clock ist 8us vor SDO), kann das auch schon zu Fehlern führen?

Außerdem nutze ich den diesen PT100. Könnte die Kabellänge von 1 Meter da Probleme machen?

Re: Temperaturmessung mit PT100 und MAX31865

#45

Ungelesener Beitrag Nico » 23. Apr 2019, 14:57

Dann sind lediglich Chip Select und Clock durchgehend auf 1, der Rest 0.
Das legt also nahe, dass DRDY offenbar nie auf low zu gehen scheint, sprich der MAX keine neuen Messergebnisse generiert.
Mir ist jetzt aufgefallen, dass jedes Bit mit einer fallenden Flanke von Clock zeitgleich angezeigt wurde, da nach Abbildung 7 des Datenblatts ein Bit mit jeder positiven Flanke von Clock gesendet wird, habe ich das jetzt noch einmal umgedreht.
Das ist genau was ich zuvor schon mal angesprochen habe. Der Chip unterstützt die SPI Modi 1 (CPOL=0, CPHA=1) und 3 (CPOL=1, CPHA=1), auf der folgenden Grafik sehr schön zu sehen:

Bild
Quelle: https://www.corelis.com/education/tutor ... -tutorial/

Welcher Mode aktiv ist, detektiert der Chip indem er den Pegel vom Clock misst, kurz nachdem du Chip Select aktivierst. Dies ist dann der idle Zustand des Clocks (also CPOL=0 beim SPI Mode 1 oder CPOL=1 beim Mode 3). Die spi_transfer die ich so vorgeschlagen habe, arbeitet im Mode 3.
Mir ist auch aufgefallen, dass die positive Flanke von Clock und das Bit auf SDO um ca 8us versetzt ist (Clock ist 8us vor SDO), kann das auch schon zu Fehlern führen?
Hier auch wieder der Verweis auf die Abbildung (siehe oben). Ich spreche weiterhin vom SPI Mode 3: Bei fallender Taktflanke schreibt der Master den Zustand auf SDO, der bei der folgenden steigenden Flanke stabil ist und dann vom Slave eingelesen wird.

Antworten