I2C, Master request integers from slave

Hi! I am having problem requesting two integers or more from slave to master. Here is the code:

Master Code

#include <Wire.h>
int config1, config2, config3;
void setup(){
  Serial.begin(9600);
  getConfig();
}
void loop(){
}
void getConfig(){
  Wire.requestFrom(22, 3);
  while(Wire.available()){
    config1=Wire.read();
    config2=Wire.read();
    config3=Wire.read();
  }
  return;
}

Slave Code

#include <SD.h>
#include <Wire.h>
int config1=10, config2=20, config3=30;
void setup(){
  Serial.begin(9600);
  Wire.begin(22);
  Wire.onRequest(requestEvent);
}
void loop(){
}
void requestEvent(){
  Wire.write(config1);
  Wire.write(config2);
  Wire.write(config3);
}

My ultimate goal is to let the master arduino to read the configuration file from the SD card on the slave Arduino every time the master start up. The configuration file contain some integers, so I need to way to transfer those integers to the master. Any idea why the code won’t work? Thanks!

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

I do realize one integer is two bytes. I tried
Wire.requestFrom(22, 1);
Wire.requestFrom(22, 2);
and Wire.requestFrom(22, 6);
all doesn't seem to work. I also tried passing the integers using highByte, lowByte on the slave side and combine them on the master side but it still doesn't work... any input would be appreciated!

The requestEvent handler must return a single thing (not necessarily a single byte). Read the above for more details.

Oh... that's why I can pass one integer but not two... Thanks!
So a work-around would be to pass those integers as a string to the master, and somehow separate the string into different segment and use the fact that int=char-48 to convert those segments from char to int on the master side? Okay let me try it out... thanks.

Just make a structure or do something like this:

void requestEvent()
  {
  int buf [2];

  buf [0] = 4256;
  buf [1] = 1284;
 
  Wire.write (buf, sizeof buf);  // send 4-byte response
  }

Thank you so much! It works. I am now able to pass "102030" to the master and separation them into config1=10, config2=20 & config3=30 using modular and subtraction. I do have one more quick question though - for example, if my config1 is 100 instead of 10, the message is going to be "1002030". Is there a way to let the master know the config1 is 100, not 10? I personally don't think there is a way to resolve the issue and I'll just have program it very carefully, but I might be wrong.

The method I described above would be more reliable because it doesn’t rely on the length of strings.

Something like this (untested but it compiles):

Master:

#include <Wire.h>
int config1, config2, config3;
void setup()
  {
  Serial.begin(9600);
  getConfig();
  }
  
void loop()
  {
  }

void getConfig()
  {
  union 
    {
    int configs [3];
    byte buf [6];
    } configUnion;
  
  if (Wire.requestFrom(22, sizeof configUnion) != sizeof configUnion)
    return;  // oops!
    
  for (byte i = 0; i < sizeof configUnion; i++)
    configUnion.buf [i] = Wire.read ();
    
  config1 = configUnion.configs [0];
  config2 = configUnion.configs [1];
  config3 = configUnion.configs [2];
}

Slave:

#include <Wire.h>
int config1=10, config2=20, config3=30;

void setup()
  {
  Serial.begin(9600);
  Wire.begin(22);
  Wire.onRequest(requestEvent);
  }
  
void loop()
  {
  }

void requestEvent(){
  union 
    {
    int configs [3];
    byte buf [6];
    } configUnion;
    
  configUnion.configs [0] = config1;
  configUnion.configs [1] = config2;
  configUnion.configs [2] = config3;
  
  Wire.write((byte *) &configUnion, sizeof configUnion);
}

That will work for any numbers including negative ones (that fit into an int, that is).

Thank you so much for all your help. I really appreciate it! :smiley: