MAX31850 working, need help with internal temperature 1-Wire

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
ajevtic
Posts: 3
Joined: Sat Jul 09, 2022 1:03 pm

MAX31850 working, need help with internal temperature 1-Wire

Post by ajevtic » Sat Jul 09, 2022 2:27 pm

Hello everyone, I wanted to learn how to interface the MAX31850 with the Pi Pico using MiroPython. I was successful about reading the temperature of the K type probe. The only thing missing in this code is the readout of the internal temperature (cold junction). If anyone wants to help me figure it out how to read the next two bytes of data, that would be lovely! The entire code is based on the DS18B20 1-Wire temperature sensor. (link provided in the code). Anyhow, if nothing else, I saw that there was little code about this device on the web, so here you go! It reads out positive and negative temperatures. The module is connected to GPIO15.

Code: Select all

from utime import sleep_ms, sleep_us
from machine import Pin
from time import sleep

#based of DS1820
#https://iopress.info/index.php/books/programming-the-raspberry-pi-pico-in-micropython/9-programs/55-picopythonprograms
#Page 245

class MAX31850:
    def __init__(self, pin):
        self.pin = Pin(pin, mode=Pin.IN)
        self.pin.high()

    def presence(self): #initialization handshake
        self.pin.init(mode=Pin.OUT)
        self.pin.high()
        sleep_ms(1)
        self.pin.low()
        sleep_us(480)
        self.pin.init(mode=Pin.IN)
        sleep_us(70)
        b = self.pin.value()
        sleep_us(410)
        return b

    @micropython.native  #writing bits 
    def writeBit(self, b):
        if b == 1:
            delay1 = 1
            delay2 = 30
        else:
            delay1 = 30
            delay2 = 0
        self.pin.low()
        for i in range(delay1):
            pass
        self.pin.high()
        for i in range(delay2):
            pass

    def writeByte(self, byte):  #will write the low eight bits of an  int to the device 
        self.pin.init(mode=Pin.OUT)
        for i in range(8):
            self.writeBit(byte & 1)
            byte = byte >> 1
        self.pin.init(mode=Pin.IN)

    @micropython.native  #reading bits 
    def readBit(self):
        self.pin.init(mode=Pin.OUT)
        self.pin.low()
        self.pin.high()
        self.pin.init(mode=Pin.IN)
        b = self.pin.value()
        sleep_us(60)
        return b

    def readByte(self): #make a byte 
        byte = 0
        for i in range(8):
            byte = byte | self.readBit() << i
        return byte

    def convert(self): #start conversion 
        self.writeByte(0x44)
        for i in range(500):
            sleep_ms(10)
            if self.readBit() == 1:
                j = i
                break
        return j

    def crc8(self, data, len): #cyclic redundancy checksum
        crc = 0
        for i in range(len):
            databyte = data[i]
            for j in range(8):
                temp = (crc ^ databyte) & 0x01
                crc >>= 1
                if temp:
                    crc ^= 0x8C
                databyte >>= 1
        return crc

    def getTemp(self):
        if self.presence() == 1:
            return -1000 #no device 
        self.writeByte(0xCC)
        if self.convert() == 500:
            return -3000 #device faild to provide data 
        self.presence()
        self.writeByte(0xCC) #skip ROM read
        self.writeByte(0xBE) #read scratchpad
        data = []
        for i in range(9):
            data.append(self.readByte())
        if self.crc8(data, 9) != 0:
            return -2000 #crc error 
        t1 = data[0]
        t2 = data[1]
        
        #t2 = 0b000001      #test data from the datasheet positive temp no fault bits 
        #t1 = 0b10010011    #in the real life the last two lsb are fault detect
        
        #t2 = 0b111100      #test data from the datasheet negative temp no fault bits 
        #t1 = 0b00011000    #in the real life the last two lsb are fault detect 
        
        t2 = t2 << 8    #shift rigft the MSB
        temp1 = t2 | t1 #conbine MSB and LSB of the K type 
        temp1 = temp1 >> 2 #remove fault detection, comment when using test data 
        print("{:8b}".format(t2))
        print("{:8b}".format(t1)) 
        print("{:16b}".format(temp1))

        if (temp1 >> 13 != 1):  #check to see if not a negative number 
            temp1 = temp1 * 0.25
            print("here i am")
        else:  
            temp1 = temp1 - 0b100000000000000 #remove the sign bit 
            temp1 = temp1 * 0.25         
        return temp1


