3D VISUALIZATION OF IMU USIING COPLEMENTORY FILTER
3D computer graphics are graphics that use a three-dimensional representation of geometric data that is stored in the computer for the purposes of performing calculations and rendering 2D images. Such images may be stored for viewing later or displayed in real-time.
3D computer graphics rely on many of the same algorithms as 2D computer vector graphics in the wire-frame model and 2D computer raster graphics in the final rendered display. In computer graphics software, the distinction between 2D and 3D is occasionally blurred; 2D applications may use 3D techniques to achieve effects such as lighting, and 3D may use 2D rendering techniques.
3D computer graphics are often referred to as 3D models. Apart from the rendered graphic, the model is contained within the graphical data file. However, there are differences. A 3D model is the mathematical representation of any three-dimensional object. A model is not technically a graphic until it is displayed.3D models are similarly rendered into a 3D physical representation of the model, with limitations to how accurate the rendering can match the virtual model.
An inertial measurement unit, or IMU is an electronic device that measures and report on crafts velocity and gravitational forces using combination of accelerometer and gyro scops.Some times also used magnetometers. By using IMU “MPU 6050” (3-axis accelerometer and 3-axis gyro scope) we can build a system that includes “complementary filter” algorithm for 3D visualization.
IMU MPU 6050 chip contains a 3-axis gyroscope and a 3-axis accelerometer. This makes it a “6 degrees of freedom inertial measurement unit” or 6DOF IMU, for short. Other features include a built in 16-bit analog to digital conversion on each channel and a proprietary Digital Motion Processor (DMP) unit.
The DMP combines the raw sensor data and performs some complex calculations onboard to minimize the errors in each sensor. Accelerometers and gyros have different inherent limitations, when used on their own. By combining the data from the two types of sensors and using some math wizardry (a process referred to as sensor fusion), you apparently can get a much more accurate and robust estimate of the heading. The DMP on the MPU6050 does exactly that and returns the result in “quaternions”. These can then can be converted to yaw-pitch-roll or to Euler angles for us humans to read and understand. The DMP also has a built in auto-calibration function that definitely comes in handy, as we will see later.
The biggest advantage of the DMP is that it eliminates the need to perform complex and resource intensive calculations on the Arduino side. The main downside is that it seems that the manufacturer did not provide much information on the proprietary inner workings of the DMP. Nevertheless, smart and creative folks figured out how to use its main features, and were nice enough to share the results with the rest of us. You can still pull the raw, accelerometer and gyro data as well, disabling the DMP, if this works better for your application, or you want to apply your own filtering and sensor fusion algorithms.
The MPU-6050 communicates with a microcontroller through an I2C interface. It even has a built in an additional I2C controller, that allows it to act as a master on a second I2C bus. The intention is for the IMU to read data from say, an external magnetometer (hooked up via those XDA / XCL pins you see on the breakout board) and send it to the DMP for processing. I have not found much detail on how to make the DMP use external magnetometer data yet, but fortunately that is not needed for my self-balancing robot at this point.Lastly, the MPU-6050 has a FIFO buffer, together with a built-in interrupt signal. It can be instructed to place the sensor data in the buffer and the interrupt pin will tell the Arduino, when data is ready to be read.
3. Block diagram description
The Inven Sense MPU-6050 sensor contains a MEMS accelerometer and a MEMS gyro in a single chip. It is very accurate, as it contains 16-bits analog to digital conversion hardware for each channel. Therefore it captures the x, y, and z channel at the same time. The sensor uses the I2C-bus to interface with the Arduino.The MPU-6050 is not expensive, especially given the fact that it combines both an accelerometer and a gyro. Reading the raw values for the accelerometer and gyro is easy. The sleep mode has to be disabled, and then the registers for the accelerometer and gyro can be read. But the sensor also contains a 1024 byte FIFO buffer. The sensor values can be programmed to be placed in the FIFO buffer. And the buffer can be read by the Arduino.The FIFO buffer is used together with the interrupt signal. If the MPU-6050 places data in the FIFO buffer, it signals the Arduino with the interrupt signal so the Arduino knows that there is data in the FIFO buffer waiting to be read. A little more complicated is the ability to control a second I2C-device.The MPU-6050 always acts as a slave to the Arduino with the SDA (Serial data line) and SCL (Serial clock line) pins connected to the I2C-bus.
But beside the normal I2C-bus, it has its own I2C controller to be a master on a second (sub)-I2C-bus. It uses the pins AUX_DA and AUX_CL for that second (sub)-I2C-bus.It can control, for example, a magnetometer. The values of the magnetometer can be passed on to the Arduino.Things get really complex with the "DMP".
The sensor has a "Digital Motion Processor" (DMP), also called a "Digital Motion Processing Unit". This DMP can be programmed with firmware and is able to do complex calculations with the sensor values.For this DMP, InvenSense has a discouragement policy, by not supplying enough information how to program the DMP. However, some have used reverse engineering to capture firmware.The DMP ("Digital Motion Processor") can do fast calculations directy on the chip. This reduces the load for the microcontroller (like the Arduino). The DMP is even able to do calculations with the sensor values of another chip, for example a magnetometer connected to the second (sub)-I2C-bus.
The sensor has a "Digital Motion Processor" (DMP), also called a "Digital Motion Processing Unit". This DMP can be programmed with firmware and is able to do complex calculations with the sensor values.For this DMP, InvenSense has a discouragement policy, by not supplying enough information how to program the DMP. However, some have used reverse engineering to capture firmware.The DMP ("Digital Motion Processor") can do fast calculations directy on the chip. This reduces the load for the microcontroller (like the Arduino). The DMP is even able to do calculations with the sensor values of another chip, for example a magnetometer connected to the second (sub)-I2C-bus.
Connection Diagram-
HARDWARE COMPONENTS:
1) Mega 328 ( Atmega 328)
2) 6 DOF IMU “ MPU 6050”(3-axis accelerometer and 3-axis gyro)
3) Male connectors
4) Bug strips
Software Used:
1) Arduino software
5) Processing
3.1 Atmega 328 Microcontroller
The Arduino Uno is a microcontroller board based on the ATmega328 (datasheet). It has 14 digital input/output pins (of which 6 can be used as PWM outputs), 6 analog inputs, a 16 MHz ceramic resonator, a USB connection, a power jack, an ICSP header, and a reset button. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started.
The Uno differs from all preceding boards in that it does not use the FTDI USB-to-serial driver chip. Instead, it features the Atmega16U2 (Atmega8U2 up to version R2) programmed as a USB-to-serial converter.
4.1.B Atmega328 PCB layout
MPU-6050
The MPU-6050 is a serious little piece of motion processing tech. By combining a MEMS 3-axis gyroscope and a 3-axis accelerometer on the same silicon die together with an onboard Digital Motion Processor™ (DMP™) capable of processing complex 9-axis MotionFusion algorithms, the MPU-6050 does away with the cross-axis alignment problems that can creep up on discrete parts.
Our breakout board for the MPU-6050 makes this tiny QFN package easy to work into your project. Every pin you need to get up and running is broken out to 0.1" headers, including the auxiliary master I2C bus which allows the MPU-6050 to access external magnetometers and other sensors.
Dimensions: 1 x 0.6 x 0.09" (25.5 x 15.2 x 2.48mm)
Features:
- I2C Digital-output of 6 or 9-axis Motion Fusion data in rotation matrix, quaternion, Euler Angle, or raw data format
- Input Voltage: 2.3 - 3.4V
- Selectable Solder Jumpers on CLK, FSYNC and AD0
- Tri-Axis angular rate sensor (gyro) with a sensitivity up to 131 LSBs/dps and a full-scale range of ±250, ±500, ±1000, and ±2000dps
- Tri-Axis accelerometer with a programmable full scale range of ±2g, ±4g, ±8g and ±16g
- Digital Motion Processing (DMP) engine offloads complex Motion Fusion, sensor timing synchronization and gesture detection
- Embedded algorithms for run-time bias and compass calibration. No user intervention required
- Digital-output temperature sensor
5. SOFTWARE IMPLEMENTATION
5.1 Program:
#include "I2Cdev.h"
#include "MPU6050.h"
#include "math.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 accelgyro;
/////////////////////////////////////////////////////////////////
int16_t ax=0, ay=0, az=0;
int16_t gx, gy, gz;
int32_t zero_ax=0,zero_ay=0,zero_az=0,zero_gx=0,zero_gy=0,zero_gz=0;
float diff_ax,diff_ay,diff_az,diff_gx,diff_gy,diff_gz;
unsigned long get_last_time;
float last_angle_x,last_angle_y,last_angle_z;
/////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(38400); ///////////////////////////////////////check////////////////////////////////
// Serial.println("Initializing I2C devices...");
accelgyro.initialize();
// Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful #" : "MPU6050 connection failed #");
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
calliberate();
last_angle_x=0,last_angle_y=0,last_angle_z=0;
get_last_time=0;
}
//////////////////////////////////////////////////////////////////
void loop()
{
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
unsigned long t_now = millis();
float accel_xout_scaled,accel_yout_scaled,accel_zout_scaled;
//accelgyro.getAcceleration(&ax, &ay, &az);
//accelgyro.getRotation(&gx, &gy, &gz);
accel_xout_scaled = ax / 16384.0;
accel_yout_scaled = ay / 16384.0;
accel_zout_scaled = az / 16384.0;
float FS_SEL = 131.0;
float gyro_scaled_x=(gx)/FS_SEL;
float gyro_scaled_y=(gy)/FS_SEL;
float gyro_scaled_z=(gz)/FS_SEL;
gyro_scaled_x =gyro_scaled_x-zero_gx;
gyro_scaled_y = gyro_scaled_y-zero_gy;
gyro_scaled_z =gyro_scaled_z-zero_gz;
float RADIANS_TO_DEGREES= 180/3.14159;
float dist_ax_az=dist(accel_xout_scaled,accel_zout_scaled);
float dist_ax_ay=dist(accel_xout_scaled,accel_yout_scaled);
float dist_ay_az=dist(accel_yout_scaled,accel_zout_scaled);
float accel_angle_x = (atan(accel_xout_scaled/dist_ay_az))*RADIANS_TO_DEGREES;
float accel_angle_y = (atan(accel_yout_scaled/dist_ax_az))*RADIANS_TO_DEGREES;
float accel_angle_z = (atan(dist_ax_ay/accel_zout_scaled))*RADIANS_TO_DEGREES;
/////////////////////////////////////////////////////////////
// Compute the (filtered) gyro angles
float dt =(t_now - get_last_time)/1000.0;
float gyro_x_delta = (gyro_scaled_x * dt);
float gyro_y_delta = (gyro_scaled_y * dt);
float gyro_z_delta = (gyro_scaled_z * dt);
float alpha=0.96;
float angle_x = (alpha*(last_angle_x+gyro_x_delta)) + ((1.0 - alpha)*accel_angle_x);
float angle_y = (alpha*(last_angle_y+gyro_y_delta)) + ((1.0 - alpha)*accel_angle_y);
float angle_z = (alpha*(last_angle_z+gyro_z_delta)) + ((1.0 - alpha)*accel_angle_z);
last_angle_x=angle_x;
last_angle_y=angle_y;
last_angle_z=angle_z;
get_last_time=t_now;
Serial.print(angle_x);Serial.print("#");
//
Serial.print(angle_y);
Serial.print("#");
Serial.println(angle_z);
//delay(10);
}
/////////////////////////////////////////////////////////////
float dist(float p,float q)
{
return sqrt((p*p)+(q*q));
}
/////////////////////////////////////////////
void calliberate()
{
int i;
for(i=0;i<50;i++)
{
// accelgyro.getAcceleration(&ax, &ay, &az);
accelgyro.getRotation(&gx, &gy, &gz);
zero_gx=gx+zero_gx;
zero_gy=gy+zero_gx;
zero_gz=gz+zero_gx;
}
zero_gx= zero_gx/(50*131);
zero_gy=zero_gy/(50*131);
zero_gz= zero_gz/(50*131);
}
Project Output
3D motion Visualization
4. BURNING PROCESS:-
Here we are using arduino 1.5.7 software .
1) Open arduino 1.5.7 software
2) Go to tools and select board arduino UNO .
3) Write program on it….
3) Save the program and verify(compile) it by clicking on ( symbol of tick 1st from left corner) symbol.
4) Connect the Atmega328 board to your system and upload the program
5) Burning process completed
CONCLUSION:
In this overall project, we learn the Data acquisition process from accelerometer and gyro scope.
We have also studied I2c protocol using “wire.h” library.
By using IMU “MPU 6050” (3-axis accelerometer and 3-axis gyro scope) we build a system of 6DOF, that includes “complementary filter” algorithm for 3D visualization.