padelt / temper-python

libusb/PyUSB-based driver to read TEMPer USB HID devices (USB ID 0c45:7401) and serve as a NetSNMP passpersist module
Other
182 stars 76 forks source link

0c45:7402 Temperature reading incorrect #91

Closed nikcross closed 3 years ago

nikcross commented 5 years ago

I have a TEMPerHUM temperature and humidity sensor connected to a Raspberry Pi lsusb gives me: 0c45:7402 Microdia TEMPerHUM Temperature & Humidity Sensor

temper-poll gives me: Found 1 devices Device #0: 106.5°C 223.6°F

Its warm in here, but not that warm :-) and there is no humidity value.

I also have a TEMPer and that works ok.

Any ideas ?

MatGit5 commented 4 years ago

Same issue here... Device #0: 109.4°C 228.9°F The temperature is actually below 21°C.

davet2001 commented 4 years ago

Quite likely it is an unrecognised sensor type. Please can you paste the output of lsusb -v -d 0c45:7402

MatGit5 commented 3 years ago

lsusb -v -d 0c45:7402

Bus 001 Device 004: ID 0c45:7402 Microdia TEMPerHUM Temperature & Humidity Sensor Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x0c45 Microdia idProduct 0x7402 TEMPerHUM Temperature & Humidity Sensor bcdDevice 0.01 iManufacturer 1 RDing iProduct 2 TEMPERHUM1V1.2 iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 0x003b bNumInterfaces 2 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xa0 (Bus Powered) Remote Wakeup MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 3 Human Interface Device bInterfaceSubClass 1 Boot Interface Subclass bInterfaceProtocol 1 Keyboard iInterface 0 HID Device Descriptor: bLength 9 bDescriptorType 33 bcdHID 1.10 bCountryCode 0 Not supported bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 65 Report Descriptor: (length is 65) Item(Global): Usage Page, data= [ 0x01 ] 1 Generic Desktop Controls Item(Local ): Usage, data= [ 0x06 ] 6 Keyboard Item(Main ): Collection, data= [ 0x01 ] 1 Application Item(Global): Report ID, data= [ 0x01 ] 1 Item(Global): Usage Page, data= [ 0x07 ] 7 Keyboard Item(Local ): Usage Minimum, data= [ 0xe0 ] 224 Control Left Item(Local ): Usage Maximum, data= [ 0xe7 ] 231 GUI Right Item(Global): Logical Minimum, data= [ 0x00 ] 0 Item(Global): Logical Maximum, data= [ 0x01 ] 1 Item(Global): Report Size, data= [ 0x01 ] 1 Item(Global): Report Count, data= [ 0x08 ] 8 Item(Main ): Input, data= [ 0x02 ] 2 Data Variable Absolute No_Wrap Linear Preferred_State No_Null_Position Non_Volatile Bitfield Item(Global): Report Count, data= [ 0x01 ] 1 Item(Global): Report Size, data= [ 0x08 ] 8 Item(Main ): Input, data= [ 0x01 ] 1 Constant Array Absolute No_Wrap Linear Preferred_State No_Null_Position Non_Volatile Bitfield Item(Global): Report Count, data= [ 0x03 ] 3 Item(Global): Report Size, data= [ 0x01 ] 1 Item(Global): Usage Page, data= [ 0x08 ] 8 LEDs Item(Local ): Usage Minimum, data= [ 0x01 ] 1 NumLock Item(Local ): Usage Maximum, data= [ 0x03 ] 3 Scroll Lock Item(Main ): Output, data= [ 0x02 ] 2 Data Variable Absolute No_Wrap Linear Preferred_State No_Null_Position Non_Volatile Bitfield Item(Global): Report Count, data= [ 0x05 ] 5 Item(Global): Report Size, data= [ 0x01 ] 1 Item(Main ): Output, data= [ 0x01 ] 1 Constant Array Absolute No_Wrap Linear Preferred_State No_Null_Position Non_Volatile Bitfield Item(Global): Report Count, data= [ 0x05 ] 5 Item(Global): Report Size, data= [ 0x08 ] 8 Item(Global): Logical Minimum, data= [ 0x00 ] 0 Item(Global): Logical Maximum, data= [ 0xff ] 255 Item(Global): Usage Page, data= [ 0x07 ] 7 Keyboard Item(Local ): Usage Minimum, data= [ 0x00 ] 0 No Event Item(Local ): Usage Maximum, data= [ 0xff ] 255 (null) Item(Main ): Input, data= [ 0x00 ] 0 Data Array Absolute No_Wrap Linear Preferred_State No_Null_Position Non_Volatile Bitfield Item(Main ): End Collection, data=none Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 10 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 3 Human Interface Device bInterfaceSubClass 1 Boot Interface Subclass bInterfaceProtocol 2 Mouse iInterface 0 HID Device Descriptor: bLength 9 bDescriptorType 33 bcdHID 1.10 bCountryCode 0 Not supported bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 41 Report Descriptor: (length is 41) Item(Global): Usage Page, data= [ 0x00 0xff ] 65280 (null) Item(Local ): Usage, data= [ 0x01 ] 1 (null) Item(Main ): Collection, data= [ 0x01 ] 1 Application Item(Local ): Usage, data= [ 0x01 ] 1 (null) Item(Global): Logical Minimum, data= [ 0x00 ] 0 Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255 Item(Global): Report Size, data= [ 0x08 ] 8 Item(Global): Report Count, data= [ 0x08 ] 8 Item(Main ): Input, data= [ 0x02 ] 2 Data Variable Absolute No_Wrap Linear Preferred_State No_Null_Position Non_Volatile Bitfield Item(Local ): Usage, data= [ 0x01 ] 1 (null) Item(Global): Report Count, data= [ 0x08 ] 8 Item(Main ): Output, data= [ 0x02 ] 2 Data Variable Absolute No_Wrap Linear Preferred_State No_Null_Position Non_Volatile Bitfield Item(Global): Usage Page, data= [ 0x0c ] 12 Consumer Item(Local ): Usage, data= [ 0x00 ] 0 Unassigned Item(Global): Logical Minimum, data= [ 0x80 ] 128 Item(Global): Logical Maximum, data= [ 0x7f ] 127 Item(Global): Report Size, data= [ 0x08 ] 8 Item(Global): Report Count, data= [ 0x08 ] 8 Item(Main ): Feature, data= [ 0x02 ] 2 Data Variable Absolute No_Wrap Linear Preferred_State No_Null_Position Non_Volatile Bitfield Item(Main ): End Collection, data=none Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 10 can't get device qualifier: Resource temporarily unavailable can't get debug descriptor: Resource temporarily unavailable Device Status: 0x0000 (Bus Powered)