max31850 = MAX31850(15)

while True:
    if max31850.presence() == 1:
        print("No device")
    else:
        print("Device present")

    print(max31850.getTemp())
    sleep_ms(750)

The Adafruit library is a bit complicated, so if anyone has code (C code also) for this that is not a library or a good step by step tutorial, that would be really helpful.

Cheers! :D

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: MAX31850 working, need help with internal temperature 1-Wire

Post by jimmo » Mon Jul 11, 2022 5:32 am

ajevtic wrote:
Sat Jul 09, 2022 2:27 pm
The module is connected to GPIO15.
Can you use the built-in onewire driver rather that bit-banging it from Python?

https://docs.micropython.org/en/latest/ ... ire-driver
ajevtic wrote:
Sat Jul 09, 2022 2:27 pm
#based of DS1820
#https://iopress.info/index.php/books/pr ... onprograms
#Page 245
Seems like they could also use the built-in DS18X20 and DHT drivers. I will write to them.

ajevtic
Posts: 3
Joined: Sat Jul 09, 2022 1:03 pm

Re: MAX31850 working, need help with internal temperature 1-Wire

Post by ajevtic » Wed Jul 13, 2022 11:02 am

Hello jimmo, thank you for your reply. Well it can be done using built-in onewire driver, but the idea is that I can carry the code across other not so user-friendly platforms. :lol: Anyhow I think I got this one solved, because the data is already there, just need to catch it.

Here is the new code:

Code: Select all

from utime import sleep_ms, sleep_us
from machine import Pin
from time import sleep

#based of DS1820
#https://iopress.info/index.php/books/programming-the-raspberry-pi-pico-in-micropython/9-programs/55-picopythonprograms
#Page 245

class MAX31850:
    def __init__(self, pin):
        self.pin = Pin(pin, mode=Pin.IN)
        self.pin.high()

    def presence(self): #initialization handshake
        self.pin.init(mode=Pin.OUT)
        self.pin.high()
        sleep_ms(1)
        self.pin.low()
        sleep_us(480)
        self.pin.init(mode=Pin.IN)
        sleep_us(70)
        b = self.pin.value()
        sleep_us(410)
        return b

    @micropython.native  #writing bits 
    def writeBit(self, b):
        if b == 1:
            delay1 = 1
            delay2 = 30
        else:
            delay1 = 30
            delay2 = 0
        self.pin.low()
        for i in range(delay1):
            pass
        self.pin.high()
        for i in range(delay2):
            pass

    def writeByte(self, byte):  #will write the low eight bits of an  int to the device 
        self.pin.init(mode=Pin.OUT)
        for i in range(8):
            self.writeBit(byte & 1)
            byte = byte >> 1
        self.pin.init(mode=Pin.IN)

    @micropython.native  #reading bits 
    def readBit(self):
        self.pin.init(mode=Pin.OUT)
        self.pin.low()
        self.pin.high()
        self.pin.init(mode=Pin.IN)
        b = self.pin.value()
        sleep_us(60)
        return b

    def readByte(self): #make a byte 
        byte = 0
        for i in range(8):
            byte = byte | self.readBit() << i
        return byte

    def convert(self): #start conversion 
        self.writeByte(0x44)
        for i in range(500):
            sleep_ms(10)
            if self.readBit() == 1:
                j = i
                break
        return j

    def crc8(self, data, len): #cyclic redundancy checksum
        crc = 0
        for i in range(len):
            databyte = data[i]
            for j in range(8):
                temp = (crc ^ databyte) & 0x01
                crc >>= 1
                if temp:
                    crc ^= 0x8C
                databyte >>= 1
        return crc

    def getTemp(self):
        if self.presence() == 1:
            return -1000 #no device 
        self.writeByte(0xCC)
        if self.convert() == 500:
            return -3000 #device faild to provide data 
        self.presence()
        self.writeByte(0xCC) #skip ROM read
        self.writeByte(0xBE) #read scratchpad
        data = []
        for i in range(9):
            data.append(self.readByte())
        if self.crc8(data, 9) != 0:
            return -2000 #crc error 
        t1 = data[0]
        t2 = data[1]
        t3 = data[2]
        t4 = data[3]
        
        #t2 = 0b000001      #test data from the datasheet positive temp no fault bits 
        #t1 = 0b10010011    #in the real life the last two lsb are fault detect
        
        #t2 = 0b111100      #test data from the datasheet negative temp no fault bits 
        #t1 = 0b00011000    #in the real life the last two lsb are fault detect
        
        #t4 = 0b0001      #test data from the datasheet positive temp no fault bits 
        #t3 = 0b10010000    #in the real life the last two lsb are fault detect
        
        #t4 = 0b1111     #test data from the datasheet negative temp no fault bits 
        #t3 = 0b11110000   #in the real life the last two lsb are fault detect
        
        t2 = t2 << 8
        temp1 = t2 | t1
        temp1 = temp1 >> 2 #remove fault detection, comment when using test data 
        print("{:8b}".format(t2))
        print("{:8b}".format(t1))
        print("{:8b}".format(t3))
        print("{:8b}".format(t4))
        print("{:16b}".format(temp1))

        if (temp1 >> 13 != 1):
            temp1 = temp1 * 0.25
            print("here i am")
        else:  
            temp1 = temp1 - 0b100000000000000
            temp1 = temp1 * 0.25         
        

        t4 = t4 << 8
        temp2 = t4 | t3
        temp2 = temp2 >> 4 #remove fault detection, comment when using test data
        print("{:16b}".format(temp2))
        if (temp2 >> 11 != 1):
            temp2 = temp2 * 0.0625
            print("hereeeee")
        else:
            temp2 = temp2 - 0b1000000000000
            temp2 = temp2 * 0.0625       
            
        print(temp2)
            
        return temp1

