When I
think about realism on user interfaces, the first thing that
comes to my mind is 3D. Unfortunately, 3D and
embedded are two worlds that don't go along very well.
When we think about embedded, we think about constrained
devices, but it doesn't have to mean ugly interfaces. Now
we have Java SE Embedded (which includes JavaFX), it provides us
with a great tool to create astonishing UI for embedded
applications.

This
was my inspiration for my next
demo, what can I build, that could be cool, applied to
embedded, and of course, how can I play with new hardware that I
haven't played with it yet! :-) That was my new and
exciting challenge.

The inspiration

The hardware:

Raspberry Pi was
definitely the device, I could easily have Java and JavaFX on
it.

I want to build an
interface that reacts to the device orientation. For the
purpose of tracking positioning I used a combination of
accelerometer + gyroscope, and the MPU-9150
Breakout from sparkfun electronics, was just perfect for
this. The MPU-9150 is a System in Package (SiP) that
combines two chips: the MPU-6050, which contains a 3-axis
gyroscope, 3-axis accelerometer, and an onboard Digital Motion
Processor (DMP) capable of processing complex 9-axis
MotionFusion algorithms; and the AK8975, a 3-axis digital
compass. The supply voltage range was from 2.4V to 3.46V, just
perfect for our RPi, and it uses I2C as a communication
protocol also supported by RPi.

The software

I'm
using I2C for the communication protocol. Fortunately,
I found Pi4J apis that just
do the job for me. It has a great set of APIs to hide
all I2C low level details, by exposing a really clean set of
APIs, very easy to use.

The parallax
effect. Some time ago I saw a very cool applications
using the Parallax effect, it provides a lot of realism to the
scene without adding the extra processing cost of the 3D
rendering. Parallax effect is a scrolling technique in
computer graphics, wherein background images move by the
camera slower than foreground images, creating an illusion of
depth in a 2D interface and adding realism to the
immersion. We see it everyday, just pay attention on how
things move when you drive around.

Getting I2C working on
the Raspberry Pi

If you pay
attention to the Raspberry Pi pins you will see that it has two
pins for I2C, one for data's bus (SDA) and one for the clock
(SCL).

Great!, I was ready to
start connecting things... But to my surprise, I2C is not
enabled by default on the RPi, and there are few steps you need
to follow.

Enabling I2C in the
RPi

First go to: /etc/modulesand add the following
lines:

i2c-bcm2708

i2c-dev

Installi2c-tools.This is not required, but
it's very handy for detecting devices and making sure
everything works properly.

sudo apt-get install python-smbus

sudo apt-get install i2c-tools

There is a file
calledraspi-blacklist.conf, and by default SPI and I2C
are part of this black list!

Edit/etc/modprobe.d/raspi-blacklist.confand comment out the
lines

blacklist spi-bcm2708

blacklist i2c-bcm2708

Connecting the
Gyroscope/Accelerometer to the Pi.

Connecting the board
and the RPi is pretty straight forward. I2C requires
pullup resistors, but the RPi provide them, so we just
need to connect the MPU-9150 directly to the Pi, following the
next diagram:

The MPU-9150 has a AD0
pin, this allows you to set the last bit of the board's
address, to either 0 (ground) or 1 (Vcc). This
allows us to connect two boards to the same bus. In my
case I just grounded this pin, then my board address is 0x68

Verifying the
communication:

Once we connect the
board to the RPi, we can continue to check if we can actually
see it as a I2C device.

You should be able
to see your device on the table. The following snapshot
shows two I2C devices, one at address 40 and the second on
address 70.

You should also see
a couple of new entries under/dev:

spidev0.0

spidev0.1

I2c-0

I2c-1

If don't see any of
these entries, try running:

sudo
modprobe i2c-dev

The Hardware setup

This is the big picture
of the demo setup. I just mounted everything on a piece of
wood, then, changes on the board position and direction will be
reflected on the UI rendered on the screen.

The software

WiringPi Native
library.

WiringPi is an
Arduino wiring-like library written in C and released under the
GNU_LGPLv3 license, which is usable from C and C++ and many
other languages with suitable wrappers. This library
provides access to GPIOs pin, I2C and SPI interface, and UART
lines.

WiringPi
includes a command-line utility gpio
which can be used to program and setup the GPIO pins. You can
use this to read and write the pins and even use it to control
them from shell scripts.

