Hello,
I am trying to communicate with 3 arduino UNO boards connected to each other via I2C bus. My setup is as follows:
- Master has an OLED.
- Slave 1 has a fingerprint device and a bluetooth connected to it.
- Slave 2 has a wifi module connected to it.
I am successfully communicating with the Master and Slave 1 back and forth via I2c bus. I need to communicate with Slave 2 after i finished communicating with the Slave 1.
Slave 1 has an address 3 and slave 2 has an address 2.
I am able to talk to the slaves using Wire.begin(2) and Wire.begin(3) separately. I want to implement both in the same file. First Wire.begin(3) gets executed and then it talks with slave 1(which i am successful), then after that i wrote Wire.beginTransmission(2) and wrote data to slave 2. But that data is not received on the slave side when i try to read it. I gives me a y with 2 dots which is empty data.
I have tried the following:
- This is my master UNO code
void setup()
{
//Finger print code here
Wire.begin(3); //Slave 1
Wire.onRequest(requestEvent); //This is for communicating with slave 1
Wire.onReceive(receiveEvent); ////This is for communicating with slave 1
delay(40000);
Serial.println("Channel 2..................");
Wire.beginTransmission(2); //talking to slave 2 -- i also tried Wire.begin(2)
Wire.write("w"); //writing to slave 2
Wire.endTransmission(); //ending the transmission
}
When i used Wire.begin(2) after Wire.begin(3) the wire.begin(3) doesn't work, it's like the last wire.begin executes. I introduced a delay so that my wire.begin(3) executes first and then i can move on to my slave 2. But it didn't work either.
I need to send commands to my second I2C device after i finished talking with first device. The master must change the wire.begin(3) to wire.begin(2). I am not sure where to call that change.
Any help?
dheerajdake:
Hello,
I am trying to communicate with 3 arduino UNO boards connected to each other via I2C bus. My setup is as follows:
- Master has an OLED.
- Slave 1 has a fingerprint device and a bluetooth connected to it.
- Slave 2 has a wifi module connected to it.
I am successfully communicating with the Master and Slave 1 back and forth via I2c bus. I need to communicate with Slave 2 after i finished communicating with the Slave 1.
Slave 1 has an address 3 and slave 2 has an address 2.
I am able to talk to the slaves using Wire.begin(2) and Wire.begin(3) separately. I want to implement both in the same file. First Wire.begin(3) gets executed and then it talks with slave 1(which i am successful), then after that i wrote Wire.beginTransmission(2) and wrote data to slave 2. But that data is not received on the slave side when i try to read it. I gives me a y with 2 dots which is empty data.
I need to send commands to my second I2C device after i finished talking with first device. The master must change the wire.begin(3) to wire.begin(2). I am not sure where to call that change.
Any help?
No, your code is not correct. Here is a simple master code:
// I2C Master Code
#include <Wire.h>
#define FIRSTSLAVE 0x10 // first Slave I2C address
#define LASTSLAVE 0x15 // Last Slave I2C address (0x15-0x10)+1 = 6 slaves
void setup(){
Serial.begin(9600); // debug monitor
Wire.begin(); // no number! passing a value to Wire.begin() assigns this Arduino as a SLAVE I2C device.
}
static uint8_t slave=FIRSTSLAVE-1; // initialize to first Slave I2C address
void loop(){
slave++; // increment to first slave
if(slave>LASTSLAVE) {
slave=FIRSTSLAVE; // start over at the beginning
delay(10000); //Delay so I can read the Serial monitor
}
uint8_t err;
Wire.beginTransmission(slave);
Wire.write((uint8_t)0); // some commands bytes that make sense for your program ...
Wire.write((uint8_t)1);
Wire.write((uint8_t)2);
Wire.write((uint8_t)3);
Wire.write((uint8_t)slave); // just because I want to verify the correct slave actually received it
err=Wire.endTransmission();
char ch[50];
if(err){ // if error is not zero
sprintf(ch,"\nSendid to Slave 0x%02x failed, error= %d",slave,err);
Serial.print(ch);
}
else { // slave accepted write, now lets see if I can get the info Back!
err=Wire.requestFrom(slave,6);
sprintf(ch,"\nRequest from Slave 0x%02X ",slave);
Serial.print(ch);
bool failed = false;
if(err==6){ // requestFrom will return the number of RequestBytes or Zero
uint8_t i = 0,b;
uint16_t tWord=0;
while(Wire.available()){
b=Wire.read();
switch(i){ // use a case statement to figure out where to store the byte
case 0 :
if(b!=0){ // first byte is Wrong!
Serial.print("bad First Byte ");
failed = true;
}
break;
case 1 :
if(b!=1){ // Second byte is Wrong!
Serial.print("bad Second Byte ");
failed = true;
}
break;
case 2 :
tWord = b;
break;
case 3 :
tWord = tWord | (uint16_t)b<<8; // build a word (16bit) from two bytes
if(tWord!=770) {
Serial.print(" Bad Word Value ");
failed = true;
}
break;
case 4 :
if(b!=slave){
Serial.print("bad Echo Slave ID ");
failed = true;
}
break;
case 5 :
if(b!=slave){
Serial.print("Bad Slave ID ");
failed = true;
}
default : ; // ignore any bytes past the fifth one.
}// case
i++;
}// while
}// if
else failed = true; // RequestFrom returned 0, marking a failure!
if(failed) Serial.println(" Failed!");
else Serial.println(" Succeeded!");
}
}
And the Matching slave code:
#include <Wire.h>
#define SLAVEID 0x10 // this is the value that must change for each slave!
struct MYSTRUCT{
uint8_t firstByte;
uint8_t secondByte;
uint16_t aWord;
char c;
uint8_t slaveI2Caddr; // a sneeky sixth byte that you have to ask for
};
volatile MYSTRUCT m; // volatile because it will be accessed during an interrupt.
volatile bool receiveFlag=false;
volatile bool requestFlag = false;
volatile uint8_t receiveCnt;
void onRequestEvent(){ // This function is call when the Master uses requestFrom().
// only ONE (1) Wire.write() call can be used
//but I want to send upto 6 bytes back irrespective of how many bytes the master actually reads?
Wire.write((uint8_t*)&m,6); // fake the compiler into thinking m is a pointer to a byte array
requestFlag = true; // I want to send a message out the serial port but Interrupt routines
// need to be really fast, and not call any library calls, so I set a flag and process it in the LOOP()
}
void onReceiveEvent(int howMany){ // this function is call when the Master Sends Data
uint8_t i=0,b; //
while(Wire.available()){
b= Wire.read();
switch(i){ // use a case statement to figure out where to store the byte
case 0 :
m.firstByte = b;
break;
case 1 :
m.secondByte = b;
break;
case 2 :
m.aWord = b;
break;
case 3 :
m.aWord = m.aWord | (uint16_t)b<<8; // build a word (16bit) from two bytes
break;
case 4 :
m.c = b;
break;
default : ; // ignore any bytes past the fifth one.
}// case
i++;
}// Wire.avail()
if(!receiveFlag){
receiveFlag = true;
receiveCnt = i;
}
}
void setup(){
Serial.begin(9600); // for debug monitor
Wire.begin(SLAVEID);
Wire.onReceive(onReceiveEvent);
Wire.onRequest(onRequestEvent);
m.slaveI2Caddr = SLAVEID;
}
void loop(){
if(receiveFlag){
Serial.print(" R=");
Serial.print(receiveCnt,DEC);
receiveFlag = false; // clear
}
if(requestFlag){
requestFlag = false;
Serial.print(" T");
}
}
Chuck.