Wire - Send values over 255

Hi All,

I’m trying to create a data logger with two Arduino’s, one to collect and the other to log and submit the information to a web server.

Trying to send the data between Arduino’s is proving a little trivial for me… I have the following sketches, but anything over 255 simply rolls over (I set the sensor value to 260 to prove this, it comes back as 4), how can I get around this?

Arduino 1 Code:

// START Wire Transmission
Wire.beginTransmission(4);
    for(int i = 0; i <= S01index; i++)
    {
      int sensor = 260;
      Wire.write(sensor);
      Wire.write(S01timestamp[i]);
      Wire.write(S01reading[i]);
    }

    if(Wire.endTransmission() == 0)
    {
      // START Wipe S01
      for(int i = 0; i <= S01index; i++)
      {
        S01timestamp[i] = 0;
        S01reading[i] = 0;
      }
      S01index = 0;
    }
    nextsend = millis() + 5000;

Arduino 2 Code:

void receiveEvent(int howMany)
{
  Serial.println("START");
  while(0 < Wire.available())
  {
    Serial.print("S: ");
    int sensor = Wire.read();
    Serial.print(sensor);
    
    Serial.print(" T: ");
    unsigned long timestamp = Wire.read();
    Serial.print(timestamp);
    
    Serial.print(" R: ");
    int reading = Wire.read();
    Serial.println(reading);
  }
  Serial.println("END");
}

Many thanks in advance!

That's because the write method only send a byte and a single byte goes from 0 to 255.Since you are above that (260) it will roll back. The solution could passes to convert that value(260) to a string and send it as a string or create an array of values and send the entire array with Wire.write(array,sizeof(array)); Try this:

int sensor = 260;
char *sensorString;
itoa(sensor,sensorString,10);
Wire.write(sensorString);

See this: http://arduino.cc/en/Reference/WireWrite

Or send the int as two bytes:-

int sensor = 260;
Wire.write(sensor >> 8); // Most significant byte
Wire.write(sensor); // Least significant byte

HugoPT:
That’s because the write method only send a byte and a single byte goes from 0 to 255.Since you are above that (260) it will roll back.
The solution could passes to convert that value(260) to a string and send it as a string or create an array of values and send the entire array with Wire.write(array,sizeof(array));
Try this:

int sensor = 260;

char *sensorString;
itoa(sensor,sensorString,10);
Wire.write(sensorString);



See this:
http://arduino.cc/en/Reference/WireWrite

HugoPT, that looks great, converting it to a char array sounds like the solution to me!

This will help me separate values in a single transmission too, I’ve bodged together some code that works in my head, but clearly not on paper (I’ve completely made some of it up!). Would you mind offering a few pointers? Do you think this approach would be efficient?

Arduino 1:

#include <Wire.h>

void setup()
{
  Wire.begin();
}

void loop()
{
  int S01index = 4;
  unsigned long S01timestamp[40] = { 1, 13, 135, 1357, 13579 };
  int S01reading[40] = { 2, 24, 246, 2468, 24680 };

  Wire.beginTransmission(4);
  for(int i = 0; i <= S01index; i++)
  {
    
    byte sensor = 1;
    Wire.write(sensor);

    // Convert Unisgned long to char array???
    char *array = S01timestamp[i];
    Wire.write(sizeof(array));
    Wire.write(array,sizeof(array));

    // Convert int to char array???
    char *array2 = S01reading[i];
    Wire.write(sizeof(array2));
    Wire.write(array2,sizeof(array2));
    
  }
  
  Wire.endTransmission();
  delay(5000);
}

Arduino 2:

#include <Wire.h>

