come inviare pacchetti di dati via i2c tra due arduino?

Cari ragazzi, sono felice che questo post abbia finito col porre le basi di tanti fecondi sviluppi.
Comunque, ieri sera sono riuscito con un po’ di culo a fare quel che mi serviva in modo piuttosto semplice, senza comporre e scomporre stringhe.
È molto banale ma bastava spedire un byte alla volta in sequenza e leggerne uno alla volta.
Una cosa così per il master :

byte x1 = map(analogRead(A0),0,1023,0,255);
byte x2 = map(analogRead(A1),0,1023,0,255);
byte x3 = map(analogRead(A2),0,1023,0,255);
{
  Wire.beginTransmission(5); // transmit to device #4

  Wire.write(x1);              // sends one byte  
  Wire.write(x2);              // sends one byte  
  Wire.write(x3);              // sends one byte  

  Wire.endTransmission();    // stop transmitting
}

E una cosa così per lo slave :

void receiveEvent(int howMany)
{
  while(1 < Wire.available()) // loop through all but the last
  {
    byte x1 = Wire.read(); 
    byte x2 = Wire.read(); 
    byte x2 = Wire.read(); 
    
    Serial.print(x1);         
    Serial.print(",");         
    Serial.print(x2);         
    Serial.print(",");         
    Serial.println(x3);         

 
  }       // print the integer

Non pensavo fosse così semplice, non so se la cosa si complessifichi molto mandando valori differenti da quello che é un byte per volta, come qui, ma per fortuna è quello che serviva a me per ora.
Poi vedrò come implementare meglio un sistema di richieste e risposte. Se a qualcuno servisse, così dovrebbe funzionare. :wink:

byte x1 = map(analogRead(A0),0,1023,0,255);

credo che potresti anche scrivere

byte x1 = analogRead(A0)/4;

Arrivo solo ora, non ho letto tutto il thread, scusate se dico qualcosa già detto. La Wire è implementata in HW nel senso che ci sono apposite circuiterie per fare il lavoro sporco di agganciarsi alla linea TWI. La ricezione avviene tramite HW/SW: la periferica riceve un carattere e contemporaneamente "suona" un interrupt di modo da avvertire la ISR preposta alla ricezione, che salva quel byte. Poi ci sono tutte le procedure per gestire i dati e su come agganciare le periferica sul bus.

meglio ancora: la twi lavora sull'hardware, la wire sono utility che lavorano sulla twi per renderela più "umana".

quindi l'idea è di rifare una wire meno umana ma più blindata.

PaoloP: byte x1 = map(analogRead(A0),0,1023,0,255);

credo che potresti anche scrivere

byte x1 = analogRead(A0)/4;

Eh si è vero! :-)

byte x1 = analogRead(A0)>>2;

tutte le divisioni che sono potenze di 2 (quindi 2^x) possono essere sostituite da un bitshift a destra di x posizioni

Più che altro il map mi era comodo perché a volte uso range diversi, ad esempio per i servi, ma grazie della dritta ;-)

Ciao Ragazzi, sto cercando di chiedere allo slave lo stato di N digital input ma penso di sbagliare qualcosa, mi sapreste aiutare?

ecco il master:

#include <Wire.h>
int Button_2 = 2;
int Button_3 = 3;
int Button_4 = 4;
int Button_5 = 5;
int led12 = 12;
int led11 = 11;
int led10 = 10;
//---- Analog input ---------
int Adc0 = A0; // W totali
int Adc1 = A1; // W prese
int Adc2 = A2; // W luci
int Adc3 = A3; // W cucina
int Adc6 = A6; // W solare prodotto
int Adc7 = A7; // W lavatrice
//— Variabili analogiche—
int val0 = 0;
//—Memorie analogiche------
int val0M = 0;
//---------------------------
int tx = 0;
//—Variabili digitali ----
int on2=0;
int on3=0;
int on4=0;
int on5=0;
//-----Memorie digitali------
int on2M=0;
int on3M=0;
int on4M=0;
int on5M=0;
byte on12=0;
byte on11=0;
byte on10=0;

