venerdì 28 febbraio 2014

I²C - num. 1

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:

BoardI2C / TWI pins
Uno, EthernetA4 (SDA), A5 (SCL)
Mega256020 (SDA), 21 (SCL)
Leonardo2 (SDA), 3 (SCL)
Due20 (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.begin()   // da chiamare all'inizio ( una sola volta) se è il Master non indicare l'indirizzo
 //------------------------------------------------------------------------------------------------------
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.........


1 commento:

Vi ringrazio per la lettura e vi invito al prossimo post.
Se il post vi è stato utile, vi è piaciuto oppure no, scrivete un commento.

Un saluto a tutti.
Sergio

Copyright - Condizioni d’uso - Disclaimer
http://avventurarduino.blogspot.it/2012/10/inizia-lavventura-arduino-12-settembre.html