Understanding data types and transmission over i2c

Hello!

I am trying to build a datalogger using arduinos and have reached a point where I need to use more than one (in short, there are 7 analog inputs, 5 hall effect inputs (4 of which unfortunately have to come from an analog channel) as well as a G-meter and hopefully a GPS unit all to be written on an SD card)

So far I have gotten the analog, hall effect and G-meters to work independently (which is not much of a feat, I know) but now is the time to piece of all these together.

Which brings me to my problem.
I do not understand how Arduino i2c works in sending data to/from each other.
I understand how the S&M relationship works (har har!) but I do not understand how the data set that is receiving a byte becomes a char, and how to change that.

I refer to this tutorial:

If I understood correctly, the receiving Arduino does not care about what datatype was transmitted, it cares what it was told the data type to be (?)

If that is the case, why does something like this not work:

void requestEvent() {
  Wire.write(analogRead(A0)); 
}

Rather than this code: (which works):

void requestEvent() {
  Wire.write("123"); 
}

This comes from the fact that the transmission is done by first sending "1", then "2" then "3" rather than "123" is that right ?

The end result that I really want is to get the slave arduinos to create and send a string of their collected values (from hall or analog or g-meter) into the master as ready formatted comma separated text so the master can combine these into one ready made csv file

ie:
arduino1 gathers its anlog into: "data0,data1,data2," transmits this when asked for, arduino2 does the same "data3,data4,data5," so the master collects this into "data0,data1,data2,data3,data4,data5,data6,etc"

Sorry for rambling and I hope you can steer me in the right direction.

Thanks.

Not sure what you mean by 'doesn't work':

void requestEvent() {
  Wire.write(analogRead(A0)); 
}

...what does this actually send? Can you try a 'serial.print' at both receiver and transmitter ends to see what's actually being sent through?
If you are using so much i/o, is there a possibility that you are inadvertently trying to use one pin for two different purposes?

quilkin:
Not sure what you mean by 'doesn't work':
...
...what does this actually send? Can you try a 'serial.print' at both receiver and transmitter ends to see what's actually being sent through?
If you are using so much i/o, is there a possibility that you are inadvertently trying to use one pin for two different purposes?

Hi,
Yes I probably should have clarified that.
So, using this code:

#include <Wire.h>
  byte x = analogRead(A0);

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  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() {
  Wire.write("123"); // respond with message of 3 bytes
  // as expected by master
}[/code ]

and this code:
[code]#include <Wire.h>

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

void loop() {
  Wire.requestFrom(8, 3);    // request 3 bytes from slave device #8

  while (Wire.available()) { // slave may send less than requested
    char c = Wire.read(); // receive a byte as character
    Serial.print(c);         // print the character
  }
  delay(500);
}

The serial output is: 123123123123123123 and so on.

But if I replace the

  Wire.write(analogRead(A0));

I only get a gibberdish serial output:

⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮

The A0 pin is only used to connect to a potentiometer, which when using the code below (but not unconnecting any wires:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print(analogRead(A0)); // respond with message of 6 bytes
}
#include <Wire.h>
  byte x = analogRead(A0);

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

try moving the assignment of analogRead into setup() as it should be...

#include <Wire.h>
  byte x;

void setup() {
  x = analogRead(A0);
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event

the hardware is not guaranteed to be ready before setup()

Are you just confusing strings with numerical values?
Wire.Write() can presumably take either a string or a byte value.
If you send a string (e.g. "123") then that's what you'll receive (as you have done)
If you send a byte then that's what you'll receive . So your output
⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
is perhaps the ASCII representation of the byte value from your analog read (repeated several times) that's being sent. Except that standard ASCII doesn't include a backwards question-mark (it does have an upside-down question-mark '¿ ', value 168).

quilkin:
Except that standard ASCII doesn't include a backwards question-mark (it does have an upside-down question-mark '¿ ', value 168).

Nope, ASCII doesn't have an upside-down question mark either. ASCII defines 128 character codes, 0-127. It's a seven-bit code, after all.

christop:
ASCII defines 128 character codes, 0-127. It's a seven-bit code, after all.

technically correct, OK, but this is a bit off the point I was trying to make (comparing strings with byte values).

The upside-down question mark is 'extended ascii'; I can still type it with ALT 168 on my keyboard. I appreciate that different output devices will interpret these values (128-255) differently - e.g. the backwards q-mark that the OP is getting is probably derived from a value between 128 and 255.