I2C Error

Hy.

I have a microchip board as a master and a arduino uno as a slave and I wanna do an I2C communication.

I'm using the Wire Slave Receiver code example but the arduino's output is always -1.
I supposed this is an error.

Can someone explain me what kind of error it is?

Thanks.

I'm using an arduino uno as a slave and a microchip explorer 16 board as master to do an I2C communication.

My arduino is not sending the ACK to the master, and I'm using the code example(See bellow please):

How can I send the ACK to my master? Thanks for the help.

// Wire Slave Receiver
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#include <Wire.h>

void setup()
{
 Wire.begin(4);                // join i2c bus with address #4
 Wire.onReceive(receiveEvent); // register event
 Serial.begin(9600);           // start serial for output
}

void loop()
{
 delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
 while (1 < Wire.available()) // loop through all but the last
 {
   char c = Wire.read(); // receive byte as a character
   Serial.print(c);         // print the character
 }
 int x = Wire.read();    // receive byte as an integer
 Serial.println(x);         // print the integer
}

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

Please do not cross-post. Threads merged.

If you do not get a response after a day or two ask a moderator to move your thread.

It is not possible to use the Serial library in the receiveEvent() function.
There is no need to use Wire.available(), since the 'howMany' parameter already contains the number of received bytes.

What are you sending ? how many bytes ?

The ACK is done inside the Wire library. The Arduino might use pulse stretching on the SCL and be slow with the ACK.

I'm sending only a char (letter m);
And sometimes arduino shows the letter m , other times shows the ascii code.
Using the software logic to see the communication I can realize that arduino never sends the ACK to the master.

I'm using the arduino example code. the code is not mine .

Microchip code (MASTER)

#include "p24fxxxx.h"
#include "i2c.h"

#define Fosc (8000000) // crystal
#define Fcy (Fosc*4/2) // w.PLL (Instruction Per Second)
#define Fsck 400000 // 400kHz I2C
#define I2C1_BRG ((Fcy/2/Fsck)-1)

int main(void) {

char SlaveAddress = 0x4;
char c='b';

OpenI2C1(I2C_ON, I2C1_BRG);

while(1){
while(1){
StartI2C1 (); //Send the Start Bit
IdleI2C1(); ////Wait to complete

MasterWriteI2C1((SlaveAddress<<0)|0); //Send device advice adress byte to the slave with the write indication
IdleI2C1(); //Wait to complete
//ACKSTAT is 0 when slave acknowledge,
//if 1 then slave has not acknowledge the data.

if( I2C1STATbits.ACKSTAT ) //ACKSTAT=1 NACK is received from the slave
{
StopI2C1(); //Send the Stop condition
IdleI2C1(); //Wait to complete
IdleI2C1();
}

else
{
break;
}

}

MasterWriteI2C1 (c);
IdleI2C1();

}
}


Arduino (slave)

// Wire Slave Receiver
// by Nicholas Zambetti http://www.zambetti.com

// Demonstrates use of the Wire library
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer" example for use with this

// Created 29 March 2006

// This example code is in the public domain.

#include <Wire.h>

void setup()
{
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
}

void loop()
{
delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
while (1 < Wire.available()) // loop through all but the last
{
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}

The Microchip seems to keep sending data at high speed. Could you add a delay and send about 10 messages per second ?

The Arduino code is not good. I didn't test the next example.

#include <Wire.h>

volatile byte data = 0;       // byte, zero is empty

void setup()
{
  Serial.begin(9600);           // start serial for output
  Serial.println("\nStarted");

  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
}

void loop()
{
  byte dataCopy;

  // test the 'data' as flag.
  noInterrupts();
  if( data != 0)
  {
    dataCopy = data;
    data = 0;
  }
  interrupts();

  Serial.print("Received : ");
  Serial.println( data);
}

void receiveEvent(int howMany)
{
  // if (howMany == 1)       // extra check

  data = Wire.read();
}

If the Arduino does not ACK to its address, the address might be wrong. The Arduino uses the 7-bit shifted address. Address "4" would become: 0 0 0 0 1 0 0 X
The 'X' is the R/W bit.
It might be address "8" for the MicroChip.