I2C bus help

I want to use two SCL and SDA devices, I've got the I2C all set up and its working, I2C scanner identifies them both. I know their addresses, can I just take my previous code and tell it that "hey, that device is at this address" instead of having to completely rewrite the code just because I want to add another device?

Basically, all I want to do is tell my Arduino that the BMP180 is at 0x77. Is there any way of doing this?

//SD card stuff
#include <SD.h>
#include <SPI.h>
File myFile;
int pinCS = 10; 


#include <SFE_BMP180.h>
#include <Wire.h>
SFE_BMP180 pressure;

double baseline; // baseline pressure

void setup()
{
  Serial.begin(9600);
  Serial.println("REBOOT");



  if (pressure.begin())
    Serial.println("BMP180 init success");
  else
  {
    Serial.println("BMP180 init fail (disconnected?)\n\n");
    while(1); // Pause forever.
  }

  // Get the baseline pressure:
  
  baseline = getPressure();
  
  Serial.print("baseline pressure: ");
  Serial.print(baseline);
  Serial.println(" mb");  



  //SD CARD 
  pinMode(pinCS, OUTPUT);
  if (SD.begin()){
    Serial.println("SD card is ready to use.");
  } else{
    Serial.println("SD card initialization failed");
    return;
  }
  if(SD.exists("Altitude.txt")){
   SD.remove("Altitude.txt");
}
}


void loop()
{
  double a,P;
  
 

  P = getPressure();

  a = pressure.altitude(P,baseline);
  
  Serial.print("relative altitude: ");
  
  if (a >= 0.0) Serial.print(" "); // add a space for positive numbers
  Serial.print(a*3.28084,0);
  Serial.println(" feet");

  //SD CARD
myFile = SD.open("Altitude.txt", FILE_WRITE);

    
  if (myFile) {
        myFile.println(a*3.28084,0);
        myFile.close();
  }
  else 
  {
    Serial.println("error opening test.txt");
  }
  
  delay(250);
}


double getPressure()
{
  char status;
  double T,P,p0,a;



  status = pressure.startTemperature();
  if (status != 0)
  {
   

    delay(status);


    status = pressure.getTemperature(T);
    if (status != 0)
    {


      status = pressure.startPressure(3);
      if (status != 0)
      {
        
        delay(status);

        

        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          return(P);
        }
        else Serial.println("error retrieving pressure measurement\n");
      }
      else Serial.println("error starting pressure measurement\n");
    }
    else Serial.println("error retrieving temperature measurement\n");
  }
  else Serial.println("error starting temperature measurement\n");
}

What is the second device?

The BMP180 library that you use has the BMP address hardcoded as 0x77; so you don't need to do anything unless you have another BMP180 with a different address.

To elaborate

I've downloaded the library from GitHub - LowPowerLab/SFE_BMP180: BMP180 Bosch sensor library; if that's the same one that you use, you can continue reading. Else you need to provide a link to the library that you use.

SFE_BMP180.h

#define BMP180_ADDR 0x77 // 7-bit address

An example of the function that uses that address is writeBytes
SFE_BMP180.cpp

char SFE_BMP180::writeBytes(unsigned char *values, char length)
// Write an array of bytes to device
// values: external array of data to write. Put starting register in values[0].
// length: number of bytes to write
{
	char x;

	Wire.beginTransmission(BMP180_ADDR);
	Wire.write(values,length);
	_error = Wire.endTransmission();
	if (_error == 0)
		return(1);
	else
		return(0);
}

Note the BMP180_ADDR used in the wire.beginTransmission().

sterretje:
To elaborate

I've downloaded the library from GitHub - LowPowerLab/SFE_BMP180: BMP180 Bosch sensor library; if that's the same one that you use, you can continue reading. Else you need to provide a link to the library that you use.

SFE_BMP180.h

#define BMP180_ADDR 0x77 // 7-bit address

An example of the function that uses that address is writeBytes
SFE_BMP180.cpp

char SFE_BMP180::writeBytes(unsigned char *values, char length)

// Write an array of bytes to device
// values: external array of data to write. Put starting register in values[0].
// length: number of bytes to write
{
char x;

Wire.beginTransmission(BMP180_ADDR);
Wire.write(values,length);
_error = Wire.endTransmission();
if (_error == 0)
return(1);
else
return(0);
}



Note the *BMP180_ADDR* used in the wire.beginTransmission().

My second device is the gy-521 accelerometer.

So do I have to write in the code that you wrote? With the "Wire.beginTransmission();" and all that? Or do I just put "#define BMP180_ADDR 0x77"?

I'm very much a noob at this, I was confused by other I2C tutorials because they made it seem like you had to completely rewrite your code just to extract the information through Wire.write or something. Why can't I just take my same code but tell it what the addresses are for the devices? Why do I have to "beginTransmission" and all that? Thanks.