davet2001 commented 3 years ago

Yes, it looks like 'TEMPERHUM1V1.2' is not supported yet by the python package, but 'TEMPERHUM1V1.3' is. There is a high chance that they behave the same. Testing it should be a matter of editing temper.py and listing 'TEMPERHUM1V1.2' in each of the places where you see 'TEMPERHUM1V1.3'.

Unfortunately the package is a bit piecemeal with not all of the sensor data in one place, see #97. But that shouldn't stop you getting it working.

davet2001 commented 3 years ago

I have made a guess at config settings for this device:

https://github.com/davet2001/temper-python/commit/728c97740bed34d00e0829cb2d5f8f6f3edf699a

Maybe you could download and try it?

davet2001 commented 3 years ago

Did it work @MatGit5 ?

skilleter commented 3 years ago

I've also got one of these and the suggested patch nearly works.

The device has a button which causes to emulate a keyboard and output temperature and humidity readings as if they'd been typed in.

With this active it reports a temperature of 25.31°C and a relative humidity of 40.71 and, by comparison, the cli.py script reports the temperature as 25.3°C and the humidity as 35.1, so temperature is correct and humidity is about 5.5% low (allowing for the fact that the keyboard emulation doesn't work on Windows, so I had to keep swapping it between Windows and Linux machines to get the readings).

davet2001 commented 3 years ago

@skilleter There's a possibility that it's working fine, but let's check.

Please could you checkout https://github.com/davet2001/temper-python/commit/a2c35d50a56fbc2e568a983f75c4ad953972cbd4

and run: python3 -m temperusb.cli -v

Please reply back with the full console output.

Then press the button again and report what it displays in keyboard mode. Try to keep time between the two as short as possible and use a plastic object (e.g. pen) to press the button to prevent your hand from heating up the device.

skilleter commented 3 years ago

Output from the script: $ python3 -m temperusb.cli -v DEBUG:temperusb.temper:Found device | Bus:1 Ports:10 SensorCount:1 INFO:temperusb.temper:Found 1 TEMPer devices Found 1 devices DEBUG:temperusb.temper:Detaching kernel driver for interface 0 of <DEVICE ID 0c45:7402 on Bus 001 Address 006> on ports 10 DEBUG:temperusb.temper:Detaching kernel driver for interface 1 of <DEVICE ID 0c45:7402 on Bus 001 Address 006> on ports 10 DEBUG:temperusb.temper:Ctrl transfer: b'\x01\x803\x01\x00\x00\x00\x00' DEBUG:temperusb.temper:Read data: '80 04 62 e4 5f c2 60 3f' DEBUG:temperusb.temper:Ctrl transfer: b'\x01\x803\x01\x00\x00\x00\x00' DEBUG:temperusb.temper:Read data: '80 04 62 dc 5f c2 60 3f' DEBUG:temperusb.temper:ID='TEMPERHUM1V1.2' DEBUG:temperusb.temper:T=21.00769C DEBUG:temperusb.temper:Ctrl transfer: b'\x01\x803\x01\x00\x00\x00\x00' DEBUG:temperusb.temper:Read data: '80 04 62 dc 5f c2 60 3f' DEBUG:temperusb.temper:Ctrl transfer: b'\x01\x803\x01\x00\x00\x00\x00' DEBUG:temperusb.temper:Read data: '80 04 62 dc 5f c2 60 3f' DEBUG:temperusb.temper:ID='TEMPERHUM1V1.2' DEBUG:temperusb.temper:RH=40.75674% Device #0: 21.0°C 69.8°F 40.8%RH

Output in keyboard mode with button-pressing performed as requested (and done on the same computer now that I've found it works if it isn't connected via a hub):

www.pcsensor.com type:hum caps lock:on/off/++ fw:1.2 num lock:off/on/-- c %rh interval ; : 20.92 46.07 01 ; : 20.94 46.26 01 ; : 20.95 46.26 01 ; : 20.96 46.44 01

davet2001 commented 3 years ago

Ok, assuming the measuring IC is an si7021 the datasheet gives formula image So in the returned data '80 04 62 dc 5f c2 60 3f' at offset 4 we have: 0x5f 0xc2 which is 0d24514 So %RH should be (125*24514)/65536 - 6 = 40.75674438

Someone else also reports that the same device reads a bit high for humidity.

It is possible (not proven - I'm just speculating), that the keyboard mode output is accidentally omitting the -6 in the calculation, outputting 46.07% RH when it should be 40.07%, and that this could be an issue with the device itself rather than temper-python.

Please note, some caveats:

I don't have one so I can't check, but it would be helpful if anyone is willing to open the device and read the IC markings to verify that it is actually an SI7021.

Also comparing the readings to an independent known good sensor would be helpful for a true RH ref.

In summary: temper-python seems to be handling the calculation correctly. Would help to confirm the sensor type and true RH being measured.

davet2001 commented 3 years ago

Unless anyone objects, I propose merging this as it improves functionality. A follow up PR could be added if someone can see a way to genuinely improve accuracy.

endolith commented 3 years ago

I don't have one so I can't check, but it would be helpful if anyone is willing to open the device and read the IC markings to verify that it is actually an SI7021.

Also comparing the readings to an independent known good sensor would be helpful for a true RH ref.

I could open mine if needed, but https://github.com/edorfaus/TEMPered/pull/30 says it's Si7021 and has photos like this:

Mine is

0x0C45  idVendor
0x7402  idProduct
0x0001  bcdDevice
0x01    iManufacturer   "RDing"
0x02    iProduct        "TEMPERHUM1V1.3"

I also have a USB Protocol Analyzer and logic analyzer if that's helpful.

endolith commented 3 years ago

Oh wait, mine is already supported. Nevermind.

Yes, it looks like 'TEMPERHUM1V1.2' is not supported yet by the python package, but 'TEMPERHUM1V1.3' is.

skilleter commented 3 years ago

I'm happy for this to be merged. I had a go at opening the case for my sensor and was defeated by it, I'm afraid. The amount of force I was applying was heading dangerously towards 'one slip with the screwdriver and there will be blood everywhere' territory!

padelt commented 3 years ago

Thanks everyone! Please reopen the issue if needed!