-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding calibration code #2
Conversation
TemperDevice.__init__() reads /etc/temper.conf if it exists, and calibrates each device which has a configuration line in the file. Format of the config file is, for example, Device 0: scale = 0.937, offset = -0.5625 (see CONF_RE in temper.py for details). Calibration is made with the formula y = scale * x + offset where x is the raw value read from the device (in celcius), y is the calibrated value, and scale and offset are read from the config file. Since TemperDevice class object doesn't know what device number it is assigned, an argument "id" is added to TemperDevice.get_temperature() to tell it which calibration data line to use.
Hi Joji, thanks a lot for the effort! If I get that right you somehow determine the coefficients for calibration using some external measurement and note them in /etc/temper.conf as tuples of the form (id, scale, offset). As long as you have got only one device, this is fine. If you have more attached at the same time, you are definitely out of luck since the order in which the devices appear, cannot be reliably determined. I have one objection with the code and that is passing the id (only) to the get_temperature method. If we somehow preassume that we know which device is which, then we should pass that value in the constructor of TemperDevice and just use the stored value. This way we can also just store the calibration data for that device instead of storing them all in each TemperDevice instance. Could you try and change that before I merge it? All the best, Philipp |
@@ -11,9 +11,9 @@ def main(): | |||
|
|||
for i, dev in enumerate(devs): | |||
readings.append({'device': i, | |||
'temperature_c': dev.get_temperature(), | |||
'temperature_c': dev.get_temperature(id=i), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The id should be a property of the TemperDevice-instance and should be passed on construction (defaulting to None). There should also be a note in the constructor to remind the user that the TEMPer device up until now are undistinguishable and can swap order with every reenumeration.
Thank you for the quick response, Philipp. You are right, perhaps I will have to look into udev rules and libusb/python-usb code to know how the order of the devices are determined. Or maybe simply consulting to USB Bus/Device ID...mmm... I'll try and see if I can come up with a better way. Regards, |
If you could find anything to establish an order that is (only) dependant on the physical ordering of the hubs and devices, that would be awesome. Note though that the obvious sources came up empty: https://github.com/padelt/temper-python#note-on-multiple-device-usage |
Just read your note mentioned above and tried experimenting with my RasPi. First attempt, TEMPer in the lower USB slot on RasPi. Second attempt. TEMPer moved to the upper USB slot. Third attempt. Unplugged TEMPer and replugged into the same (upper) USB slot. Yeah, confirmed. Device number can vary easily ... the only possibility that might work to physically identify this device seems to be Bus/Port/If combination. That should at least survive reboots and temporary disconnections. Of course if you move TEMPers around among multiple USB ports, you will need to reassign these numbers (in config file maybe) again though. |
You are seeing more structure than I had on a RasPi, that is encouraging! But also try to unplug and replug a device multiple times (same socket/slot/connector). In my tests on a PC, something (can't remember) changed so even the order in the tree would change. |
TemperDevice now accepts "bus" argument in its __init__() method. Initializer code looks upon usb sysfs directory using this bus and deviceID information, and finds the port(or chain of ports) which this device is plugged on. After that, it reads configuration file (/etc/temper.conf) and uses calibration parameters found on the line with matching bus-ports. This is needed to uniquely identify the physical location of a TEMPer device, since only bus-ports combination can persist across reboots or connection losses.
… into with-calibration Conflicts: temper/temper.py
Adjusted regular expression for USB bus-ports pair, so that example line can be commented out with a preceding hash mark.
Instead of reading devpath from sysfs entry, use matched pattern for entry name itself. Add error handling to readattr() Fix regular expression to match sysfs entry
Merge "Usage" section of README.md to Instllation section since temper/temper.py does not have it's own main() code.
Add some note about multiple devices in README.md Minor spelling correction in temper/temper.conf.sample
Modified the way the devices are distinquished, using port numbers. I've looked into the usbutils source code to see what lsusb is doing inside. There was a python version in there (lsusb.py), which saved time for me. From what I see, it is peeking into /sys/bus/usb/devices and reading there recursively to get the usb device tree. So I borrowed the idea from there to get the port numbers that are leading to the device with matching bus/device ID. So far the bus/port combination seems to be working and persistent enough. The cases which this scheme might not work that come int my mind are; usb sysfs is not in /sys/bus/usb/devices. can happen on some distros. (your RasPi maybe?) But for most regular use cases hopefully this method would work. |
Store ports (string like "2.1.2") as an attribute so that it can be used later for output. Modify find_ports() method accordingly.
Add -h option to temper/cli.py for usage help. Add -p option to temper/cli.py for bus-port output.
Adding calibration code by GM3D, thanks!
Add "all" sensor flag support to cli.py
Hello Philipp,
I've read an article about the TEMPer device on the March issue of Linux Journal, which is based on your code.
I've given a try for it and it's working great.
However, as it is often the case with these cheap devices, my TEMPer needed some calibration to show a correct value. So I looked into your code and made some modification to include a simple linear calibration formula.
Basically TemperDevice class reads a configuration file /etc/temper.conf for calibration parameters (which are decided beforehand by other means), stores them into calib_data attribute. And when get_temperature() is called, it checks if there is a calibration data for this device ( had to add a new argument to this method to indicate what "this device" means), and if there is one, applies it to calibrate temp_c.
I'm new to Github and this is actually my first pull request, so there might be several points that should be done in better way. Any comments/suggestions or modifications will be appriciated.
Regards,
Joji Monma (GM3D on Github)