1-wire protocol has been invented originally by Dallas Semiconductors.
It's a protocol where the devices only have max. 3 wires: Vcc, GND and Data.
You have two types of 1-wire setup: parasitic power and real power.
Parasitic power takes advantages of the energy capturing while the signal is high. An internal capacitor in the chip, e.g. DS18B20, captures the energy and uses it later on to internally power the chip.
However, there are situations where that doesn't work well. Therefor, I prefer to use the powered version of 1-wire.
To take advantage of the 1-wire protocol you have to activate it in the Raspberry Pi. You can do so editing (as root) /boot/firmware/config.txt and adding the following line:
dtoverlay-w1-gpio
By default, the pin used for 1-wire on the Raspberry Pi is physical pin 7 on the 40-pin header. This pin is also is also known as BCM pin GPIO4.
See https://pinout.xyz/pinout/1_wire.
You can change the pin if you want. To do so, add the pin you want to use at the end of the overlay command:
dtoverlay=w1-gpio,gpiopin=x, where x is the pin of your choice. x is always the GPIO pin, not the physical pin.
Suppose you want to use GPIO17 as 1-wire pin then the x will be 17. This means, physical pin 11 will be used.
To check if all works fine you can do the following:
Make sure 1-wire is activated on the Raspberry Pi. If not, activate and reboot the Raspberry Pi
Take a 1-wire device: I will use the DS18B20 temperature sensor as an example (since that's the only 1-wire device I have..)
Connect pin 1 to GND
Connect pin 2 to GPIO4 of the Raspberry Pi (default 1-wire pin)
Connect pin 3 to VCC
Connect a resistor of 4k7 between VCC and the data pin (pin 2)
go to /sys/bus/w1/devices
If the 1-wire device is detected, you should see a directory starting with the family number (for the DS18B20 temperature sensor this is 0x28)
Inside that directory you will see quite a few files and subdirectories. This is what I have:
pi@trixie2:/sys/bus/w1/devices/28-31c7de4ec5b7 $ lla
total 0
0 drwxr-xr-x 4 root root 0 Dec 19 17:02 .
0 drwxr-xr-x 4 root root 0 Dec 19 17:02 ..
0 -rw-r--r-- 1 root root 4096 Dec 19 17:02 alarms
0 -rw-r--r-- 1 root root 4096 Dec 19 17:02 conv_time
0 lrwxrwxrwx 1 root root 0 Dec 19 17:02 driver -> ../../../bus/w1/drivers/w1_slave_driver
0 --w------- 1 root root 4096 Dec 19 17:02 eeprom_cmd
0 -r--r--r-- 1 root root 4096 Dec 19 17:02 ext_power
0 -rw-r--r-- 1 root root 4096 Dec 19 17:02 features
0 drwxr-xr-x 3 root root 0 Dec 19 17:02 hwmon
0 -r--r--r-- 1 root root 4096 Dec 19 17:02 id
0 -r--r--r-- 1 root root 4096 Dec 19 17:02 name
0 drwxr-xr-x 2 root root 0 Dec 19 17:02 power
0 -rw-r--r-- 1 root root 4096 Dec 19 17:02 resolution
0 lrwxrwxrwx 1 root root 0 Dec 19 17:02 subsystem -> ../../../bus/w1
0 -r--r--r-- 1 root root 4096 Dec 19 17:02 temperature
0 -rw-r--r-- 1 root root 4096 Dec 19 17:02 uevent
0 -rw-r--r-- 1 root root 4096 Dec 19 17:02 w1_slave
You can now play around a bit with some parameters to see if all works fine:
cat w1_slave will show you this:
pi@trixie2:/sys/bus/w1/devices/28-31c7de4ec5b7 $ cat w1_slave
fb 00 55 aa 7f ff 15 10 ed : crc=ed YES
fb 00 55 aa 7f ff 15 10 ed t=15687
The last part follwing t= is showing you the current temperature in °C millidegrees, so you have to divide by 1000 to get the value in °C.
So, in the example the temperature is 15.687°C
cat tempearture will show you this:
pi@trixie2:/sys/bus/w1/devices/28-31c7de4ec5b7 $ cat temperature
15687
Here you have only the temperature in °C millidegrees.
cat name will show you the 64 bit serial number, family number shown first (that's how the Linux 1-wire driver is representing it)
pi@trixie2:/sys/bus/w1/devices/28-31c7de4ec5b7 $ cat name
28-31c7de4ec5b7
Note that the CRC byte (MSB) is not shown by the Linux 1-wire driver.
So, the real ROM code is divided in the following groups
MSB (byte 8) = 8 bit CRC, not shown in the 1-wire driver in Linux
Bytes 7-2 (6 bytes) = 48-bit serial number, in the example this is 31c7de4ec5b7
Byte 1 (LSB) is the family code (0x28 for the temperature sensor family)
Below is the representation of the 64 bit ROM code
To use one or more temperature sensors DS18B20 the application iCtherm has to be used.
John has also written an immediateC application called therm.ic that can be used in conjunction with iCterm.
therm.ic uses the IEC variabel IW0 to check the temperature change. If IW0 is changing then iCtherm should fire a trigger so that the imm int variable temperature in therm.ic is triggered and some action is taken accordingly.
This is the therm.ic code, at least the immedateC part:
imm int temperature = IW0;
if (EOI) { /* end of initialisation */
if (opt_I) {
printf("%s ", opt_I);
}
if (opt_d) {
t = time(0);
printf("start recording %s", ctime(&t));
} else {
printf("\n");
}
}
if (CHANGE(temperature)) {
if (opt_I) {
printf("%s ", opt_I);
}
printf("%5.1f °%c", (double)temperature/10.0, opt_C);
if (opt_d) {
t = time(0);
printf(" %s", ctime(&t));
} else {
printf("\n");
}
}
However, I don't think I have it already up and running as it should. I was able to get the following working:
pi@trixie2:~/mystuff/immediatec/src $ ./iCtherm -r 1 IW0 -R therm
0 @ARGV = '-r 1 IW0 -R therm'
$ iCserver -z -ak &
iCserver created. Waiting for events
iCtherm 'iCtherm' connecting at server
Connection 127.0.0.1:36162 at iCserver
1: iCtherm: registering now
$ therm -z &
'therm' connected to iCserver at '127.0.0.1:8778'
Connection 127.0.0.1:36166 at iCserver
2: therm: registering now
start recording Fri Dec 19 19:00:33 2025
16.0 °C Fri Dec 19 19:00:35 2025
Here I will get a read-out of the temperature if the temperature is changing because the option -r 1 is given. The default is 60 seconds, so when a temperature is changing you won't see it earlier than every minute by default.
The below command is assigning IW0 as IEC variable. IW0 is used in therm.ic to check for temperature changes.
./iCtherm -r 1 IW0 -R therm -R iCbox -n DS18B20 -d IW0,0,500
I'm also calling the compiled version of therm.ic where IW0 is used to be assigned to imm int temperature (see listing in beginning of this chapter).
Next to this I'm also starting up iCbox and giving it a name. I want it to show IW0 (using the -d option) within a range of 0 to 500 which will correspond to a temperature from 0°C to 50°C. So, a temperature of 20.5°C will be shown as 205 on the slider of iCbox.
I don't know yet how to represent the resolution so that the slider is also showing 20.5 instead of 205.
When you work with 2 or more temperature sensors you can get the values like so:
./iCtherm -r 1 IW0-IW1 -F -R therm -R iCbox -n DS18B20 -d IW0,0,500 IW1,0,500
Note that the sensors are treated alphabetically: first alphabetical sensor is assigne to IW0, second to IW1 and so on, unless you specify which sensor belongs to which IW.
Note that you have to adapt the file therm.ic accordingly.
This is an example where IW's are connected to dedicated temperature sensors:
./iCtherm -r 1 IW0:28-31c7de4ec5b7 IW1:28-666de446e652 -C -R therm -R iCbox -n DS18B20 -d IW0,0,500 IW1,0,500
By doing the following you revert the connections between IW and the temperature sensors:
./iCtherm -r 1 IW1:28-31c7de4ec5b7 IW0:28-666de446e652 -C -R therm -R iCbox -n DS18B20 -d IW0,0,500 IW1,0,500
Note that the first line at the beginning of this chapter requested the temperature in °Fahrenheit (-F) while the latter two iCtherm commands requested the temperature in °Celcius (-C).
When I was studying the way John has made his 1-wire component by analysing the file therm.ic I came to see an immediateC file with quite some C code init.
The C code starts with iCbegin and to be honest, I have no idea what's behind this. But it's needed to have the therm.ic filel working fine since the C code is defining options that are later on used in the same therm.ic file.
What I also experienced is that you can pass options to the iCbegin function. Its signature is similar to that of the official main() method in regular C files: an argument counter and an array of arguments.
Depending on the types of options you pass to therm.ic, they will be taken into account. What I mean by this, is the following:
If you call therm.ic on the command line like so:
./iCtherm -r 1 IW0-IW1 -C -R therm -R iCbox -n DS18B20 -d IW0,0,500 IW1,0,500
then therm.ic has no options provided, since the therm.ic options must have two (2) hyphens (--) to be taken into account. Here, there are none.
Should you try to provide an option using only one (1) hypen, it will be ignored and an error will be thrown like so:
pi@trixie2:~/mystuff/immediatec/src $ ./iCtherm -r 1 IW0-IW1 -C -R therm -n -R iCbox -n DS18B20 -d IW0,0,500 IW1,0,500
0 @ARGV = '-r 1 IW0-IW1 -C -R therm -n -R iCbox -n DS18B20 -d IW0,0,500 IW1,0,500'
Number of thermometers = [2]
IEC = [IW0]
IEC = [IW1]
$ iCserver -z -ak &
iCserver created. Waiting for events
iCtherm 'iCtherm' connecting at server
Connection 127.0.0.1:57786 at iCserver
1: iCtherm: registering now
$ therm -z -n -R iCbox -n DS18B20 -d IW0,0,500 IW1,0,500 &
ERROR: therm: invalid argument 'iCbox' (IEC variables start with ~ I Q X or D for dummy)
ERROR: therm: '-d IW0,0,500' is not a well formed octal string or exceeds range 3777
The system will think that iCbox is an argument for term, which is not correct of course.
Since here the option coming after the call to therm is -R, the method iCbegin will count no therm options and as such, if you look to the code of iCbegin, the forking (of iCbox, in this example) will be executed using the command iC_fork_and_exec(argv);, where argv is iCbox at that moment.
If you call therm.ic on the command line like so:
./iCtherm -r 1 IW0-IW1 -C -R therm --n -R iCbox -n DS18B20 -d IW0,0,500 IW1,0,500
then the option --n in this case (that is: show the temperature without the date and time) will be taken into account.
Now that I know that the options for therm have to contain double hyphens, I can add other options too that are valid for that therm application. See the beginning of the code for therm.ic: Usage.