Extending Arduino’s Digital Input

[PT]

Ontem escrevi um post sobre como aumentar o número de portas de saída digital do Arduino pois só dispõe de 13 Pins Digitais de Input e Output.

Hoje é altura de escrever sobre o aumento do número de portas de entrada digital (Digital Input). Tal como no post anterior, a solução passa pela utilização de um circuito integrado designado por “Multiplexers“.

Para este caso utilizo o IC 74HC165 (existem outros que fazem o mesmo efeito). Este IC é um conhecido “8 bit parallel in – serial out shift register”. Isto quer dizer que é possível receber ao mesmo tempo o valor de 8 inputs !! Recordo de novo que, tal como no post anterior, é possível ligar vários IC em paralelo e assim continuar a aumentar o número de portas digitais de entrada.

Os Pins A a H são entradas (inputs).

Pin GND deverá de estar ligado a Terra (GND).

Pin SH/LH é o “Parallel Input” e para se activar o IC para poder receber data deverá de estar LOW. Mas após a recepção, tem de se mudar para HIGH para parar as entradas e se conseguir “ler” os inputs.

Os Pins QH’s são “Serial Outputs”.

Pin CLK é o “Clock Input” do IC e tal como o SH/LH dever-se-á activar quando se quiser enviar data para o IC e desactivar após a transferência.

Pin Vcc é o Vcc (corrente).

Pin CLK INH é o “Clock Enable Input” ou seja, o pin pelo qual a informação vai do Arduino para o IC.

Pin SER é o “Serial Data Input” e será utilizado caso se pretenda ligar mais ICs em paralelo.

Caso queiram utilizar menos do que 8 inputs, os pins “vazios” deverão ser ligados à Terra para que o IC funcione. (reparem nos arames brancos e nos 2 arames pequenos arames verdes)

image

