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);
}
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, http://gammon.com.au/i2c#reply4
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.
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'.