I2C help

I've got boards up and running with i2C. I'm wanting to use use a master reader type program on an arduino mega and a slave sender on a 328 arduino. I'm sending out a request for 2 bytes and trying to receive them into 2 different variables but I cant split them up. it just prints gibberish. Does anybody know how to do this?

Master code:

#include <Wire.h>

int t;
boolean w;

void setup()

{

Wire.begin();
// join i2c bus (address optional for master)

Serial.begin(9600);
// start serial for output
}

void loop()
{
Wire.requestFrom(2,2); // request 1 byte from slave device #2
while(Wire.available()) // slave may send less than requested
{
t=Wire.receive();
Serial.print(t);
w = Wire.receive(); // receive a byte as character
//delay(100);
Serial.print(w); // print status
}
delay(500);
}

void receiveEvent(int howmany)
{
Wire.requestFrom(2,2); // request 2 bytes from slave device #2
while(Wire.available()<2)
{
int t=Wire.receive(); // receives t integer
}

while(Wire.available()<1)
{
boolean w=Wire.receive(); // receives w boolean
}

delay(10);
Serial.print(t);
Serial.print(w);
}

Slave Code:

#include <Wire.h>

int t;
boolean w;

void setup()
{
Wire.begin(2); // join i2c bus with address #2
Wire.onRequest(requestEvent); // register event
}

void loop()
{
delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
t=4;
w=0;
Wire.send(t); // respond with a message of 1 byte
Wire.send(w); // sends boolean w
}

it should be returning a 4 then a 0. but its returning 0 then a y with two dots over it?? seriously, does anyone have any idea whats going on??!!

Wire.requestFrom(2,2); // request 1 byte from slave device #2

How many?

Are you missing some begin/end Transmissions?

Wire.requestFrom([glow]2[/glow],2); // request [glow]1[/glow] byte from slave device #2
while(Wire.available()) // slave may send less than requested  
{
 t=Wire.receive();
 Serial.print(t);
 w = Wire.receive(); // receive a byte as character
 //delay(100);
 Serial.print(w); // print status
}

Your comment notes that the slave may send less than the requested number of bytes. You test that there is at least one byte, then read two. The second is not available, so wire.receive() is returning a -1, which you are then trying to print. The print function defaults to printing characters, in the absence of any contrary directive. The -1, as a character, prints a y with the two dots above it.

 while(Wire.available()<1)
 {
 boolean w=Wire.receive(); // receives w boolean
 }

Receive every byte, and stuff it in a local variable that goes out of scope immediately, as long as there is nothing to receive. This makes no sense at all.

 while(Wire.available()<2)
 {
 int t=Wire.receive(); // receives t integer
 }

Receive every byte, and stuff it in a local variable that goes out of scope immediately, as long as there is less than two bytes to receive. This makes little sense.

You need to study the purpose of while loops, which are not the same as if tests, and you need to study scope.

oh so you're saying that my variables are only being staying declared in my while loop? I figured they would stay unless I changed them. I was just messing around with different wire.available combinations trying to find a way to split up the data I sent in over the bus.

Now I'm reading with this. It gets 1 and 255.

#include <Wire.h>

int t;
int w;

void setup()

{
Wire.begin();
// join i2c bus (address optional for master)

Serial.begin(9600);
// start serial for output
}

void loop()
{
receiveEvent();
delay(1000);
}

void receiveEvent()
{
Wire.requestFrom(2,2); // request 2 bytes from slave device #2
if(Wire.available())
{

t=Wire.receive(); // receives t integer first which is the supply #
Serial.print(t);

delay(1000);
w=Wire.receive(); // receives w boolean which is status good or bad
Serial.print(w);
}
}

Ok, here's what I've got. I've made some changes but still don't understand why it doesn't receive a 4 then a 1.

Slave sender:

#include <Wire.h>

int t;
int w;

void setup()
{
Wire.begin(2); // join i2c bus with address #2
Wire.onRequest(requestEvent); // register event
}

void loop()
{
delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
t=4;
w=1;
Wire.send(t);
Wire.send(w); // sends w
}

Master Receiver:

#include <Wire.h>

int t;
int w;

void setup()

{
Wire.begin(); // join i2c bus (address optional for master)

Serial.begin(9600); // start serial for output
}

void loop()
{
receiveEvent();

delay(100);
}

void receiveEvent()
{
Wire.requestFrom(2,4); // request 2 bytes from slave device #2
if(Wire.available())
{

t=Wire.receive(); // receives t integer first
Serial.print(t);

w=Wire.receive(); // receives w second
Serial.print(w);
}
}

I2c uses address's so thing about reading something about I2c as you are not acounting for the address thingie.

I'm not sure what you are referring to. You have to include the address of the slave device when you initialize and also when you request data from the slave. Other than that, I'm not sure where I would be missing any address information.

You are still trying to read two bytes whenever there is at least one available.

How do I fix that? I'm sure it has something to do with wire.available, but I don't fully understand what is happening there...

This:

 if(Wire.available())

says "I have at least one byte available to read"

And then you go and read two bytes.

What if there is really only one available?

I got ya. It needs to be more like

if(Wire.available()>=2)

Ok, I got some help from a friend and feel like I'm getting much closer. I am now receiving a 4 for t and blank space for w. Maybe someone will see what is happening and causing me not to get a 0 for w.

Slave Sender:

#include <Wire.h>

int t;
boolean w;
byte dataOut[2];

void setup()
{
      Wire.begin(2);                // join i2c bus with address #2
      Wire.onRequest(requestEvent); // register event
}

void loop()
{
      delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
      t=4;
      w=0;
  
      dataOut[0] = t;
      dataOut[1] = w;

      Wire.send(dataOut, 2);
}

Master Receiver:

#include <Wire.h>

int t,i;
boolean w;
byte dataIn[2];


void setup()

{
      Wire.begin();        
      // join i2c bus (address optional for master)
  
      Serial.begin(9600);  
      // start serial for output
}


void loop()
{
      receiveEvent();
      delay(500);
}

void receiveEvent()
{
      Wire.requestFrom(2,2); // request 2 bytes from slave device #2
      while(Wire.available())
      { 
          for(i=0;i<=1;i++)
          {
            dataIn[i] = Wire.receive();
            
          }
      }
  
      t = dataIn[0];
      w = dataIn[1];
  
      Serial.print(t);
      delay(1000);
      Serial.print(w); 
        
}

You are STILL determining that there is at least one byte to read and reading two.