gpiozero icon indicating copy to clipboard operation
gpiozero copied to clipboard

Temperature Sensor

Open bennuttall opened this issue 10 years ago • 22 comments

Currently we just inherit the w1thermsensor class from its own library, and alias a value property to return the temperature in Celsius.

What do we need to do to provide a typical GPIO Zero interface?

bennuttall avatar Oct 25 '15 21:10 bennuttall

Perhaps adding a values property would be handy, but would require a way of channelling it between 0 and 1. Suggestion:

>>> temp = TemperatureSensor()
>>> temp.high = 30
>>> temp.low = 20
>>> temp.value
25.0
>>> temp.values
0.5

That might not be the right usage of values, but do you follow my meaning? @waveform80

bennuttall avatar Oct 27 '15 22:10 bennuttall

Any thoughts?

bennuttall avatar Nov 02 '15 12:11 bennuttall

Yup - basically the same - that the user can specify an "expected range" which we can default to the limits of the sensor (assuming the class targets a specific sensor - might make a generic temperature sensor class and subclass it for specific ones like the ADC stuff - not sure about that bit yet)

waveform80 avatar Nov 03 '15 21:11 waveform80

Not sure if this is going to make it into 1.0 - I'm digging fairly deeply into the dallas 1-wire stuff trying to make this as brutally simple as possible and so far the short version is that there's no way we can make this as simple as other stuff in gpiozero. One-wire stuff relies on a kernel module (which needs sudo modprobe to load it) and a device-tree overlay (which means tweaking /boot/config.txt with root privs too).

I'm contemplating digging into other temperature sensors to see if there's anything a little easier out there, but given the DS18B20 is the one in the CamJam 2 kit I'm guessing we'll have to support it out of sheer popularity.

waveform80 avatar Nov 04 '15 14:11 waveform80

Shall we pull it from the module (or just from the docs) for now?

bennuttall avatar Nov 04 '15 15:11 bennuttall

Hmm ... although pulling it from the module is a bit drastic, I'm half tempted given it's not ready and unlikely to be in time for 1.0. Any objections?

Just thinking out loud on this ... I'm still digging into why a kernel module and device tree overlay is necessary for 1-wire stuff (I'm sure there's a good reason, but I'd like to understand it for my own curiosity). Anyway, SPI and I2C both have options in raspi-config for activating them simply (which takes care of editing /boot/config.txt and loading modules automatically). Having a similar option for 1-wire would significantly ease the documentation burden of this (do you fancy explaining in complete-newbie-friendly language how to edit /boot/config.txt as root?!).

What do you reckon the chances are of adding such an option to raspi-config?

waveform80 avatar Nov 04 '15 15:11 waveform80

@spl237 any thoughts?

bennuttall avatar Nov 04 '15 15:11 bennuttall

Don't see any reason why not - we already do it for the camera.

spl237 avatar Nov 04 '15 15:11 spl237

Excellent; if there's anything I can do to help, let me know!

waveform80 avatar Nov 04 '15 15:11 waveform80

Decision is to drop this for the 1.0 release and work back in later

bennuttall avatar Nov 15 '15 12:11 bennuttall

@waveform80 note it's still a dependency in the deb stuff

bennuttall avatar Nov 15 '15 13:11 bennuttall

Yeah - I might chop that out before the release just to keep things as minimal as possible. We can always re-add this stuff by reverse committing stuff associated with this ticket.

waveform80 avatar Nov 15 '15 16:11 waveform80

yup

bennuttall avatar Nov 15 '15 16:11 bennuttall

Reopening this

bennuttall avatar Feb 13 '16 11:02 bennuttall

Someone needs to tell me exactly how this is enabled and disabled....

spl237 avatar Mar 18 '16 11:03 spl237

The full instructions are here but I think all you need to do in raspi-config is enable the following overlay:

dtoverlay=w1-gpio

bennuttall avatar Mar 18 '16 11:03 bennuttall

Done - changes to raspi-config and rc_gui checked in; will be in next release.

spl237 avatar Mar 18 '16 14:03 spl237

Great - thanks!

(this change doesn't close this issue though...)

bennuttall avatar Mar 18 '16 14:03 bennuttall

Fair point... :)

spl237 avatar Mar 18 '16 14:03 spl237

Unless you fancy writing some Python code? :P

bennuttall avatar Mar 18 '16 14:03 bennuttall

Hi folks. Apologies in advance for the long rambling post.

