SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By leonardonoronha
#197190
Hello, i'm having a problem with a i2c comunication project.

In my project i have a master acquiring raw data at 250Hz from a MPU9250 and calculating roll and pitch angles. This information than is sended to a slave at 5Hz. The slave collectit and display the angles at a LCD i2c module. However, when the slave is receiving the information its seems that the lcd get corrupted as well the slave doesnt collect the information from the master.

MPU i2c address: 0x68
Slave i2c address: 0x20
LCD i2c address: 0x27

Does anyone knows why this is happening? I'm doing something wrong with the master-slave communication? When i just use the master to acquire and display it at the lcd, everything works fine.

Thanks!!

Slave code:
Code: Select all
#include <Wire.h>
#define nodeAdress 0x20
#define dataSize 4
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);

int data[4];
unsigned int aux0;
unsigned int aux1;
float rollAngle, pitchAngle;
int ok = 1;

void setup() {
  
  Serial.begin(57600);
  Serial.println("1");
  Wire.begin(nodeAdress);
  Wire.setClock(400000);
  Serial.println("1");
  Wire.onReceive(receiveEvent);
  Serial.println("1");
  lcd.begin();
  Serial.println("1");
  lcd.backlight();
  Serial.println("1");
  lcd.clear();
}

void loop() {
  delay(100);
  
  aux0 = (data[1]<<8) | data[0];
  pitchAngle = (aux0/100.0)-180.0;

  aux1 = (data[3]<<8) | data[2];
  rollAngle = (aux1/100.0)-180.0;
  
  Serial.print("Pitch angle: ");
  Serial.print(pitchAngle);
  Serial.print("     -     Roll angle: ");
  Serial.println(rollAngle);
  
  lcdPrint();
}

void lcdPrint() {
  lcd.setCursor(0, 0);
  lcd.print(F("Pitch: "));
  lcd.print(pitchAngle);
  lcd.print(F("o"));
  lcd.setCursor(0, 1);
  lcd.print(F("Roll: "));
  lcd.print(rollAngle);
  lcd.print(F("o"));
}

void receiveEvent(int howMany) {
  if(Wire.available()){
    data[0] = Wire.read();
    data[1] = Wire.read();
    data[2] = Wire.read();
    data[3] = Wire.read();
   }    
}
Master code:
Code: Select all
#include <Wire.h>
#define dataSize 4
#define nodeAdress 21

int gyro_x, gyro_y, gyro_z;
long acc_x, acc_y, acc_z, acc_total_vector;
int temperature;
long gyro_x_cal, gyro_y_cal, gyro_z_cal;
long loop_timer;
int lcd_loop_counter;
float angle_pitch, angle_roll;
int angle_pitch_buffer, angle_roll_buffer;
boolean set_gyro_angles;
float angle_roll_acc, angle_pitch_acc;
float angle_pitch_output, angle_roll_output;
byte data[4];
unsigned int aux;
int contador;

void setup() {
  Serial.begin(57600);

  Wire.begin(); 
  Wire.setClock(400000);
  setup_mpu_6050_registers(); 

  for (int cal_int = 0; cal_int < 2000 ; cal_int ++) { 
    read_mpu_6050_data(); 
    gyro_x_cal += gyro_x;      
    gyro_y_cal += gyro_y;    
    gyro_z_cal += gyro_z;  
    delay(3);  
  }
  gyro_x_cal /= 2000;  
  gyro_y_cal /= 2000;  
  gyro_z_cal /= 2000;  

  loop_timer = micros();   

}

