Comunicación I2C no funciona.

Hola, soy nuevo en esto del Arduino, antes he programado PIC, y en el proyecto fin de carrera tengo que usar un Arduino.

Estoy intentando mandar la configuración a un sintonizador por I2C. El hardware está bien, pues con un PIC consigo sintonizar la emisora para la que es configurada, pero con el Arduino no hay manera.

En la simulación en Proteus, ocurre lo mismo, con el PIC salen los datos correctos por el bus, pero con el Arduino solo llega un dato y es erroneo.

El código del Arduino es este:

#include <Wire.h>

int ledPin =  13;    // LED connected to digital pin 13

void setup() {
  pinMode(ledPin, OUTPUT);
  Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;

void loop() {
  x = 0xC2;
  Wire.beginTransmission(x);//DIR_SINTO); // transmit direccion
  x = 0x08;
  Wire.send(x);//ParteAlta);   // sends ParteAlta
  x = 0x31;
  Wire.send(x);//ParteBaja);   // sends ParteBaja 
  x = 0x8E;
  Wire.send(x);//CONF_1);   // sends configuración general.
  x = 0xA0;
  Wire.send(x);//Banda);   // sends configuración de la banda.
  Wire.endTransmission();    // stop transmitting
  
  digitalWrite(ledPin, HIGH);
  delay(5000);
  digitalWrite(ledPin, LOW);    // set the LED off
  delay(5000);                  // wait for a second
}

Y en el pic envio la misma configuración:

i2c_start();
i2c_write(0xC2);//dirección
i2c_write(0x08);//parte alta 
i2c_write(0x31);//parte baja 
i2c_write(0x8E);//configuración general.
i2c_write(0xA0);//configuración de la banda.
i2c_stop();

He probado a poner resistencias de pull-up entre 1K y 4K7, a acortar los cables del bus, a recargar el botloader del micro... y no consigo hacerlo funcionar. Solo me falta cambiar el micro, pero eso me va a tardar unos dias pues lo tendria que pedir.

Espero que alguien me pueda echar una mano.

Saludos.

Hola de nuevo, al menos me gustaria saber si el codigo del Arduino es correcto. He visto varios ejemplos de comunicación I2C como maestro, y se hace de esa forma, pero quizás tengo algo mal.

Pues mirando el código parece estar perfecto. A mi el I2C me funciona tanto en Proteus como en real.

Mira a ver si ArduBus te soluciona la papeleta, ya que lo cree precisamente para estos casos, lo puedes encontrar en:
http://wiki.kungfulabs.com/arduino/ardubus

Un saludo

Gracias por la respuesta chiva.

El enlace que me pones resulta muy interesante, pero no entiendo muy bien como funciona. Veamos, para mi caso tendria que enviar estos comandos:

2 --> Para seleccionar 100KHz
{0xC2}
{0x08}
{0x31}
{0x8E}
{0xA0}

Es lo que estoy haciendo, pero no veo respuesta alguna.

La configuración del COM está bien, pues el mensaje donde aparece la selección de frecuencia me aparece.

Saludos.

Si estás usando el terminal/monitor que viene con Arduino (el cual desaconsejo usar) deberás cambiar el modo de funcionamiento de 'No line ending' a 'Carriage return'.

Lo que deberías mandar es {0xC2 0x08 0x31 0x8E 0xA0} + Intro
^ ----------------------
| datos
dirección

Un saludo

Bueno, he probado como me dijiste, y el simulador parece que funciona, pero del Arduino no sale nada por el bus.

He montado también un clon del PicKit Serial Analizer de Microchip, y no sale nada por el bus del Arduino, sin embargo como dije con el programa equivalente en un PIC, me muestra los datos que envio correctamente.

Por lo que deduzco que me he cargado el micro del Arduino, no sé muy bien como, pues solamente he echo conexiones en los pines de alimentación y los del bus I2C (4 y 5 analogicos).

El resto del micro parece funcionar bién, el led del pin 13 parpadea, y se pueden cargar los programas. Y el regulador y el transistor que conmuta la alimentación también.

Asique no sé, pediré un micro, a no ser que se os ocurra otra cosa.

Saludos.

PD: Chiva, ¿Que versión de Proteus usas? ¿Podrias simular el código que puse? Gracias.

Bueno, el tema está solucionado, el problema era la dirección del dispositivo.

La dirección del dispositivo es 0xC2, (0b11000010) pero en el programa del Arduino se debe poner esa dirección rotada a la derecha un bit, osea 0x61 (0b01100001).

Eso es todo el problema, al parecer el compilador de CCS hace esa operación y se le pasa la dirección tal cual (0xC2).

Saludos.

En realidad la dirección del dispositivo no es 0xC2, es 0x61. Si miras la especificación del bus I2C verás que la dirección se expresa con 7 bits, esto es, que se pueden manejar hasta 127 dispositivos de 0x01 al 0x7F ya que el 0x00 es "de acceso general" para todos los dispositivos que tengamos conectados en el BUS.

La confusión está en que el BUS I2C usa el bit menos significativo para indicar el tipo de operación: Si es 0, significa que queremos escribir y si es 1 significa que es una operación de lectura.

Por poner un ejemplo, si queremos escribir en el dispositivo 0x61 tengo que enviar el byte 0xC2, pero si quiero leer de este mismo dispositivo, tendré que enviar el 0xC3. En ambos casos la direción real del dispositivo es 0x61.

No entiendo esa ultima parte, yo estoy poniendo el el programa Wire.beginTransmission(0x61); ¿Con eso le estoy enviando 0xC2?

Entonces para leer el dispositivo ¿Tendria que poner Wire.beginTransmission(0x62);? y con eso ¿Envio 0xC3?

Si te fijas en las funciones de la librería wire Wire - Arduino Reference , que es la encargada de manejar el I2C, encontramos la siguiente explicación:

"There are both 7- and 8-bit versions of I2C addresses. 7 bits identify the device, and the eighth bit determines if it's being written to or read from. The Wire library uses 7 bit addresses throughout. If you have a datasheet or sample code that uses 8 bit address, you'll want to drop the low bit (i.e. shift the value one bit to the right), yielding an address between 0 and 127. "

Explicla claramente que todas las funciones de esta librería usan la direción real de 7 bits del dispositivo.

Cuando pones Wire.beginTransmission(0x61); significa que vas a comunicarte con el dispositivo 0x61, si quieres hacer una escritura usaras Wire.send(); y si quieres leer de este dispositivo Wire.receive();
Tienes ejemplos de todo esto en el propio IDE de Arduino

OK, comprendido, estoy acostumbrado al CCS para los PIC, y nunca profundicé en las direcciones de los dispositivos I2C, simplemente ponia la que viene en las hojas de datos de dichos dispositivos, que son de 8bit, incluyendo el bit que indica si se escribe o se lee.

A la cama no te irás sin saber una cosa más.

Saludos.