COMUNICACION I2C

Estoy haciendo un proyecto con arduino.
A la hora de comunicar datos entra dos arduinos, solo consigo trasferir valores int hasta 255. Cuando introduzco un numero mayor lo reduce a un byte.
envio codigo master:

#include <Wire.h>

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

int x = 0;

void loop() {
 Wire.beginTransmission(8); // transmit to device #8
 Wire.write("x is ");        // sends five bytes
 Wire.write(x);              // sends one byte
 Wire.endTransmission();    // stop transmitting
 Serial.print("x es:  ");
 Serial.println(x);
 x++;
 delay(250);
}

y codigo slave:

#include <Wire.h>

void setup() {
 Wire.begin(8);                // join i2c bus with address #8
 Wire.onReceive(receiveEvent); // register event
 Serial.begin(9600);           // start serial for output
}

void loop() {
 delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
 while (1 < Wire.available()) { // loop through all but the last
   char c = Wire.read(); // receive byte as a character
   Serial.print(c);         // print the character
 }
 int x = Wire.read();    // receive byte as an integer
 Serial.println(x);         // print the integer
}

el codigo funciona bien hasta 255, cuando el master envia 256 el slave lee 0

Pienso que puede ser definicion de tipo de dato.

Querria un ejemplo de la instruccion: Wire.write(data, length)

Muchas gracias

Wire.write(x, DEC);

Muchas gracias GO_zalo.
he hecho el cambio a :

Wire.write(x, DEC);

y al compilar me da este error:

call of overloaded 'write(byte&, int)' is ambiguous

Pues prueba a cambiar:

Wire.write("x is ");        // sends five bytes
Wire.write(x);              // sends one byte

Por:

char buffer[30];
sprintf (buffer, "x is %d", x);
Wire.write(buffer);

Muchas gracias GOL_zalo, nos vaños acercando

La transmision de un numero del master al esclavo se produce correctamente pero el último digito se representa en ASCII.

y me explico

master envia 0 esclavo lee 48
master envia 10 esclavo lee 148
master envia 11 esclavo lee 48

Muchas gracias GOL_zalo, nos vamos acercando

La transmision de un numero del master al esclavo se produce correctamente pero el último digito se representa en ASCII.

y me explico

master envia 0 esclavo lee 48 en ascii 0=48
master envia 10 esclavo lee 148 en ascii 0=48
master envia 12 esclavo lee 150 en ascii 2=50
master envia 125 esclavo lee 1253 en ascii 5=53
master envia 348 esclavo lee 3456 en ascii 8=56

perdona que el anterior mensaje fuera erroneo

es que claro con este sistema no te vale leer las letras y luego leer un int, por que lo que estas mandando son todo letras

Con esto deberías recuperar todo el string,

{
char buffer[30];
  for (i=0;Wire.available();i++) { // loop through all but the last
    buffer[i] = Wire.read(); // receive byte as a character
    Serial.print(buffer[i]);         // print the character
  }
buffer[i+1]='\0';

}

Ahora yo recorreria el string en busqueda del primer espacio en blanco y cuando lo encuentre recorreria en busqueda de un '\0' que significa que ha acabado el string esta parte de la dejo a ti para que te esfuerces un poco, son dos bucles.

Luego cuando has aislado los numeros del texto aun te queda pasarlos a un int... creo que este metodo se esta complicando pero se puede hacer.

es cuestion de primer contar la cantidad de numeros (sizeof(variable)-1 el menos uno por el '\0') y entonces para con un for (i=0;i<sizeof(variable); i++) recorres el string, y vas haciendo result +=(buf2_-'0')10(sizeof(variable)-1)*i_
Se entiende que result es el int inicializado a 0 y que el -'0' es para restar 48 que es en el asci el numero 0
No se si me explico, aun que seguro que hay una manera mas sencilla

Hola GO_zalo, buenos días y michas gracias por tu interés.
Quiero decirte que mis conocimientos sobre programación son muy básicos tanto en C como en el Arduino.
Dicho lo cual, pienso que no he enfocado bien el tema porque mi problema es trasmitir de un arduino master a arduino esclavo un numero entero (int) comprendido entre -32767 y 32767.
No necesito trasmitir caracteres.
Posiblemente el mal enfoque por mi parte en por haber empleado los ejemplos que vienen en el IDE de Arduino de La librería Wire master_writer y slave_receiver, en los que se trasmiten y reciben datos de tipo char.
He modificado los programas quitando los datos char.

En master:*************************

// VAMOS A TRANSFERIR UN NUMERO ENTERO DE MASTER A ESCLAVO

#include <Wire.h>


int numero;

void setup() {
 Wire.begin(); // join i2c bus (address optional for master)
 Serial.begin(9600);          //  Inicialización del modulo Serial.
}


void loop() {

 Serial.println("INTRODUCIR NUMERO");
 while (Serial.available()==0){  }// Espera a introducir la posicion

 numero=Serial.parseInt(); // Leo numero
// x=numero;
Wire.beginTransmission(8); // transmit to device #8
 Wire.write(numero);              // sends one byte
 Wire.endTransmission();    // stop transmitting

Serial.print("NUMERO:  ");
Serial.println(numero);
 delay(500);
}

En slave:***************************

// VAMOS A RECIBIR UN NUMERO ENTERO DE MASTER A ESCLAVO




#include <Wire.h>

void setup() {
 Wire.begin(8);                // une el bus i2c con la EL ESCLAVO #8
 Wire.onReceive(receiveEvent); // evento registrado
 Serial.begin(9600);           // inicia serial para salida
}

