Some times it it just easier from the point of view of hardware to connect a set of 1-wire devices to the same GPIO line but this makes the software more complex. Find out how to discover what devices are present on a multi-drop bus and how to select the one you want to work with.
Now On Sale!
You can now buy a print or ebook edition of Raspberry Pi IoT in C from Amazon.
For Errata and Listings Visit: IO Press
This our ebook on using the Raspberry Pi to implement IoT devices using the C programming language. The full contents can be seen below. Notice this is a first draft and a work in progress.
Chapter List
-
Introducing Pi (paper book only)
-
Getting Started With NetBeans In this chapter we look at why C is a good language to work in when you are creating programs for the IoT and how to get started using NetBeans. Of course this is where Hello C World makes an appearance.
-
First Steps With The GPIO
The bcm2835C library is the easiest way to get in touch with the Pi's GPIO lines. In this chapter we take a look at the basic operations involved in using the GPIO lines with an emphasis on output. How fast can you change a GPIO line, how do you generate pulses of a given duration and how can you change multiple lines in sync with each other? -
GPIO The SYSFS Way
There is a Linux-based approach to working with GPIO lines and serial buses that is worth knowing about because it provides an alternative to using the bcm2835 library. Sometimes you need this because you are working in a language for which direct access to memory isn't available. It is also the only way to make interrupts available in a C program. -
Input and Interrupts
There is no doubt that input is more difficult than output. When you need to drive a line high or low you are in command of when it happens but input is in the hands of the outside world. If your program isn't ready to read the input or if it reads it at the wrong time then things just don't work. What is worse is that you have no idea what your program was doing relative to the event you are trying to capture - welcome to the world of input. -
Memory Mapped I/O
The bcm2835 library uses direct memory access to the GPIO and other peripherals. In this chapter we look at how this works. You don't need to know this but if you need to modify the library or access features that the library doesn't expose this is the way to go. -
Near Realtime Linux
You can write real time programs using standard Linux as long as you know how to control scheduling. In fact it turns out to be relatively easy and it enables the Raspberry Pi to do things you might not think it capable of. There are also some surprising differences between the one and quad core Pis that make you think again about real time Linux programming. -
PWM
One way around the problem of getting a fast response from a microcontroller is to move the problem away from the processor. In the case of the Pi's processor there are some builtin devices that can use GPIO lines to implement protocols without the CPU being involved. In this chapter we take a close look at pulse width modulation PWM including, sound, driving LEDs and servos. -
I2C Temperature Measurement
The I2C bus is one of the most useful ways of connecting moderately sophisticated sensors and peripherals to the any processor. The only problem is that it can seem like a nightmare confusion of hardware, low level interaction and high level software. There are few general introductions to the subject because at first sight every I2C device is different, but here we present one. -
A Custom Protocol - The DHT11/22
In this chapter we make use of all of the ideas introduced in earlier chapters to create a raw interface with the low cost DHT11/22 temperature and humidity sensor. It is an exercise in implementing a custom protocol directly in C. -
One Wire Bus Basics
The Raspberry Pi is fast enough to be used to directly interface to 1-Wire bus without the need for drivers. The advantages of programming our own 1-wire bus protocol is that it doesn't depend on the uncertainties of a Linux driver. -
iButtons
If you haven't discovered iButtons then you are going to find of lots of uses for them. At its simples an iButton is an electronic key providing a unique coce stored in its ROM which can be used to unlock or simply record the presence of a particular button. What is good news is that they are easy to interface to a Pi. -
The DS18B20
Using the software developed in previous chapters we show how to connect and use the very popular DS18B20 temperature sensor without the need for external drivers. -
The Multidrop 1-wire bus
Some times it it just easier from the point of view of hardware to connect a set of 1-wire devices to the same GPIO line but this makes the software more complex. Find out how to discover what devices are present on a multi-drop bus and how to select the one you want to work with. -
SPI Bus
The SPI bus can be something of a problem because it doesn't have a well defined standard that every device conforms to. Even so if you only want to work with one specific device it is usually easy to find a configuration that works - as long as you understand what the possibilities are. -
SPI MCP3008/4 AtoD (paper book only)
-
Serial (paper book only)
-
Getting On The Web - After All It Is The IoT (paper book only)
-
WiFi (paper book only)
The1-wire bus has a very sophisticated addressing mechanisms that lets you discover what devices are connected to a single 1-wire implementation. This is an algorithm worth knowing about for its ingenious design and in this chapter a 1-wire bus scanning function is developed. Unlike the one presented by Maxim the 1-wire bus' inventor it is recursive and as a result simpler.
Every 1-wire bus device has a unique 64-bit serial number that serves as its address on the bus. You can select just one device by writing its serial number. However how do you discover what devices are connected?
The Hardware
The first thing to clear up is that you can run multiple 1-wire devices on the same bus by simply adding them in parallel. You only need a single pull up resistor no matter how many devices there are on the bus.
In this chapter the DS18B20 will be used as an example because it is often used in this way but the same techniques will work with other devices and mixed devices.
The 1-Wire Search Algorithm
The serial number has a standard format the least significant byte is a family code i.e. what sort of device it is, the next six bytes are the serial number and the most significant byte is a check sum.
All eight bytes are used as the devices address and this means we can check for transmission errors by simply applying the CRC function developed in earlier chapters.
If you know what the serial numbers are of the devices are then you can simply write your program to work with them. However this means that you need to hardcode the serial numbers into your program which doesn't make it very portable.
A better solution is to scan the bus to search for connected devices and discover their serial numbers. This is what the 1-wire search algorithm is for. It has a reputation for being difficult to understand and even more difficult to implement. The good news it that it isn't as difficult as it first appears to do either and it is very instructive.
The basic idea is that the master sends an initialization pulse on the bus and all of the connected devices respond with their presence pulse.
Next the master places the search command 0xF0 on the bus which places all of the devices into search mode.
The master then reads two bits from the bus - these represent the first bit of all of the serial numbers from all of the devices. Given the nature of the 1-wire bus and the way the pull-up works what the master receives is the logical And of all of the bits sent from each of the slaves. The first bit the slaves send is their low order bit and the second bit is the logical complement i.e Not, of their first bit.
From these two bits the master can deduce the following:
1st Bit |
2nd Bit |
Conclusion |
---|---|---|
0 | 0 | There is at least one device with a 1 in this position and another with a 0. |
0 | 1 | All devices have a 0 in this position |
1 | 0 | All devices have a 1 in this position |
1 | 1 | No devices are present |
Obviously 1,1 is an error condition - something has removed the devices from the bus.
In the case of receiving either a 0,1 or 1,0 the bit at that position has been determined to be a 0 or 1 respectively and all of the devices on the bus share this value in their serial numbers at this bit position.
If the master receives a 0,0 then there are devices with a 1 and devices with a 0 in their serial number at this position and the master can pick one of the values to explore further. Of course if the master wants to list all of the devices on the bus it has to return to this point and explore the second possibility.
The master selects which value it is going to follow by transmitting a single bit. All of the devices that match the bit in their serial number continue to transmit bits to the master all of the devices that do no have a serial number which matches the bit at that position go into a wait state until the next initialization pulse from the master.
The search algorithm determines a single bit of a serial number by reading two bits from the slaves and transmitting one bit to reduce the number of slaves participating in the scan.
By repeating the "read two bits write one" action the master eventually finds all 64 bits of one of the slave's serial number. It then has to back track to one of the bit locations where there was a choice of which bit to select and select the alternative.
In this way the master eventually lists all of the serial numbers on the bus.
Notice that the master starts off trying to determine bit zero for a single device connected to the bus. It determines each bit where all of the devices agree on a zero or a one. Each time the master encounters a bit conflict i.e. there are devices with a zero and a one in that bit position it selects one value and tells the devices with the other value to switch off. It then continues to determine the subsequent bit positions for the remaining devices. As the serial numbers are unique the master always ends up talking to just one device.
You can probably see that this is a depth first tree search with branches where the bit values are in conflict.
Suppose there four devices on the bus then they must all differ in at least one bit position. When the master starts the scan it reads all 1 or all 0 as it processes each but until it comes to the first location where there is another device with a different value at that bit. The master receives a 0,0 back from the slaves and arbitrarily sends a 0 to switch off all the slaves with a 1 in that location. The master then continues to read bits and if all of the other devices had a 1 in that bit position there are no more conflict.
When the master reaches bit 63 then it has the complete serial number of device 1.
It then backtracks to the bit position where the first conflict occurred. It now writes a 1 to switch off device 1 and continues to read bits until it encounters another conflict. Again it arbitrarily chooses a 0 and switches off all of the devices with a 1 in that bit position.
Notice in the example there are two devices with a 0 in that bit position and so as the master reads bits it encounters another conflict. Again it sends a 0 and switches of the other device and completes reading bits until it reaches bit 63 when it has the serial number of the second device.
The master now back tracks to the most recent conflict, sends a 1 and continues down the next branch to get the next devices serial number and so on until there are no conflict points to back track to.
Make sure you understand the algorithm before moving on to consider the implementation.
- Prev
- Next >>