MicroPython Driver for LM75A Sensor

LM75A Driver Code for micro:bit

Download as zip file

'''
LM75A temperature sensor
MicroPython driver for micro:bit

AUTHOR: fredscave.com
DATE  : 2025/01
VERSION : 1.00
'''

from microbit import i2c, sleep
from micropython import const

I2C_ADDR   = const(0x48)
REG_TEMP   = const(0x00)
REG_CONFIG = const(0x01)
REG_HYST   = const(0x02)
REG_OS     = const(0x03)

CtoF = lambda C: round((C * 9/5) +32, 1)

class LM75A():
    def __init__(self, Addr = I2C_ADDR):
        self.Addr = Addr

    def Read(self, Res = 9):
        res = Res if (Res in [9, 11]) else 8
        i2c.write(self.Addr, bytes([REG_TEMP]))
        buf = i2c.read(self.Addr, 2)
        return LM75A._Convert(buf, res)

    def GetConfig(self):
        i2c.write(self.Addr, bytes([REG_CONFIG]))
        return i2c.read(self.Addr, 1)[0]

    def SetConfig(self, Queue = 1, Polarity = 0, CmpInt = 0):
        cmpint = CmpInt if (CmpInt in (0, 1)) else 0
        polarity = Polarity if (Polarity in (0, 1)) else 0
        t = (1, 2, 4, 6)
        if Queue in t:
            queue = t.index(Queue)
        else:
            queue = 0
        config = self.GetConfig()
        config = LM75A._ChangeBit(config, cmpint, 1)
        config = LM75A._ChangeBit(config, polarity, 2)
        config = LM75A._ChangeBit(config, queue & 0b01, 3)
        config = LM75A._ChangeBit(config, queue >> 1, 4)
        i2c.write(self.Addr, bytes([REG_CONFIG, config]))

    def Off(self):
        i2c.write(self.Addr, bytes([REG_CONFIG]))
        config = i2c.read(self.Addr, 1)[0]
        config = config | 0x01
        i2c.write(self.Addr, bytes([REG_CONFIG, config]))

    def On(self):
        i2c.write(self.Addr, bytes([REG_CONFIG]))
        config = i2c.read(self.Addr, 1)[0]
        config = config & 0b11111110
        i2c.write(self.Addr, bytes([REG_CONFIG, config]))
        sleep(300)


    def Hyst(self, Temp = None):
        if Temp == None:
            i2c.write(self.Addr, bytes([REG_HYST]))
            binary = i2c.read(self.Addr, 2)[0]
            return LM75A._fromComp2(binary, 8)
        else:
            if isinstance(Temp, int):
                temp2comp = LM75A._toComp2(Temp, 8)
                buf = bytes([REG_HYST, temp2comp, 0])
                i2c.write(self.Addr, buf)

    def OS(self, Temp = None):
        if Temp == None:
            i2c.write(self.Addr, bytes([REG_OS]))
            binary = i2c.read(self.Addr, 2)[0]
            return LM75A._fromComp2(binary, 8)
        else:
            if isinstance(Temp, int):
                temp2comp = LM75A._toComp2(Temp, 8)
                buf = bytes([REG_OS, temp2comp, 0])
                i2c.write(self.Addr, buf)

    @staticmethod
    def _Convert(buf, res):
        b = LM75A._fromComp2(buf[0], 8)
        dec = buf[1] >> (16 - res)
        return b + dec/(2**(res-8))

    @staticmethod
    def _fromComp2(binary, bits):
        mask = 1 << (bits-1)
        if not (binary & mask) >> (bits-1):
            return  binary
        else:
            return -((binary ^ 2**bits - 1) + 1)

    @staticmethod
    def _toComp2(sint, bits):
        if sint >= 0:
            return sint
        else:
            return (abs(sint) ^ 2**bits - 1) + 1

    @staticmethod
    def _ChangeBit(byte, bit, pos):
        if bit == 1:
            return byte | (1 << pos)
        else:
            return byte & ~(1 << pos)

          

NXP Semiconductors' LM75A

The breakout board used while developing and testing this driver coincidentally used the NXP Semiconductor LM75A chip.

This wasn't discovered until it was viewed under a digital microscope. Even though it is possible to read the sensor's markings with a good magnifying glass we always have a look under the microscope.

Micrograph of LM75A breakout board using the NXP chip
LM75A breakout board using the NXP chip

As mentioned previously the NXP's LM75A has an 11-bit temperature reading resolution. The driver is fine to use with this chip for a 9-bit resolution reading. In which case it remains a direct drop-in replacement option for any other LM75A chip and doesn't require any firmware change.

However, this driver offers the option of obtaining the temperature reading at the full 11-bit resolution.


Example:
# Test the micro:bit's MicroPython driver
# for the NXP Semiconductors' LM75A
# temperature sensor.

# Temperature readings are taken at 
# both 9-bit and 11-bit resolution.

from fc_lm75a import *

lm75a = LM75A()
T_9bits = lm75a.Read(Res=9)
T_11bits = lm75a.Read(Res=11)
print('Temperature (9-bits):', T_9bits)
print('Temperature (11-bits):', T_11bits)

Output:
Temperature (9-bits): 26.5
Temperature (11-bits): 26.625
          
LM75A breakout board (NXP chip) and the micro:bit
LM75A breakout board (NXP chip) and the micro:bit