void setup()
{
  Wire.begin(4);
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void loop()
{
  delay(100);
}

void receiveEvent(int howMany)
{
  Serial.println("Data Start");
  
  // Read Sensor
  byte sensor = Wire.read();
  Serial.print("Sensor: ");
  Serial.println(sensor);

  // Read Timestamp
  datasize = Wire.read();
  Serial.print("Timestamp: ");
  for(byte i = 0; datasize > i; i++)
  {
    char dataprint = Wire.read();
    Serial.print(dataprint);
  }
  Serial.println();

  // Read Value
  datasize = Wire.read();
  Serial.print("Reading: ");
  for(byte i = 0; datasize > i; i++)
  {
    char dataprint = Wire.read();
    Serial.print(dataprint);
  }
  Serial.println();

  Serial.println("Data End");
}

Grumpy_Mike:
Or send the int as two bytes:-

int sensor = 260;

Wire.write(sensor >> 8); // Most significant byte
Wire.write(sensor); // Least significant byte

Thanks Grumpy_Mike, but I’m not sure exactly what is happening here? What does the ‘>> 8’ represent exactly?

I’m more than happy to read up on this, but could you throw me a couple of keywords for me to google, I’m not really sure what to look for, thanks!

UPDATE:

I think we are getting somewhere, I understand what we are doing here now, new code below… Now for the unsigned long…

Arduino 1:

#include <Wire.h>

void setup()
{
  Wire.begin();
}

void loop()
{
  int S01index = 4;
  unsigned long S01timestamp[40] = { 1, 13, 135, 1357, 13579 };
  int S01reading[40] = { 2, 24, 246, 2468, 24680 };

  Wire.beginTransmission(4);
  for(int i = 0; i <= S01index; i++)
  {
    
    byte sensor = 1;
    Wire.write(sensor);

    // Convert Unsigned long to char array???
    char *array = S01timestamp[i];
    Wire.write(sizeof(array));
    Wire.write(array,sizeof(array));

    // Send Value
    Wire.write(S01reading[i] >> 8);
    Wire.write(S01reading[i]);
    
  }
  
  Wire.endTransmission();
  delay(5000);
}

Arduino 2:

#include <Wire.h>

void setup()
{
  Wire.begin(4);
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void loop()
{
  delay(100);
}

void receiveEvent(int howMany)
{
  Serial.println("Data Start");
  
  // Read Sensor
  byte sensor = Wire.read();
  Serial.print("Sensor: ");
  Serial.println(sensor);

  // Read Timestamp
  byte datasize = Wire.read();
  Serial.print("Timestamp: ");
  for(byte i = 0; datasize > i; i++)
  {
    char dataprint = Wire.read();
    Serial.print(dataprint);
  }
  Serial.println();

  // Read Value
  Serial.print("Reading: ");
  byte b1 = Wire.read();
  byte b2 = Wire.read();
  Serial.println((b1 * 256) + b2);
  
  Serial.println("Data End");
}

I've figured out how to break down these values, but how do I reconstruct?

I have tried:

unsigned long S01timestamp = 13579; Wire.write(S01timestamp >> 24); Wire.write(S01timestamp >> 16); Wire.write(S01timestamp >> 8); Wire.write(S01timestamp);

But this doesn't seem to work for me, it is wrong on the higher values. Am I on the right path??

Another solution to brake it in a char array:

#include <Wire.h>

void setup()
{
  Wire.begin();
}

void loop()
{
  int S01index = 4;
  unsigned long S01timestamp[40] = { 1, 13, 135, 1357, 13579 };
  int S01reading[40] = { 2, 24, 246, 2468, 24680 };

  Wire.beginTransmission(4);
  for(int i = 0; i <= S01index; i++)
  {
    
    byte sensor = 1;
    Wire.write(sensor);

    // Convert unsisgned long to char array???
   unsigned char* longArray = reinterpret_cast < uint8_t* > (S01timestamp);
//Now the longArray is an array of bytes with content of S01timestamp.Now send it as you want to the other side and reverse the process
  }
  
  Wire.endTransmission();
  delay(5000);
}

byte b[3];//your array only has 3 elements b[0] = Wire.read(); b[1] = Wire.read(); b[2] = Wire.read();//You array ends here! b[3] = Wire.read();//Opps this memory part does not belong to b array since arrays are 0 indexed so you only can read @ b[2] unsigned long ul = ((256^3) * b[0]) + ((256^2) * b[1]) + (256 * b[2]) + b[3];

Thanks for your help! I’ve gone down the route of splitting into bytes, I feel this might be cleaner and results in less data being transmitted.

I’ve (almost) got it working now… However I’m getting some strange results, some sort of transmission error or memory issue? The code does continue to loop, but seems to struggle after so many entries.

Sender:

#include <Wire.h>

int S01index = 5;
unsigned long S01timestamp[6] = { 
  13579, 1357, 135, 13, 1, 0 };
int S01reading[40] = { 
  24680, 2468, 246, 24, 2, 0 };

void setup()
{
  Wire.begin();
}

void loop()
{
  Wire.beginTransmission(4);
  for(int i = 0; i <= S01index; i++)
  {
    byte sensor = 1;
    Wire.write(sensor);
    // Send Timestamp
    Wire.write(S01timestamp[i] >> 24);
    Wire.write(S01timestamp[i] >> 16);
    Wire.write(S01timestamp[i] >> 8);
    Wire.write(S01timestamp[i]);
    // Send Value
    Wire.write(S01reading[i] >> 8);
    Wire.write(S01reading[i]);
  }
  Wire.endTransmission();
  delay(5000);
}

Receiver:

#include <Wire.h>

int i = 0;
unsigned long ul = 0;

void setup()
{
  Wire.begin(4);
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void loop()
{
  delay(100);
}

void receiveEvent(int howMany)
{
  Serial.println("Data Start");
  while(0 < Wire.available())
  {
    // Read Sensor
    byte sensor = Wire.read();
    Serial.print("S: ");
    Serial.print(sensor);
    // Read Timestamp
    Serial.print(", T: ");
    ul = 0;
    ul = Wire.read() << 24;
    ul |= Wire.read() << 16;
    ul |= Wire.read() << 8;
    ul |= Wire.read();
    Serial.print(ul);
    // Read Value
    Serial.print(", R: ");
    i = 0;
    i = Wire.read() << 8;
    i |= Wire.read();
    Serial.println(i);
    Serial.println(" - ");
  }
  Serial.println("Data End");
}

Output:

Data Start
S: 1, T: 13579, R: 24680
 - 
S: 1, T: 1357, R: 2468
 - 
S: 1, T: 135, R: 246
 - 
S: 1, T: 13, R: 24
 - 
S: 1, T: 4294967295, R: -1
 - 
Data End

Once this issue has been solved I think we will be done, many thanks for your help!

Try doing:-

int S01index = 6;
unsigned long S01timestamp[] = {  13579, 1357, 135, 13, 1, 0 };
int S01reading[] = {  24680, 2468, 246, 24, 2, 0 };

and

for(int i = 0; i < S01index; i++)

Try this way:

#include <Wire.h>

int S01index = 5;
unsigned long S01timestamp[6] = { 
  13579, 1357, 135, 13, 1, 0 };
int S01reading[40] = { 
  24680, 2468, 246, 24, 2, 0 };

void setup()
{
  Wire.begin();
}

void loop()
{
  Wire.beginTransmission(4);
  for(int i = 0; i <= S01index; i++)
  {
    byte sensor = 1;
    Wire.write(sensor);
    // Send Timestamp
    
 byte byte1 = S01timestamp[i] & 0xff;
Wire.write(byte1);
byte byte2 = (S01timestamp[i]>> 8) & 0xff;
Wire.write(byte2);
byte byte3 = (S01timestamp[i]>> 16) & 0xff;
Wire.write(byte3);
byte byte4 = (S01timestamp[i]>> 24) & 0xff;
Wire.write(byte4);


  }
  Wire.endTransmission();
  delay(5000);
}