In my last post I hooked up one DS18B20 to a RaspberryPi. The neat thing about the DS18B20 and the 1-wire protocol is that multiple such devices can be connected together in a star topology. What's really great about this is that identifying an individual sensor doesn't depend on its position in a chain (for example) each device has its own unique 64-bit identifier. This means the layout of the probes doesn't have to be determined ahead of time. Also the length of the wires attached to the sensor can vary by a considerable amount. Therefore sensors near and far can be connected to the same microcontroller.
I had a number of varieties of protoboard, one of which is this type which features long buses:
This style of board works perfectly for this scenario.
I also happened to have a bunch of these x3 male headers. Most likely from some servo project.
Wouldn't it be great if there were a way to add a connector to the end of the temperature probes so they could plug into this header easily? As it turns out, it's Pololu to the rescue! Among the many things they sell, they also have crimp connector housings in various configurations, and all the other accessories to go with it.
I know this probably sounds like I have some relationship with Pololu but I don't. I know other electronics suppliers provide such items too, but Pololu's site makes it quite easy to buy the right things the first time around and give me the confidence to try this out (thanks to their supporting videos and information). After a little practice on test wires I'm able to add connectors to my temperature probes:
Cutting off a piece of protoboard and soldering on the header gives me a hub into which to plug all the temperature probes. Since we need a 4.7k pull-up resistor in the design anyway, I might as well add it to the hub so it's ready to go:
You'll notice there's no picture of the underside 😉 It's bad enough showing this hack job from the top, I'm not about to show the disaster on the other side. Thankfully all the buses are still separate from each other, and that's all that matters 😂
With the pull-up resistor in place I'm forcing the middle bus to be the ground. The connectors aren't keyed, so I just have to line up the VDD and DQ lines together myself.
…and with the RaspberryPi:
Now when I boot my device I get a kernel log message about my GPIO setup and one log message each for each of the sensors attached to my hub:
[ 5.135283] gpio-25 (onewire@19): enforced open drain please flag it properly in DT/ACPI DSDT/board file [ 5.202823] w1_master_driver w1_bus_master1: Attaching one wire slave 28.01131bb70fee crc 30 [ 5.497062] w1_master_driver w1_bus_master1: Attaching one wire slave 28.01131b7ad963 crc f6 [ 5.599175] w1_master_driver w1_bus_master1: Attaching one wire slave 28.01131b62790b crc 83
Note: these messages don't appear side-by-side in the log, but they do appear in this order.
Now when I look in the 1-wire sysfs location I find:
root@raspberrypi3-64:~# cd /sys/bus/w1/devices/ root@raspberrypi3-64:/sys/bus/w1/devices# ls -l lrwxrwxrwx 1 root root 0 Dec 29 04:22 28-01131b62790b -> ../../../devices/w1_bus_master1/28-01131b62790b lrwxrwxrwx 1 root root 0 Dec 29 04:22 28-01131b7ad963 -> ../../../devices/w1_bus_master1/28-01131b7ad963 lrwxrwxrwx 1 root root 0 Dec 29 04:22 28-01131bb70fee -> ../../../devices/w1_bus_master1/28-01131bb70fee lrwxrwxrwx 1 root root 0 Dec 29 04:22 w1_bus_master1 -> ../../../devices/w1_bus_master1
To read the temperatures of the probes I could visit each probe individually and simply "cat" the "temperature" file. This will cause the kernel to perform the "Convert T [44h]" command followed by the "Read Scratchpad [BEh]" command on each probe individually.
A small performance improvement can be had by visiting the master driver device and issuing a "trigger" command to its "therm_bulk_read" sysfs entry, then reading the temperatures from the probe devices individually. This causes the "Convert T [44h]" command to be issued to all the temperature probes connected to this master.
Notice that once the bulk command is given, the value of "therm_bulk_read" will read -1 if at least one sensor is still performing the conversion, 1 if one of the sensors has not had its temperature read out, and 0 once all the temperatures have been read for the most recent bulk conversion:
root@raspberrypi3-64:~# cd /sys/bus/w1/devices/ root@raspberrypi3-64:/sys/bus/w1/devices# ls -1 28-01131b62790b 28-01131b7ad963 28-01131bb70fee w1_bus_master1 root@raspberrypi3-64:/sys/bus/w1/devices# cat w1_bus_master1/therm_bulk_read 0 root@raspberrypi3-64:/sys/bus/w1/devices# echo "trigger" > w1_bus_master1/therm_bulk_read root@raspberrypi3-64:/sys/bus/w1/devices# cat w1_bus_master1/therm_bulk_read 1 root@raspberrypi3-64:/sys/bus/w1/devices# cat 28-01131b62790b/temperature 23375 root@raspberrypi3-64:/sys/bus/w1/devices# cat w1_bus_master1/therm_bulk_read 1 root@raspberrypi3-64:/sys/bus/w1/devices# cat 28-01131b7ad963/temperature 28-01131bb70fee/temperature 23125 23437 root@raspberrypi3-64:/sys/bus/w1/devices# cat w1_bus_master1/therm_bulk_read 0
Note that I can't issue the bulk command and read out the status fast enough to demonstrate the -1 case. Writing the "trigger" to start the bulk command appears to block until all the probes have performed their temperature conversions.
The interesting thing about the bulk command is that it allows all the probes to check their temperatures at roughly the same time, then the code can take its time reading out the temperatures that existed when the bulk command was given. If each probe were to be visited one at a time, the timing of the temperature checks from all the probes would be skewed. This might not be a problem, but it's handy having this feature available.
Another neat thing about this setup is that the kernel actively probes the 1-wire bus during its operation. Therefore adding probes is plug-and-play at runtime! If a new probe is added to the bus at runtime, the kernel detects it, adds it to the list of devices, and prints a message indicating the probe's unique serial number. This feature makes it easier to add probes to an installation and correlate which probe is measuring which temperature. For example, if you have a project that needs 5 probes, each probe measuring a different part of a project, you can boot your hardware with the probes un-attached then attach them one-by-one to the bus at runtime taking note of their serial numbers and the part of the project each probe is measuring as they're being added.