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:

BMP180:
Code:

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

#define Temperature_Register 0x2E
#define Pressure_Register 0x34

int x1,x2;

void setup(){
  Wire.begin();
  Serial.begin(9600);  
  
}

void BMP180(){
  Wire.beginTransmission(BMP180_address);
  Wire.write(0);
  Wire.write(Temperature_Register);
  Wire.write(Pressure_Register);
  Wire.endTransmission();
  
  Wire.requestFrom(BMP180_address,2);
  if(Wire.available()<=2){
    x1 = Wire.read();
    x2 = Wire.read();
  }
  Serial.print(x1);
  Serial.print(" , ");
  Serial.println(x2);
  delay(1000);
}

void loop(){
    BMP180();
}

Datasheet page 20~21:
https://www.vssec.vic.edu.au/media/41229/BMP180-datasheet.pdf

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


http://www.robot-electronics.co.uk/i2c-tutorial

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:

yes

#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.begin(9600);
  if(!bmp.begin())
  {    
    Serial.print("Ooops, no BMP085 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
    if(!mag.begin())
  {
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
}

void BMP_180(){
    sensors_event_t event;
  bmp.getEvent(&event);
 

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

    float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
    Serial.print("Altitude:    "); 
    Serial.print(bmp.pressureToAltitude(seaLevelPressure,
                                        event.pressure)); 
    Serial.println(" m");
    Serial.println("");
  }
  else
  {
    Serial.println("Sensor error");
  }
}

void Compas(){
  sensors_event_t event; 
  mag.getEvent(&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() {

  BMP_180();
  delay(1000);
  Compas();
  delay(1000);
}

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:
Master:

#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]){
    Serial.print(data[i]);
    Serial.print("\t");
  }
  Serial.println();
  delay(10);
}

Slave:

#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() {
  SerialEvent++;
}
void setup() {
  // initialize i2c as slave
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
  Serial.begin(115200);
  Serial.println("Hello");
  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(",");
    Serial.print(Measurements[ii]);
    Serial.print(".");
    ii++;
  }
  //  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
  DataMessage();
  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);
    x++;
    dataB[x] = (uint8_t)Measurements[i];
    x++;
  }
}
void SendSerialData()
{
  SerialEvent = 0;
  int val = Serial.read() - '0';
  while (Serial.available())Serial.read();
  if (val == 0) {
    DataMessage();
    Serial.write(dataB, 30); // respond with message
  } else  if (val == 1){
    RadarOut( 360);
    Serial.println();
  }
}

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.

https://www.youtube.com/watch?v=MN3M7Ch6LvE

D.60