Mag 052019
 

Ci sono molte situazioni in cui i pin a disposizione della nostra scheda di prototipizzazione non sono sufficienti. Abbiamo visto tante volte come incrementare le uscite digitali con il chip 74HC595 o gli ingressi digitali con il 74HC165. Oggi vediamo il 74HC4051 che ci permette di espandere gli ingressi analogici. 

Introduzione

In un progetto che sto portando avanti, mi sono trovato di fronte ad un problema, ossia il numero di ingressi analogici di cui avevo bisogno era superiore al numero di ingressi disponibili sulla scheda. A questo punto avrei potuto rinunciare ad alcune letture andando a ridimensionare il progetto, oppure avrei potuto cambiare scheda di controllo scegliendono una con più ingressi ma che era molto più grande e meno performante o ancora avrei potuto espandere il numero di ingressi con un apposito integrato, strada che alla fine ho scelto. 

Il funzionamento del 74HC4051 è piuttosto semplice. Potremmo pensare che la nostra scheda di acquisizione sia una stazione dei treni e gli ingressi analogici i binari che arrivano alla stazione. Ora, se avessimo 8 ingressi ci sarebbero 8 binari che arrivano diretti alla stazione. Ma come fanno le stazioni dei treni a far arrivare un numero superiore di binari? Semplice, utilizzano degli scambi. Ecco, il 74HC4051 funziona proprio come una serie di scambi. Da una parte lo collegheremo ad Arduino o scheda analoga, dall’altra ci saranno 8 ingressi che di volta in volta possiamo andare a “scambiare” per collegarli direttamente all’uscita. Quindi in ogni istante abbiamo uno solo degli ingressi del 4051 connesso direttamente all’ingresso di Arduino o scheda analoga. 

Ma come per gli scambi dei treni, anche per questo chip ci vorrà un sistema che ci permette di indicare “come azionare gli scambi”. Il 74HC4051 utilizza tre pin digitali per selezionare l’ingresso voluto.  3 pin digitali permettono, guarda caso, di creare 8 combinazioni univoche per cui in base ai valori 0 / 1 dei singoli pin è possibile selezionare il numero dell’ingresso che vogliamo andare a leggere.Pensate a quanto può essere utile nelle schede basate su ESP8266 che possiedono un solo ingresso analogico: sacrificando tre pin digitali possiamo portare gli ingressi analogici da 1 a 8.

Faccio notare, anche se non approfondiremo, che come per l’esempio dei binari è possibile fare il percorso inverso, ossia il treno potrebbe uscire dalla stazione anziché arrivare. Sarà perciò possibile smistare un segnale digitale su una delle 8 uscite

Il pinout

Vediamo rapidamente come sono disposti i pin di questo integrato. Siccome il pinout dello schema qui vicino differisce un po’ da quello dello schema successivo, vi riporto entrambe le definizioni:

Z (IO): pin input/output (connesso agli Input/Output Arduino )
E (INH): pin di enable (attivo  su LOW da connettere a GND)
VEE: tensione di alimentazione negativa (connettere a GND)
GND (VSS): terra (connettere a GND)
(S0-1-2) A-B-C: pin di selezione input da connettere a rispettivi pin digitali di Arduino – A bit meno significativo (LSB), C bit più significativo (MSB)
Da Y0 a Y7 (IO0 – IO7): pin di inputs/outputs
VCC (VDD): tensione di alimentazione positiva (da 3V a 5v)

Qui sotto vi riporto un esempio di cablaggio. In verde vediamo i vari ingressi, in arancio la line che arriva ad Arduino (o chi per esso), in rosso la linea di alimentazione (3.3 o 5V) e in nero la linea di massa. In blu i pin digitali che controllano quale uscita leggere, si noti che li ho connessi ai pin analogici di Arduino, in tal caso dovranno essere utilizzati in modalità digitale. Ovviamente può essere usato qualunque altro pin digitale, io ho usato gli analogici solamente per praticità di disegno.

Come controlliamo l’ingresso da leggere? Guardiamo la tabella che segue: 

Ingressi
INH (E) C (S2) B (S1) A (S0) Canale
0 0 0 0 IO0 – Y0
0 0 0 1 IO1 – Y1
0 0 1 0 IO2 – Y2
0 0 1 1 IO3 – Y3
0 1 0 0 IO4 – Y4
0 1 0 1 IO5 – Y5
0 1 1 0 IO6 – Y6
0 1 1 1 IO7 – Y7
1 X X X Nessuno

In base a come viene settata l’uscita dei tre pin di controllo viene letto un ingresso piuttosto che un altro.

