I2C 3X 328p +3X Sensors [HELP]

I know this is a long post but it’s important for me so please give a try reading this post
and help as you can.

So 1st because I knew people would ask me for a diagram or something I designed fast on paint
a exact circuit that I want to make/build.

If you looked the picture you already know what approximately I want to make but let me explain,
I want to use:

3x ATmega328p (1x Master(transmitting) and 2x Slaves only receiving).
3x Sensors :

Now I want to have the [HMC5883L] and [BMP180] being connected (code) to Master and Master transmitting to Slave#1 and Slave#2, [MPU6050] connected to Slave#1.
I want as well the Master communicating with the Slave#1 (just transmitting) data to be processed.

The tutorials that I followed are:
#1. http://tronixstuff.com/2010/10/20/tutorial-arduino-and-the-i2c-bus/
#2. How I2C Communication Works and How To Use It with Arduino - YouTube

Because it’s my 1st time ever using more than 2x devices in I2C I gave a try 1st to write a code receiving data from a sensor using addresses and registers:


#include "Wire.h"
#define BMP180_address 0x77

#define Temperature_Register 0x2E
#define Pressure_Register 0x34

int x1,x2;

void setup(){

void BMP180(){
    x1 = Wire.read();
    x2 = Wire.read();
  Serial.print(" , ");

void loop(){

Datasheet page 20~21:

but I got a problem and in my serial.print i get only 0,0 for unknown reason I don’t get any data from the sensor / module BMP180.

I2C requires pull up resistors? some devices (sensors etc) have them included others don’t


Your diagram didn’t show any pull up resistors could this be an issue?

Your diagram didn't show any pull up resistors could this be an issue?

Well as I said bellow in my previous comment I test only one sensor as a start to learn about the I2C which I don't think a pullup resistors are the problem for a single device/module [BMP180] I tested the BMP180 library and it's working fine but when I try to do it the I2C way it's not working. I don't receive any kind of data back.

Btw is there a possible way to use the already libraries instead reinventing the wheel ? :D

Btw is there a possible way to use the already libraries instead reinventing the wheel ? :smiley:


#include <Wire.h>
#include <HMC5883L.h>
#include <I2Cdev.h>
#include <MPU6050.h>
#include <SFE_BMP180.h>

// all libraries are included now

// use example code provided with each libraries to get data from each sensor

So I’m kinda exited that it’s working :smiley:

Instead of reinventing the wheel and using I2C, pull up resistors …etc Why not using the same libraries that
we have been using till now?

Making a new I2C addresses, registers it’s kinda exhausting, the libraries of the modules already done that job, so I opened the libraries and saw exactly what a user need to do to get the data and calculate the same thing, why reinventing the wheel when you already got them?

So what I have done?
Using normal examples, I used BMP180 with BMP085 lib. and HMC5883L connected to the same I2C, I got the necessary code, created some functions and put them in the way to receive data only in a way that will allow the sensor to open receive data and close so letting the I2C clear / free for the next sensor.

Here is my code:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>   
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);

#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

void setup(void) 
    Serial.print("Ooops, no BMP085 detected ... Check your wiring or I2C ADDR!");
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");

void BMP_180(){
    sensors_event_t event;

  if (event.pressure)
    Serial.print("Pressure:    ");
    Serial.println(" hPa");
    float temperature;
    Serial.print("Temperature: ");
    Serial.println(" C");

    float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
    Serial.print("Altitude:    "); 
    Serial.println(" m");
    Serial.println("Sensor error");

void Compas(){
  sensors_event_t event; 
  Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print("  ");
  Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print("  ");
  Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print("  ");Serial.println("uT");

  float heading = atan2(event.magnetic.y, event.magnetic.x);
  float declinationAngle = 0.22;
  heading += declinationAngle;
  if(heading < 0)
    heading += 2*PI;
  if(heading > 2*PI)
    heading -= 2*PI;
  // Convert radians to degrees for readability.
  float headingDegrees = heading * 180/M_PI; 
  Serial.print("Heading (degrees): "); Serial.println(headingDegrees);

void loop() {


and here to prove that it’s actually working and I’m not joking :smiley:

Now what’s left is to learn how to use Master and Slave in I2C, btw does it still needs pullup resistors?

I think the mpu6050 has them already attached no you don’t need extras. looks great
to talk to other arduinos I use this code:

#include <Wire.h>
void setup()
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(115200);  // start serial for output
void loop()
  int count = 0;
  uint16_t data[16];
  Wire.requestFrom(0x2A, 30);    // request 6 bytes from slave device #2
  bool msb = true; // starts with MSB, then LSB
  for (; Wire.available() ;) {
    if (msb) {
      data[count] = Wire.read() << 8; // first byte is bits 15-8 (MSb=15)
    else {
      data[count++] |= Wire.read(); // second byte is bits 7-0 (LSb=0)
    msb = !msb;
  for (int i = 0; i < 15; i++) if(data[i]){


#include <Wire.h>
#define SLAVE_ADDRESS 0x2A // define slave address (0x2A = 42 [the answer to the ultimate question of life, the universe, and everything ;)] )

#define DisplayTimeDelay 50     // wait this long before sending serial output

unsigned long Timer, DisplayTimer; // Delay timers

int Measurements[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

int SerialEvent = 0;
int I2CsendDataGo = 0;
uint8_t dataB[32] ; // Max Wire library buffer size
unsigned long  i2cLive = 0;
// port change Interrupt

void serialEvent() {
void setup() {
  // initialize i2c as slave
  pinMode(2, OUTPUT);
  pinMode(13, OUTPUT);
  DisplayTimer = millis();

void loop() {
  Timer = millis(); // required for all general timing events!
  if (SerialEvent) SendSerialData();
  if (I2CsendDataGo)I2CsendData();
void RadarOut( int Degrees) {
  //Serial.print("Radar Out ");
  static int x = 0;
  static bool xz = true;
  static byte SensorCount = 8;
  static byte ii = 0;
  int deg = Degrees / SensorCount;
  ii = 0;
  while (ii < 8) {

    Serial.print((ii * deg) );
  //  Serial.print("*");


// callback for received data
void receiveData(int byteCount)
  String requestCommand = "";
  while (Wire.available())
    requestCommand = requestCommand + (char)Wire.read();
void sendData()
  I2CsendDataGo ++;
// callback for sending data
void I2CsendData()
  I2CsendDataGo = 0;
  i2cLive = Timer + 3000;// Stop Serial output for 3 Seconde after last i2c Request
  Wire.write(dataB, 30); // respond with message
  digitalWrite(13, !digitalRead(13));
  // as expected by master
  // Serial.println("Data Sent");
uint8_t DataMessage() {

  int x = 0;
  for (int i = 0; i < 15; i++ ) {
    dataB[x] = (uint8_t)(Measurements[i] >> 8);
    dataB[x] = (uint8_t)Measurements[i];
void SendSerialData()
  SerialEvent = 0;
  int val = Serial.read() - '0';
  while (Serial.available())Serial.read();
  if (val == 0) {
    Serial.write(dataB, 30); // respond with message
  } else  if (val == 1){
    RadarOut( 360);

Sorry i may have left code in that isn’t relevant The full code wouldn’t fit in the post… I wanted to send working example… The slave code will switch to I2C from serial if a master device requests data.

slave address 42 :D btw a master doesn't needs address ?

I will take a look at your code and make a small example.

I knew you took your code from somewhere so i gave a try to follow it and used this arduino example as well https://www.arduino.cc/en/Tutorial/MasterWriter

Now I'm not sure how exactly gonna my sensors and transmitting data from one atemga to another so I thought about:

If I use sensors to read the data from them with I2C and use Time as a way to read one by one the sensor each 100ms(sensor1), 200ms(sensor2), 300ms(sensor3) then why not dividing the time and use all sensors and data that I need to transmit as a clock, what I mean?

I need to transmit data from Master to slave 1 and slave 2 as well need to receive data from 3x sensors.

So... = 5x function/tasks of receiving and transmitting if we take 1000ms (1sec) dividing it by 5 = 200ms so if we take the 3x sensors, we have as follow: Sensor 1 = 200ms Sensor 2 = 400ms Sensor 3 = 600ms Master (TX_Slave#1) = 800ms Master (TX_Slave#2) = 1000ms

Gonna manually synchronize and do the tasks one by one, so every sensor or RX/TX will have the I2C free 200ms to communicate freely without any problem.

I hope my theory gonna work.

Btw here is my work of this topic today, I2C working well.