Utilizzare Arduino per controllare l’integrato PCF8591

L’integrato PCF8591 prodotto da NXP dispone di 4 ingressi analogici con risoluzione di 8 bit e di una uscita analogica sempre ad 8 bit. La sua gestione avviene tramite bus I2C, permettendo così il collegamento nel bus di diversi integrati (per un massimo di 127 unità). Avendo una gestione software semplice ed un costo intorno ai 3€ viene impiegato in diversi shield Arduino per aumentare il numero di porte ADC, inoltre la presenza di una uscita analogica programmabile (DAC) permette di generare segnali utili in diversi progetti e applicazioni.

Nella figura seguente viene mostrato lo schema a blocchi del PCF8591:

Schema Blocchi PCD8591P

Per specificare l’indirizzo del dispositivo all’interno del bus I2C vengono impiegati i pin A0, A1 e A2. La scelta del canale ADC che vogliamo impiegare avviene tramite il registro control byte, configurabile via software come anche la gestione dell’uscita analogica, che in questo tutorial non verrà trattata.

Il circuito di esempio che  utilizza un integrato PCF8591P ed un Arduino UNO, di seguito lo schema:

Schema Elettrico PCF8591P

I pin A0, A1,e A2 sono collegati a massa, quindi il loro valore logico è pari a zero. Sul datasheet del componente possiamo dedurre quale sarà l’indirizzo sul bus I2C seguendo questa tabella:

PCF8591 Table Address

i quattro bit piu significativi sono fissi e non possono essere cambiati, mentre i tre bit meno significativi sono appunto collegati ai pin A0 A1 e A2. Nello schema essendo collegati a massa, otterremo l’indirizzo del dispositivo che  corrisponderà, al valore binario seguente:

0b1001000

che convertito in esadecimale diventa:

0x48

Una volta stabilito l’indirizzo, è necessario configurare il dispositivo tramite il registro ‘control byte’. Questo registro permette di scegliere il canale analogico da rendere attivo per l’acquisizione (bit 0 e bit 1 A/D Channell Number) e la configurazione degli ingressi analogici (bit4 e bit5 Analog Input Programming).
Le informazioni di questo registro sono riassunte in questo schema, presente nel datasheet:

Control register

Tralasciamo il bit per l’uscita analogica (bit6) e il bit  auto increment (bit2), assegnandoli il valore logico zero.
I valori da assegnare al control byte per selezionare i diversi ingressi analogici in configurazione four single-ended inputs (bit4 e bit5 a zero) dovranno essere:

0b00000000 -> 0x00 -> attiva l’ingrasso analogico AIN0
0b00000001 -> 0x01 -> attiva l’ingrasso analogico AIN1
0b00000010 -> 0x02 -> attiva l’ingrasso analogico AIN2
0b00000011 -> 0x03 -> attiva l’ingrasso analogico AIN3

La sequenza di byte da inviare è la seguente:

Registro controllo

quindi tramite le dovute istruzioni, invieremo sul bus I2C un primo byte contenente l’indirizzo del dispositivo e un secondo byte riguardante la configurazione interna del dispositivo.
L’integrato PCF8591 è così pronto ad acquisire ed inviare il dato sul canale I2C.
Il codice seguente permette di acquisire un dato analogico sul pin AIN0 e sul pin AIN1 del dispositivo e di inviarlo al serial monitor dell’ IDE Arduino:

//libreria I2C
#include <Wire.h>

void setup()
{
 //inizializzo la libreria Wire
 Wire.begin();
 //init seiale
 Serial.begin(9600);
 //avviso che il programma è avviato
 Serial.println("START");
}

void loop()
{
 //avvio una richiesta di scrittura al
 //dispositivo con indirizzo 0x48
 Wire.beginTransmission(0x48);
 //invio il byte di configurazione
 //in questo caso abilito il canale analogico AIN0
 Wire.write(byte(0x00));
 //fine trasmissione
 Wire.endTransmission();
 //richiedo un byte allo slave che ha indirizzo 0x48
 Wire.requestFrom(0x48, 1);
 //attendo la disponibilità di dati sul bus i2c
 while(Wire.available())
 {
  //leggo il byte che mi invia il PCD8591
  byte c = Wire.read();
  //invio il dato al serial monitor
  Serial.println(c);
 }
 //pausa 10 millis
 delay(10);
 //avvio una richiesta di scrittura al
 //dispositivo con indirizzo 0x48
 Wire.beginTransmission(0x48);
 //invio il byte di configurazione
 //in questo caso abilito il canale analogico AIN01
 Wire.write(byte(0x01));
 //fine trasmissione
 Wire.endTransmission();
 //richiedo un byte allo slave che ha indirizzo 0x04
 Wire.requestFrom(0x48, 1);
 //attendo la disponibilità di dati sul bus i2c
 while(Wire.available())
 {
  //leggo dal bus il dato relativo alla
  //conversione a/d sul pin AIN01
  byte c = Wire.read();
  //invio il dato al pc
  Serial.println(c);
 }
 //esegui il codice ogni secondo
 delay(1000);
}

 

Sinteticamente viene prima configurato, tramite il ‘control byte’, il dispositivo PCF8591 e successivamente viene avviata una richiesta di lettura dal dispositivo. Per eseguire la lettura dei quattro, è necessario eseguire quattro configurazioni e quattro letture.