I²C Inter Integrated Circuit
I2C è un sistema di comunicazione seriale bifilare.
(tratto da Wikipedia)
In sintesi è un sistema di comunicazione seriale (bus), che prevede un "Master" ed uno o più "Slave".
Il protocollo richiede due linee.
SDA = per i dati (serial data line).
SCL = per il clok.
occorre anche il riferimento GND
e la Vdd ( +5V o +3,3V).
I2C ha 7 bit di indirizzo quindi ( teoricamente) si possono avere128 dispositivi sul bus.
Per approfondire l'argomento trovate su Wikipedia ottime spiegazioni in Italiano, sul sito della Sparkfun esiste un tutorial dedicato, altro tutorial che ho letto è su :
Vediamo come utilizzare I²C con Arduino.
Sul sito di arduino troverete una libreria "Wire Library". con funzioni che consentono una utilizzazione del protocollo I2C abbastanza agevole.
Esperimenti e prove con le funzioni messe a disposizione da Wire.
Ho cominciato con la lettura e la prova degli esempi sul sito di Arduino e sul sito di Marco Lai.
Ecco lo schema del primo esperimento.
La prova consiste nel comandare da Arduino Master, un led attaccato su Arduino Slave, attraverso il bus I2C.
Su Arduino UNO r3 il bus è anche su i due pin dopo AREF, nella parte sottostante si legge SDA, e SCL.
Sul sito Arduino si trovano queste indicazioni:
Board | I2C / TWI pins |
Uno, Ethernet | A4 (SDA), A5 (SCL) |
Mega2560 | 20 (SDA), 21 (SCL) |
Leonardo | 2 (SDA), 3 (SCL) |
Due | 20 (SDA), 21 (SCL), SDA1, SCL1 |
Le due resistenze sono da 2,2 k. la resistenza del pulsante 10k. la resistenza led 330 omm.
Nello sketch (modificato da quello di Marco Lai) ho gestito il pulsante sul master, inviato un byte che comunica allo slave il cambiamento di stato ( led on - led off), lo slave accende il led lampeggiante, e a sua volta comunica al master ( led "Acceso"), quando sul master viene premuto nuovamente il pulsante, lo slave lo spenge e comunica (led Spento).
Con questo piccolo esperimento ho utilizzato:
Le seguenti funzioni della libreria Wire://------------------------------------------------------------------------------------------------------
Wire.beginTransmission(address) // inizia una trasmissione allo Slave con (address xxxx)
Wire.write(value) // trasmette un byte.
Wire.endTransmission() // chiude la trasmissione
//-------------------------------------------------------------------------------------------------------
Wire.requestFrom(address, quantity) // si chiede allo slave con (address, ( n ) byte )
Wire.available() // restituisce il numero dei byte disponibili sul Bus che verranno letti da (read)
Wire.read() //legge i byte in arrivo sul bus
//-------------------------------------------------------------------------------------------------
Wire.begin(address); // da chiamare all'inizio ( una sola volta) se è lo Slave indicare il suo indirizzo
//-----------------------------------------------------------------------------------------------------
Wire.onReceive(receiveEvent); // lo slave chiama la funzione ( void receiveEvent ) quando il master
void receiveEvent(int data) // gli trasmette i byte, e li legge con (read.)
//----------------------------------------------------------------------------------------------------
Wire.onRequest(requestEvent); // lo slave chiama la la funzione ( void requestEvent )
void requestEvent() // quando il master gli chiede di inviare dei byte con (write)
//----------------------------------------------------------------------------------------------------
Praticamente ho usato tutte le funzioni messe a disposizione dalla libreria .
In realtà alcune funzioni accettano ulteriori opzioni. ( che non ho usato).
Nello sketch troverete indicato cosa fanno le varie funzioni, e tutto dovrebbe essere più chiaro.
Leggete comunque per approfondire quanto si trova sul sito Arduino.
Qui sopra la foto dell'esperimento,
A destra il pulsante bianco collegato al pin 8 del Master.
Al centro il Led verde collegato al pin 8 dello Slave.
Qui sopra la schermata del monitor seriale dove lo Slave comunica al Master la situazione del Led.
Qui sotto lo sketch del Master.
/* *** Sergio & Adriano Prenleloup **** ***** Prova I 2 C ************ **** M A S T E R **** *** Versione 1.01 ************ ****** 16/02/2014 ********** ****************************** Questa prova della seriale I2C ha lo scopo di capire l'uso della libreria Wire. Ho avuto la fortuna di leggere un post di Marco Lai sul sito logica programmabile.it. --- Un grazie a Marco ------ Per la routin pulsante vedi sul mio blog http://avventurarduino.blogspot.it Ho seguito le indicazioni del Prof. Michele Maffucci */ //------------------------------------------------ // MASTER //------------------------------------------------ #include (Wire.h) // Libreeria per usare I2C int Button_1 = 8; // il pulsante è collegato al pin 8 // DEL MASTER int StatoButton_1 = 0; //stato del pulsante //lo leggiamo con la digitalRead (Button_1) int old_StatoButton_1 = 0; //stato al passo precedente del pulsante int OnOff = 0; //condizione on off ci dice lo stato in cui si //trova il LED OnOff=0 spento, OnOff= 1 acceso. int cambio = 0; //questa serve per conoscere se è cambiato lo stato // del led ( Acceso o spento) 0,1 //-------------------------------------------------------------- // Impostiamo il pin in INPUT, inizializzo la libreria seriale I2C // Inizializzo la seriale a 9600 baud void setup() { pinMode (Button_1, INPUT); // imposta il pin digitale come input //inizializzo la libreria Wire come Master Wire.begin(); // nelle () non si mette l'indirizzo. //init seriale Serial.begin(9600); //avviso che il programma è avviato Serial.println("START"); } //---------------------------------------------------------------- // lettura pulsante gestione antirimbalzo // la varabile cambio viene messa ad 1 ogni volta // che cambia lo stato void Pulsante () { StatoButton_1 = digitalRead (Button_1); // legge il valore restituito //dal pin e lo memorizza in StatoButton_1 if ((StatoButton_1 == HIGH) && (old_StatoButton_1 == LOW)) // controlla se lo stato attuale è cambiato { cambio = 1; // è cambiato lo stato (pulsante premuto // per accendere o spenfgere il led) OnOff = 1 - OnOff; // se il led è on (1) 1-1 OnOff viene posto a 0 ed il led si spenge // se il led è off (0) 1-0 OnOff viene posto a 1 ed il led si accende delay(20); // attesa antirimbalzo } old_StatoButton_1 = StatoButton_1; // mettiamo in oldStatoButton_1 il valore attuale } //----------------------------------------------------------------------- void loop() { // ---------------------------------------------------------- // gestione pressione pulsante Pulsante(); //---------------------------------------------------------- // Si trasmette allo slave il comando pressione pulsante //invio sul bus I2C un byte al device //che ha come indirizzo il valore 0x04 //start trasmissione Wire.beginTransmission(0x04); //invio un byte Wire.write(OnOff); //fine trasmissione Wire.endTransmission(); delayMicroseconds(500); //---------------------------------------------------------------- if (cambio == 1) // se il pulsnte è stato premuto { // il master chiede allo slave lo stato del LED Wire.requestFrom(0x04, 6); // chiedo allo Slave 6 byte while(Wire.available()) // in attesa disponibilità // di dati in arrivo dallo slave { char c = Wire.read(); // ricevo i caratteri dallo slave Serial.print(c); // si stampa i caratteri ricevuti // ----------------------------- } Serial.println(); cambio =0 ; // metto a 0 in attesa di nuova pressione del pulsante } delay(500); } // end ----------------------------------------------------------------
Qui sotto lo sketch dello Slave.
/* *** Sergio & Adriano Prenleloup **** ***** Prova I 2 C ************ **** S L A V E **** *** Versione 1.01 ************ ****** 16/02/2014 ********** ****************************** Questa prova della seriale I2C ha lo scopo di capire l'uso della libreria Wire. Ho avuto la fortuna di leggere un post di Marco Lai sul sito logica programmabile.it. --- Un grazie a Marco ------ Per la routin pulsante vedi sul mio blog http://avventurarduino.blogspot.it Ho seguito le indicazioni del Prof. Michele Maffucci //------------------------------------------------ // SLAVE //------------------------------------------------ //L'INDIRIZZO DELLO SLAVE = 0X04 (scelta libera) //----------------------------------------------- // */ #include (Wire.h) int LED = 8; // il nostro led è collegato al pin 8 int OnOff= 0; //-------------------------------------------------------- void setup() { pinMode(LED, OUTPUT); // imposta il pin digitale come output //inizializzo la libreria Wire //imposto l'indirizzo dello slave Wire.begin(0x04); //eventi per la ricezione del dato //e per la richiesta del dato Wire.onReceive(receiveEvent); Wire.onRequest(requestEvent); } //------------------------------------------------------------ void receiveEvent(int data) { //questo evento viene generato quando sul bus //è presente un dato da leggere //eseguo la lettura OnOff = Wire.read(); } //---------------------------------------------------------- void requestEvent() { if (OnOff == 1) { Wire.write("Acceso"); // respond with message of 6 bytes } // as expected by master else { Wire.write("Spento"); } } //----------------------------------------------------------- void loop() { if (OnOff == 1) // si controlla lo stato led { digitalWrite(LED, HIGH); delay (500) ; digitalWrite(LED, LOW); delay (500) ; } else { digitalWrite(LED, LOW); //Si spegne il led o comunque si lascia spento } } // end --------------------------------------------------
alla prossima ....... the next.........
Articolo molto interessante e utile.
RispondiElimina