come inviare pacchetti di dati via i2c tra due arduino?

Ho tradotto parte del datasheet del 328, riguardante proprio twi guarda caso.
Leggete, se trovate errori postate la traduzione corretta e per chi se la sente traduca anche il resto.

Traduzione non fedele di parte del datasheet ATmega328 (parte 1).
{
L'interfaccia seriale 2-wire (TWI) è la soluzione ideale per le tipiche applicazioni con i microcontrollori
Il protocollo permette al proggettista di sistemi di interconnettore fino a 128 differenti dispositivi
usando solo due line bidirezionali, una per il clock(SCL) e una per i dati (SDA). Il solo hardware esterno
necessario per realizzare il bus è un singolo resistore di pull-up per ogni linea del bus TWI.

Tutti i dispositivi connessi al bus hanno un'indirizzo individuale e i meccanismi per risolvere
la comunicazione sono previsti dal protocollo TWI.

Figura 21-1 TWI Bus interconnection (pag 215)

La terminologia TWI:

  • Master Il dispositivo che inizia e termina la trasmissione e genera anche il clock SCL.
  • Slave Il dispositivo indirizzato dal master
  • Trasmitter Il dispositivo che pone i dati sul bus
  • Receiver Il dispositivo che legge i dati dal bus

Entrambe le linee del bus sono connesse al positivo dell'alimentazione attraverso
un resistore di pull-up. Le porte del bus di tutti i dispositivi compatibili con il bus TWI
sono open-drain o open-collector. Un livello LOW su una linea del bus è generato quando uno
o più dispositivi forniscono in uscita uno zero. Un livello HIGH è presente solo quando
tutti i dispositivi connessi al bus si pongono in alta impedenza, permettendo ai resistori
di pull-up di portare il livello della linea HIGH. Nota che tutti i dispositivi AVR connessi
al bus TWI devono essere alimentati con ordine per permettere alcune operazioni.

Il numero di dispositivi che possono essere connessi al bus è limitato solo dalla capacità
del bus che non deve superare i 400 pF e dalla grandezza di 7-bit dell'indirizzo di slave.

Due set di specifiche sono trattate qui, una per le velocità del bus sotto i 100Khz, e
una valida per velocità del bus fino a 400Khz.

Trasferimenti di bits
Ogni bit trasferito sul bus è accompagnato da un'impulso sulla linea di clock SCL.
Il livello della linea dati SDA deve essere stabile quando la linea SCL è HIGH.
La sola eccezione a questa regola è quando si genera una condizione di start o di stop.

Fig 21-2 Data Validity (pag. 217)

Condizione START e STOP
Il master inizia e termina una trasmissione di dati. La trasmissione è iniziata quando
il master emette una condizione di START sul bus e termina quando il master emette
la condizione di STOP. Dopo una condizione di START il bus è considerato occupato
e nessun altro master dovrebbe provare a prendere il controllo del bus. Uno speciale
caso si verifica quando una nuova condizione di START viene emessa, questa è conosciuta come
condizione REPEATED START ed è usata quando il master desidera iniziare un nuovo
trasferimento senza cedere il controllo del bus. Dopo la condizione REPEATED START
il bus è considerato occupato fino a che una condizione di stopo non viene emessa.
Il comportamento è identico a START, e quindi in tutto il documento START è utilizzato
per descrivere sia START e REPEATED START, se non diversamente specificato.

Come si vede in Fig 21-3 lo START e lo STOP avvengono cambiando il livello della linea
SDA quando la linea SCL è HIGH

continua nel post seguente......

Io cercavo indicazioni circa l'interrupt su twi, cioè ogni quando la isr viene esguita e non ho trovato nulla di chiaro, ma ho sperimentato che dopo uno start la isr viene chiamata ripetutamente, non so il motivo.

Chi ne sa di più e pregato di far luce sul twi del 328.

Ciao.

...continuazione del post precedente

Address packet format
Tutti i pacchetti di indirizzo trasmessi sul bus TWI sono lunghi 9 bit, dei quali 7 rappresentano
l'indirizzo, uno per il bit di controllo READ/WRITE e uno per ACK bit (acknowledge bit).

Se il bit READ/WRITE è impostato a 1 viene eseguita una lettura, se impostato a 0 viene eseguita
una scrittura.

READ = 1
WRITE = 0

Il bit di controllo READ/WRITE è chiamato SLA+R in caso di lettura o SLA+W in caso
di scrittura.

Quando uno slave riconsce l'indirizzo inviato sul bus, dovrà mettere a 0 il pin SDA
in corrispondenza del nono impulso di clock, questo corrisponde al bit ACK. In pratica
lo slave comunica con il master per dirgli che lo slave che ha indirizzato esiste e
ha risposto con il bit di conoscenza indirizzo.

Se lo slave indirizzato è occupato, o per altre ragioni non può rispondere alla richiesta
del master, la linea SDA deve essere lasciata HIGH in corrispondeza del nono impulso di clock.

Il master allora può trasmettere la condizione di STOP, oppure REPEATED STARD per iniziare una
nuova trasmissione senza per questo rilasciare il bus.

L'indirizzo di uno slave può essere scelto liberamente dallo sviluppatore, ma l'indirizzo
0000 000 è riservato per la chiamata generale. La trasmissione dell'indirizzo
inizia dal bit più significativo MSB.

Una chiamata generale è usata quando il master vuole trasmettere lo stesso messaggio
a tutti gli slave connessi al bus. In caso di chiamata generale, tutti gli slave
dovrebbero rispondere ponendo il bit ACK LOW. Quando una chiamata generale è seguita dal
bit WRITE, tutti gli slave devono rispondere con ACK LOW, in questo caso tutti i pacchetti dati
inviati dal MASTER saranno ricevuti da tutti gli SLAVE che hanno risposto con ACK LOW.

Nota che una chiamata generale seguita dal bit READ non ha alcun significato e può
portare confusione nel caso in cui più slave stanno trasmettendo dati differenti.

Tutti gli indirizzi del seguente formato 1111 xxx dovrebbero essere riservati per
scopi futuri.

Fig. 21-4 Address Packet Format (Pag. 218)

Data Packet Format

Tutti i pacchetti di dati trasmessi sul bus TWI sono lunghi 9 bits, composti da
un byte di dati e ACK bit. Durante il trasferimento dei dati, il Master genera
il clock e le condizioni START e STOP, mentre il ricevitore è responsabile
del bit ACK. Se il ricevitore non risponde ACK allora lascia la linea SDA HIGH
e questo sarà segnalato come un NACK, cioè non conoscenza.

Quando il ricevitore ha ricevuto l'ultimo byte, o per alcune ragioni non
può riceverne altri, di questo si dovrebbe informare il trasmittente
inviando un NACK dopo l'ultimo byte. Come per l'address packet anche i
data packet sono inviati a partire dal bit più significativo.

Fig 21-5 Data Packet Format (Pag.219)

Combinare address e data packets insieme

Una trasmissione di base è composta da una condizione di START, seguita da SLA+R/W,
a cui segue uno o più pacchetti dati, e alla fine una condizione di STOP.
Un messaggio vuoto è composto da uno START e STOP senza nulla in mezzo, questo
è considerato illegale. Nota che il Wired-ANDing della linea SCL può essere usato per
implementare handshaking tra MASTER e SLAVE.

Lo SLAVE può estendere il periodo LOW di SCL, tenendo LOW il pin SCL
che normalmente è di pertinenza del MASTER. Questo può tornare utile
nel caso in cui la frequenza di trasmissione impostata dal MASTER risulta
essere troppo alta per lo SLAVE, questo però non modifica il periodo dell'impulso
HIGH di SCL, perchè è determinato dal MASTER. Come conseguenza si ha che
lo SLAVE può ridurre la velocità di trasferimento impostata dal MASTER.

La Fig 21-6 mostra una tipica trasmissione dati. Nota che diversi
data byte possono essere trasmessi tra il bit SLA+R/W e la condizione di STOP,
questo viene deciso dal protocollo software.

Fig. 21-6 Typical Data Trasmission

Multi-master Bus System, Arbitration e Synchronization

Il protocollo TWI permette di connettere più MASTER al bus.
Particolati misure sono state prese per assicurare che la trasmissione abbia
buon fine anche se più MASTER iniziano la trasmissione nello stesso istante.

Due sono i problemi che sorgono nella connessione multi-master:

  • Deve essere realizzato un algoritmo che permettere ad un solo MASTER di
    completare la trasmissione. Tutti gli altri MASTER dovrebbero cessare di
    trasmettere quando scoprono di avere perso il processo di selezione, detto
    anche processo di arbitrazione. Quando un MASTER scopre di aver perso
    il processo di arbitrazione dovrebbe passare in modalita SLAVE per controllare
    se è stato indirizzato dal MASTER che ha vinto il processo di arbitrazione.
    Il fatto che, più master hanno iniziato la trasmissione allo stesso tempo,
    non deve essere rilevabile agli slave, vale a dire, i dati trasferiti sul bus
    non devono essere danneggiati.

  • I master possono usare differenti frequenze di clock, in tal caso un'algoritmo
    si occupa di sincronizzare le frequenze di clock di tutti i master così da permettere
    la trasmissione in modo sincrono. Questo facilità il processo di arbitraggio.

Il wired-ANDing del bus è usato per risolvere emtrambe questi problemi.
Il clock fornito da tutti i master viene combinato in uno solo, dove il periodo HIGH
verrà dal master che ha il periodo HIGH più breve e il periodo LOW viene dal master
che ha il periodo LOW più lungo.

Si noti che tutti i master in ascolto sulla linea SCL, in effetti iniziano a contare il
loro periodo HIGH o LOW, quando la combinazione ottenuta va HIGH o LOW rispettivamente.

Fig. 21-7 SCL Sinchronization Between Multiple Master

L'arbitrazione è effettuata da tutti i master monitorando continuamente la linea
SDA dopo avere inviato dati, If il valore letto sulla linea SDA non corrisponde a
quello che ha inviato esso ha perso l'arbitrazione. Si noti che un master può perdere
l'arbitrazione solo quando esso ha emesso HIGH sulla linea SDA, mentre un altro
Master ha emesso LOW. Il MASTER che ha perso l'arbitrazione dovrebbero immediatamente
porsi in modo SLAVE controllando se il MASTER vincitore li ha indirizzati,

Il master che hanno perso il processo di arbitrazione devono lasciare la linea
SDA HIGH, ma è permesso loro di generare il clock fino alla fine del dato corrente
o pacchetto indirizzo. Il processo di arbitrazione procede fino a che non rimane un solo
MASTER e questo può comportare l'invio di molti bit. Se più MASTER provano ad indirizzare
lo stesso SLAVE il processo di arbitrazione continua ma si sposta in Data Packet.

Fig. 21-8 Arbitration Between Two Master (Pag.221)

continua nel post successivo...

....continuazione dal post precedente

Ci sono operazione considerate illegali durante il processo di arbitrazione.
Una arbitrazione non può avvenire tra:

  • Un REPEATED START e un data bit
  • Un STOP e un data bit
  • Un REPEATED STARD ed uno STOP

La responsabilità di assicurare che queste operazione illegali non si verifichino
ricade sul software utente. Questo implica che in multi-master, tutti i trasferimenti di dati
devono usare la stessa composizione di SLA+R/W e pacchetti dati. In altre parole
tutte le trasmissioni devono contenere lo stesso numero di pacchetti dati, diversamente il
risultato dell'arbitrazione è indefinito.

Overview of the TWI Module

Il modulo TWI è composto da diversi sub-moduli come mostrato in Fig. 21-9.

SCL e SDA pins

Questi pin sono l'interfaccia con il resto della MCU. Il driver di uscita contiene
un limitatore di slew-rate per conformità alle specifiche TWI. Lo stadio d'ingresso
contiene un soppressore di rumore che sopprime gli impulsi più brevi di 50ns.

La resistenza di pull-up si questi pin può essere abilitata come spiegato nella sezione
I/O port, abilitandola per entrambe i pin può in alcuni casi eliminare la necessità
di resistenze esterne. Se si decide di usare delle pull-up esterne e meglio
disabilitare quelle interne.

Bit Rate Generator Unit

Questa unità controlla il periodo del segnale SCL quando si opera in Master mode.
Il periodo è controlla impostando il valore del bitrate nel registro (TWBR) e il prescaler
tramite i bits del registro (TWSR).

In modalità SLAVE il bitrate e prescaler non influiscono, ma ha importanza rilevante la
frequenza di clock a cui lavora la MCU, questa deve essere almeno 16 volte maggiore
della frequenza di SCL.

La frequenza di clock del pin SCL è generata in accordo alla seguente equazione:

SCL frequency = MCU clock / 16+2(TWBR)+(prescalerValue)

Bus Interface Unit

Questa unità contiene il data e address shift register (TWDR), uno START/STOP controller
e un hardware per il processo di arbitration. Il registro TWDR contiene l'indirizzo
o il data byte da trasmettere, oppure l'indirizzo o data byte ricevuto. In aggiunta a TWDR
questa unità contiene anche il registro (N)ACK in trasmissione o in ricezione, comunque il registro
(N)ACK non è accessibile direttamente da software. In ricezione può essere impostato o pulito
maipolando il registro TWCR. In trasmissione il valore del bit (N)ACK ricevuto può essere
determinato dal valore di TWSR.

Il controller START/STOP è responsabile della generazione e rilevamento di START,
REPEATED START e STOP. Il controller è capace di rilevare le condizioni di START e STOP
anche quando la MCU è in uno stato sleep. Abilitando il risveglio se il master ha inviato
il giusto indirizzo. ?????? non so se è così

Se una trasmissione è stata iniziata come Master, l'hardware che rileva l'attività di
arbitrazione continua a monitorare la trasmissione provando a determinare se un processo
di arbitrazione è in atto. Se il MASTER ha perso l'arbitrazione l'unità di controllo START/STOP
viene informata così le giuste azioni verranno intraprese e gli appropriati
codici di stato verranno generati.

Address Match Unit

pag 223
}

