Chiarimenti I2C

Buongiorno ragazzi, sto giocherellando con due Arduino, su uno ho caricato lo sketch di esempio slave_receiver, mentre l’altro l’ho collegato tramite jtag e lo programmo con atmel studio 7 per provare inviare dei dati manipolando direttamente i registri (non per una utilità, ma per imparare bene il funzionamento. Son dell’idea che se conosci bene il meccanismo puoi affrontare meglio i problemi).
Allora, son riuscito a inviare i dati, ho provato con due banali lettere, invio in sequenza una A e una o. Il problema è che sul monitor seriale dell’arduino con lo sketch slave_receiver mi viene stampata correttamente la A, ma la o mi viene convertita nel valore decimale 111, quindi il dato che mi ritrovo invece di essere Ao è A111. Ho provato a inviare più dati, vengono stampati correttamente tutti i caratteri, ma l’ultimo è sempre convertito nel suo valore decimale. Pensavo fosse un errore mio, così ho provato a caricare lo sketch master_writer e a inviare la stringa “Ao”, e il serial monitor mi stampa A111 ugualmente.

Lo sketch di prova master_writer è il seguente:

#include <Wire.h>

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

byte x = 0;

void loop() {
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write("Ao");
  Wire.endTransmission();    // stop transmitting

  x++;
  delay(2000);
}

Lo sketch di prova slave_receiver è esattamente quello che propone l’ide senza alcuna modifica:

#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
}

Ho provato a leggere il dato inviato con l’oscilloscopio e i due byte sono corretti.

0001000 (Indirizzo)
0 (W)
0 (Ack)
01000001 (A)
0 (Ack)
01101111 (o ma a monitor seriale diventa 111)
0 (Ack)

Ho provato anche a inviare come ultimo dato il terminatore 0x00 (\0), ma la stampa a monitor seriale diventa Ao(0).
Cosa mi sfugge??? Pensavo fosse un problema del monitor seriale, così ne ho scaricato uno da Internet, ma la stampa è la stessa… In base a cosa “decide” se stamparmi il carattere o il valore decimale del byte??? Grazie infinite in anticipo.

Ma che imbecille… Scusate ragazzi. Postando lo sketch di esempio ho risolto proprio perchè nel copiarlo mi è caduto l’occhio su questo:

int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer*/

Lui essendo abbinato allo sketch master_writer si aspettava che l’ultimo byte fosse un intero. In effetti non modificandolo master_writer incrementa una variabile x e la spedisce come ultimo byte.
Scusatemi, la prossima volta imparo a leggere e non a dare per scontato.
E son giorni che mi ci picchio…

Hai notato che tutti i caratteri, meno l'ultimo, li metti in una variabile char:

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

... mentre l'ultimo lo ricevi come int:

int x = Wire.read();

Quindi ?

Guglielmo

P.S.: la mia risposta si è sovrapposta alla tua :smiley: :smiley: :smiley:

Grazie infinite per la risposta Guglielmo, e scusami se ti ho fatto perdere tempo...
Lorenzo.

Lollo82:
… scusami se ti ho fatto perdere tempo…

… ma figurati :smiley: :smiley: :smiley:

Guglielmo