Friday, November 28, 2014

57. Exploring the Pi B+'s Ports III - Connecting the MPU-6050 Inertial Measurement Unit to the I2C bus

Some time back (see HERE) I had this GY-521 breakout board connected to an Arduino.  This time it's connected to the Raspberry Pi through the Cyntech paddle board:
As before, moving the small breadboard about (it's a blue one this time) generates signals in the on-board gyroscope and accelerometer, which are read via the I2C interface (serial data line, SDA - GPIO2 and serial clock line, SCL - GPIO3) by the Raspberry Pi.

A video of the demonstration is shown below:
I used ShareX 9.4.2 free software with FFmpeg added to capture the Pi's desktop from my PC, and used Vimeo to embed the video.

In the video I ran 3 different programs, using the following commands: ./demo_dmp, ./demo_raw and ./demo_3d which I will explain later.


Enabling the I2C interface

  • Install the i2c-tools:
sudo apt-get install python-smbus
sudo apt-get install i2c-tools
  • Enable I2C and SPI protocols:
sudo nano /etc/modprobe.d/raspi-blacklist.conf
  • This will open the above file in a text editor, allowing the following lines to be commented out:
#blacklist spi-bcm2708
#blacklist i2c-bcm2708
  • Edit the following file as follows, to allow the I2C module to be started automatically on start up:
sudo nano /etc/modules
  • When opened in the editor, add the last line as follows:
i2c-dev
  • Add the ‘pi’ user to the I2C group:
sudo adduser pi i2c
  • Update the Pi to ensure that all the latest packages are installed:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
  • Finally re-boot the Pi:
sudo reboot

The Pi will now automatically support I2C on startup.


Interfacing the MPU-6050

Make the connections as follows:
  • Pin 1 - 3.3V connect to VCC on the MPU-6050
  • Pin 3 - SDA connect to the MPU's SDA
  • Pin 5 - SCL connect to the MPU's SCL
  • Pin 6 - Ground connect to GND


Checking the 
Addresses of the I2C bus & the MPU-6050's Registers

Using the command:

i2cdetect -y 1 (the 1 refers to Revision 2 or later Raspberry Pis)

the following output was printed on the terminal:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                       


The entry at the hexadecimal address 0x68 shows that an I2C device has been detected at that address.  The UU at 0x3b appears to be reserved by the kernel for a driver.

These addresses allow us to examine their contents.  For example, entering the command:

sudo i2cget -y 1 0x68 0x75

reads the contents of the address 0x68 of I2CBUS 1 (the 1 refers to a Rev 2 or later Raspberry Pi) and retrieves the value in the register 0x75, which has a default value the same as the address (I think it is called the WHO_AM_I register - this is where the device itself 'knows' where it is on the I2C bus), and so it returns the value:

0x68

This apparently indicates that everything is working properly. :)


The Test Programs

I don't pretend to fully understand these programs, which have been written in the C++ language by Richard G Hirst, and available at https://github.com/richardghirst/PiBits/tree/master/MPU6050-Pi-Demo, but the first one, demo_dmp outputs the 4 quaternion values, followed by the yaw, pitch and roll values corresponding to the position and movement of the GY-521 breakout board.

The second program, demo_raw outputs the values of accelerometer measurements in the x, y and z directions, followed by the gyroscope measurements in the x, y and z directions.

The third program, demo_3d plots the 3D geometrical wireframe object's orientation in space, based on the calculated values mentioned above.

What Next?

What I would like to do is use the calculated values to feed to a 2-servo combination to control a self-levelling platform.

I think this might be a bit ambitious, so if anyone out there has any ideas how I could do this, I would be very grateful for your suggestions.


Wednesday, November 12, 2014

56. Exploring the Pi B+'s Ports II - Pulse Width Modulation

25,000 page views!!
In a previous post, http://smokespark.blogspot.co.uk/2013/04/15-programming-attiny85-with.html I experimented with RGB LEDs and control of LED brightness using Pulse Width Modulation (PWM).  That post includes explanations of how our human Persistence of Vision (POV) enables us to perceive a flashing LED as having less than maximum brightness.  That was using the ATMega 328 (Arduino) chip to program an ATTiny85 microchip to produce Pulse Width Modulation.

The difference here, of course, is that we are programming the Raspberry Pi in the Python language.  Not only are there coding differences, but we are working with 3V3 from the Pi's GPIO logic levels instead of 5V.


The circuit is a bit simpler than the last post at
http://smokespark.blogspot.co.uk/2014/10/55-exploring-pis-gpio-ports.html.  The switches have been removed as there are now no input GPIO ports, only outputs corresponding to the red, green and blue anodes of the RGB LED.  So the RGB LED is wired exactly the same as before - with its common cathode going to GND through a 
325 resistor.  You may have noticed that I still have wires running to GPIO ports 21, 22 and 23.  These are not connected to anything on the breadboard - I just forgot to remove them when I took off the switches!

What the experiment does is simply to increase the brightness of the red LED from zero to maximum, decrease it back to zero, move on the green LED, do the same, and then do this all over again for the blue LED.  The routine is in an infinite loop, but can be terminated gracefully by pressing CTRL-C on the keyboard:




For this video, I turned the ambient lighting down, as the LED colours all look white to the camera, in bright light.  You can see that there is a little bit of flicker, and this is intentional.  With a frequency of 40 hertz (40 Hz), my personal vision can detect flicker when the LEDs are in the dim part of their cycle.  A higher frequency will easily remove this flicker.  




It's interesting that this looping program doesn't use much in the way of processor resources.  You can see from the above image of the Pi's desktop, that the Raspberry Pi's CPU indicator is fairly activity-free, presumably because the code keeps the processor in the idle state for most of the time with the sleep() command. 

This experiment has been using software controlled PWM.  There are some GPIO pins (GPIO12, GPIO13 & GPIO18 - although I have also seen GPIO18 described as the PWM pin*) which are labelled PWM and therefore seem to have a special role in pulse width modulation.  When I find out how and when to use these, I'll post it up.

* servos require accurately timed pulses - which software alone cannot always provide, but GPIO18 with special software can (not sure I understand the subtleties here).