Python USB and TEMPer V1.2

In preparation for a bigger project I’ve recently written a driver for the USB Temperature Sensor TEMPer V1.2. As this is going to be part of a bigger project that will interface with these sensors I wanted to integrate the driver with the project. So I decided to write it in Python.

Story

So a friend of mine wanted to use these relatively inexpensive USB Temperature Sensors (available on Amazon for less than $20) to keep an eye on his indoor garden. But he found the software available for these sensors to be inadequate for what he had in mind. So I told him I’d look into the issue of writing a better front-end Software for these sensors. Since he wanted to use them in controlling his indoor garden I decided it would be best to have the Software be compatible with low cost embedded boards that don’t take up as much power as a big Computer. Naturally this meant I had to check the sensors for Linux compatibility first. Fair enough it seemed that many people have worked with these devices before, even on Linux, so I bought one and started experimenting.

It turned out that the driver situation for these sensors is in no way straight forward. There were a bunch or Perl scripts and other things floating around, but I’m not a Perl programmer and I didn’t want to have to install a multitude of interpreters. I wanted it to be as plain and simple as possible and if at all possible I wanted it to be platform independent. After a while I found a C Program called pcsensor that would interface with the TEMPer V1.2. I was much more comfortable with a small C Program than with all thing Perl, but since the interface to the USB library in Python is very similar to C I decided I could just as well use the C program as a template and rewrite it in Python.

Source Code

So after about 2 hours of transcoding C to Python I had a working driver! This driver is still a little rough around the edges, as it very closely resembles the C Program, but it’s a good start.

I thought I would share this piece of code. I’ll of course write some more about this as soon as I make more progress with this project.

import sys, os, time, usb
 
VENDOR_ID = 0x0c45
PRODUCT_ID = 0x7401
 
INTERFACE1 = 0x00
INTERFACE2 = 0x01
 
reqIntLen=8
reqBulkLen=8
endpoint_Int_in=0x82 #/* endpoint 0x81 address for IN */
endpoint_Int_out=0x00 #/* endpoint 1 address for OUT */
 
uTemperatura = [ 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 ]
uIni1 = [ 0x01, 0x82, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00 ]
uIni2 = [ 0x01, 0x86, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00 ]

calibration = 0

def setup_libusb_access():
        for bus in usb.busses():
                for dev in bus.devices:
                        if dev.idVendor == VENDOR_ID and dev.idProduct == PRODUCT_ID:
                                print "Found Temper"
                                return dev
                        else:
                                print "searching for Temper Devices..."
        print "no devices found"
        return None

def ini_control_transfer(connection):
        question = [0x01, 0x01]
        
        # Detaching Kernel drivers on interfaces if any are present
        try:
                connection.detachKernelDriver(INTERFACE1)
        except:
                print "couldn't detach Kernel driver for interface1"
        try: 
                connection.detachKernelDriver(INTERFACE2)
        except:
                print "couldn't detach Kernel driver for interface2"
        
        # claim interfaces
        try:
                connection.claimInterface(INTERFACE1)
                connection.claimInterface(INTERFACE2)
        except:
                print "couldn't claim one of the interfaces"
        
        r = connection.controlMsg(requestType=0x21, request=0x09, value=0x0201, index=INTERFACE1, buffer=question)
        if r < 0:
                print "Control Message failed"
                return False
        return True
        
def control_transfer(connection, question):
        r = connection.controlMsg(requestType=0x21, request=0x09, value=0x0200, index=INTERFACE2, buffer=question)
        return 
        
def interrupt_read(connection):
        r = connection.interruptRead(endpoint_Int_in, reqIntLen)
        return
        
def interrupt_read_temperature(connection):
        answer = connection.interruptRead(endpoint_Int_in, reqIntLen)
        
        #debug output
        print "read_temperature answer:"
        print answer
        
        tmp = answer[2]
        
        if (answer[2] & 0x80): #So the device is working with a signed integer... we don't have that in Python. So whenever the value is greater than 127 we're actually dealing with a negative int
                print "adjusting negative temp"
                tmp = -0x10 + answer[2]
        
        temperature = (answer[3] & 0xFF) + (tmp << 8)
        temperature += calibration
        tempC = temperature * (125.0 / 32000.0)

        return tempC
        
        
def usb_release_interface(con, iface):
        try:
                con.releaseInterface()
        except:
                pass
        
def usb_close(con):
        con.reset()

def main(argv):
        temper = setup_libusb_access()
        
        if (temper == None):
                sys.exit(17)
        connection = temper.open()
        connection.reset()
        
        ini_control_transfer(connection)
        
        control_transfer(connection, uTemperatura )
        interrupt_read(connection)
        
        control_transfer(connection, uIni1 )
        interrupt_read(connection)
        
        control_transfer(connection, uIni2 )
        interrupt_read(connection)
        interrupt_read(connection)
        
        while 1:
                try:
                        control_transfer(connection, uTemperatura )
                        tempc = interrupt_read_temperature(connection)
                        
                        print time.time()
                        print str(tempc)+" C"
                        
                        time.sleep(1)
                except KeyboardInterrupt:
                        print "Execution Interrupted by User"
                        break
                        
        usb_release_interface(connection, INTERFACE1)
        usb_release_interface(connection, INTERFACE2)
        
        usb_close(connection)
        
        return 0

if __name__ == "__main__":
        main(sys.argv)

Flattr this!

Leave a Reply

Your email address will not be published. Required fields are marked *



Time limit is exhausted. Please reload CAPTCHA.