Wire send multiple values

Hi all, this forum has been a great help thus far, lets see how this goes :slight_smile:

I have 4 sensors, which are 555 circuits which measure capacitance through the use of interrupts. This goes into one MEGA (secondary), which I also want to measure an accelerometer, voltage and current. All of this needs to be piped to another MEGA (primary) which will do the heavy lifting (it has an Ethernet shield and sends/receives the sensor data and control commands via OSC).

I’ve got Wire working (easy stuff) for small values. However, I’m looking to send all of this sensor information to the primary MEGA. Looking around, large values are difficult to send, and I’m guessing sending an array with multiple large values will be harder.

The values I’m sending will be 4 x 5 digit (00,000) numbers, and 3 x 3 (000) digit numbers. I’m a hobbyist with a vague understanding of C programming (I’m a web programmer - PHP, HTML, JavaScript - by profession), so be gentle :slight_smile:

How do I do that with the wire library? Is there a better communication method?

You could do something like this:

#include <Wire.h>
#define SLAVE_ADDRESS 42

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

void loop() {
  int myData [7];

  myData [0] = 123;
  myData [1] = 456;
  // etc.

  Wire.beginTransmission(SLAVE_ADDRESS);
  Wire.send((byte *) myData, sizeof myData);
  Wire.endTransmission();

  delay (100);
}

That sends 7 ints - these can hold -32768 to +32767. That would be 14 bytes. If you need larger numbers than that change “int” to “long”. If you make the ints longs it will be 28 bytes, which is just within the range of what you can send (32 bytes).

How do I pick it up on the receiving end, the basic slave_receiver example doesn't give me the results I was expecting?

I have some examples here:

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

Basically the receiving end does a Wire.requestFrom of the number of bytes it expects. It can then copy those (byte by byte) into a buffer. You might need a bit of typecasting but it can be done.

Hi Guys,
I’m looking for the same thing, I’m new to the i2c bus, and dealing with arrays. I was able to hack together sending multiple int vars as bytes in an array (because their values will always fall within 0-255, so I’m okay there), but what I’m struggling with is where they get positioned in the array on the receiving end. For me, it is skipping position 1. so for example, if I send 2 byte values in an array, myArray[0] == the correct value, but the second byte is not in [1], it shows up in [2]. I’m sure I’m missing something simple :slight_smile:

Here’s my “Slave sender” sub:

void requestEvent()
{
  Serial.println(tempF);
  Serial.println(humidity);
  Serial.println("-----");
  myData [0] = tempF;
  myData [1] = humidity;
  Serial.println(myData[0]);
  Serial.println(myData[1]);
        
  Wire.send((byte *) myData, sizeof myData);
 
}

…and here’s my “Master receiver” code:

byte index = 0;
  Wire.requestFrom(2, 3);
  while (Wire.available() > 0 && index <3)
  {
    wireArray[index] = Wire.receive();
    index++;
  }

  int data0 = wireArray [0];
  int data1 = wireArray [1];
  int data2 = wireArray [2];

so, I can’t figure out why on the receiving end, my two byte values show up in data0 and data2, and data1 is “0”. I cant figure out why data1 is skipped when populating the array.

:~

How are myData and wireArray declared? That is crucial to understanding the problem.

  int data0 = wireArray [0];
  int data1 = wireArray [1];
  int data2 = wireArray [2];

wireArray is presumably a byte array. So, why are data0, data1, and data2 ints?

Hi guys, thanks for jumping in!

wireArray is defined globally as:

byte wireArray[4];

…and myData is defined globally as:

int myData[2];

As i understand it Wire.send cannot send int’s, so I am defining the array as int, then converting it to bytes with (byte *)

on the receiving end, if I have the variables defined as bytes, i just get junk when I println them to Serial, but when they’re int’s i get my actual values.

I tried one thing just for testing, i extended the array on the receiving side and printed to serial, and I see that I always get the array position following the one with actual data, populated with a zero. So for example, If I am sending 2 bytes, and on the receiving end I write out 5 positions to an array, (and lets assume my two bytes are “45” and “75”) I get “45,0,75,0,255”.

I understand the “255” is a null value and that’s what I would expect from an empty value in a byte array, but what I would expect to get when writing the 2 bytes and then reading the array is “45,75,255,255,255”, indicating 3 empty values. Is my code interpreting a carriage return or something?

If you are sending an int array (cast as bytes), you need to receive the data into an int array (cast as bytes).

If you are sending 2 ints (4 bytes), you need to request (and get) 4 bytes from Wire.

When you get 4 bytes, in wireArray:

int val1 = (wireArray[0] << 8) + wireArray[1];
int val2 = (wireArray[2] << 8) + wireArray[3];

That makes sense. We’re getting closer, but trying to byte cast is giving me garbage output. When I take the values of the array as follows, I get a non-nonsensical result:

array values:
wireArray[0] = 73
wireArray[1] = 0
wireArray[2] = 46
wireArray[3] = 0

code:

int val1 = (wireArray[0] << 8) + wireArray[1];
int val2 = (wireArray[2] << 8) + wireArray[3];

output:
val1 = 18688
val2 = 11776

In the sender, print out the highByte() and lowByte() parts of each int.

In the receiver, print the whole array received.

The highByte() value for int 1 should be in either position 0 or 1 in the array. The lowByte() value should be in the other position. It is the highByte() position that gets left-shifted 8 bits.

The highByte() value for int 2 should be in either position 2 or 3 in the array. The lowByte() value should be in the other position. Again, it is the highByte() position that gets left-shifted 8 bits.

So, you might need to have:

int val1 = (wireArray[1] << 8) + wireArray[0];
int val2 = (wireArray[3] << 8) + wireArray[2];

That did it! actually I did not make any changes to my sender, but I switched the array positions for converting byte to int, and now my vals are correct. I just did wireArray[1] then wireArray[0], and we're good.

Thank you!

I have more Wire. questions, but I'll start a new thread, as they are off-topic for the OP's question.

Just to round up what I ended up doing, I grabbed the EasyTransfer library which does everything I wanted and made it simple too :)

Bill Porter rules! http://www.billporter.info/easytransfer-arduino-library/