//------------------------------------------------
void setup()
{
pinMode (Button_2, INPUT);
pinMode (Button_3, INPUT);
pinMode (Button_4, INPUT);
pinMode (Button_5, INPUT);
pinMode (led12, OUTPUT);
pinMode (led11, OUTPUT);
pinMode (led10, OUTPUT);
pinMode (Adc0, INPUT);
pinMode (Adc0, INPUT);
pinMode (Adc1, INPUT);
pinMode (Adc2, INPUT);
pinMode (Adc3, INPUT);
pinMode (Adc6, INPUT);
pinMode (Adc7, INPUT);
Wire.begin();
Serial.begin(19200);
Serial.println(“START”);
}
//-----------------------------------------------
void cambiostatoinput ()
{
if (on2 != on2M) tx = 1;
if (on3 != on3M) tx = 1 ;
if (on4 != on4M) tx = 1 ;
if (on5 != on5M) tx = 1 ;
if (val0 > (val0M+1)) tx = 1 ;
if (val0 < (val0M-1)) tx = 1 ;
}
//-----------------------------------------------
void Pulsante ()
{
on2 = digitalRead (Button_2);
on3 = digitalRead (Button_3);
on4 = digitalRead (Button_4);
on5 = digitalRead (Button_5);
val0 = analogRead (Adc0);
}
//----------------------------------------------
void loop()
{
Pulsante();
cambiostatoinput ();
if (tx == 1)
{
Wire.beginTransmission(0x04);
Wire.write(on2);
on2M = on2;
Wire.write(on3);
on3M = on3;
Wire.write(on4);
on4M = on4;
Wire.write(on5);
on5M = on5;
Wire.write(val0);
val0M = val0;
tx = 0;
Wire.endTransmission();
Serial.println(“Trasmesso”);
}
//------- richiedo dati-----------------------
Wire.requestFrom(0x04, 6);
while(Wire.available())
{on12 = Wire.read();
on11 = Wire.read();
on10 = Wire.read();
}
if (on12 == 1){digitalWrite(led12, HIGH);}
else{digitalWrite(led12, LOW); }
if (on11 == 1){digitalWrite(led11, HIGH);}
else{digitalWrite(led11, LOW); }
if (on10 == 1){digitalWrite(led10, HIGH);}
else{digitalWrite(led10, LOW); }

}

e lo slave:

#include <Wire.h>
int LED2 = 2;
int LED3 = 3;
int LED4 = 4;
int LED5 = 5;
int analog = 6;
int button10 =10;
int button11 =11;
int button12 =12;
//---- le variabili------------------------------
int on2 = 0;
int on3 = 0;
int on4 = 0;
int on5 = 0;
int val = 500;
byte on10 = 0;
byte on11 = 0;
byte on12 = 0;
//------------------------------------------------
void setup()
{
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
pinMode(LED5, OUTPUT);
pinMode (analog, OUTPUT);
pinMode (button10, INPUT);
pinMode (button11, INPUT);
pinMode (button12, INPUT);
Wire.begin(0x04);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
}
//------------------------------------------------
void receiveEvent(int data)
{
on2 = Wire.read();
on3 = Wire.read();
on4 = Wire.read();
on5 = Wire.read();
val = Wire.read();
}

//-----------------------------------------------
void requestEvent()
{
on10 = digitalRead (button10);
on11 = digitalRead (button11);
on12 = digitalRead (button12);
if (on10 == 1){ Wire.write(1);}
else {Wire.write(0);}
if (on11 == 1){ Wire.write(1);}
else {Wire.write(0);}
if (on12 == 1){ Wire.write(1);}
else {Wire.write(0);}
}
//-----------------------------------------------

