TMP100 library - Please critique

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
jimako
Posts: 14
Joined: Fri Dec 23, 2016 6:36 pm

TMP100 library - Please critique

Post by jimako » Sat Dec 24, 2016 9:37 am

Hello. The following code is for the TMP100 [1] temperature sensor. I would like your feedback on the code. What would make the code more correct?

Code: Select all

"""TMP100 driver for ESP8266 in MicroPython."""

from machine import I2C


class TMP100:
    # Registers
    T_REG = 0x00
    CONF_REG = 0x01

    # Configuration Register
    SHUTDOWN = 0x01
    RES_9bits = 0x00  # 9bits, 0.5C, 40ms
    RES_10bits = 0x20  # 10bits, 0.25C, 80ms
    RES_11bits = 0x40  # 11bits, 0.125C, 160ms
    RES_12bits = 0x60  # 12bits, 0.0625C, 320ms
    ONESHOT = 0x80

    def __init__(self, scl, sda, addr, res):
        self.i2c = I2C(scl=scl, sda=sda, freq=400000)
        self.write_address = addr
        self.read_address = addr | 0x01
        self.set_resolution(res)

    def write_register(self, reg, data):
        buf = bytearray(1)
        self.i2c.start()
        buf[0] = self.write_address
        self.i2c.write(buf)
        buf[0] = reg
        self.i2c.write(buf)
        buf[0] = data
        self.i2c.write(buf)
        self.i2c.stop()

    def read_register(self, reg):
        buf = bytearray(1)
        self.i2c.start()
        buf[0] = self.write_address
        self.i2c.write(buf)
        buf[0] = reg
        self.i2c.write(buf)
        self.i2c.start()
        buf[0] = self.read_address
        self.i2c.write(buf)
        if reg == self.T_REG:
            rbuf = bytearray(2)
        elif reg == self.CONF_REG:
            rbuf = bytearray(1)
        self.i2c.readinto(rbuf)
        self.i2c.stop()
        return rbuf

    def set_resolution(self, res):
        current = self.read_register(self.CONF_REG)[0] & 0x9F
        self.write_register(self.CONF_REG, current | res)

    def set_shutdown(self, state):
        current = self.read_register(self.CONF_REG)[0] & 0xFE
        if state is True:
            self.write_register(self.CONF_REG, current | self.SHUTDOWN)
        else:
            self.write_register(self.CONF_REG, current)

    def set_oneshot(self):
        current = self.read_register(self.CONF_REG)[0] & 0xEF
        self.write_register(self.CONF_REG, current | self.ONESHOT)

    def read_temp(self):
        t = self.read_register(self.T_REG)
        return ((t[0] << 8 | t[1]) >> 4) * 0.0625
Usage:

Code: Select all

>>> from tmp100 import TMP100
>>> from machine import Pin
>>> mytmp = TMP100(Pin(5), Pin(4), 0x90, TMP100.RES_9bits)
>>> mytmp.read_temp()
23.5
>>> mytmp.set_resolution(TMP100.RES_12bits)
>>> mytmp.read_temp()
23.875
[1] http://www.ti.com/lit/ds/symlink/tmp101.pdf

User avatar
ernitron
Posts: 89
Joined: Fri Jun 03, 2016 5:53 pm
Location: The Netherlands

Re: TMP100 library - Please critique

Post by ernitron » Tue Dec 27, 2016 12:35 am

It looks like (but I can be wrong as I don't have a TMP100) you didn't consider the negative values. According to specs negative are represented as twos complement with msb set. Check the code for ds18b20.

Test it putting your sensor in the refrigerator ;)

Besides, I would have called read_temp() temperature() to be similar to other libraries like dht11. But it's more personal style.

User avatar
ernitron
Posts: 89
Joined: Fri Jun 03, 2016 5:53 pm
Location: The Netherlands

Re: TMP100 library - Please critique

Post by ernitron » Wed Dec 28, 2016 7:31 am

Bonus. The corrected read_temp()

Code: Select all

def read_temp(self):
     t = self.read_register(self.T_REG)
     temp = ((t[0] << 8 | t[1]) >> 4)
     if temp & 0x800: # sign bit set
         temp = -((temp ^ 0xfff) + 1)
     return temp * 0.0625

jimako
Posts: 14
Joined: Fri Dec 23, 2016 6:36 pm

Re: TMP100 library - Please critique

Post by jimako » Wed Dec 28, 2016 3:25 pm

Thank you for your comments. You are right, I neglected negative numbers. Thanks for the two's complement code too!

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: TMP100 library - Please critique

Post by deshipu » Thu Dec 29, 2016 9:42 am

Why don't you use the ustruct module to do such conversions?

jimako
Posts: 14
Joined: Fri Dec 23, 2016 6:36 pm

Re: TMP100 library - Please critique

Post by jimako » Thu Dec 29, 2016 7:18 pm

Hm but the number is made out of 12 bits. Also (for my understanding) wouldn't importing ustruct module consume more resources than those bitwise operations?

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: TMP100 library - Please critique

Post by deshipu » Sat Dec 31, 2016 2:40 pm

No, ustruct is built into the firmware, it already takes those resources whether you use it or not.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: TMP100 library - Please critique

Post by pythoncoder » Sun Jan 01, 2017 9:31 am

How about

Code: Select all

def read_temp(self):
    t = self.read_register(self.T_REG)
    return 0.00390625 * ustruct.unpack('>h', t)[0]
@jimako the point being that ustruct performs the sign handling on a 16 bit quantity before it is reduced to 12 bits. Although the reduction to 12 bits is not explicit: it's subsumed into the floating point scale factor.
Peter Hinch
Index to my micropython libraries.

jimako
Posts: 14
Joined: Fri Dec 23, 2016 6:36 pm

Re: TMP100 library - Please critique

Post by jimako » Sun Jan 01, 2017 8:41 pm

Thanks guys for your valuable feedback. I will incorporate the changes in the code.

User avatar
ernitron
Posts: 89
Joined: Fri Jun 03, 2016 5:53 pm
Location: The Netherlands

Re: TMP100 library - Please critique

Post by ernitron » Mon Jan 02, 2017 9:59 pm

pythoncoder wrote:How about

Code: Select all

def read_temp(self):
    t = self.read_register(self.T_REG)
    return 0.00390625 * ustruct.unpack('>h', t)[0]
@jimako the point being that ustruct performs the sign handling on a 16 bit quantity before it is reduced to 12 bits. Although the reduction to 12 bits is not explicit: it's subsumed into the floating point scale factor.
Brilliant! You guys rock! Still as performance is concern I think the bitwise operation is faster, but the elegance of ustruct is undeniable.

Post Reply