/*
Código retirado do forum do site do Arduino e adaptado para o circuito que liguei.
*/
// Caso se pretenda ligar vários ICs em paralelo
#define NUMBER_OF_SHIFT_CHIPS 1
#define DATA_WIDTH NUMBER_OF_SHIFT_CHIPS*8
// Largura do pulso que servirá de "trigger" para o IC ler e armazenar
#define PULSE_WIDTH_USEC 5
// delay opcional entre leituras do IC
#define POLL_DELAY_MSEC   1
// Caso se tenham vários IC em paralelo, deverão alterar o tipo de dados de int para long
#define BYTES_VAL_T unsigned int
// Pins do Arduino
int SH_LD        = 2; int CLK_INH  = 5;  // Liga ao Clock Enable (15)
int QH = 4; // Liga ao Q7 (7)
int CLK = 3; // Liga ao Clock (2)
BYTES_VAL_T pinValues;
BYTES_VAL_T oldPinValues;
// Rotina de "Shift-In"
// para ler o Serial Data do Shift-Register
// e representar esses dados em valores nos Pins
BYTES_VAL_T read_shift_regs()
{
byte bitVal;
BYTES_VAL_T bytesVal = 0;
// Disparar a leitura das ligações Parallel e armazenar a informacao
digitalWrite(CLK_INH, HIGH);
digitalWrite(SH_LD, LOW);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(SH_LD, HIGH);
digitalWrite(CLK_INH, LOW);
// ler todos os bits que entraram via Serial Out
for(int i = 0; i < DATA_WIDTH; i++)
{
bitVal = digitalRead(QH);
// transformar os bits em bytes
bytesVal |= (bitVal << ((DATA_WIDTH-1) - i));
// Ligar e desligar o "clock" faz com que se mude para a próxima entrada
digitalWrite(CLK, HIGH);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(CLK, LOW);
}
return(bytesVal);
}
// método para mostrar todos os bits
void display_pin_values()
{
Serial.print("Pin States:\r\n");
for(int i = 0; i < DATA_WIDTH; i++)
{
Serial.print("  Pin-");
Serial.print(i);
Serial.print(": ");
if((pinValues >> i) & 1)
Serial.print("HIGH");
else
Serial.print("LOW");
Serial.print("\r\n");
}
Serial.print("\r\n");
}
void setup()
{
Serial.begin(9600);
pinMode(SH_LD, OUTPUT);
pinMode(CLK_INH, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(QH, INPUT);
digitalWrite(CLK, LOW);
digitalWrite(SH_LD, HIGH);
pinValues = read_shift_regs();
display_pin_values();
oldPinValues = pinValues;
}
void loop()
{
pinValues = read_shift_regs();
if(pinValues != oldPinValues)
{
Serial.print("*Pin value change detected*\r\n");
display_pin_values();
oldPinValues = pinValues;
}
delay(POLL_DELAY_MSEC);
}

Divirtam-se!

[EN]

Yesterday I wrote a blogpost about how to extend the number of Arduino’s digital output pins.

Today I will write about how to extend the number of Arduino’s digital input pins. Like the previous post, the solution might goes by using “Multiplexers“, a common integrated circuit.

I use the IC 74HC165 (there are others with the same purpose). This IC is a well known “8 bit parallel in – serial out shift register”. This means that you may capture up to 8 inputs !! Remember that all these ICs may work in parallel with others, extending even further the number of pins.

Pins A to H are input pins.

Pin GND should be connected to Ground.

Pin SH/LH it’s the “Parallel Input” and to activate the IC to read data it has to be LOW. After readings, switch it up to HIGH.

Pins QH’s are the “Serial Outputs”.

Pin CLK this one is the “Clock Input”, and like the SH/LH you should activate to send data into the IC and deactivate after.

Pin Vcc it’s the power source.

Pin CLK INH it’s the “Clock Enable Input”, where all data “goes” from Arduino into IC.

Pin SER it’s the “Serial Data Input” and you will use it if you have “daisy-chains” (ICs connected in parallel).

If you want to use less then the 8 available inputs, remember to connect the “empty” ones to Ground (take a note on the small white wires and the two small green ones)

image

/*
Code was taken from Arduino's forum and adapted to my circuit.
*/
// If you want to connect several ICs in parallel
#define NUMBER_OF_SHIFT_CHIPS 1
#define DATA_WIDTH NUMBER_OF_SHIFT_CHIPS*8
// pulse width that will trigger the IC to read and latch
#define PULSE_WIDTH_USEC 5
// optional delay for readings
#define POLL_DELAY_MSEC   1
// If you have several ICs in parallel, need to change the data type from int to long
#define BYTES_VAL_T unsigned int
// Arduino's pins
int SH_LD        = 2; int CLK_INH  = 5;  // Connects to Clock Enable
int QH = 4; // Connects to the Q7
int CLK = 3; // Connects to the Clock
BYTES_VAL_T pinValues;
BYTES_VAL_T oldPinValues;
// "Shift-In" routine
// to read all Serial Data from Shift-Register
// and send those values to the Pins
BYTES_VAL_T read_shift_regs()
{
byte bitVal;
BYTES_VAL_T bytesVal = 0;
// triggers the reading from the Parallel connections and latch
digitalWrite(CLK_INH, HIGH);
digitalWrite(SH_LD, LOW);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(SH_LD, HIGH);
digitalWrite(CLK_INH, LOW);
// Read all bits available
for(int i = 0; i < DATA_WIDTH; i++)
{
bitVal = digitalRead(QH);
bytesVal |= (bitVal << ((DATA_WIDTH-1) - i));
// Turning the "clock" On/Off will make the Shift-Register to shift to the next bit
digitalWrite(CLK, HIGH);
delayMicroseconds(PULSE_WIDTH_USEC);
digitalWrite(CLK, LOW);
}
return(bytesVal);
}
// Printing all values
void display_pin_values()
{
Serial.print("Pin States:\r\n");
for(int i = 0; i < DATA_WIDTH; i++)
{
Serial.print("  Pin-");
Serial.print(i);
Serial.print(": ");
if((pinValues >> i) & 1)
Serial.print("HIGH");
else
Serial.print("LOW");
Serial.print("\r\n");
}
Serial.print("\r\n");
}
void setup()
{
Serial.begin(9600);
pinMode(SH_LD, OUTPUT);
pinMode(CLK_INH, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(QH, INPUT);
digitalWrite(CLK, LOW);
digitalWrite(SH_LD, HIGH);
pinValues = read_shift_regs();
display_pin_values();
oldPinValues = pinValues;
}
void loop()
{
pinValues = read_shift_regs();
if(pinValues != oldPinValues)
{
Serial.print("*Pin value change detected*\r\n");
display_pin_values();
oldPinValues = pinValues;
}
delay(POLL_DELAY_MSEC);
}

Have fun!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>