In this article by Jack Creasey, author of Raspberry Pi Essentials, we will learn about the remote input/output technology and devices that can be used with the Raspberry Pi. We will also specifically learn about 1-wire, and how it can be interfaced with the Raspberry Pi.
The concept of remote I/O has its limitations, for example, it requires locating the Pi where the interface work needs to be done—it can work well for many projects. However, it can be a pain to power the Pi in remote locations where you need the I/O to occur. The most obvious power solutions are:
- Battery-powered systems and, perhaps, solar cells to keep the unit functional over longer periods of time
- Power over Ethernet (POE), which provides data connection and power over the same Ethernet cable which achieved up to 100 meters, without the use of a repeater.
- AC/DC power supply where a local supply is available
Connecting to Wi-Fi could also be a potential but problematic solution because attenuation through walls impacts reception and distance.
Many projects run a headless and remote Pi to allow locating it closer to the data acquisition point. This strategy may require yet another computer system to provide the Human Machine Interface (HMI) to control a remote Raspberry Pi.
(For more resources related to this topic, see here.)
I’d like to introduce you to a very mature I/O bus as a possibility for some of your Raspberry Pi projects; it’s not fast, but it’s simple to use and can be exceptionally flexible. It is called 1-Wire, and it uses endpoint interface chips that require only two wires (a data/clock line and ground), and they are line powered apart from possessing a few advanced functionality devices. The data rate is usually 16 kbps and the 1-Wire single master driver will handle distances up to approximately 200 meters on simple telephone wire. The system was developed by Dallas Semiconductor back in 1990, and the technology is now owned by Maxim. I have a few 1-wire iButton memory chips from 1994 that still work just fine.
While you can get 1-Wire products today that are supplied as surface mount chips, 1-Wire products really started with the practically indestructible iButtons. These consist of a stainless steel coin very similar to the small CR2032 coin batteries in common use today. They come in 3 mm and 6 mm thicknesses and can be attached to a key ring carrier. I’ll cover a Raspberry Pi installation to read these iButtons in this article.
The following image shows the dimensions for the iButton, the key ring carriers, and some available reader contacts:
The 1-Wire protocol
The master provides all the timing and power when addressing and transferring data to and from 1-Wire devices. A 1-Wire bus looks like this:
When the master is not driving the bus, it’s pulled high by a resistor, and all the connected devices have an internal capacitor, which allows them to store energy. When the master pulls the bus low to send data bits, the bus devices use their internal energy store just like a battery, which allows them to sense inbound data, and to drive the bus low when they need to return data. The following typical block diagram shows the internal structure of a 1-Wire device and the range of functions it could provide:
There are lots of data sheets on the 1-Wire devices produced by Maxim, Microchip, and other processor manufacturers. It’s fun to go back to the 1989 patent (now expired) by Dallas and see how it was originally conceived (http://www.google.com/patents/US5210846). Another great resource to learn the protocol details is at http://pdfserv.maximintegrated.com/en/an/AN937.pdf.
To look at a range of devices, go to http://www.maximintegrated.com/en/products/comms/one-wire.html.
For now, all you need to know is that all the 1-Wire devices have a basic serial number capability that is used to identify and talk to a given device. This silicon serial number is globally unique. The initial transactions with a device involve reading a 64-bit data structure that contains a 1-byte family code (device type identifier), a 6-byte globally unique device serial number, and a 1-byte CRC field, as shown in the following diagram:
The bus master reads the family code and serial number of each device on the bus and uses it to talk to individual devices when required.
Raspberry Pi interface to 1-Wire
There are three primary ways to interface to the 1-Wire protocol devices on the Raspberry Pi:
- W1-gpio kernel: This module provides bit bashing of a GPIO port to support the 1-Wire protocol. Because this module is not recommended for multidrop 1-Wire Microlans, we will not consider it further.
- DS9490R USB Busmaster interface: This is used in a commercial 1-Wire reader supplied by Maxim (there are third-party copies too) and will function on most desktop and laptop systems as well as the Raspberry Pi. For further information on this device, go to http://datasheets.maximintegrated.com/en/ds/DS9490-DS9490R.pdf.
- DS2482 I2C Busmaster interface: This is used in many commercial solutions for 1-Wire. Typically, the boards are somewhat unique since they are built for particular microcomputer versions. For example, there are variants produced for the Raspberry Pi and for Arduino. For further reading on these devices, go to http://www.maximintegrated.com/en/app-notes/index.mvp/id/3684.
I chose a unique Raspberry Pi solution from AB Electronics based on the I2C 1-Wire DS2482-100 bridge.
The following image shows the 1-Wire board with an RJ11 connector for the 1-Wire bus and the buffered 5V I2C connector pins shown next to it:
For the older 26-pin GPIO header, go to https://www.abelectronics.co.uk/products/3/Raspberry-Pi/27/1-Wire-Pi, and for the newer 40-pin header, go to https://www.abelectronics.co.uk/products/17/Raspberry-Pi–Raspberry-Pi-2-Model-B/60/1-Wire-Pi-Plus.
This board is a superb implementation (IMHO) with ESD protection for the 1-Wire bus and a built-in level translator for 3.3-5V I2C buffered output available on a separate connector. Address pins are provided, so you could install more boards to support multiple isolated 1-Wire Microlan cables. There is just one thing that is not great in the board—they could have provided one or two iButton holders instead of the prototyping area.
The schematic for the interface is shown in the following diagram:
1-Wire software for the Raspberry Pi
The OWFS package supports reading and writing to 1-Wire devices over USB, I2C, and serial connection interfaces. It will also support the USB-connected interface bridge, the I2C interface bridge, or both.
Before we install the OWFS package, let’s ensure that I2C works correctly so that we can attach the board to the Pi’s motherboard. The following are the steps for the 1-Wire software installation on the Raspberry Pi.
- Start the raspi-config utility from the command line:
- Select Advanced Options, and then I2C:
- Select Yes to enable I2C and then click on OK.
- Select Yes to load the kernel module and then click on OK.
- Lastly, select Finish and reboot the Pi for the settings to take effect.
- If you are using an early raspi-config (you don’t have the aforementioned options) you may have to do the following:
- Enter the sudo nano /etc/modprobe.d/raspi-blacklist.conf command.
- Delete or comment out the line:
- Save the file.
- Edit the modules loaded using the following command:
sudo nano /etc/modules
- Once you have the editor open, perform the following steps:
- Add the line i2c-dev in its own row.
- Save the file.
- Update your system using sudo apt-get update, and sudo apt-get upgrade.
- Install the i2c-tools using sudo apt-get install –y i2c-tools.
- Lastly, power down the Pi and attach the 1-Wire board.
If you power on the Pi again, you will be ready to test the board functionality and install the OWFS package:
Now, let’s check that I2C is working and the 1-Wire board is connected:
- From the command line, type i2cdetect –l. This command will print out the detected I2C bus; this will usually be i2c-1, but on some early Pis, it may be i2c-0.
- From the command line, type sudo i2cdetect –y 1.This command will print out the results of an i2C bus scan. You should have a device 0x18 in the listing as shown in the following screenshot; this is the default bridge adapter address.
Finally, let’s install OWFS:
- Install OWFS using the following command:
sudo apt-get install –y owfs
When the install process ends, the OWFS tasks are started, and they will restart automatically each time you reboot the Raspberry Pi. When OWFS starts, to get its startup settings, it reads a configuration file—/etc/owfs.conf. We will edit this file soon to reconfigure the settings.
- Start Task Manager, and you will see the OWFS processes as shown in the following screenshot; there are three processes, which are owserver, owhttpd, and owftpd:
The default configuration file for OWFS uses fake devices, so you don’t need any hardware attached at this stage. We can observe the method to access an owhttpd server by simply using the web browser. By default, the HTTP daemon is set to the localhost:2121 address, as shown in the following screenshot:
You will notice that two fake devices are shown on the web page, and the numerical identities use the naming convention xx.yyyyyyyyyyyy. These are hex digits representing x as the device family and y as the serial number.
You can also examine the details of the information for each device and see the structure. For example, the xx=10 device is a temperature sensor (DS18S20), and its internal pages show the current temperature ranges. You can find details of the various 1-Wire devices by following the link to the OWFS home page at the top of the web page.
Let’s now reconfigure OWFS to address devices on the hardware bridge board we installed:
- Edit the OWFS configuration file using the following command:
sudo nano /etc/owfs.conf
Once the editor is open:
- Comment out the server: FAKE device line.
- Comment out the ftp: line.
- Add the line: server: i2c = /dev/i2c-1:0.
- Save the file.
Since we only need bare minimum information in the owfs.conf file, the following minimized file content will work:
######################## SOURCES ######################## # # With this setup, any client (but owserver) uses owserver on the # local machine... # ! server: server = localhost:4304 # # I2C device: DS2482-100 or DS2482-800 # server: i2c = /dev/i2c-1:0 # ####################### OWHTTPD ######################### http: port = 2121 ####################### OWSERVER ######################## server: port = localhost:4304
You will find that it’s worth saving the original file from the installation by renaming it and then creating your own minimized file as shown in the preceding code Once you have the owfs.conf file updated, you can reboot the Raspberry Pi and the new settings will be used.
You should have only the owserver and owhttpd processes running now, and the localhost:2121 web page should show only the devices on the single 1-Wire net that you have connected to your board. The owhttpd server can of course be addressed locally as localhost:2121 or accessed from remote computers using the IP address of the Raspberry Pi.
The following screenshot shows my 1-Wire bus results using only one connected device (DS1992-family 08):
At the top level, the device entries are cached. They will remain visible for at least a minute after you remove them. If you look instead at the uncached entries, they reflect instantaneous arrival and removal device events. You can use the web page to reconfigure all the timeouts and cache values, and the OWFS home page provides the details.
Program access to the 1-Wire bus
You can programmatically query and write to devices on the 1-Wire bus using the following two methods (there are of course other ways of doing this). Both these methods indirectly read and write using the owserver process:
- You can use command-line scripts (Bash) to read and write to 1-Wire devices.
The following steps show you to get program access to the 1-Wire bus:
- From the command-line, install the shell support using the following command:
sudo apt-get install –y ow-shell
- The command-line utilities are owget, owdir, owread, and owwrite.
- While in a multi-section 1-Wire Microlan, you need to specify the bus number, in our simple case with only one 1-Wire Microlan, you can type owget or owdir at the command line to read the device IDs, for example, my Microlan returned:
Notice that the structure of the 1-Wire devices is identical to that exposed on the web page, so with the shell utilities, you can write Bash scripts to read and write device parameters.
- From the command-line, install the shell support using the following command:
- You can use Python to read and write to the 1-Wire devices. Install the Python OWFS module with the following command:
sudo apt-get install –y python-ow
- Open the Python 2 IDLE environment from the Menu, and perform the following steps:
- In Python Shell, open a new editor window by navigating to File | New Window.
- In the Editor window, enter the following program:
#! /usr/bin/python import ow import time ow.init('localhost:4304') while True: mysensors = ow.Sensor("/uncached").sensorList( ) for sensor in mysensors[:]: thisID = sensor.address[2:12] print sensor.type, "ID = ", thisID time.sleep(0.5)
- Save the program as testow.py.
You can run this program from the IDLE environment, and it will print out the IDs of all the devices on the 1-Wire Microlan every half second. And if you need help on the python-pw package, then type import ow in the Shell window followed by help(ow) to print the help file.
We’ve covered just enough here to get you started with 1-Wire devices for the Raspberry Pi. You can read up on the types of devices available and their potential uses at the web links provided in this article. While the iButton products are obviously great for identity-based projects, such as door openers and access control, there are 1-Wire devices that provide digital I/O and even analog-to-digital conversion. These can be very useful when designing remote acquisition and control interfaces for your Raspberry Pi.
Resources for Article:
Further resources on this subject:
- Develop a Digital Clock [article]
- Raspberry Pi Gaming Operating Systems [article]
- Penetration Testing [article]