Thursday, 14 August 2014

Getting Gyroscope values from MPU-6050

Part 4 in my series on the MPU-6050, In the last entry we got the roll and pitch values out of the Accelerometer and displayed them on a little LabVIEW vi with some dials. In this entry I want to get to the gyroscope values and see if I can get them displaying on some dials too. After we have the gyroscope values we can look at combining the 2 sets of data and having a useful Roll,Pitch and Yaw sensor.

How does a gyroscope work?

A gyroscope is a MEMS which contain small strips of metal that bend when the gyro twists and moves. By measuring the amount of bending the gryo can accurately report what angular velocity it is experiencing (1)

I found Pieter Jan's blog post on this very useful to understand this subject, all the maths is from there.

Well what is "Angular velocity"? 

Angular velocity is "The rate of change of angular position" and it's units are "degrees per second". The gyroscope has 3 axis so the value we get when we poll each axis is going to be the angular velocity at the current time in deg/sec.

$$Angular\: Velocity = \: \dot{\theta}= \: \frac{\mathrm{d}\theta }{\mathrm{d} t}$$
where theta is just the angle.

We really want the angle not the rate of change of the angle so if you remember from calculus, to get rid of a derivative you integrate it giving us.

$$ \theta(t)\:=\:\int_{0}^{t}\dot{\theta}\:dt $$
 So all we need to do is integrate the 3 axis values and it will give us the current angle, now you ask yourself..

How do we integrate in software? 

As we are using a microcontroller (digital system) we are going to need to make a software approximation of an integral. You may remember that an integral is just the area under a curve so what if we just took the current sample and multiplied it by the time since the last sample to give us the area of a rectangle and we just sum this and all other rectangles together to give us the area under the curve as shown in the photo below.
Where u(t) is our current value and T is the sample time. This is known as the rectangular approximation  it is good enough for what we need but as you can see from the diagram if the sample time is too long then bits of the graph may be overestimated (the red bits going over the curve). A more accurate approximation is the trapezoidal but we will just use rectangular for ease.

The pseudocode of what we are trying to achieve is going to be:
  1. Start timer
  2. Wait for timer to elapse
  3. Read in gyroscope values
  4. Multiply each by the sample time to get area of rectangle
  5. Add area to sum of all previous areas to give us current position

 Building on the project we made in the last part I am going to get the PSoC to constantly sample the gyroscope values and when it is polled with the character "g" at 9600 baud it will respond with the current integrated angles.

What sample time should I choose?

I will finish this soon


Sunday, 20 July 2014

Getting Roll, Pitch and Yaw from MPU-6050

Part 3 in our quest for Accelerometer and gyroscope values. In the previous entry we got the acceleration values in the form of G's and also the linear velocity in terms of degrees/s however these values aren't much use to us. Wouldn't it be better if we had roll,pitch and yaw and also angular position instead? Well that's what I am going to try to achieve in this post.

Roll, Pitch and Yaw

enter image description here
For those that don't know what these are look at the diagram above, it shows that the roll is the rotation about the Y axis, the pitch is the rotation about the X axis and the yaw is the rotation about the Z axis.

How do we convert gravity into these values?

Well I am not going to go into the theory of how these values convert to roll and pitch because some nice mathematicians over on stackoverflow have done that for us.
The formulas to convert the acceleration values to pitch and roll are as follows.
Roll = atan2(Y, Z) * 180/PI;
Pitch = atan2(X, sqrt(Y*Y + Z*Z)) * 180/PI;
 We use atan2 as it works over 4 quadrants, if we used atan then we would have problems with angles over 90 degrees. Don't worry about Yaw for now as we can't determine that using just the accelerometer, this is intuitive if you think about how Yaw is rotation about the Z axis. We will just read a constant 1G in the Z axis no matter how the accelerometer is rotated, We will need to augment our acceleration values with the Gyroscope ones to get the full picture which we will do in a later entry.

I have rewritten the PSoC code to respond to an interrupt on the UART. Whenever the PSoC receives the character 'a' it will respond with the acceleration values in comma seperated form of X,Y,Z.

So if you send 'a' it will give you back something like "0.1, 0.2, 1"  < these are all abitrary but something around 0 for X, 0 for Y and 1 for Z is expected if the MPU6050 is on a flat surface.

