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.
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.
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 if (answer & 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 temperature = (answer & 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)