const byte MY_ADDRESS = x; // where x is whatever unique address you like
byte RxByte[32] //32 byte buffer
void setup() {
//insert unique ddress
Wire.begin(MY_ADDRESS);
// this line allows the arduino to listen for i2c broadcast at address 0
TWAR = (MY_ADDRESS << 1) | 1;
//set up a receive handler
Wire.onReceive(receive_data);
then call
Wire.beginTransmission (0) //transmit broadcast so all devices will receive
Wire.write( address of destination) // make the first byte the destination
Wire.endTransmission ();
then you need a receive handler
void receive_data() {
//use a buffer to temporarily store the data
for ( int d = 0; Wire.available() > 0 ;d++){
RxByte[d] = Wire.read();} // READ WIRE BUFFER UPTO 32BYTES, INTO AN ARRAY
datareceived = 1;
//then test if it was for this device
if (RxByte[0] == MYADDRESS){ do somthing with RxBytes[1-31];}
else {}
I use this extensively its very handy and works well I have a complex transmission table which has a 4 byte header and the rest of the bytes can be used as data send
destination, myaddress, a command, and how many data bytes to follow
Addendum to Original answer. below is a complete working example.
//so the basics of the tranmission table are the first 4 bytes (ie Rx or Tx byte 0-3 depending on if we are talking about the sender or recipient)
//are used as a header 0= recipient (0 for broadcast. or address) 1= senders address 2= is the command (ie tells the recipient what to do)
//and 4= the number of data bytes which follow in the packet
//not all of these need to be specified at any time but its usefull to have a structure to follow at each end which never changes
//copy and past this upload to 2 arduinos connected by i2c change the 2 addresses and it should work.
its a n example of how data can be moved around in a multi master situation
that should hopefully give you some ideas. it looks complicated but half of it is just generating some example data and triggering method and the transmit part is repeated 3 times to send out different data.. you should be able to create a more general purpose transmit block for your application
to send data just attach a button or wire to pin 2 directly to ground
watch the 2 serial windows
#include <Wire.h>
//device address MAKE DIFFERENT FOR EACH
const byte MY_ADDRESS = 20;
const byte PARTNER_DEVICE = 25;
// transmission table stuff
byte RxByte[32]; //setup a receive buffer to hold data
byte TxByte[32]; //setup a transmit buffer to hold data
byte datareceived;
// stuff to generate some data
const int Sensor1 = A0;
byte SensorVal1 = 0;
//stuff to debounce pin 2
const byte digitalpin = 2;
byte pinstate = 0;
byte lastpinstate = 0;
unsigned long checktime = 0;
const byte debouncetime = 50;
// timer
unsigned long timing_loop = 5000;
void setup() {
Wire.begin (MY_ADDRESS);
TWAR = (MY_ADDRESS << 1) | 1; // ENABLE BROADCASTS TO BE RECEIVED
Wire.onReceive(ReceiveData); // INTERUPT ON I2C DATA RECEIVE
Serial.begin(9600);
pinMode ( digitalpin , INPUT_PULLUP );// set the pin to input pullup so we can trigger the code by connecting directly to ground
Serial.println( "READY" );
}
void loop() {
// generate some random data
GenRandData();
//Serial.print( pinstate);Serial.print( " " );Serial.println( lastpinstate );
// debounces pin 2 so we can trigger a data broadcast
pinstate = digitalRead (digitalpin);
if ( pinstate != lastpinstate && millis() >= checktime) {
if ( pinstate == 0 && lastpinstate == 1 ) {
checktime = millis() + debouncetime;
Serial.println( " button working" );
REQUEST();
}
lastpinstate = pinstate ;
}
// this triggers the process data method after receive of data
if (datareceived == 1 ) {
datareceived = 0 ;
ProcessData();
}
// 10 second timer triggers transmission of some data
if ( millis() >= timing_loop ) {
BROADCAST();
}
}
void GenRandData() {
// this just reads analog0 and maps it to a byte then sequentially shifts the transmit buffer
SensorVal1 = random(255);
TxByte[7] = TxByte[6];
TxByte[6] = TxByte[5];
TxByte[5] = TxByte[4];
TxByte[4] = SensorVal1;
}
void ReceiveData() {
// READ AVAILABLE BYTES INTO 32BYTE BUFFER (while data is available)
for ( byte d = 0; Wire.available() > 0 ; d++) {
RxByte[d] = Wire.read();
}
//set a trigger event
datareceived = 1;
Serial.println( "receive" );
}
void ProcessData() {
Serial.println( "process" );
// check what the data is an who its for then do something with it (RECEIVE TABLE)
if (RxByte[0] == MY_ADDRESS) { // for this device
switch (RxByte[2]) {
case 1: Serial.print("RECEIVED DATA FOR THIS DEVICE, = "); Serial.println( RxByte[4] ); break;
case 255: Serial.println("RECEIVED A REQUEST FOR DATA, SENDING READ FROM > Sensor1" ); ActAsMaster(); break;
default: Serial.print("D-Type byte = error"); Serial.println(RxByte[2]); break;
}
}
else if (RxByte[0] == 0) { //handle broardcast
Serial.print( "RECEIVED BROADCAST FROM DEVICE = " ); Serial.println( RxByte[1] );
Serial.print( "DATASIZE = " ); Serial.print( RxByte[3] ); Serial.println( " Bytes" );
Serial.print( "DATABYTE 1 = " ); Serial.println( RxByte[4] );
Serial.print( "DATABYTE 2 = " ); Serial.println( RxByte[5] );
Serial.print( "DATABYTE 3 = " ); Serial.println( RxByte[6] );
Serial.print( "DATABYTE 4 = " ); Serial.println( RxByte[7] );
Serial.println( "DONE" );
}
Serial.println( );
}
void BROADCAST() {
// this is transmission table to send data to everyone
Serial.println("Sending broadcast");
byte count = 0;
byte errorcode;
Tx:
Wire.beginTransmission (0); // broadcast
Wire.write(0); // ADDRESS =0 BROARDCAST
Wire.write(MY_ADDRESS); // SEND my address
Wire.write(0); // DATA TYPE CODE
Wire.write(4); //number of bytes being sent
Wire.write(TxByte[4]); //data
Wire.write(TxByte[5]); //data
Wire.write(TxByte[6]); //data
Wire.write(TxByte[7]); //data
errorcode = Wire.endTransmission ();
if (errorcode != 0 && count <= 2) {
count++;
Serial.println( "fail" );
goto Tx;
}
//reset timer to run this again
timing_loop = millis() + 10000 ;
Serial.println( );
}
void ActAsMaster() {
//this is transmission table to send data to specific device OR return a result of a task
Serial.println("Sending data");
byte count = 0;
byte errorcode;
Tx:
Wire.beginTransmission (RxByte[1]); //the return address
Wire.write(RxByte[1]); //recipient address (return)
Wire.write(MY_ADDRESS); // SEND MASTER ADDRESS
Wire.write(1); // DATA TYPE CODE
Wire.write(1);
Wire.write(SensorVal1);
errorcode = Wire.endTransmission ();
if (errorcode != 0 && count <= 2) {
count++; // if fail and not exceed count try again
Serial.println( "fail" );
goto Tx;
}
Serial.println( );
}
void REQUEST() {
//this is transmission table to send data request of partner device
Serial.println("Sending request");
byte count = 0;
byte errorcode;
Tx:
Wire.beginTransmission (PARTNER_DEVICE); //the return address
Wire.write(PARTNER_DEVICE); //recipient address (return)
Wire.write(MY_ADDRESS); // SEND MASTER ADDRESS
Wire.write(255); // DATA TYPE CODE (MASTER ADDRESS)
Wire.write(0);
errorcode = Wire.endTransmission ();
if (errorcode != 0 && count <= 2) {
count++; // if fail and not exceed count try again
Serial.println( "fail" );
goto Tx;
}
Serial.println( );
}