How to connect 2 devices on I2C?

I want to use 2 sensors on the pin A4, A5. The sensors are BMP180, AltIMU-10 v5, and I have no clue what to do. Please assist me in this, because I combined 2 codes thinking that there would be no conflicting pins. I have little to no understanding of I2C, so your help would be greatly appreciated.

#include <SD.h> 
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <DHT.h>
#define DHTTYPE DHT22
#define DHTPIN 7
#define IMU_V5
int SENSOR_SIGN[9] = {1,1,1,-1,-1,-1,1,1,1}; 
#define GRAVITY 256
#define seaLevelPressure_hPa 1013.25
#define ToRad(x) ((x)*0.01745329252)  // *pi/180
#define ToDeg(x) ((x)*57.2957795131)  // *180/pi
#define Gyro_Gain_X 0.07 //X axis Gyro gain
#define Gyro_Gain_Y 0.07 //Y axis Gyro gain
#define Gyro_Gain_Z 0.07 //Z axis Gyro gain
#define Gyro_Scaled_X(x) ((x)*ToRad(Gyro_Gain_X)) //Return the scaled ADC raw data of the gyro in radians for second
#define Gyro_Scaled_Y(x) ((x)*ToRad(Gyro_Gain_Y)) //Return the scaled ADC raw data of the gyro in radians for second
#define Gyro_Scaled_Z(x) ((x)*ToRad(Gyro_Gain_Z)) //Return the scaled ADC raw data of the gyro in radians for second
#define DHT22_PIN 8 
#define M_X_MIN -1000
#define M_Y_MIN -1000
#define M_Z_MIN -1000
#define M_X_MAX +1000
#define M_Y_MAX +1000
#define M_Z_MAX +1000
#define Kp_ROLLPITCH 0.02
#define Ki_ROLLPITCH 0.00002
#define Kp_YAW 1.2
#define Ki_YAW 0.00002
#define OUTPUTMODE 1
#define PRINT_DCM 0     //Will print the whole direction cosine matrix
#define PRINT_ANALOGS 0 //Will print the analog raw data
#define PRINT_EULER 1   //Will print the Euler angles Roll, Pitch and Yaw
#define STATUS_LED 13
const int buttonPin = 2;   
int buttonState = 0; 
const int chipSelect = 4;
File myFile;
float G_Dt=0.02;    // Integration time (DCM algorithm)  We will run the integration loop at 50Hz if possible
long timer=0;   //general purpuse timer
long timer_old;
long timer24=0; //Second timer used to print values
int AN[6]; //array that stores the gyro and accelerometer data
int AN_OFFSET[6]={0,0,0,0,0,0}; //Array that stores the Offset of the sensors

int gyro_x;
int gyro_y;
int gyro_z;
int accel_x;
int accel_y;
int accel_z;
int magnetom_x;
int magnetom_y;
int magnetom_z;
float c_magnetom_x;
float c_magnetom_y;
float c_magnetom_z;
float MAG_Heading;

float Accel_Vector[3]= {0,0,0}; //Store the acceleration in a vector
float Gyro_Vector[3]= {0,0,0};//Store the gyros turn rate in a vector
float Omega_Vector[3]= {0,0,0}; //Corrected Gyro_Vector data
float Omega_P[3]= {0,0,0};//Omega Proportional correction
float Omega_I[3]= {0,0,0};//Omega Integrator
float Omega[3]= {0,0,0};

// Euler angles
float roll;
float pitch;
float yaw;
// idk
float hum;  
float temp; 
Adafruit_BMP085 bmp;
DHT dht(DHTPIN, DHTTYPE);

float errorRollPitch[3]= {0,0,0};
float errorYaw[3]= {0,0,0};

unsigned int counter=0;
byte gyro_sat=0;

float DCM_Matrix[3][3]= {
  {
    1,0,0  }
  ,{
    0,1,0  }
  ,{
    0,0,1  }
};
float Update_Matrix[3][3]={{0,1,2},{3,4,5},{6,7,8}}; //Gyros here


float Temporary_Matrix[3][3]={
  {
    0,0,0  }
  ,{
    0,0,0  }
  ,{
    0,0,0  }
};