void loop()
{
if (on2 == 1){digitalWrite(LED2, HIGH);}
else{digitalWrite(LED2, LOW); }
if (on3 == 1){digitalWrite(LED3, HIGH);}
else{digitalWrite(LED3, LOW); }
if (on4 == 1){digitalWrite(LED4, HIGH);}
else{digitalWrite(LED4, LOW); }
if (on5 == 1){digitalWrite(LED5, HIGH);}
else{digitalWrite(LED5, LOW); }
tone(analog,(val*100));

La trasmissione dal Master allo slave funziona perfettamente ma non il contrario

Aggiornamento

ho visto che lo slave manda un solo treno di bit anche se si susseguono diversi Wire.write !!

Quindi nello slave ho implementato questa assurda funzione per inviare lo stato di soli 3 input al Master:

void requestEvent() { Serial.println("richiesta dati"); on10 = digitalRead (button10); on11 = digitalRead (button11); on12 = digitalRead (button12);

Serial.println(on10); Serial.println(on11); Serial.println(on12);

if (on10 != 1 && on11 != 1 && on12 !=1){ Wire.write(000);} if (on10 == 1 && on11 != 1 && on12 !=1){ Wire.write(100);} if (on10 != 1 && on11 == 1 && on12 !=1){ Wire.write(010);} // in questo caso invia il valore 8 if (on10 == 1 && on11 == 1 && on12 !=1){ Wire.write(110);} if (on10 != 1 && on11 != 1 && on12 ==1){ Wire.write(001);} if (on10 == 1 && on11 != 1 && on12 ==1){ Wire.write(101);} if (on10 != 1 && on11 == 1 && on12 ==1){ Wire.write(011);} if (on10 == 1 && on11 == 1 && on12 ==1){ Wire.write(111);} }

e sul master il relativo opposto di decodifica

Mipare assurdo che mi debba sviluppare una tabella booleana con tutte le condizioni per svolgere questa funzione

Vorrei realizzare una rete come in foto per implementare funzioni alla mia domotica che gira su un PLC ma non potendo passare piu cavi per cas)tubi saturi) ho pensato di sfruttare gli ultimi cavi rimasti liberi per I2C convertendo prima il segnale con i max485

mirkoelettronics:
Vorrei realizzare una rete come in foto per implementare funzioni alla mia domotica che gira su un PLC ma non potendo passare piu cavi per cas)tubi saturi) ho pensato di sfruttare gli ultimi cavi rimasti liberi per I2C convertendo prima il segnale con i max485

Non puoi.
L’RS485 va messo sulla seriale. Poi puoi comunque farti un sistema con master/multimaster/id … come in IIC, ma devi farlo tutto ia software…

Non vedo una buona idea far andare in giro per casa una I2C , è fatta per distanze inferiori ai 30cm

Salve a tutti ragazzi, ho letto e seguito questo vecchio post ma continuo ad avere dei problemi con questo protocollo, ho bisogno di inviare e ricevere più variabili tra 2 arduino nao, credo che nell invio da master a slave sia quasi tutto ok, ma quando richiedo come master di ricevere dei dati da slave, mi arriva solo e sempre una sola variabile giusta, ho utilizzato l’esempio base che esiste anche nella ide di arduino ma niente…sicuramente sbaglio qualcosa nel master perchè non è possibile. se invio 1 sola variabile ok, se ne invio 2 mi arriva la 2° al posto della 1° e come 2° mi arriva un numero massimo di 255, se ne invio 3 stessa cosa, mi arriva per prima la 3° e come 2° e 3° mi arrivano numeri massimi di 255.
Codice Master

#include <Wire.h>
int x=0;
int y=0;
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}

void loop()
{
Wire.requestFrom(8, 2); // request 6 bytes from slave device #8

while (Wire.available()) // slave may send less than requested
{

x=Wire.read();
y = Wire.read();
Serial.println(x); // print the character
Serial.println(y);
}

delay(1000);
}

Codice Slave:
#include <Wire.h>
int lettura = {2,7};
void setup()
{
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(myHandler); // register event
}

void loop()
{
delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void myHandler()
{
Wire.write(lettura[0] );
Wire.write(lettura[1] );

}

Nel caso postato sopra, mi arriva al master il numero 7 e il numero 255......

>rubex: prima di tutto, NON avendolo tu ancora fatto, nel rispetto del regolamento, ti chiedo di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione … possibilmente evitando di scrivere solo una riga di saluto) e di leggere con attenzione il su citato REGOLAMENTO

… poi, in conformità al suddetto regolamento, punto 7, devi editare il tuo post (in basso a destra del post, bottone More → Modify) e racchiudere il codice all’interno dei tag CODE (… sono quelli che in edit inserisce il bottone fatto così: </>, tutto a sinistra) …

… infine, sempre con riferimento al regolamento … il punto 16.9 ti chiarisce perché ho chiuso il thread. Se vuoi continuare la discussione, ne apri uno nuovo, spieghi i problemi e, al limite, fai riferimento ai post di questo thread.

Guglielmo