2 sensors and I2C

Hi,
I want to read the data from 2 differents photoresistor connected to the same Arduino slave. I was able to receive the data from 1 photoresistor using the code below , but I don’t know if it is possible with 2. (I would monitor the 2 data separatly) .

I just want to know if it is possible and if yes, maybe just an example or a link that would explains the concept. Thank you!!

Arduino Slave:

#include <Wire.h>

int IRead1 = 3; 
int ORead1=0;

void setup()
{
  Wire.begin(4);                // join i2c bus with address #2
  Wire.onRequest(requestEvent); // register event
}

void loop()
{
  ORead1 = analogRead(IRead1)/ 4;
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
  
  Wire.write(ORead1); 
}

So you have an Arduino as I2C slave ? And the photoresistors are connected to the slave ?

You have to write two bytes, and the master has to read two bytes. Nick Gammon has an example for multiple bytes, http://www.gammon.com.au/forum/?id=10896

So you have an Arduino as I2C slave ?

Yes

And the photoresistors are connected to the slave ?

Yes

You have to write two bytes, and the master has to read two bytes. Nick Gammon has an example for multiple bytes, http://www.gammon.com.au/forum/?id=10896

Thank you!! I will give it a try.

Ok, I looked at the site and I presume this is the part you pointed me out:

// Written by Nick Gammon
// February 2011

#include <Wire.h>

const byte MY_ADDRESS = 42;   // me
const byte LED = 13;          // LED is on pin 13

byte ledVal = 0;

void receiveEvent (int howMany)
 {
 
 // we are expecting 2 bytes, so check we got them
 if (howMany == 2)
   {
   int result;
   
   result = Wire.read ();
   result <<= 8;
   result |= Wire.read ();
 
   // do something with result here ...
  
   // for example, flash the LED  
    
   digitalWrite (LED, ledVal ^= 1);   // flash the LED
     
   }  // end if 2 bytes were sent to us

  // throw away any garbage
  while (Wire.available () > 0) 
    Wire.read ();

  }  // end of receiveEvent

void setup () 
  {
  Wire.begin (MY_ADDRESS);  // initialize hardware registers etc.

  TWAR = (MY_ADDRESS << 1) | 1;  // enable broadcasts to be received

  Wire.onReceive(receiveEvent);  // set up receive handler
  pinMode(LED, OUTPUT);          // for debugging, allow LED to be flashed
  }  // end of setup

void loop () 
  {
  }  // end of loop

Even thought the slave is receiving information, the idea should be the same. is it what I should try to understand??

I show you my own code. The Master code does not check for errors yet.
It is the same as Nick Gammon’s “Request/response” part, Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino
But we use a different approach.

The explanation is in the files below.
If something is not clear, please post your comments.

The Master:

// -------------------------------------------------------
//
//  I2C Master-Slave between 2 Arduino boards
//  The Slave behaves like a sensor, the simulated registers
//  can be read and written via I2C.
//
//  MASTER
//  -------
//  Arduino 1.5.2
//

// There are a few ways to read data from an Arduino as I2C slave.
// (1) For example the I2C Slave could receive a command from the Master,
//     to become a Master itself in a new session and send data to
//     the requesting Master.
// (2) The I2C Slave could return the data during the same session,
//     as with most hardware I2C devices.
//     However the number of requested bytes is not known,
//     so all the data is send as one block of data.
//     This example is for this option.
// 

#include <Wire.h>

const int SLAVE_ADDRESS = 42;

void setup()
{      
  Serial.begin(9600);
  Serial.println(F("I2C Master"));
  
  Wire.begin();
}


void loop() 
{
  char c;
 
  delay( 2000);
  
  // Read signature
  Wire.requestFrom( SLAVE_ADDRESS, 1);
  c = Wire.read(); // receive a byte as character
  Serial.print( "Signature :");
  Serial.println( c, HEX);
  
  delay( 2000);
  
  // Read all 8 registers
  Serial.println( "Read all registers");
  Wire.requestFrom( SLAVE_ADDRESS, 8);
  while( Wire.available())   // slave may send less than requested
  {
    char c = Wire.read();    // receive a byte as character
    Serial.print( c);        // print the character
  }
  Serial.println();

  delay (2000);
  
  // Write 2 bytes.
  // It is possible to write 1 or more bytes.
  Serial.println( "Write two bytes to [6] and [7]");
  Wire.beginTransmission( SLAVE_ADDRESS);
  Wire.write( 6);            // register address.
  Wire.write( 'X');
  Wire.write( 'Y');
  Wire.endTransmission();

  delay (2000);

  // Read all 8 registers
  Serial.println( "Read all registers");

  Wire.requestFrom( SLAVE_ADDRESS, 8);
  while( Wire.available())   // slave may send less than requested
  {
    char c = Wire.read();    // receive a byte as character
    Serial.print( c);        // print the character
  }
  Serial.println();

  delay(2000);
}