maurotec, credo che la ISR sia legata al clock, probabilmente stile change. ma nella libreria wired trovi anche twi.c e .h che saranno un ottimo punto di partenza, no?
in oltre se cerchi su iternet, come ti dicevo trovi mille implementazioni. se vuoi ci possiamo lavorare sopra, a me piacerebbe creare una libreria i2c simile alla serial, nel senso che abbia un buffer di richeste e di risposte, che lavorano "in background" tramite interrupt.

poi con calma mi leggo il datasheet, che descire lo standard twi più che parlare dell'hardware... ma se non erro twi è una implementazione opensource/openhardware, quindi non mi stupirei se tutti i micro hanno lo stesso circuito, o molto simile.

La wire di arduino lo guardata e ci ho capito poco, in particolare non capisco i due puntatori a funzione con il come "event".

La isr twi di arduino implementa una macchina a stati con switch case e usa due buffer, come li usa non lo so perchè non ho studiato la classe, ma solo il codice C.

In pratica dopo uno start si possono scrivere e leggere un numero qualunque di byte e questo lo deve stabbilire il protocollo software, diversamente senza protocollo ogni scrittura o lettura il master deve sempre emettere la condizione di star e poi inviare il bit Read/Write e infine dopo aver ricevuto ACK invia un solo byte, per il prossimo deve fare nuovamente start.