void loop() {


  read_mpu_6050_data();                                                

  gyro_x -= gyro_x_cal;                                                
  gyro_y -= gyro_y_cal;                                               
  gyro_z -= gyro_z_cal;                                               

  angle_pitch += gyro_x * 0.0000611;                                   
  angle_roll += gyro_y * 0.0000611;                                   

  
  angle_pitch += angle_roll * sin(gyro_z * 0.000001066);            
  angle_roll -= angle_pitch * sin(gyro_z * 0.000001066);              

  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
  angle_pitch_acc = asin((float)acc_y / acc_total_vector) * 57.296;    
  angle_roll_acc = asin((float)acc_x / acc_total_vector) * -57.296;   

  angle_pitch_acc -= 0.0;
  angle_roll_acc -= 0.0; 

  if (set_gyro_angles) {
    angle_pitch = angle_pitch * 0.9996 + angle_pitch_acc * 0.0004; 
    angle_roll = angle_roll * 0.9996 + angle_roll_acc * 0.0004;  
  }
  else {
    angle_pitch = angle_pitch_acc;
    angle_roll = angle_roll_acc;   
    set_gyro_angles = true;    
  }

  angle_pitch_output = (angle_pitch_output * 0.9 + angle_pitch * 0.1);
  angle_roll_output = (angle_roll_output * 0.9 + angle_roll * 0.1);

  
  aux = (unsigned int)((angle_pitch_output + 180.0) * 100.0);
  data[0] = (int)((aux & 0XFF));
  data[1] = (int)((aux >> 8) & 0XFF);
  aux = (unsigned int)((angle_roll_output + 180.0) * 100.0);
  data[2] = (int)((aux & 0XFF));
  data[3] = (int)((aux >> 8) & 0XFF);

  Serial.print("Pitch angle: ");
  Serial.print(angle_pitch_output);
  Serial.print("     -     Roll angle: ");
  Serial.println(angle_roll_output);

  if(contador < 50){
    contador++;
  } else{
    Wire.beginTransmission(0x20);
    Wire.write(data[0]);
    Wire.write(data[1]);
    Wire.write(data[2]);
    Wire.write(data[3]);
    Wire.endTransmission();
    contador = 1;
  }

  Serial.println(contador);

  Serial.println(micros() - loop_timer);

  while (micros() - loop_timer < 4000)
  loop_timer = micros(); 
}

void read_mpu_6050_data() { 
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x3B);                                                    //Send the requested starting register
  Wire.endTransmission();                                              //End the transmission
  Wire.requestFrom(0x68, 14);                                          //Request 14 bytes from the MPU-6050
  while (Wire.available() < 14);                                       //Wait until all the bytes are received
  acc_x = Wire.read() << 8 | Wire.read();                              //Add the low and high byte to the acc_x variable
  acc_y = Wire.read() << 8 | Wire.read();                              //Add the low and high byte to the acc_y variable
  acc_z = Wire.read() << 8 | Wire.read();                              //Add the low and high byte to the acc_z variable
  temperature = Wire.read() << 8 | Wire.read();                        //Add the low and high byte to the temperature variable
  gyro_x = Wire.read() << 8 | Wire.read();                             //Add the low and high byte to the gyro_x variable
  gyro_y = Wire.read() << 8 | Wire.read();                             //Add the low and high byte to the gyro_y variable
  gyro_z = Wire.read() << 8 | Wire.read();                             //Add the low and high byte to the gyro_z variable

}

void setup_mpu_6050_registers() {
  //Activate the MPU-6050
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x6B);                                                    //Send the requested starting register
  Wire.write(0x00);                                                    //Set the requested starting register
  Wire.endTransmission();                                              //End the transmission
  //Configure the accelerometer (+/-8g)
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x1C);                                                    //Send the requested starting register
  Wire.write(0x10);                                                    //Set the requested starting register
  Wire.endTransmission();                                              //End the transmission
  //Configure the gyro (500dps full scale)
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x1B);                                                    //Send the requested starting register
  Wire.write(0x08);                                                    //Set the requested starting register
  Wire.endTransmission();                                              //End the transmission
}
By paulvha
#197210
shouldn't you include the receiveEvent() call at the beginning of the loop in the slave. I do not see how else you data-array is getting it's data.