The Slave (like a simulated I2C sensor):

// -------------------------------------------------------
//
//  I2C Master-Slave between 2 Arduino boards
//  The Slave behaves like a sensor, the simulated registers
//  can be read and written via I2C.
//
//  SLAVE
//  ------
//  Arduino 1.5.2
//


// Create a I2C slave device that acts as a sensor:
//    Writing is to a one or more registers
//       format: I2C-address, register-addres, data0, ...
//    Reading is only the full 8 bytes.
//       format: I2C-addres, data0, ... data7.
//
// With the Arduino libraries, the slave don't know how many
// bytes are requested. 
// That makes it impossible to read a one or more bytes,
// starting from a specific registers address.

#include <Wire.h>

const byte MY_ADDRESS = 42;

// The simulated registers of the I2C slave device
// It could be filled with status, sensors, temperatures and so on.
// It can also be written with commands, offsets, and so on.
// The first byte is the signature and is 0x55
// In this example, only register [4] to [7] can be written.
byte i2c_reg[8];

// The reg_address is a global variable.
// It could be set to be used to read data.
byte reg_address;

void setup()
{      
  Serial.begin( 9600);
  Serial.println( F("I2C Slave"));
  
  // fill with dummy data
  i2c_reg[0] = 0x55;   // 'signature' 0x55 = 'U'
  i2c_reg[1] = 'A';          
  i2c_reg[2] = 'G';
  i2c_reg[3] = 'C';
  i2c_reg[4] = 'D';    // first writable register
  i2c_reg[5] = 'E';
  i2c_reg[6] = 'F';
  i2c_reg[7] = 'G';
  
  reg_address = 0;     // global variable, default to 0
  
  Wire.begin( MY_ADDRESS);
  Wire.onReceive( receiveEvent);
  Wire.onRequest( requestEvent);
}


void loop() 
{
}


// called by interrupt service routine when incoming data arrives
void receiveEvent (int howMany)
{
  // The Slave is receiving data.
  // It can be one byte or more.
  // The second parameter is used as the addres of the register to write.
  
  byte data;
  
  // At least the register address is needed.
  if (howMany >= 1)
  {
    reg_address = Wire.read();
    howMany--;
  }
  
  while( howMany > 0)
  {    
    // Be sure to read all data from buffer.
    // Even if it is discarded.
    data = Wire.read();
    howMany--;

    // For this example, only registers [4] to [7] can be written.
    // The registers [0] to [3] are therefor write protected.
    if (reg_address >= 4 && reg_address <= 7)
    {
      i2c_reg[reg_address] = data;
      reg_address++;
    }
  }
}


void requestEvent (void)
{
  // Slave transmitter mode.
  // The Master is requesting data from the slave.
  // The whole 8 simulated registers are returned.
  
  // IMPORTANT:
  //   Use a single Wire.write() call with a buffer.
  //   If seperate Wire.write() are used for each byte,
  //   only the last byte received by the Master is valid.
  
  // The reg_address could be the register address to be read.
  // But that is not used now, since the amount of requested bytes
  // is not known.
  Wire.write( i2c_reg, 8);
}

I don't see any problem with writing 8 bytes. They will be put in a buffer, and if the master doesn't want all 8 then the communication will be dropped before they are all sent.

[quote author=Nick Gammon link=topic=156639.msg1173854#msg1173854 date=1364347271] I don't see any problem with writing 8 bytes. They will be put in a buffer, and if the master doesn't want all 8 then the communication will be dropped before they are all sent. [/quote] Thank you.

If I would like to read 100 bytes, I have to remember that the I2C buffer is only 32 bytes. In that situation I have to use something like 'pages' of 16 bytes and use the way you send commands to select the 'page'.

@playagood, A library EasyTransfer can transfer data over serial, i2c, wireless, https://github.com/madsci1016/Arduino-EasyTransfer Perhaps that is easier for you to use ?