Io penso che se la twi di arduino usa il buffer ci deve essere un metodo per inviare una array di caratteri, magari non prende string direttamente.

poi con calma mi leggo il datasheet, che descire lo standard twi più che parlare dell'hardware... ma se non erro twi è una implementazione opensource/openhardware, quindi non mi stupirei se tutti i micro hanno lo stesso circuito, o molto simile.

Twi deve per forza essere aderente allo standard i2c altrimenti non potrebbe dialogare con sensori, memorie ecc che usano i2c, quindi si tratta dello standard i2c chiamato twi per motivi di licenza.

A me serve una lib C per il twi, quindi disponibile a discutere e scrivere codice di test, ma solo C non C++ e no arduino IDE, perchè non c'è lo.

Ciao.

bhe allora più tardi quando sono a casa (se funziona internet ]:D) apro un post apposta (ahahah gioco di parole che non fa ridere nessuno) così ci possiamo sbizzarrire a farci suggerire trucchetti.

Io come limite impongo l'essere il più possibile "invisibile" all'utente (interrupt driven), asincrona (come la read della seriale) e quindi antiblocco.

Tu imponi C e nessun riferimento all'IDE (che cmq a priori credo sarebbe fuori discussione)

propongo di implementare solo il master/slave, roba più complessa la lasciamo a chi conosce bene il protocollo :slight_smile:
Partiamo dal master visto che ho un sacco di sensori slave da usare come riferimento, poi lo slave speri diventi una specie di master semplificato.

Tu imponi C e nessun riferimento all'IDE (che cmq a priori credo sarebbe fuori discussione)

La mia più che una imposizione è una constatazione del fatto che non posso scrivere e testare con il core,
quindi C significa codice funzionale, poi il code design ognuno lo può sviluppare come crede.

Non so se mi sono spiegato, ad esempio partiamo dalla funzione che invia dati allo slave, questa deve prendere
come parametro un'array di byte (meglio se prende un const char*). So per certo (ma faro un test in serata) sollevando
una condizione di start con:

 // send START condition
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

avviene l'esecuzione della isr, e per qualche mistero il codice esce dalla isr e ci rientra e così via
fino a che non invii uno stop.

Ciao.

guarda quà: Arduino Playground - WireLibraryDetailedReference

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! :slight_smile:

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 :wink:

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