The new PSoC code can be found on my Github under "GettingG'sWithInterrupt" I have left the conversion to Roll and Pitch in the code but kept it commented out as I will be doing the conversion from LabVIEW but just uncomment it if you want the conversion on the PSoC.

Visualising our values

Now this part is up to you are the PSoC code will work on any platform/language aslong as you poll it with the character 'a' at 9600 Baud. I personally used LabVIEW to do the polling as it has some nice inbuilt dials and bar graphs as can be seen in the screenshot below.

 I have uploaded a Windows exe on my Github under /Examples/LabVIEW/Dials/EXE//MPU6050dials.exe of the Labview progam, please note you will have to install the LabVIEW runtime engine to run the EXE

I have also added the vi if you want to have a go at changing it.

Instructions for use
Change COM port to whatever your device is connected to, click write then read, you should see the text box fill up with values and you should see the LED blinking on the PSoC pioneer. If not you probably have a problem with your serial port connections.

In the next entry I will look at getting the Gyroscope values off the PSoC onto LabVIEW dials and then move onto combining the values and filtering them to get accurate non noisy values. You will notice at the minute the values jump around a lot, we need to get rid of this.

Friday, 18 July 2014

Processing data from MPU-6050

In the previous entry we got the MPU-6050 talking to the PSoC 4 over I2C and had it giving us raw values on a serial screen. Now let us take it further and see if we can turn those values into angles and such.

Finding out the offsets

First of all we need to work out the offset errors and remove them from our data. Offsets are caused by a number of factors such as mechanical assembly, mounting, package damage and temperature fluctuations. So we need to work out what the offsets of our chip are and then remove them before processing the data.

I am getting all of my methods and theory from this application note from Freescale.

So what we need to do is to place the sensor level on a table (use a spirit level or something to make sure it is actually level), then we need to:

  1. Measure the average acceleration/angle in the X, Y and Z axis over 10-20 samples
  2. These values should be 0G in the X and Y axis and will be 1G in the Z axis 
  3. Anything over 0G in the X and Y and 1G in Z will be our offsets
So after keeping the device level and leaving a large (0.5 second) delay in between each sample (to let temperature stabilise) my average values are as shown below.

Test finished, offset values are shown below

AXoff:435, AYoff:-352, AZoff:15236 || GXoff:74, GYoff:131, GZoff:-126,

Don't worry if yours were different we are going to incorporate the calibration into our future code so that the device can auto zero regularly.

So from now on when we measure we will need to remove those offsets from our values before we process them.

The offset testing program is available on my Github under "CalibrateOffsets"

Getting some G's

Now we know what our offsets are but we don't know what they mean in the form of angles and G's so lets do some scaling and conversion to get the real values.

Understanding the scaling

As Jeff Rowberg said in his own i2cdevlib forums 
"The accelerometer and gyroscope measurements are explained in the MPU-6050 datasheet in the GYRO_CONFIG and ACCEL_CONFIG register descriptions (sections 4.4 and 4.5 on pages 14 and 15). The scale of each depends on the sensitivity settings chosen, which can be one of +/- 2, 4, 8, or 16g for the accelerometer and one of +/- 250, 500, 1000, or 2000 deg/sec for the gyroscope. The accelerometer produces data in units of acceleration (distance over time2), and the gyroscope produces data in units of rotational velocity (rotation distance over time). The output scale for any setting is [-32768, +32767] for each of the six axes. The default setting in the I2Cdevlib class is +/- 2g for the accel and +/- 250 deg/sec for the gyro. If the device is perfectly level and not moving, then:
  • X/Y accel axes should read 0
  • Z accel axis should read 1g, which is +16384 at a sensitivity of 2g
  • X/Y/Z gyro axes should read 0
In reality, the accel axes won't read exactly 0 since it is difficult to be perfectly level and there is some noise/error, and the gyros will also not read exactly 0 for the same reason (noise/error)."
 So first of all we need to know the sensitivity of our sensor. The default is +/-2G and +/-250deg/sec but where do we confirm we are running the default settings and how do we change the values.

If you look in mpu6050.c at line 66 you will find the function

