Raspberry Pi IoT In C Using Linux Drivers - 1-Wire And The DS18B20 |
Written by Harry Fairhead | ||||
Monday, 22 November 2021 | ||||
Page 2 of 3
Listing DevicesWhen the driver is loaded it scans the 1-Wire bus for connected devices. It repeats the scan at intervals, so keeping the system up-to-date if you add new devices. For each device it finds, it creates a directory with the same name as the serial number of the device in /sys/bus/w1/devices/. Inside the folder are, among other things, files that let you work with the sensor. In particular there is the w1_slave file that allows you to initiate a measurement and read the result. What we have to do is read the names of the folders in /sys/bus/w1/devices/ and extract each one and use this to construct paths to each of the w1_slave files that have been created. Usually we know the class of device we are working with by the form of its serial number. Each device has a 64-bit number that is composed of a family code that tells you the type of the device and a unique serial number: For example, all DS18B20 Temperature Sensors have a serial number that starts with 28-. Variations on the device have different family codes: W1_THERM_DS18S20 0x10 W1_THERM_DS1822 0x22 W1_THERM_DS18B20 0x28 W1_THERM_DS1825 0x3B W1_THERM_DS28EA00 0x42 All of these are supported by the Linux driver. Working with directories in Linux isn’t difficult, but you you need a refresher then see Applying C for the IoT with Linux, ISBN: 9781871962611. The following is the usual way to find out what devices are connected, but there is arguably a better way, see later. First we open the devices directory: int getDevices(char path[][100], int *num) { DIR *dirp; char name[10][50]; struct dirent *direntp; if ((dirp = opendir("/sys/bus/w1/devices/")) == Next we scan through all of the directories that this contains, looking for names that start with 28-: *num = 0; while ((direntp = readdir(dirp)) != NULL) { if (strstr(direntp->d_name, "28-")) { strncpy(name[*num], direntp->d_name, 50); (*num)++; } } closedir(dirp); Each one found is copied to an element of the name string array. Notice that the name array only has space for 10 devices – you could make it bigger. Finally we construct a string array with the path to each of the w1_slave files that allow us to read each of the sensors: for (int i = 0; i < *num; i++) { snprintf(path[i],100, Notice that when the getDevices function is called it has to be supplied with a path string array of the required dimensions. The complete function is: int getDevices(char path[][100], int *num) { DIR *dirp; char name[10][50]; struct dirent *direntp; if ((dirp = opendir("/sys/bus/w1/devices/")) == It is also possible to arrange for an action to occur when a new device is added as outlined in the next chapter. The DS18B20As an example of a 1-Wire bus device the DS18B20 is a good choice as it is almost the only device anyone makes significant use of. It is low-cost, easy to use and you can use multiple devices on a single GPIO line. The DS18B20 is available in a number of formats, but the most common makes it look just like a standard BJT (Bipolar Junction Transistor) which can sometimes be a problem when you are trying to find one. You can also get them made up into waterproof sensors complete with cable.
No matter how packaged, they will work at 3.3V or 5V. The basic specification of the DS18B20 is:
It can also be powered from the data line, making the bus physically need only two wires - data and ground. However, this "parasitic power" mode is difficult to make work reliably and best avoided in an initial design. To supply it with enough power during a conversion, the host has to connect it directly to the data line by providing a "strong pull-up" - essentially a transistor. In normal-powered mode there are just three connections:
|
||||
Last Updated ( Saturday, 27 November 2021 ) |