Wednesday, October 16, 2013

Radxa Rock communicating with I2C devices

Since I'm a hardware tinkerer at heart, and my background is more on electronics than on software, the Radxa Rock board had a deeper interest for me.

This board has a lot of potential for all kind of low level electronics, thanks to its two expansion headers:

Expansion Headers from Radxa Rock schematics



As you can see there are two UARTs (number 3 is shared with some GPS pins), one I2C bus, two SPI buses (SPI1 on J8 is shared with GPS pins), a full 24 bits LCD display output (!!), one USB port (HOST_D*2), one audio Line In (LINE_L/R), as well as several other GPIO I/Os.



I then set out to test my latest kernel for booting Linux on the Radxa Rock to access one of the, for me, most interesting low level hardware buses: I2C.

This one is heavily used for low bandwidth (control/status, sensor data readings, EEPROMs, etc...) communications inter integrated circuits (I I C... I2C ;). This bus consists of just two lines: SCL (master clock) and SDA (bi-directional data), which makes it extremely handy.

And for this test, a handy old friend of mine: the BMP085 pressure sensor (featured on this blog's first post) inside a little PCB with an accelerometer chip, gyroscope chip, magnetometer compass chip, and our pressure and temperature sensor chip, the BMP085.

This is all called a 10-DOF or Ten Degrees of Freedom sensor board, since it allows for precise movement/position detection through "sensor fusion" (though I really dislike using nerdy "magic words").

So first's first, I wired the 10-DOF board to the Radxa's left expansion header (J8) in the following manner:
- PCB's VCC (5V) wired to J8 exp. header's pin 40 (DC5V)
- PCB's GND wired to J8 exp. header's pin 39 (GND)
- PCB's SDA wired to pin 32 (I2C0_SDA)
- PCB's SCL wired to pin 31 (I2C0_SCL)


The result looks like this:

Radxa Rock board bus I2C #0 connected to a 10 degrees-of-freedom sensor board


So, what to do to start communicating with the board? Well, since my kernel already has all the needed things built-in, you just have to follow these steps (shamelessly taken from this guide):

#install i2c-tools (user space) for talking to I2C buses/devices
sudo apt-get install i2c-tools
#insmod the I2C-dev module to allow user space access to I2C
sudo modprobe i2c-dev
#probe I2C bus 0, the one at expansion header J8
sudo i2cdetect -y 0

The result of this last command is the possibly detected I2C devices on bus 0 (remember the 10-DOF board has 4 devices sharing the same bus). In our case we do know the I2C address of the BMP085 (0x77), so we can talk to it directly.

Since I know the calibration parameters of my device (see AC* at first screenshot in this post) and their addresses, I can just compare to see if this is random data, or actually the BMP085 chip, being talked to from Linux running on the RK3188 of the Radxa Rock board:

Calibration parameter AC1, which for my 10-DOF board has a 2 byte value of 6746 (0x1A5A) is located at I2C registers 0xAA (MSB) and 0xAB (LSB), by reading the sensor's datasheet.

Let's dump the contents of the device at that address (the BMP085) to confirm we are talking to it:

#dump non-interactively (-y) contents of selected device (0x77)
#on given I2C bus (0) in byte read mode (b)
sudo i2cdump -y 0 0x77 b

Not really illustrating, but the result is:
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: a5 94 52 49 a4 27 77 a6 1e 26 1a 5a fb dd c7 bc    ??RI?'w??&?Z????
90: 7c 9e 60 2c 59 11 15 7a 00 37 80 00 d4 bd 09 80    |?`,Y??z.7?.????
a0: a5 94 52 49 a4 27 77 a6 1e 26 1a 5a fb dd c7 bc    ??RI?'w??&?Z????
b0: 7c 9e 60 2c 59 11 15 7a 00 37 80 00 d4 bd 09 80    |?`,Y??z.7?.????
c0: 00 00 bc 33 00 00 00 00 00 00 00 10 00 00 00 03    ..?3.......?...?
d0: 55 01 06 00 00 00 00 00 00 00 00 00 00 00 00 00    U??.............
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00    ......?.........


And sure enough! you can find the values (1a and 5a) of this little example at the expected register addresses (0xAA and 0xAB).

RK3188 is communicating with the 10-DOF board through one I2C bus at the expansion header!

Radxa Rock meets the world of electronics!






8 comments:

  1. Fantastic...
    Opens the door for the next level of work around it...

    Great work !!

    ReplyDelete
  2. Hi Galland,

    i2cdetect on an empty bus returns complete bullcrap for me

    sudo i2cdetect -y 0
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
    10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
    20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
    30: -- -- -- -- -- -- -- -- 38 39 3a 3b 3c 3d 3e 3f
    40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
    70: 70 71 72 73 74 75 76 77

    I am on the current stock kernel 3.0.36+, is yours specifically patched for i2c?

    ReplyDelete
    Replies
    1. No patching, try connecting something :P

      Delete
    2. Unfortunately no changes with a connected I2C device.
      Curiously lsmod lists only:

      Module Size Used by
      8723au 849716 0
      rk30xxnand_ko 161856 0

      Shouldn't there be an i2c-dev kernel module?

      Delete
    3. Have you used the kernel pointed to by this post? In that case the I2C references in your .config should be the ones in here:
      https://github.com/Galland/Linux3188/blob/master/.config

      I2C is built-in, not a module in this kernel

      Delete
  3. No, I did not try your kernel. I was afraid the wifi would not work :(
    Or is that fixed already?

    ReplyDelete
    Replies
    1. Then recompile your kernel with the .config "I2C" related options of the link above and you may have the best of both worlds

      Delete
    2. i2cdetect -y -r 0
      the -r did the trick on the stock radxa kernel ;)

      Delete