Here you can see that we are running at the default selection of 2G for the accelerometer and 250 for the gyro, If you look at the defines in mpu6050.h you can change these to whatever you want.

So we know we are running at a sensitivity of +/-2G and +/- 250deg/s but how do our values correspond to those accelerations/angles.

These are both straight line graphs and we can work out from them that for 1G we will read 16384 and for 1degree/sec we will read 131.07 (Although the .07 will get ignore due to binary) these values were just worked out by drawing the straight line graph with 2G at 32767 and -2G at -32768 and 250/-250 at the same values.

So now we know our sensitivity values (16384 and 131.07) we just need to minus the offsets from our values and then devide by the sensitivity as it explains in the freescale application note. 

These will work fine for the X and Y values but as the Z was recorded at 1G and not 0 we will need to minus off 1G (16384) before we divide by our sensitivity. This is explained in the freescale note.

I have written a project which calculates the values in G's and angles and it can be found on my GitHub under "GetG's"

Thursday, 17 July 2014

Getting started with MPU-6050 IMU

It has been a while but I have been struggling to get this thing working and hopefully my instructions might help someone else out there.

So the MPU-6050 is an IMU unit which has an accelerometer and a gyroscope built into it and communicates over I2C, it also has some complex processor in there too called a DMP which filters and processes all the results but I haven't got that working yet - Maybe as this blog develops I will post about how I got it up and running but let us just concentrate on the basics for now.

I am using the GY-521 breakout board which I bought off eBay for a couple of quid.


The board communicates over I2C and it has internal pull up resistors built in so all you have to do is connect the following. Note that the SDA and SCL lines will be specific to your microcontroller I am using a PSoC 4 Pioneer board but I also tested it on an Arduino UNO)

  • VCC - 5V (I have not tested 3.3V)
  • GND - 0V
  • SDA - SDA on your microcontroller (P0[5] on PSoC 4)
  • SCL - SCL on your microcontroller (P0[4] on PSoC 4)

Here it is connected to the PSoC 4


Here is where things get interesting because it is very easy to get communicating and get the raw values out of the sensor but actually understanding those values, filtering them and getting useful data from them is a different story.

Let us just start though by seeing if we can get some values out of the chip.

Reading raw data

Jeff Rowberg has created a nice library for the MPU-6050 on his Github it is an extensive I2C library for many other development boards and is definitely worth checking out. I am going to be using it in our project except as I am using a PSoC and not an Arduino or a MSP430 I will be using an edited version of the i2cdevlib designed to work with the PSoC 4 Pioneer which a kind individual named Hernán Sánchez released on the PSoC forums.

I have altered his project to display the values in a more useful way and also to move a lot of the extraneous code out to another source file, I think this will help you understand more what is happening.

You can find my getting started code on my Github under Examples "Getting Started"

Just connect a serial monitor (PuTTY) to the relevant port and you should see the connection being made and the raw values being printed to the screen.

In the next post I am going to look at turning the values into angles and accelerations but for now, keep watching the skies.

Wednesday, 2 January 2013

Installing MongoDB on the Raspberry Pi

This will become a full post soon

$ PATH=$PATH:/opt/mongo/bin/
$ export PATH

Node.js Raspberry Pi Tutorial 2 - Our first site

Well this is part 2 in a series of blogs I am making surrounding the Raspberry Pi and node.ns - Here is part 1

So in the last tutorial we installed node.js 0.8.16,

The aim of this tutorial is to create a site running on the Express framework.. Express is sort of like the defacto standard now for building web apps in node.js, there are more complex ones such as Meteor and Derby which feature loads more stuff.. and we might go into them in the future.. but they are built using express and the principles we are going to learn here anyway so it is worth starting at the bottom.. I think diving right into Meteor would be confusing..

So what is express?

Express is the glue which holds our app together.. it is the framework of our app.. express is a series of tools bundled together which when initialized will spit out a ready to use app.. 

For example, say I wanted to create a website using node.js.. where would I start? Well first of all I know that I would need a HTTP server as that's just how the web works.. So I would look into nodes documentation and pull out its HTTP module and create a server..

