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.

 

 

Now On Sale!

You can now buy a print edition of Raspberry Pi IoT in C

You can buy it from:

USA and World   Amazon.com
Canada              Amazon.ca
UK                     Amazon.co.uk
France               Amazon.fr
Germany            Amazon.de
Spain                 Amazon.es
Brazil                  Amazon.br
Italy                    Amazon.it
Japan                 Amazon.co.jp
Mexico               Amazon.com.mx 

 

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

  1. Introducing Pi (paper book only)

  2. 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.

  3. 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? 

  4. 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.

  5. 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.

  6. 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. 

  7. 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.

  8. 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.

  9. 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.

  10. 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. 

  11. 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.

  12. 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. 

  13. 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. 

  14. 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.

  15. 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. 

  16. SPI MCP3008/4 AtoD  (paper book only)

  17. Serial (paper book only)

  18. Getting On The Web - After All It Is The IoT (paper book only)

  19. WiFi (paper book only)

 

The I2C bus is a serial bus that can be used to connect multiple devices to a controller. It is a simple bus that uses two active wires - one for data and one for a clock. Despite there being lots of problems in using the I2C bus because it isn't well standardized and devices can conflict and generally do things in there own way it is still commonly used and too useful to ignore. 

The big problem in getting started with the I2C bus is that you will find it described at many different levels of detail - from physical bus characteristics, the protocol, the details of individual devices. It can be difficult to relate all of this together and produce a working anything.

In fact you only need to know the general workings of the I2C bus, some general features of the protocol and know the addresses and commands used by any particular device. 

To explain and illustrate these idea we really do have to work with a particular device to make things concrete. However the basic stages of getting things to work - the steps, the testing and verification - are more or less the same irrespective of the device.  

I2C Hardware Basics 

The I2C bus is very simple.

Just two signal lines SDA and SCL the data and clock lines respectively.

Each signal line is pulled up by a suitable resistor to the supply line at what ever voltage the devices are working at 3.3V and 5V are common choices, The size of the pullup resistors isn't critical, but 4.7K is typical as shown.  

You simply connect the SDA and SCL pins of each of the devices to the pull up resistors. Of course if any of the devices have built-in pullup resistors you can omit the external resistors. More of a problem is if multiple devices each have pull ups. In this case you need to disable all but one set. 

The I2C bus is an open collector bus.

This means that it is actively pulled down by a transistor set to on. When the transistor is off, however, the bus returns to the high voltage state via the pullup resistor. The advantage of this approach is that multiple devices can pull the bus low at the same time. That is an open collector bus is low when one or more devices pulls it low and high when none of the devices is active. 

The SCL line provides a clock which is used to set the speed of data transfer - one data bit is presented on the SDA line for each pulse on the SCL line. In all cases the master drives the clock line to control how fast bits are transferred. The slave can however hold the clock line low if it needs to slow down the data transfer. 

In most cases the I2C bus has a single master device - the Pi in our case - which drives the clock and invites the slaves to receive or transmit data. Multiple masters are possible, but this is advanced and not often necessary. 

At this point we could go into the details of how all of this works in terms of bits. However, the library handles these details for us. All you really need to know is that all communication occurs in 8-bit packets.

The master sends a packet, an address frame, which contains the address of the slave it wants to interact with. Every slave has to have a unique address - usually 7 bits but it can be 11 bits and the Pi does support this.

One of the problems in using the I2C bus is that manufacturers often use the same address or same set of selectable addresses and this can make using particular combinations of devices on the same bus difficult or impossible.

The 7-bit address is set as the high order 7 bits in the byte and this can be confusing as an address that is stated as 0x40 in the data sheet results in 0x80 being sent to the device. The low order bit of the address signals a write or a read operation depending on whether it is a zero or a one respectively.  

After sending an address frame it then sends or receives data frames back from the slave, There are also special signals used to mark the start and end of an exchange of packets but the library functions take care of these. 

This is really all you need to know about I2C in general to get started but it is worth finding out more of the details as you need them - you almost certainly will need them as you debug I2C programs. 

The Pi I2C 

The processor has three built in I2C masters.

They are referred to as BSC controllers but BSC - Broadcom Serial Controller is essentially an implementation of the I2C bus and you generally don't have to worry about incompatibilities.

Of the three controllers one, BSC2, is dedicated to working with the HDMI interface. Of the two remaining I2C buses BSC1 is brought out on the main connector at pin 3 GPIO2/SDA1 and pin 5 GPIO3/SCL1 and BSC0 is brought out on pin 27 GPIO0/SDA0 and pin 28 GPIO1/SCL0.

There are 1.6K pull-up resistors on BSC1 and BSC0 is used for expansion card identification and you best not using it. On older versions of the Pi BSC0 was brought out on P5 which wasn't fitted - and is best ignored.

The bcm2835 library only supports BSC1 but it isn't difficult to extend it to support BSC0 if required.

To summarize:

There is one easy to use I2C bus available on pins 3 and 5 complete with 1.6K pullup resistors. 

There is an additional I2C bus on pins 27 and 28 but it is allocated to expansion EPROM use and best avoided if possible. There are no pullup resistors fitted.

The bcm2835 only supports the bus on pins 3 and 5. 

The hardware can work at 100kHz up to 250MHz and while it supports clock stretching you have to know how to make it work - see later.