I2C architecture


hello,
i try establish dialog master slave using i2c bus.
the master send "order" , slave must send response.
the order small structure:

code: [select]

union i2c_order{
struct order{
unsigned char masterorder;
unsigned int masterparam;
bool logicaloutput2;
} order;
char byteval[sizeof(order)];
};



the response small structure:
code: [select]

union i2c_slave_response{
struct response{
weight_output weight;
boolean logical1;
boolean logical2;
float floatparameter;
unsigned char parameter; 
unsigned char error;
} response;
char byteval[sizeof(response)];
unsigned char i2c_address;
};


i use method send order (and response):
code: [select]

i2c_slave_response i2c_tools::getdatafromdevice(unsigned char i2cdevice, i2c_order order){
  i2c_slave_response response;
  response.i2c_address = i2cdevice;
  wire.begintransmission(i2cdevice);
  if (!wire.endtransmission()){
    wire.begintransmission(i2cdevice);
    (unsigned char = 0; < sizeof(i2c_order); i++){
       wire.write(order.byteval[i]);   
    }
    wire.endtransmission();
    delay(5); // necessary !!!!
    wire.requestfrom(i2cdevice, sizeof(i2c_slave_response));
   
    unsigned char = 0;
    switch (wire.available()){
      case sizeof(i2c_slave_response):
          while(wire.available()){
            response.byteval[i++] = wire.read();
          }
      break;

      default: response.response.error = i2c_bad_response_format;
   displayremoteresponse(response);
      break;               
    } // switch on receive size
  } else {
#ifdef debug
    serial.print(f("device i2c adress: ")); serial.print(i2cdevice, dec); serial.println(f(" not responding"));
#endif
    response.response.error = i2c_device_not_responding;   
  }
  return response;
}



in slave device, have methods:
code: [select]

// i2c regsitration
  wire.begin(scale.hiveconf.i2c_address);
  wire.onrequest(i2crequestevent);
  wire.onreceive(i2creceiveevent); // register event


basically, have switch in on i2creceiveevent method identify "order"

and send response int method:
code: [select]

wire.write(response.byteval, sizeof(i2c_slave_response));   


so if order "sending value" work well.

if order more complicated, requesting temperature using dalas library, system work many times, after may 20 cycles of master / slave exchange, slave crash !

is problem in architecture ?

what can reason of slave crash ?

any welcome.

best regards

thierry vorms

you shouldn't return struct or array value.

best systems little ram, avoiding dynamic memory, if caller provides memory function fill in result (by reference) , return ok status.

code: [select]
bool i2c_tools::getdatafromdevice(byte i2cdevice, i2c_order& order,  i2c_response& response) {
  response.i2c_address = i2cdevice;
  wire.begintransmission(i2cdevice);
  if (!wire.endtransmission()){
    wire.begintransmission(i2cdevice);
    (unsigned char = 0; < sizeof(i2c_order); i++){
       wire.write(order.byteval[i]);   
    }
    wire.endtransmission();
    delay(5); // necessary !!!!
    wire.requestfrom(i2cdevice, sizeof(i2c_slave_response));
   
    unsigned char = 0;
    switch (wire.available()){
      case sizeof(i2c_slave_response):
          while(wire.available()){
            response.byteval[i++] = wire.read();
          }
      break;

      default:
          response.response.error = i2c_bad_response_format;
          displayremoteresponse(response);
          return false;               
    } // switch on receive size
  } else {
#ifdef debug
    serial.print(f("device i2c adress: ")); serial.print(i2cdevice, dec); serial.println(f(" not responding"));
#endif
    response.response.error = i2c_device_not_responding;
    return false;   
  }
  return true;
}


of course use real c pointers instead of c++ references, need more changes code...


Arduino Forum > Using Arduino > Programming Questions > I2C architecture


arduino

Comments