i2c problem.incorrect data from one arduino to another.

so approach my project once again.I have a stopwatch on one arduino plus an nrf24l01 which feedback some data.I wanted to save that data and i know that using 2 spi modules could prove difficult.So i connected a slave arduino to the master via i2c and then hooked an sd card.So then i wanted to sent a float(time) to the slave arduino which cannot be done unless you create a union which i did(i think).
Although testing the union on the master gives back correct results, when the slave receives the data it takes some bytes incorrectly.Ive made a union with 2 arrays B[2] as you can see from the code bellow, at b[0] which are seconds i take the time correct but at b[1] always false data.Is there something wrong regarding my union structure? Or is it the code about i2c wrong?Please help im out of ideas.
Master code

#include <LiquidCrystal.h>
#include <Wire.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);


void setup()
{
  lcd.begin(16, 2);
  lcd.clear();
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);
  
  pinMode(8, INPUT);
  digitalWrite(8, HIGH);
  pinMode(9, INPUT);
  digitalWrite(9, HIGH);
  pinMode(10, INPUT);
  digitalWrite(10, HIGH);
  

}
double i = 0;
double a = millis();
double c ;
unsigned int g;
double f ;
unsigned int p;


 union u_tag {
   int b[2];
   //float fval;
 } u;

void loop()
{
  
lcd.clear();
lcd.print("press start");
delay(100);
  
 if(digitalRead(8) ==HIGH)
 {

    lcd.clear();
 a = millis();
   while(digitalRead(9) == LOW)
   {
   
     c = millis();
   i = (c - a) / 1000;
   g= (c - a);
   p=i;
   lcd.print(i);
   lcd.setCursor(11,0);
   lcd.print("Sec's");
   lcd.setCursor(0,0);
   Serial.println(c);
   Serial.println(a);
   Serial.println(i);
   Serial.println("......");
//   delay(100);
 f=(g - p*1000) ;
 //f are milliseconds :25
 //i is the whole time 02:25 
u.b[0]=i ;
u.b[1]=f ;
Serial.println(u.b[0]);
Serial.println(u.b[1]);
 
  
   }
   
   if(digitalRead(9) == HIGH)
   {
     while(digitalRead(8) == LOW)
     {
       lcd.setCursor(0,0);
       lcd.print(i);
       lcd.setCursor(11,0);
       lcd.print("Sec's");
       lcd.setCursor(0,0);
//       delay(100);
       
   
 
     }
     
      Serial.print("F=");
     Serial.print(p);
     Serial.print(":");
     Serial.println(f);
     Wire.beginTransmission(9); // transmit to device #4

//Wire.write( p);   
  //Wire.write(f);
   Wire.write(u.b[0]);
   Wire.write(u.b[1]);
 //sends one byte  
Wire.endTransmission();    // stop transmitting
 


 }

 }
  

}

Slave code

#include <Wire.h>
#include <SPI.h>
#include <SD.h>
const int chipSelect = 10;
void setup()
{
 Wire.begin(9);                // join i2c bus with address #4
 Wire.onReceive(receiveEvent); // register event
 Serial.begin(250000);           // start serial for output
 Serial.println("slave setup");
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}
union u_tag {
 int b[2];
   //float fval;
 } u;
 //int f ;
  //int p;
void loop()
{
 

// 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
 {
  
 
  //p = Wire.read();    // receive byte as an integer
  //f = Wire.read(); 
  u.b[0] = Wire.read();
  u.b[1] = Wire.read();
 Serial.print("time is:");
 //Serial.print(p);         // print the integer
 //Serial.print(":");
  //Serial.println(f);
  Serial.print(u.b[0]);
  Serial.print(":");
  Serial.println(u.b[1]);
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
   dataFile.print(u.b[0]);
    dataFile.print(":");
    dataFile.println(u.b[1]);
    dataFile.close();
 
  
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
 }
}

If you are sending the float as 4 separate bytes, your union should be composed of a byte array of 4 bytes and a float. An integer (you are using a signed integer) is 2 bytes long.

An integer (you are using a signed integer) is 2 bytes long.

sp."An int (you are using a signed int) is 2 bytes long."

sp."An int (you are using a signed int) is 2 bytes long."

Oops yes. That is the self correcting proof reader at it again. You have to watch it like a hawk :slight_smile:
But is the compiler really so pedantic over simple spelling errors ?

The OP can look here for something similar. See post #10

