I2C doesn't seem to work correctly

Hi, I have two Arduino nano board connected via an I2C connection on analog pins 4 and 5 with 4.8k pull up resistors connected to the 5V rail. Now i am using some simple code to send a character string between the two Arduinos:

Slave:

#include <SPI.h>
#include <SoftwareSerial.h>
#include <Wire.h>

void setup() {
        Serial.begin(4800);
        Wire.begin(2); //Establish the device on the I2C network as slave (Address 2)
}
  
void loop() 
{
  Serial.println("Writing Data");
  Wire.write("Hello"); //Write data to the buffer for transmission
}

Master:

#include <SPI.h>
#include <SoftwareSerial.h>
#include <Wire.h>                       
                        
void setup() 
{
          
	Serial.begin(4800);
        Wire.begin(); //Establish the device on the I2C network as master (Slave Address 2)
}
char data[5]; 
char c;
int j;
void loop()
{
                        Serial.println("Requesting Data");
                        Wire.requestFrom(2, 5); //Request 5 bytes from address 2
                        j = 0;
                        Serial.println("Reading Data");
                        while(Wire.available())
                        {
                          c = Wire.read();
                          Serial.println(c);
                        }
}

The output is as follows:

Requesting Data
Reading Data

ÿ
ÿ
ÿ
ÿ

You can't just have Wire.write on its own. You need a Wire.beginTransmission and Wire.endTransmission.

Take a look a this:

There are examples there of communicating between two devices.

Apparently you only need wire.begin and wire.end if you are sending master->slave messages which I'm not. That's why the wire.begin function takes an address. The master node does not have an address so i can't use the wire.begin function... Can someone confirm this?

You need Wire.beginTransmission();

an address is not needed for the master but the command is.

Can someone confirm this?

I can confirm that it is rubbish if that helps.

Did you look at my examples? You are doing this:

                        Wire.requestFrom(2, 5); //Request 5 bytes from address 2

If one end does a requestFrom that generates an interrupt at the other end. It needs to have installed a onRequest handler to intercept the request. It doesn't just pump out data.

  Wire.onRequest (requestEvent);  // interrupt handler for when data is wanted

Inside the onRequest you don't do a beginTransmission or endTransmission. But you don't have such a handler.

I did read the examples. And thanks for the help, according to the documentation the beginTransmission takes an address, it was never mentioned that it can be used without, so i assumed it wasn't overloaded to not take an address for the case of a slave->master transfer. I will try the request handler now, i assumed there must be something i'm missing to detect the request of the master. Thanks everyone for the help!

It is my understanding that the Master controls everything. The Slave can not push data to the Master, the Master must request data from the slave.
That is why the Master does not have an address. The Master knows who he is.
Also one slave can not push data to another slave. The Master must always be in the middle.

Since the Slave must respond to the Master in the Masters time frame, there are interrupt service routines that the Slave sets up so the Slave can do productive work but still respond to a request from the Master.

Again, these are only my understandings.

You can have multiple masters. One of the examples on my linked pages shows two Arduinos, both with addresses and both with requestEvent handlers.

So really the word "master" refers to a period in time when one device "seizes" the bus in an attempt to communicate with another one.

Contrast this to SPI where there really is a MISO (master in, slave out) line, and a MOSI (master out, slave in) line.

With the wire.onRequest() function defined on the slave, this works fine. Thanks alot :slight_smile:

But Nick,
If you have multiple masters and one master wishes to communicate with another master. Isn't the second master going into 'slave' mode? In that case the node is idle as a slave, waiting to respond to a master. But if it needs something from another node, it can go into master mode to control the dialog.

Randall
BTW: You have probably forgotten more about this stuff than I have learned. Thank you for you contributions.

RandallR:
But Nick,
If you have multiple masters and one master wishes to communicate with another master. Isn't the second master going into 'slave' mode?

I have an example of multiple masters here:

See the Atmega328 datasheet page 218:

21.4 Multi-master Bus Systems, Arbitration and Synchronization

The TWI protocol allows bus systems with several masters. Special concerns have been taken in order to ensure that transmissions will proceed as normal, even if two or more masters initiate a transmission at the same time.

(TWI being the same as I2C more or less).


If multiple devices register a slave address then they can be addressed by any other device. So you might have "slaves" 2, 3 and 4. Now device 3 can "call" 2 or device 2 can "call" 3.

At the moment when you do the Wire.endTransmission() call, the device doing that attempts to initiate a transfer (ie. become the master) and if possible, send the data. When complete, it goes back into "slave" status. So effectively every one can be a master and a slave.

This is made possible electrically because each device has the two wires as high impedance (input) until such time as they attempt to become the master.