void setup()
{
  Serial.begin(115200);
  pinMode (STATUS_LED,OUTPUT);  // Status LED
  dht.begin();

  I2C_Init();

  Serial.println("Pololu MinIMU-9 + Arduino AHRS");

  digitalWrite(STATUS_LED,LOW);
  delay(1500);

  Accel_Init();
  Compass_Init();
  Gyro_Init();

  delay(20);

  for(int i=0;i<32;i++)    // We take some readings...
    {
    Read_Gyro();
    Read_Accel();
    for(int y=0; y<6; y++)   // Cumulate values
      AN_OFFSET[y] += AN[y];
    delay(20);
    }

  for(int y=0; y<6; y++)
    AN_OFFSET[y] = AN_OFFSET[y]/32;

  AN_OFFSET[5]-=GRAVITY*SENSOR_SIGN[5];

  //Serial.println("Offset:");
  for(int y=0; y<6; y++)
    Serial.println(AN_OFFSET[y]);

  delay(2000);
  digitalWrite(STATUS_LED,HIGH);

  timer=millis();
  delay(20);
  counter=0;
 pinMode(buttonPin, INPUT);
Serial.println("Initializing SD card...");
  if(!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  myFile=SD.open("DATA.txt", FILE_WRITE);
  if (myFile) {
    Serial.println("File opened ok");
    myFile.println("Output of BMP180, DHT22");
  }
  myFile.close();
  if (!bmp.begin()) {
  Serial.println("Could not find a valid BMP085 sensor, check wiring!");
  while (1) {}
  }
}

void loop() //Main Loop
{
  buttonState = digitalRead(buttonPin);
  if(buttonState == HIGH){
      Serial.print("Temperature = ");
      Serial.print(bmp.readTemperature());
      Serial.println(" *C");
      Serial.print("Pressure = ");
      Serial.print(bmp.readPressure());
      Serial.println(" Pa");
      Serial.print("Altitude = ");
      Serial.print(bmp.readAltitude());
      Serial.println(" meters");
      Serial.print("Pressure at sealevel (calculated) = ");
      Serial.print(bmp.readSealevelPressure());
      Serial.println(" Pa");
      Serial.print("Real altitude = ");
      Serial.print(bmp.readAltitude(seaLevelPressure_hPa * 100));
      Serial.println(" meters");
      Serial.println();
      hum = dht.readHumidity();
      temp = dht.readTemperature();
      Serial.print("Humidity: ");
      Serial.print(hum);
      Serial.print(" %, Temp: ");
      Serial.print(temp);
      Serial.println(" Celsius");
      myFile = SD.open("DATA.txt", FILE_WRITE);
    if (myFile) {
      Serial.println("open with success");
      myFile.print(temp);
      myFile.println(",");
      myFile.print(hum);
    }
  myFile.close();
    delay(2000); 
  } 
  else{
    Serial.println("Error!!!");
  }
  if((millis()-timer)>=20)  // Main loop runs at 50Hz
  {
    counter++;
    timer_old = timer;
    timer=millis();
    if (timer>timer_old)
    {
      G_Dt = (timer-timer_old)/1000.0;    // Real time of loop run. We use this on the DCM algorithm (gyro integration time)
      if (G_Dt > 0.2)
        G_Dt = 0; // ignore integration times over 200 ms
    }
    else
      G_Dt = 0;



    // *** DCM algorithm
    // Data adquisition
    Read_Gyro();   // This read gyro data
    Read_Accel();     // Read I2C accelerometer

    if (counter > 5)  // Read compass data at 10Hz... (5 loop runs)
    {
      counter=0;
      Read_Compass();    // Read I2C magnetometer
      Compass_Heading(); // Calculate magnetic heading
    }

    // Calculations...
    Matrix_update();
    Normalize();
    Drift_correction();
    Euler_angles();
    // ***

    printdata();
  }

}

I2C is a bus - the whole point of a bus is that it can take multiple things.

On the I2C bus, they just connect in parallel:

The important thing is that each device must have a distinct address:

The so-called pullup resistors are an important part of I2C:

Use an I2C Scanner sketch to test that your devices are responding, and find what address(es) they are using:

Why do you believe it's an I2C problem?

1 Like

Hi,
Rather than try and use your main code, forget your code for the moment.
AND
Write some simple code to JUST communicate with ONE of the I2C devices say the BMP180, there are library examples that will help. AND get that working.
Just Google;

arduino and BMP180

THEN
Write some simple code to JUST communicate with the AltIMU, and get that working.
Just Google;

arduino and AltIMU-10 v5

THEN think about combining the two, WITHOUT your main code in the way.

This is called writing code in stages, getting each stage to work before going onto the next, it helps prevent major bugs and misdiagnosis of problems.
It also makes sure your hardware works and that you can communicate with it.

Tom.. :smiley: :+1: :coffee: :australia:

1 Like

@gantugsmk this is excellent advice!

But, before getting into actually reading the sensors, use a simple I2C scanner sketch - this will confirm (or not) that your hardware is working, and that you have the correct addresses for your sensors.

1 Like

So which is it: AltIMU-10 v5 or MinIMU-9 ?
:thinking:

Hi, I hope that you are not confused by the previous posts. This forum puts the text from a link in a light-gray box, if that link is on its own line. You can just click on that link and you don't have to read all the text below the link in the light-gray box.

Where is the rest of the code ? For example the function "I2C_Init()", "Accel_Init()", "printdata()", and so on.

This is wrong use of millis():

long timer = 0;     // must be unsigned long
long timer_old;     // must be unsigned long. this extra variable is not needed

void loop()
{
  ...
  if ((millis() - timer) >= 20)  // okay
  {
    timer_old = timer;
    timer = millis();   // okay
    if (timer > timer_old)  // bug
    {
      ...
    }
    else
    {
      ...
    }
  } 
}

If you do something with millis(), then use "unsigned long" variables.
Avoid the rollover problem in a mathematical way with: millis() - previousMillis
Trying to capture the rollover introduces a bug.

Have you read the Blink Without Delay page ? https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay

If you are using the number of elapsed millis in your sketch, then you can use that for the millis timer as well:

unsigned long previousMillis;

void loop()
{
  unsigned long currentMillis = millis();
  unsigned long elapsedMillis = currentMillis - previousMillis; // no rollover problem, always correct
   
  if (elapsedMillis >= 20)           // Main millis timer runs at 50Hz
  {
    previousMillis = currentMillis;  // update for the millis timer

    G_Dt = float(elapsedMillis) / 1000.0; 
    ...
  }
}

[UPDATE]
TomGeorge already wrote what I wanted to say. This is just an explanation about the use of millis().

Hi, @Koepel
Not sure what Millis has to do with reading 2 x I2C devices.

Tom.. :smiley: :+1: :coffee: :australia:

1 Like

I believe @Koepel is trying to correct the usage of millis() in the code, but you are right it isn't directly related to the 2 devices on i2c problem. :grin: :+1:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.