But is the compiler really so pedantic over simple spelling errors ?

Unless you have the word "integer" as a macro or typedef, yes it absolutely is.

are you talking about B? yeah i cant declare it as float as this prohibits the compiler from sending it via i2c.my method shows correct results on the master arduino as i print the unions data but over the slave the data is false.im gonna post some readings

What's so hard about two SPI devices on the same bus/board? The whole point of SPI is to support multiple devices, otherwise there'd be no need for MOSI and MISO.

It seems to me you're jumping through double flaming hoops to do with two boards what you should be doing with one, now wasting time solving problems that you have needlessly injected into the project.

The NRF24 is a 3.3 volt device, you already have to address that at the interface level, an SD card is the same 3.3 volt level. Were is the difficult part of this?

i tried putting both on the main arduino but didnt work,actually the sd module is 5v

Anyway, if you use Wire.write() , you have to include the length in bytes of the data you are sending, unless it is the default length.

Wire.write(u.b[0],2);

where b in an int array, would be correct.

i think the main cause is the wire communication.the first reading i get as the slave is correct but everything else goes horribly wrong whereas on the master the union's data seems to give correct results
master http://imgur.com/gF3VbHV
slave http://imgur.com/gF3VbHV

6v6gt:
Anyway, if you use Wire.write() , you have to include the length in bytes of the data you are sending, unless it is the default length.

Wire.write(u.b[0],2);

where b in an int array, would be correct.

call of overloaded write(int&,int) is ambiguous

OK. Try:

Wire.write(u.b,4); // write the whole array

But also look at the example post #10 : http://forum.arduino.cc/index.php?topic=438187.0

6v6gt:
OK. Try:

Wire.write(u.b,4); // write the whole array

But also look at the example post #10 : http://forum.arduino.cc/index.php?topic=438187.0

still same problem.i dont think it has to do with the union ,i2c maybe is the problem .Sometimes it gets correct reading.The first reading is usually correct and the rest are not.

What value pull-up resistors are you using for the I2C lines?

I haven't put any resistors on i2c .is that a problem?

Yes sir. I2C no work-ee without pull-ups, the outputs are "open drain" with an external pull-up resistor.

This is how the master and slaves share the SDA line. Without open-drain outputs and the external pull-up, the slaves would never be able to assert the SDA line to acknowledge receipt of data.

So, your earlier diagnosis of the slave not receiving correctly was absolutely correct, the first byte appears okay and then everything else is wrong because the master never receives the ack that the data was received correctly so it probably stops transmitting, it just depends if the library handles the failure or ignores it.

You'll need two 4.7k resistors, not super critical so anything from 2k to 10k should work for what you're doing. One resistor between +5v and SCL and the other between +5v and SDA. It doesn't matter which end, master or slave, so long as the wire length between boards is as short as possible.

The first thing you always do with a new I2C setup is to confirm that the master can at least see the slave. This proves that you have the addresses correct for both the master and the slave.

You just hook them up and run this sketch on the master: I2cScanner

If the connection is good, it will report the address of any slave(s) it finds to the serial terminal.

Right from the Wire Library page:

Please note that a pull-up resistor is needed when connecting SDA/SCL pins. Please refer to the examples for more informations. MEGA 2560 board has pull-up resistors on pins 20 - 21 onboard.

Some I2C boards also contain their own pull-ups, like the Liquid Crystal I2C interface (aka backpack) board and many of the I2C clock modules (DS3231 and the like). In those cases, you do not need any other pull-ups but for board to board, unless one of them is a Mega, you absolutely must add the resistors.

this is the whole project via fritzing http://imgur.com/iVUEdVW with the actual wiring.
missing the nrf but doesnt matter.
you mean something like this ? http://imgur.com/fI7HKOI

No!!!! You can/will destroy your Uno that way. That has SCL and SDA connected to the 5 volt supply. Did you read ALL of my previous post where is says you don't need pull-ups if you have a Mega in the mix?

The problem will your original connections is that you have the 5 volt supplies of the Mega and Uno shorted together. You need to remove the red wire that bridges the red strips of the breadboard together.

so if i understand correctly, i removed the 5v of uno going to the breadboard.Nothing changed on reading.correct me if im wrong.
Btw i scanned for addresses and seems to be correct
Scanning...
I2C device found at address 0x09 !
done
i dont know how will this work.union data on mega works.i ve tried every possible way.