From what I'm reading here on Github, it seems that progress on getting 1-wire temp sensors into a full release version of GPIOZero has stalled. I'm going to try to generate some enthusiasm for getting it going again. (If I've misread this - if it's not stalled - please accept my apologies)

I run Cotswold Raspberry Jam and on Sat 2 July 2016 we ran two 15-pupil tutorials using the DS18B20 waterproof temperature sensor, with children mostly in the age range 8-14. I wrote the tutorial.

I very much missed the temp sensor's inclusion in GPIOZero and I thought you might be interested to know how we handled it.

We try to keep the tutorials down to 45-50 minutes, and my rule of thumb is that more than 4 pages of tutorial document means that it will overrun.

http://cotswoldjam.org/downloads/2016-07/cjam-temperature-tutorial.pdf

First the good news.

Top of the list is that DS18B20 sensors are dirt cheap - around £1.30 if ordered in packs of ten or more - and we easily made kits comprising sensor, 170-point breadboard, resistors, LEDs and jumpers for under our target price of £2.50 per kit (we run entirely from donations, tickets are free and all pupils get to take home their kits). In my opinion the DS18B20 makes for a great cheap tutorial.

Every single child, without fail, was able to enable 1-Wire in the new Raspberry Pi Configuration tool (raspi-config GUI). A couple may have forgotten or skipped ahead without doing it, but they soon figured it out with only a little reminder from classroom assistants.

Furthermore they all understood that they needed to reboot their Pi to bring the 1-Wire setting into effect - so I don't think GPIOZero folks need to worry about attempting rebootless methods such as modprobe. I think GPIOZero can safely just throw an exception if it's not enabled.

All children got their kits to work inside 45 minutes. Using PWMLED they got the blue LED to shine brightest when the sensor got cold, then ramp blue down and red up, until the red LED shone brightest when the sensor was hot. Camping freezer blocks were great non-spill accessories, as were antibacterial wipes for when a pupil (inevitably) put the sensor in their mouth (thank goodness it was only their mouth). PWMLED gave me a good opportunity to explain what pulse width modulation was and why it affected LED brightness.

Next the not-so-good news. This is where we need GPIOZero to come to the rescue.

The boilerplate to detect the correct 1-wire /sys/bus/w1/devices folder & file is WAY too complex to explain in a short tutorial to children. The same can be said of the output grepping required to extract the decimal celcius reading from the assorted other output. Worse, that boilerplate is pretty long, especially if you put in exception handling, and it would fill one page of my max-4-pages tutorial just by itself.

As a result, I had to create a library readtemp.py to hold all the boilerplate. My OO is rubbish so it was just a couple of DEFs, not even proper classes or methods or anything. I will readily admit that the code is cobbled together snippets from multiple other tutorials, plus some dreadful exception handling. It does the job, but it is not neat. A proper GPIOZero way of doing it would be much easier to run a tutorial from. For example, children who typed-in code rather than loaded in the example files, often saved to the wrong directory and didn't pick up readtemp.py . Sure, that's a silly example - I should have placed my library somewhere in a path - but it's an example of how GPIOZero makes a tutor's life easier.

http://cotswoldjam.org/downloads/2016-07/cjam-temperature-files.zip

So GPIOZero developers - many thanks for everything you've done to date, and please, please keep trying to get 1-wire temp sensors into a release soon. For the sake of Stan the Sloth, if nothing else: https://www.youtube.com/watch?v=iWzvtnnUyVo

aoakley avatar Jul 06 '16 14:07 aoakley

Long overdue update: it appears our concerns over modprobe were invalid. With the raspi-config/rcgui changes, the modprobe was unnecessary. And so reading the file interface makes it trivial, just like reading the CPU temperature. In fact, I believe the API should probably match CPUTemperature exactly.

The following example seems to work:

from gpiozero import CPUTemperature

class TemperatureSensor(CPUTemperature):
    @property
    def temperature(self):
        with io.open(self.sensor_file, 'r') as f:
            return float(f.readlines()[1].split("=")[1]) / 1000
        
temp = TemperatureSensor('path_to_w1_slave')

print(temp.temperature)

Obviously we wouldn't really want to extend CPUTemperature, this is just a proof of concept, and the easiest way of making it work.

Other things to consider:

  • Find out which GPIO pin is in use, and add it to the pins lock (defaults to GPIO4 unless changed in config)
  • Can we support multiple sensors like w1thermsensor does?
  • Can we auto-fill the temperature file location like w1thermsensor does? (or is that just using a wildcard?)

bennuttall avatar Mar 08 '17 22:03 bennuttall