Pages: [1]   Go Down
Author Topic: I2C doesn't seem to work correctly  (Read 748 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
#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:
Code:
#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

ÿ
ÿ
ÿ
ÿ
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Take a look a this:

http://www.gammon.com.au/i2c

There are examples there of communicating between two devices.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 441
Posts: 23834
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You need Wire.beginTransmission();

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

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Manchester (England England)
Online Online
Brattain Member
*****
Karma: 514
Posts: 31534
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Can someone confirm this?
I can confirm that it is rubbish if that helps.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
                        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.

Code:
  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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 314
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Sr. Member
****
Karma: 1
Posts: 314
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

http://www.gammon.com.au/i2c

See the Atmega328 datasheet page 218:

Quote
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.
Logged

Pages: [1]   Go Up
Jump to: