Go Down

Topic: How to get analog output from mpu 6050 using dac (mcp 4725)??  (Read 636 times) previous topic - next topic

knithin3

I have an IMU sensor mpu 6050, I need to get the analog output of the sensor using digital to analog converter mcp 4725, I am confused how should I go with the connections and also how should I code it?? I am a noob, I really need your help.

I have attached the data sheets of mpu 6050 and mcp 4725. Also below is the code that I am using right now for the IMU sensor. I wanted to get the output angle in terms of voltage using digital to analog converter.

onic Level Sketch
/*
Electronic Level
mpu-6050-level.ino
Uses MPU-6050 IMU
Displays on 128x64 OLED and LED

DroneBot Workshop 2019
https://dronebotworkshop.com
*/

// Include Wire Library for I2C
#include <Wire.h>

// Include NewLiquidCrystal Library for I2C
#include <LiquidCrystal_I2C.h>

// Define LCD pinout
const int  en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;

// Define I2C Address - change if reqiuired
const int i2c_addr = 0x3F;

LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);

// Level LEDs
int levelLED_neg1 = 9;
int levelLED_neg0 = 10;
int levelLED_level = 11;
int levelLED_pos0 = 12;
int levelLED_pos1 = 13;



//Variables for Gyroscope
int gyro_x, gyro_y, gyro_z;
long gyro_x_cal, gyro_y_cal, gyro_z_cal;
boolean set_gyro_angles;

long acc_x, acc_y, acc_z, acc_total_vector;
float angle_roll_acc, angle_pitch_acc;

float angle_pitch, angle_roll;
int angle_pitch_buffer, angle_roll_buffer;
float angle_pitch_output, angle_roll_output;

// Setup timers and temp variables
long loop_timer;
int temp;

// Display counter
int displaycount = 0;

void setup() {

//Start I2C
Wire.begin();

// Set display type as 16 char, 2 rows
lcd.begin(16,2);

// Set Level LEDs as outputs
pinMode(levelLED_neg1, OUTPUT);
pinMode(levelLED_neg0, OUTPUT);
pinMode(levelLED_level, OUTPUT);
pinMode(levelLED_pos0, OUTPUT);
pinMode(levelLED_pos1, OUTPUT);


//Setup the registers of the MPU-6050                                                      
setup_mpu_6050_registers();

//Read the raw acc and gyro data from the MPU-6050 1000 times                                          
for (int cal_int = 0; cal_int < 1000 ; cal_int ++){                  
read_mpu_6050_data();
//Add the gyro x offset to the gyro_x_cal variable                                            
gyro_x_cal += gyro_x;
//Add the gyro y offset to the gyro_y_cal variable                                              
gyro_y_cal += gyro_y;
//Add the gyro z offset to the gyro_z_cal variable                                            
gyro_z_cal += gyro_z;
//Delay 3us to have 250Hz for-loop                                            
delay(3);                                                          
}

// Divide all results by 1000 to get average offset
gyro_x_cal /= 1000;                                                
gyro_y_cal /= 1000;                                                
gyro_z_cal /= 1000;

// Start Serial Monitor                                                
Serial.begin(115200);

// Init Timer
loop_timer = micros();                                              
}

void loop(){

// Get data from MPU-6050
read_mpu_6050_data();
 
//Subtract the offset values from the raw gyro values
gyro_x -= gyro_x_cal;                                                
gyro_y -= gyro_y_cal;                                                
gyro_z -= gyro_z_cal;                                                
     
//Gyro angle calculations . Note 0.0000611 = 1 / (250Hz x 65.5)

//Calculate the traveled pitch angle and add this to the angle_pitch variable
angle_pitch += gyro_x * 0.0000611;  
//Calculate the traveled roll angle and add this to the angle_roll variable
//0.000001066 = 0.0000611 * (3.142(PI) / 180degr) The Arduino sin function is in radians                                
angle_roll += gyro_y * 0.0000611;
                                 
//If the IMU has yawed transfer the roll angle to the pitch angle
angle_pitch += angle_roll * sin(gyro_z * 0.000001066);
//If the IMU has yawed transfer the pitch angle to the roll angle              
angle_roll -= angle_pitch * sin(gyro_z * 0.000001066);              

//Accelerometer angle calculations

//Calculate the total accelerometer vector
acc_total_vector = sqrt((acc_x*acc_x)+(acc_y*acc_y)+(acc_z*acc_z));

//57.296 = 1 / (3.142 / 180) The Arduino asin function is in radians
//Calculate the pitch angle
angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;
//Calculate the roll angle      
angle_roll_acc = asin((float)acc_x/acc_total_vector)* -57.296;      

//Accelerometer calibration value for pitch
angle_pitch_acc -= 0.0;
//Accelerometer calibration value for roll                                              
angle_roll_acc -= 0.0;                                              

if(set_gyro_angles){

//If the IMU has been running
//Correct the drift of the gyro pitch angle with the accelerometer pitch angle                      
angle_pitch = angle_pitch * 0.9996 + angle_pitch_acc * 0.0004;
//Correct the drift of the gyro roll angle with the accelerometer roll angle    
angle_roll = angle_roll * 0.9996 + angle_roll_acc * 0.0004;        
}
else{
//IMU has just started  
//Set the gyro pitch angle equal to the accelerometer pitch angle                                                          
angle_pitch = angle_pitch_acc;
//Set the gyro roll angle equal to the accelerometer roll angle                                      
angle_roll = angle_roll_acc;
//Set the IMU started flag                                      
set_gyro_angles = true;                                            
}

//To dampen the pitch and roll angles a complementary filter is used
//Take 90% of the output pitch value and add 10% of the raw pitch value
angle_pitch_output = angle_pitch_output * 0.9 + angle_pitch * 0.1;
//Take 90% of the output roll value and add 10% of the raw roll value
angle_roll_output = angle_roll_output * 0.9 + angle_roll * 0.1;
//Wait until the loop_timer reaches 4000us (250Hz) before starting the next loop  

// Print to Serial Monitor  
//Serial.print(" | Angle  = "); Serial.println(angle_pitch_output);


// Increment the display counter
displaycount = displaycount +1;

if (displaycount > 100) {

lcd.clear();
// Print on first row of LCD
lcd.setCursor(0,0);
lcd.print("Pitch: ");
lcd.print(angle_pitch_output);
lcd.setCursor(0,1);
lcd.print("Roll: ");
lcd.print(angle_roll_output);



}

displaycount = 0;

}


while(micros() - loop_timer < 4000);
//Reset the loop timer                                
loop_timer = micros();

}

Robin2

To make it easy for people to help you please modify your post and use the code button </>


Code: [Select]
so your code
looks like this
and is easy to copy to a text editor. See How to use the Forum

Your code is too long for me to study quickly without copying to my text editor. The text editor shows line numbers, identifies matching brackets and allows me to search for things like all instances of a particular variable or function.

Also please use the AutoFormat tool to indent your code consistently for easier reading.



As far as I can tell there are two completely separate parts to your project - {A} getting values from the MPU6050 and interpreting them and {B} converting a number to a voltage using a DAC. I suggest yo learn how to do both separately before trying to combine them.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up