max31850 = MAX31850(15)

while True:
    if max31850.presence() == 1:
        print("No device")
    else:
        print("Device present")

    print(max31850.getTemp())
    sleep_ms(750)

Here is the output (room temp):

Code: Select all

Device present
100000000
10011100
11010000
   11010
         1100111
here i am
       110101101
hereeeee
26.8125
25.75
And using a lighter:

Code: Select all

Device present
101000000000
  100100
11110000
   11010
      1010001001
here i am
       110101111
hereeeee
26.9375
162.25

Any news?
Going to try it with built-in onewire driver but as always very little documentation. :?:

Thank you for your time!

HarryF
Posts: 1
Joined: Wed Jul 20, 2022 7:57 am

Re: MAX31850 working, need help with internal temperature 1-Wire

Post by HarryF » Wed Jul 20, 2022 8:57 am

Hi
When I wrote the book the Pico micropython wasn't complete and the drivers for a few sensors weren't available or
weren't documented - hence no mention but the bit banging is still worth knowing about.
I will write something about them in the next edition (when ever that is)
However I will still keep in the bit banging because that is a good way to find out how things work
and its a step to using the PIO to interface to things - also covered in the book.
Harry

ajevtic
Posts: 3
Joined: Sat Jul 09, 2022 1:03 pm

Re: MAX31850 working, need help with internal temperature 1-Wire

Post by ajevtic » Mon Jul 25, 2022 12:07 pm

HarryF wrote:
Wed Jul 20, 2022 8:57 am
Hi
When I wrote the book the Pico micropython wasn't complete and the drivers for a few sensors weren't available or
weren't documented - hence no mention but the bit banging is still worth knowing about.
I will write something about them in the next edition (when ever that is)
However I will still keep in the bit banging because that is a good way to find out how things work
and its a step to using the PIO to interface to things - also covered in the book.
Harry
Hi Harry,
First, thank you for your books, they helped a lot! Of course, the bit banging is the idea of my post so that the code is not library and architecture dependent. The code is for now glitchy (time dependent), not too often, but I get the error that the device is not present (-2000), but other than that the code works.

That's all from me for now.
Cheers,
Saša

Post Reply