Using I2C devices is fairly easy once you have successfully used one - and hence know what information you need and what to look for in a working system. In this chapter we use the HTU21D temperature and humidity sensor as a case study of I2C in action. It also happens to be a useful sensor.

Now On Sale!

You can now buy a print edition of micro:bit IoT in C.

You can buy it from:

USA and World


 The full contents can be seen below. 

Chapter List

  1. Getting Started With C/C++
    Anyone who wants to use the BBC micro:bit to its full potential as an IoT device needs to look outside the coding environments provided by its own website. As an mbed device, however, the micro:bit  is capable of being programmed in C/C++. Here we look at how to use the mbed online compiler for a simple demo program.

  2. Offline C/C++ Development  
    We have already discovered how to use the online editor to create a C/C++ program. Now we are going to move to the desktop with an offline approach. This has the advantage that we can use any tools we care to select and no Internet connection is needed.
  3. First Steps With The GPIO 
    The most basic task when working with the micro:bit is controlling the I/O lines. This isn't difficult if you use the framework provided but there some subtle points to watch out for. This chapter looks a the basics of using the GPIO.

  4. Working Directly With The Hardware - Memory Mapping. 
    The framework makes working with the GPIO and other devices as easy as it can be but there are many layers of software to go through before you get to the hardware. Writing directly to the hardware can make things up to ten times faster and give you access to things that their framework doesn't. It is also an educational experience to deal with the raw hardware directly.

  5. Pulse Width Modulation, Servos And More
    In this chapter we take a close look at pulse width modulation PWM including, sound, driving LEDs and servos.

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

  7. I2C Temperature Measurement
    Using I2C devices is fairly easy once you have successfully used one - and hence know what information you need and what to look for in a working system. In this chapter we use the HTU21D temperature and humidity sensor as a case study of I2C in action. It also happens to be a useful sensor.

  8. A Custom Protocol - The DHT11/22

  9. The DS18B20 - One Wire Bus

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

  11. SPI MCP3008/4 AtoD   
    The SPI bus can be difficult to make work at first but once you know what to look for about how the slave claims to work it gets easier. To demonstrate how its done let's add eight channels of 12 bit AtoD using the MCP3008.

  12. Serial Connections
    The serial port is one of the oldest of ways of connecting devices together but it is still very, very useful. The micro:bit has a single serial interface but it can be directed to use any of the GPIO piins as Rx and Tx. 

  13. WiFi 
    The micro:bit has a radio that works in Bluetooth LE and point-to-point ad-hoc mode, but at the moment it lacks WiFi connectivity. The solution is to use the low cost ESP8266 to make the connection via the micro:bit's serial port. 

  14. LED Display 
    The micro:bit's LED display may only be 5x5 but it is very versatile. If you want to make use of it directly then you are going to have to master some lower level functions.


Using an I2C device has two problems - the physical connection between master and slave and second figuring out what the software has to do to make it work. In this chapter we take the principle outlined in the previous one and add the information in the HTU21D data sheet to make a working temperature humidity sensor using the framework I2C functions. 

First the hardware.

The SparkFun HTU21D

The HTU21D Humidity and Temperature sensor is one of the easiest of I2C devices to use.  

The only problem is that the HTU21D is only available in a surface mount package. To overcome this simply solder some wires onto the pads, it is possible to do, or you can buy a general breakout board.

However, it is much simpler to buy the SparkFun HTU21D breakout board because this has easy connections and built-in pull up resistors. This means that you don't need to add any components to get this circuit working - just four connections.



If you decide to work with some other I2C device you can still follow the steps in this account, but you would have to modify what you do to be correct for the device you are using. In particular if you select a device that works at 5V you might need a level converter.

Wiring the HTU21D

In the first instance we can use the same I2C bus that the accelerometer and magnetometer are connected to.

Physical Pin
Pin 20 SDA
Pin 19 SCL


Given that the HTU21D has pull up resistors we really should disable them when used on the internal I2C bus which already has pullups. In practice the additional pullups don't seem to make much difference to the waveforms and you can leave them in place while testing. Later when we try the same device on a separate bus the pulls will be required.

You can use a prototype board to make the connections and this makes it easier to connect other instruments such as a logic analyzer. 

A First Program 

After wiring up any i2C device the first question that needs to be answered is - does it work? 

Unfortunately for most complex devices finding out if it works is a multi-step process. 

Our first program will aim to read some data back from the HTU21D - any data will do. 

If you look at the data sheet you will find that the device address is 0x40 and its  supports the following commands/registers:

Command  Code  Comment 
Trigger Temperature Measurement 0xE3  Hold master
Trigger Humidity Measurement 0xE5  Hold master
Trigger Temperature Measurement 0xF3  No Hold master
Trigger Humidity Measurement  0xF5  No Hold master
 Write user register 0xE6   
 Read user register 0xE7   
 Soft Reset 0xFE  


The easiest of these to get started with is the Read user register command. The user register gives the current setup of the device and can be used to set the resolution of the measurement. 

Notice that the codes that you send to the device can often be considered addresses or commands. In this case you can think of sending 0xE7 as a command to read the register or the read address of the register - it makes no difference. In most cases the term command is used when sending the code makes the device do something and and the term address is used when it simply makes the device read or write specific data.      

To read the user register we have to write a byte containing 0xE7 and then read the byte the device sends back. Notice that means sending an address frame, a data frame and then another address frame and reading a data frame. The device seems to be happy if you send a stop bit between each transaction or just a new start bit.

A program to read the user register is fairly easy to put together. The address of the device is 0x40 so its write address is 0x80 and its read address is 0x81. As the framework I2C functions add the lower bit we simply use 0x80 as the device's address:

  char buf[] = {0xE7};
  uBit.i2c.write(0x80, buf, 1);, buf,1);
  printf("User Register = %X \r\n",buf[0]);

This sends the address frame for 0x80 and then the data byte 0xE7 to select the user register. Next it sends an address frame for 0x81 to read the data. 

If you run the program you will see: 

Register= 02

this is the default value of the register and it corresponds to a resolution of 12 and 14 bits for the humidity and temperature respectively and a supply voltage greater than 2.25V.