You don't have to do anything for the.BMP.; just leave that as it is.

What I showed is in the library.

sterretje:

#define BMP180_ADDR 0x77 // 7-bit address

Once, I was asked by a Trainer to find the 7-bit address from 0x77. In response, I expanded the code to 01110111 as it is given in hex format. I was confused about which 7-bit to accept -- 0111011 or 1110111. From that time, I always put my device address in this form: 0b1110111.

sterretje:
You don't have to do anything for the.BMP.; just leave that as it is.

What I showed is in the library.

Oh wow it does just work lol Thank you. So will it work like this for the accelerometer too? How did you know that it would work without having to do anything?

EDIT: Oh right it was in the library. I will find the library that I will use for my GY-521 and show it to you. Unless you can explain how to see if the library does it. That is in the .cpp thing right?

GolamMostafa:
Once, I was asked by a Trainer to find the 7-bit address from 0x77. In response, I expanded the code to 01110111 as it is given in hex format. I was confused about which 7-bit to accept -- 0111011 or 1110111. From that time, I always put my device address in this form: 0b1110111.

That doesn't make a lick of sense to this noob lol Sounds cool though :slight_smile:

Look at the examples for the accelerometer. Maybe it takes an argument in the begin() method to specify the address or maybe not. It does not matter too much how it's implemented unless it needs to be changed.

Post the link to the library if you don't come right.

sterretje:
Look at the examples for the accelerometer. Maybe it takes an argument in the begin() method to specify the address or maybe not. It does not matter too much how it's implemented unless it needs to be changed.

Post the link to the library if you don't come right.

This will probably be the one I use.

GolamMostafa:
Once, I was asked by a Trainer to find the 7-bit address from 0x77. In response, I expanded the code to 01110111 as it is given in hex format. I was confused about which 7-bit to accept -- 0111011 or 1110111. From that time, I always put my device address in this form: 0b1110111.

Trivial considering the value is going to be stored as an 8-bit word in memory anyway...

sterretje:
Look at the examples for the accelerometer. Maybe it takes an argument in the begin() method to specify the address or maybe not. It does not matter too much how it's implemented unless it needs to be changed.

Post the link to the library if you don't come right.

Also, it says you are an electrical engineer? Could you help me with the pull-up resistors? I have no idea what I'm doing, I found somewhere in the BMP180 datasheet that it needs 4.7 Kohm so I put a couple 5 kohm resistors on. I know the gy-521 doesn't need pull-up resistors, so is this necessary? Some videos made it seem like it wasn't important, others made it seem like you needed a specific amount depending on the devices in the bus.

Power_Broker:
Trivial considering the value is going to be stored as an 8-bit word in memory anyway...

You mean that the address is queued/stored as: 01110111 and during data movement from Master to Slave (write mode), the value is shifted to the left by 1-bit position and then ANDed with 11111110. While reading data from Slave (read mode), the original queued value is again shifted to the left by 1-bit position and is ORed with 00000001.

Tristan234567:
Also, it says you are an electrical engineer? Could you help me with the pull-up resistors? I have no idea what I'm doing, I found somewhere in the BMP180 datasheet that it needs 4.7 Kohm so I put a couple 5 kohm resistors on. I know the gy-521 doesn't need pull-up resistors, so is this necessary? Some videos made it seem like it wasn't important, others made it seem like you needed a specific amount depending on the devices in the bus.

You must also read the rest of my signature :wink: To my knowledge (but it might be wrong)

Yes, you need pull-up resistors on the bus, no question about that.
2)
You only need one set of pull-up resistors unless you put a lot of I2C devices on one bus (two devices is not a lot). If your devices are both detected while on the bus at the same time with your current setup, you should not experience problems with your current setup. You can not endlessly keep on adding pull-up resistors (or use lower values (e.g. 2x5K in parallel will give 2.5K) as you will eventually overload the I2C pins on the microcontroller).
3)
If you use an AVR micro (e.g. 328P on Uno, Nano or Pro Mini), there are built-in pull-up resistors on the I2C bus; you might not need the external ones but they don't hurt.

GolamMostafa:
Once, I was asked by a Trainer to find the 7-bit address from 0x77. In response, I expanded the code to 01110111 as it is given in hex format. I was confused about which 7-bit to accept -- 0111011 or 1110111. From that time, I always put my device address in this form: 0b1110111.

0111011 will never read 0x77. Needlessly complicated to use 0b1110111.

GolamMostafa:
You mean that the address is queued/stored as: 01110111 and during data movement from Master to Slave (write mode), the value is shifted to the left by 1-bit position and then ANDed with 11111110. While reading data from Slave (read mode), the original queued value is again shifted to the left by 1-bit position and is ORed with 00000001.

The address is indeed stored as the specified address (not shifted). You can look at twi_writeTo and twi_readFrom in twi.c how it's further implemented.