So far so good.. Okay well, I am happy with my server just serving up "Hello World" or whatever the most basic example is and I have decided I want to add another page to my site which will serve up some other content.. let's go with a picture of a cat..
Well I only have the http server so I would have to set up some sort of request handler/router which would take the new page url (/cat) and figure out what functions to carry out and then actually execute those functions and pipe the image of the cat to the user.

I now have a server and a router.. (no split files or organisation yet just one file with some router code) say I want to parse the cookies of the user visiting my site so that they can stay logged in even when they leave the tab in their browser.. well I would have to look around in node.js libraries and would use the connect-cookie module and play around with that..
HTML or CSS templating? maybe pull in stylus or Jade and try and get the thing going..
This all sounds like a ball ache right? well that's where our good friend express comes into play..

Express just does all this for you.. all you have to do is type "express myApp" and it will create all the configuration, file organisation and module installation for you.. all you do is sat back and smoke a cigar. So are we agreed.. express is awesome? Okay let's install the thing.

What is NPM?

NPM if you have never used it is this cool way to install packages in node.. it is much like apt in Raspbian, instead of typing "sudo apt-get install porno" you would type "npm install porno" and it would find the relevant porno for your needs.. the files get dumped in every directory you use the npm install command in.. for example if I was in a directory /bacon and I type npm install random-package, then npm would create a folder inside bacon called "node_modules" and inside that would be my random-package.. node always looks inside the node_modules folder..

There is one other way to install packages in Node and that is globally so instead of just installing them for the current project like I showed above they are installed on the whole computer. This is especially useful for installing packages like express, as you are going to want to use them for every project you set up so it makes sense to be able to use them everywhere..

So that is what we are going to do, install express onto the whole computer but first of all we want to make sure our package manager NPM is up to date.. 

Type the above into any directory, this will tell NPM to update itself, once this is done type npm -v to make sure you are running an up to date version (1.1.69 is my version).

This will install express on the pi so we can use it in our projects.. the -g is the global install option which is mentioned above..

Express installed.. let's make an App

Right for this tutorial we are just going to create the most basic Express app, there are some options you can tweak depending on your preferences, but as we are assuming you are all beginners lets not go into those just yet..

First of all find a directory you want to try out an express app in.. for this kind of thing I have a folder called "node-playground" where I test out all of this kind of stuff.. maybe try that.

The above commands make the directory we are going to play in, then the express command makes a separate directory called myApp (or anything you want to call it) with all the relevant files in..

If you have done it right you should see the following screen, I have listed the files inside the folder too

if you have something that looks like above then all is going well.. express it telling us to install the dependencies this app needs.. so we will do that in a second.. this also uses NPM,  (npm is used for everything pretty much so get used to it).. when you download or clone someones app you always have to let npm install the dependencies on your computer and compile them properly. So let's do it..

Change directory into the app if you haven't already like I have done above.. and then type

This should set loads of text going.. what npm is doing here is reading from the file called package.json for which modules express wants to use. It then goes through its libraries to find whatever versions are specified and downloads and installs them to a folder called node_modules.

I will go into package.json and how JSON works soon but for now just know that npm has installed everything express has asked for.. if you get any error which I am sure you won't.. maybe try installing the package build-essential (sudo apt-get install build-essential).. this just contains some basic tools for building packages which npm might want to use.

That's it.. you have a finished website which will run on the Raspberry Pi

Seriously that's how easy it is.. install express.. npm install and then finally to actually run your app just type
node app.js
This tells node to run it.. if everything is working node should say.. "running on localhost:3000" if you go to the pi's ip and then type :3000 you should see a page saying "welcome to Express"..

eg my pi is on so in chrome I type to see my amazing express app.

Well that's all well and good but how does all this work so I can make my own cool apps I hear you ask.. well full explanation is coming soon.. I am tired right now bed time!

Tuesday, 1 January 2013

Installing bcrypt with Windows 8 and Visual studio 2012

Okay so I was using this tutorial here.. which wanted me to use bcrypt.. I am using Windows 8 and Visual Studio 2012 (I have the 2010 C++ stuff installed too as TooLateNate says to on the node-gyp github. Anyway I couldn't get it running with: as bcrypt just wouldn't play ball.. but thanks to finding this thread here I managed to solve the problem with typing So if you are having trouble with anything and you have my problem just type npm install PACKAGE --msvs_version=2012 So for bcrypt happy trails