Pi4J

Provides a bridge
between the native libraries (WiringPi) and Java for full
access to the Raspberry Pi.

Access system
information and network information from the Raspberry Pi

Wrapper classes for
direct access to WiringPi Library from Java

Installing and using
Pi4J

First, get the APIs.
From the Pi command line type:

wget
http://pi4j.googlecode.com/files/pi4j-0.0.5.deb

Install the packages

sudo dpkg -i pi4j-0.0.5.deb

Check the source
files at:

/opt/pi4j/lib

/opt/pi4j/examples

Make sure you
include the Pi4J lib folder in the classpath:

javac -classpath .:classes:/opt/pi4j/lib/'*'
...

sudo java -classpath
.:classes:/opt/pi4j/lib/'*' ...

Pi4J comes with a
set of demos, you can build them and start from there.

Build all demos:

cd /opt/pi4j/examples

./build

At any time you can
uninstall Pi4J

sudo dpkg -r pi4j

The Code:

First, we need to get the I2CBus. I2CFactory class has a
method called getInstance
that allows us to do that. Once we get the bus, we get the
device itself (our board), just make sure you provide the correct
address (did you ground or not the AD0 pin on your board?),
in our case we grounded AD0 and our address is x68).

After getting the
device, I thought I was going to get the readings right away,
but it wasn't the case. For the MPU-9150 few registries
need to be set before the reading start: (Find full
description at the MPU_9150
Register
Map and Description Revision)

Register 107 –
Power Management 1 PWR_MGMT_1

This register
allows the user to configure the power mode and clock source. It
also provides a bit for resetting the entire device, and a bit
for disabling the temperature sensor.

Parameters:

DEVICE_RESET

When
set to 1, this bit resets all internal registers to
their default values.

SLEEP

When
set to 1, this bit puts the MPU-9150 into sleep mode.

CYCLE

When
this bit is set to 1 and SLEEP is disabled, the MPU-9150
will cycle between sleep mode and waking up to take a
single sample of data from active sensors at a rate
determined by LP_WAKE_CTRL (register 108).

TEMP_DIS

When
set to 1, this bit disables the temperature
sensor.

CLKSEL

3-bit
unsigned value. Specifies the clock source of the
device.

Register 108 –
Power Management 2 PWR_MGMT_2

This register allows the user to configure the frequency of
wake-ups in Accelerometer Only Low Power Mode. This
register also allows the user to put individual axes of the
accelerometer and gyroscope into standby mode. Parameters:

LP_WAKE_CTRL

2-bit
unsigned value. Specifies the frequency of
wake-ups during Accelerometer Only Low Power Mode.

STBY_XA

When
set to 1, this bit puts the X axis accelerometer into
standby mode.

STBY_YA

When
set to 1, this bit puts the Y axis accelerometer into
standby mode.

STBY_ZA

When
set to 1, this bit puts the Z axis accelerometer into
standby mode.

STBY_XG

When
set to 1, this bit puts the X axis gyroscope into
standby mode.

STBY_YG

When
set to 1, this bit puts the Y axis gyroscope into
standby mode.

STBY_ZG

When
set to 1, this bit puts the Z axis gyroscope into
standby mode.

Register 27:
Gyroscope Configuration GYRO_CONFIG

This register is used
to trigger gyroscope self-test and configure the gyroscopes’
full scale range.
The self-test for each gyroscope axis can be activated by
controlling the XG_ST, YG_ST, and ZG_ST bits of this register.
FS_SEL is a 2-bit unsigned value and it allows us to select
the full scale range of gyroscopes.

Register 28:
Accelerometer Configuration ACCEL_CONFIG

This register is used
to trigger accelerometer self test and configure the
accelerometer full scale range.
The self-test for each accelerometer axis can be activated by
controlling the XA_ST, YA_ST, and ZA_ST bits of this register.
Parameters:

Now how to read the
gyroscope and accelerometers values? The values for the
accelerometer measurements are stored in registers 59 to 64.
Each measurement is a 16-bit value, stored in two consecutive
registers, as shown in the following table.

After you get the values
from the accelerometer and gyroscope, you can use them as you
wish. In my next blog entry we see how this values are going
to be used to update the UI to provide realism to our interface.