I2C protocol + Serial comminication

Hi,
I am trying to let two boards communicate with each other using serial communication through 12C communication pins. The boards are Arduino UNO and Adafruit Feather 32u4 board.
I connected A5 pin of Arduino UNO to SCL pin of Adafruit Feather 32u4 board and I connected A4 pin of Arduino UNO to SDL pin of Adafruit Feather 32u4 board.
Then I wrote my code as I can write a message on the serial monitor and this message was received to the Arduino UNO and displayed on the serial monitor as well as Arduino UNO can do the same things. By the way, both boards were coded to work as slave and master. But while I uploaded the code to both boards through different Arduino IDE the boards stopped receiving and transmitting data. If anyone way please explain to me...

Arduino UNO Code

#include <Wire.h>
String msgArd;
void setup() {
  Wire.begin(8);     
  Serial.begin(9600); 
Wire.onRequest(requestEvent);
}

void loop() {
//Recevie response from slave (LORA)
    Wire.requestFrom(9,10);    
  while (0<Wire.available()) { 
      char c = Wire.read(); 
       Serial.print(c);       
    }
Serial.println();
  delay(500);
 }
void requestEvent(){
  //Send request to slave
  msgArd=Serial.readStringUntil('\n');
    int len = msgArd.length() + 1; 

// Prepare the character array (the buffer) 
char buff[len];

  msgArd.toCharArray(buff, len);//buf=to copy the characters into (char []),len=size
  Wire.write(buff); // respond with message of 6 bytes
  
}

Adafruit Feather 32u4 board Code

#include <Wire.h>
String msgLora;
void setup() {
    Serial.begin(9600); 
  Wire.begin(9);             
  Wire.onRequest(requestEvent);
}

void loop() {
     Wire.requestFrom(8, 13); 
  while (0<Wire.available()) { 
     char c = Wire.read(); 
   Serial.print(c);   
    
  }
Serial.println();
  delay(500);
}
void requestEvent() {
  if(Serial1.available()){
    msgLora=Serial1.readStringUntil('\n');
    int len = msgLora.length() + 1; 
char buf[len];
  msgLora.toCharArray(buf, len);
  Wire.write(buf); 
  
  }
 
}

Your post was MOVED to its current location as it is more suitable.

Please post both of your sketches here following the advice given in the link below about posting code , use code tags when posting the code to make it easier to read and copy for examination

The Arduino Uno is a 5V board with a 5V I2C bus (the SDA and SCL signals are 0V or 5V).
The Feather 32U4 is a 3.3V board with a 3.3V I2C bus.
That means you have a voltage mismatch on the I2C bus, you may not ignore that.

If both do a Wire.requestFrom(), then both are a Master. That will not work. Make one board the Master.

The requestEvent() function is called from a interrupt routine. Keep it as small and as fast as possible.
Try to rewrite that function without using Serial functions or String objects.

Explanation:
The requestEvent() is called from a interrupt routine, because the Wire library is interrupt driven. The whole Wire library is around a interrupt routine that handles all the different situations. The Serial library also uses interrupts to read and write data. You can not use those Serial interrupts while in a interrupt routine. The Serial.readStringUntil() waits until the LineFeed is received or until a timeout. That means it waits in a interrupt routine. That halts the sketch, nothing will work anymore.

@albusaitidi
1. If you are learning I2C Based Serial Data Communication, then connect two compatiable Arduinos (UNO-UNO or UNO-NANO or UNO-MEGA). Fig-1 shown below may help you to connect UNO (Master) and NANO (Slave).


Figure-1:

2. Remember that it is the Master whcih always generates the SCL (Serial Clock PUlse). Follow @Koepel suggeation of Post-3 and operate UNO as Master and NANO as Slave.

3. Example: Write sketches for both Master and Slave of Fig-1; where Master requests Slave to send Temperature Signal of LM35, which when received is displayed on Serial Monitor-1 (SM1).

Did you forget to connect the GND pin of the UNO to the GND pin of the Feather? The SCL and SDA pins are relative to GND so the two devices have to share a ground. They would do that if they were both connected to the same laptop but they may not if they are connected to separate laptops.

Why I can not let both boards work as master and slave at the same time or u said that because I used the Serial function?
Since I typed the attached code and It worked correctly where Arduino UNO can send messages to the other board as well as it well-received message from the Adafruit Feather 32u4 board Code. And it is the same things happened in the other board code

Arduino Code

#include <Wire.h>
String msgArd;
void setup() {
Wire.begin(8);     
Serial.begin(9600); 
Wire.onRequest(requestEvent);
}

void loop() {
//Recevie response from slave (LORA)
 Wire.requestFrom(9,10);    
while (0<Wire.available()) { 
   char c = Wire.read(); 
    Serial.print(c);       
 }
Serial.println();
delay(500);
}
void requestEvent(){
//Send request to slave
Wire.write("Arduino");

}

Adafruit Feather 32u4 board Code

#include <Wire.h>
String msgLora;
void setup() {
    Serial.begin(9600); 
  Wire.begin(9);             
  Wire.onRequest(requestEvent);
}

void loop() {
     Wire.requestFrom(8, 13); 
  while (0<Wire.available()) { 
     char c = Wire.read(); 
   Serial.print(c);   
    
  }
Serial.println();
  delay(500);
}
void requestEvent() {
  if(Serial1.available()){
    msgLora=Serial1.readStringUntil('\n');
    int len = msgLora.length() + 1; 
char buf[len];
  msgLora.toCharArray(buf, len);
  Wire.write(buf); 
  
  }

Thanks for your information I will try that .

Try to make a requestEvent() without Serial functions and without String objects.
Remove these things from the requestEvent():

  • Serial1.available()
  • Serial1.readStringUntil()
  • msgLora.length()
  • msgLora.toCharArray()

When there is more than one Master on the I2C bus, they could start a I2C session at the same time. That gives a collision on the I2C bus. You don't want that.

By the way the code was working properly even If I not removed them .But
I removed them as your request and I just typed inside requestEvent ()
Wire.write("Hi");
And also this code working properly .

So I think I can have two board and both of them can work as master and slave in the same time .

By the way , if I let Arduino UNO send message through serial function I mean that I typed inside requestEvent () all these :

  • Serial1.available()
  • Serial1.readStringUntil()
  • msgLora.length()
  • msgLora.toCharArray()

And later I let the other board send static message just used Wire.write("Hi");
The code not working properly .

I don't think so.
I have not seen a good implementation of a multi-master bus with Arduino boards yet. Until that does not exist, I call a multi-master bus with Arduino boards a fairy tale.

You should not wait in a interrupt with the function Serial1.readStringUntil(). The other functions that I mentioned should be avoided as well to make it more reliable.

The requestEvent() function can respond with data that is in a global variable which already has the right data.

I understand your point , But I provided to u a code that working as each board can be multiMaster board so what can u said about this codes ?Is there something I do not understand yet ??

Yes! It is possible under the following agreement between the two boards:
(1) Initially, Board-1 (UNO) starts as Master and the Board-2 (NANO) starts as Slave.

(2) After the delvery of data to the Slave, Board-1 executes this code (Wire.begin(0x08)) to become Slave and then informs (through interrupt) Borad-2 to act as Master.

(3) The above arrangement might work (Fig-1); but, it has no practical value other than doing an exercise.


Figure-1:

Ok , that is good
But the hex number 0x08 in this code Wire.begin(0x08) it is mention the address of the board ??

When Board-1 will respond as Slave, then its "7-bit Address Tag is given as: 0001000 (0x08)".

1 Like