void loop() {
 delay(100);
}


//función que se ejecuta cada vez que se reciben los datos de maestro
// Esta función se ha registrado como un evento, consulte setup ()

void receiveEvent(int howMany)
{
/*
 while (1 < Wire.available())
 { // loop through all but the last
   char c = Wire.read(); // receive byte as a character
   Serial.print(c);         // print the character
 }
 */
 int x = Wire.read();    // receive byte as an integer
 Serial.print("NUMERO: ");
 Serial.println(x);         // print the integer
}

Y como te comente en mi primera comunicación:
el codigo funciona bien hasta 255, cuando el master envia 256 el slave lee 0.

Muchas gracias

Cuando tienes dudas investiga por tu cuenta y ve a la fuente en el Arduino Playground
Si buscas Arduino wire.write encuentras esto

write()

Description

Writes data from a slave device in response to a request from a master, or queues bytes for transmission from a master to slave device (in-between calls to beginTransmission() and endTransmission()).

Syntax

Wire.write(value)
Wire.write(string)
Wire.write(data, length)

Parameters

value: a value to send as a single byte

string: a string to send as a series of bytes

data: an array of data to send as bytes

length: the number of bytes to transmit

Returns

byte: write() will return the number of bytes written, though reading that number is optional

O sea.
Los valores los envia como bytes simples
Si quieres puedes enviar mas bytes como con .write(data, lenght)
por ende para enviar un entero, debes enviar 2 bytes
o sea longitud 2.

Wire.write(entero,2); //debería funcionar

Ahora read, solo lee de a 1 byte por vez, de modo que si envias algo de mas bytes debes unir en la recepción la trama
De acuerdo a esto. En tu programa maestro lees del puerto serie un entero con ParseInt, lo envías.
Aparentemente lo hace bien porque funciona mientras recibe 1 byte (hasta 255) pero luego falla porque el entero es 256 en adelante y ahi son dos bytes
entonces modifica tu Slave asi
Esta rutina

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while (1 < Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

Se comporta de un modo cuando no esta comentada y de otro cuando comentas la parte en que recibi los dos bytes individualmente.
Debería funcionar bien completa.
Si te molesta el resultado parcial de los caracteres comenta solo //Serial.print(c);

Muchas gracias Surbyte.
Ya he probado para trasmitir dos bytes con la instrucción Wire.write(data, length) y al compilar me da un error que dice:

call of overloaded 'write(int&, int)' is ambiguous

Entonces la info es vieja o tu IDE es mas nuevo.
Por eso cuando comiences una consulta indica que IDE usas.
yo ahora pruebo si quieres porque tengo un ejemplo con proteus y dos arduinos comunicandos y enviandose 7 bytes
pero en mi caso no queria mas que leer la trama
Tu quieres leer enteros

egarde:
Muchas gracias Surbyte.
Ya he probado para trasmitir dos bytes con la instrucción Wire.write(data, length) y al compilar me da un error que dice:

call of overloaded 'write(int&, int)' is ambiguous

Entiendo que necesitas hacer un cast en tu llamada. Pon el código que te da ese error y lo miramos.

creo que deberias enviar byte a byte asi:

Wire.write(0x00FF&numero);              // Byete bajo
Wire.write(0x00FF&numero>>8);              // Byete alto

Y leerlo como:

char c = Wire.read(); // receive byte as a character
char c1 = Wire.read(); // receive byte as a character

int x=c1<<8|c; aqui recomponemos los dos bytes en un int

Hace un tiempo habia armado una simulación master slave I2C.
En algun punto me detuve y ahora veo porqué.
Por alguna razón el programa sea cual sea empieza enviando datos pero luego no funciona mas.
Asi que si no lo pruebo no se si funciona o no.
Por el momento lo que sugiere Go_zalo es lo mejor.
Otra alternativa es que envies un string y luego lo pases a entero.

No se porque no funciona bien en Proteus.

Yo todos estos temas me gusta hacerlos en binario directamente, ya que es la manera más económica y sencilla (aunque en principio no lo parezca). Se trata de aplicar la misma filosofía para enviar cualquier dato o incluso estructura que la que utilizamos para guardarlos en EEPROM, por ejemplo. Sólo se trata de aprovechar bien el Wire.write(data, length).

Pero dice que Wire.write(data, length) le da error.
Que esta pasando?

Ya he probado para trasmitir dos bytes con la instrucción Wire.write(data, length) y al compilar me da un error que dice:

call of overloaded 'write(int&, int)' is ambiguous

Pero dice que Wire.write(data, length) le da error.
Que esta pasando?

Ya he probado para trasmitir dos bytes con la instrucción Wire.write(data, length) y al compilar me da un error que dice:

call of overloaded 'write(int&, int)' is ambiguous

Ahhh ya veo.. lo usó mal aparentemente?

Exacto.
Tirándome un poco al río, me imagino que habrá hecho algo así como:

int valor;
wire.write(&valor, 2);

Y la solución será algo así como

wire.write( (byte *) &valor, 2);

Aunque no lo he comprobado, porque ando un poco varado por el sublime, que no me termina de chutar bien.

Tengo el mismo problema

Hilo cerrado.
@afelio no debes responder Topicos que tienen 4 meses sin movimientos.
Crea tu propio hilo y luego de leer las normas coloca la referencia a éste para que quien te vaya a responder pueda valerse de esta información.