Vediamo qui sotto uno sketch di base. E’ molto semplice, infatti non facciamo altro che modificare il valore dei tre pin APin, BPin e CPin per poi andare a leggere il valore analogico restituito e scriverlo sulla porta seriale. Si noti che la lettura analogica avviene sempre nel medesimo pin di ingresso di Arduino. Pensate a quanto può essere utile questo stratagemma in tutte quelle schede dotate di un solo ingresso analogico come i vari moduli ESP. 

int sensorPin = A0; // select the input pin for the potentiometer
int APin = 3;
int BPin = 4;
int CPin = 5;
int sensorValue = 0;
void setup() {
// declare the ledPin as an OUTPUT:
Serial.begin(115200);
pinMode(APin, OUTPUT);
pinMode(BPin, OUTPUT);
pinMode(CPin, OUTPUT);
}
void loop()
{
digitalWrite(APin, LOW);
digitalWrite(BPin, LOW);
digitalWrite(CPin, LOW);
sensorValue = analogRead(sensorPin);
Serial.print(“0 0 0 : “);
Serial.println(sensorValue);
delay(200);
digitalWrite(APin, HIGH);
digitalWrite(BPin, LOW);
digitalWrite(CPin, LOW);
sensorValue = analogRead(sensorPin);
Serial.print(“0 0 1 : “);
Serial.println(sensorValue);
delay(200);
digitalWrite(APin, LOW);
digitalWrite(BPin, HIGH);
digitalWrite(CPin, LOW);
sensorValue = analogRead(sensorPin);
Serial.print(“0 1 0 : “);
Serial.println(sensorValue);
delay(200);
digitalWrite(APin, HIGH);
digitalWrite(BPin, HIGH);
digitalWrite(CPin, LOW);
sensorValue = analogRead(sensorPin);
Serial.print(“0 1 1 : “);
Serial.println(sensorValue);
delay(200);
digitalWrite(APin, LOW);
digitalWrite(BPin, LOW);
digitalWrite(CPin, HIGH);
sensorValue = analogRead(sensorPin);
Serial.print(“1 0 0 : “);
Serial.println(sensorValue);
delay(200);
digitalWrite(APin, HIGH);
digitalWrite(BPin, LOW);
digitalWrite(CPin, HIGH);
sensorValue = analogRead(sensorPin);
Serial.print(“1 0 1 : “);
Serial.println(sensorValue);
delay(200);
digitalWrite(APin, LOW);
digitalWrite(BPin, HIGH);
digitalWrite(CPin, HIGH);
sensorValue = analogRead(sensorPin);
Serial.print(“1 1 0 : “);
Serial.println(sensorValue);
delay(200);
digitalWrite(APin, HIGH);
digitalWrite(BPin, HIGH);
digitalWrite(CPin, HIGH);
sensorValue = analogRead(sensorPin);
Serial.print(“1 1 1 : “);
Serial.println(sensorValue);
Serial.println(“—————————-“);
delay(3000);
}

Anche se lo sketch funziona alla perfezione, da un punto di vista della programmazione vera e propria è un insulto alla decenza. Vediamo infatti che ci sono un sacco di pezzi di codice ripetuti ogni volta che andiamo a modificare i singoli valori dei pin. E poi diciamocelo, davvero voi vi ricordereste che per leggere l’ottava uscita dobbiamo impostare tutti e tre i pin ad HIGH. Non sarebbe più semplice tenere una variabile con un valore compreso fra 0 e 7 per selezionare l’ingresso desiderato? Qui sotto vi riporto una versione che fa lo stesso identico lavoro, ma il listato è decisamente più compatto:

int sensorPin = A0; // select the input pin for the potentiometer
int APin = 3;
int BPin = 4;
int CPin = 5;
int i=0;
void setup() {
// declare the ledPin as an OUTPUT:
Serial.begin(115200);
pinMode(APin, OUTPUT);
pinMode(BPin, OUTPUT);
pinMode(CPin, OUTPUT);
}
void loop()
{
ReadSensorValue(i);
i++;
}
int ReadSensorValue(int num)
{
unsigned char registri=num%8;
bool A=(registri&1);
bool B=(registri&2)>>1;
bool C=(registri&4)>>2;
digitalWrite(APin,A);
digitalWrite(BPin,B);
digitalWrite(CPin,C);
Serial.print(“A”);
Serial.print(” “);
Serial.print(“B”);
Serial.print(” “);
Serial.print(“C”);
Serial.print(” “);
Serial.println(analogRead(sensorPin));
if(registri==7))
{
Serial.println(“—————————-“);
delay(3000);
}
else delay(200);
}

Non mi resta che lasciarvi con il consueto video riassuntivo. Come sempre vi invito ad iscrivervi al mio canale youtube e se vi è piaciuto l’articolo lasciate un like. 

 

 




Salva