Neste tutorial, veremos como gerir vários sensores com um registo de turnos. Vimos no último tutorial sobre o assunto, que o registo podia ser utilizado para conduzir LEDs. Veremos aqui, como ler o valor de 8 sensores numa única entrada analógica. Em electrónica, o número de entradas e saídas torna-se crítico quando se utilizam vários sensores. A utilização de um registo de turnos é uma boa solução para reduzir o número de pinos utilizados.
Neste artigo, utilizamos o registo de turnos 74HC595 mas é possível utilizar um multiplexador ou um 74HC165 (Paralelo ao serial, mais adequado para a leitura de sensores)
Material
- Computador
- Arduino UNO
- Cabo USB A Macho/B Macho
- Registo de turnos 74HC595
Princípio funcional
O registo de turno é um componente electrónico que contém chinelos de dedo síncronos. Estes são circuitos lógicos que mantêm na memória um estado alto ou baixo (como um pouco) ligados pelo mesmo relógio. O princípio da mudança vem do facto de cada memória ser escrita ou lida pouco a pouco.
Para gerir os sensores, utilizaremos a saída do registo de deslocamento como fonte de tensão e todas as saídas dos sensores serão ligadas a uma entrada analógica do Arduino. Os sensores serão alimentados um após o outro, o que nos permitirá recuperar, no pino analógico, o valor do sensor alimentado.
Esquema
O registo de turno requer 3 pinos de saída de um microcontrolador. É possível gerir vários registos ligados em série.
- GND Ligação à terra do circuito integrado
- Pino de potência Vcc. Normalmente ligado a 5V
- SH_CP ou RCLK entrada de relógio de registo de turnos. O sinal do relógio de registo que determina se a memória é escrita para
- ST_CP ou SRCLK entrada do relógio de registo de armazenamento. O sinal do relógio de armazenamento que define de que memória se está a ler ou a escrever.
- DS ou SER entrada de dados. Sinal contendo os dados a registar (UP ou DOWN)
- Q0-Q7 saída de dados paralelos. Pinos de saída do registo de turnos
- Saída OE permitida, activa BAIXA. Pino ligado ao GND para activar as saídas
- MR Master reset, activo BAIXO. Pino de reinicialização. Ligado a 5V
- Q7′ saída de dados em série (pino utilizado apenas se vários registos estiverem ligados em série)
Assim que o registo de turno estiver devidamente ligado, ligaremos cada um dos botões. Para podermos detectar o estado de vários botões, precisamos de adicionar um díodo a cada saída, para que a corrente não flua de uma saída do registo de turnos para a outra.
Código
Para comunicar com o registo de turnos, faremos malabarismos com os seus pinos de entrada. Precisamos de colocar o pino RCLK baixo para escrever para um registo. Para escrever aos chinelos de dedo, precisamos de colocar o relógio de armazenamento em baixo. Com cada pulso de relógio, passamos para o próximo flip-flop. Para simplificar o nosso código, vamos definir este procedimento na função writeRegister().
Para gerir o grupo de sensores através do registo, vamos pulsar cada flip-flop e ler o valor do botão quando o flip-flop é alto, ou seja, uma corrente flui através do botão.
//Constants #define number_of_74hc595s 1 #define numOfRegisterPins number_of_74hc595s * 8 #define SER_Pin 2 #define RCLK_Pin 3 #define SRCLK_Pin 4 //Parameters const int grpBtnPin = A0; //Variables boolean registers[numOfRegisterPins] = {0, 0, 0, 0, 0, 0, 0, 0}; boolean grpBtnState[numOfRegisterPins] = {0, 0, 0, 0, 0, 0, 0, 0}; boolean oldGrpBtnState[numOfRegisterPins] = {0, 0, 0, 0, 0, 0, 0, 0}; int grpBtnVal[numOfRegisterPins] = {0, 0, 0, 0, 0, 0, 0, 0}; void setup() { //Init Serial USB Serial.begin(9600); Serial.println(F("Initialize System")); //Init register pinMode(SER_Pin, OUTPUT); pinMode(RCLK_Pin, OUTPUT); pinMode(SRCLK_Pin, OUTPUT); pinMode(grpBtnPin, INPUT); } void loop() { readGrpBtn(); } void clearRegisters() { /* function clearRegisters */ //// Clear registers variables for (int i = numOfRegisterPins - 1; i >= 0; i--) { registers[i] = LOW; } } void writeRegisters() { /* function writeRegisters */ //// Write register after being set digitalWrite(RCLK_Pin, LOW); for (int i = numOfRegisterPins - 1; i >= 0; i--) { digitalWrite(SRCLK_Pin, LOW); int val = registers[i]; digitalWrite(SER_Pin, val); digitalWrite(SRCLK_Pin, HIGH); } digitalWrite(RCLK_Pin, HIGH); } void setRegisterPin(int index, int value) { /* function setRegisterPin */ ////Set register variable to HIGH or LOW registers[index] = value; } void readGrpBtn() { /* function readGrpBtn */ //// Read each btn for (int i = numOfRegisterPins - 1; i >= 0; i--) { grpBtnState[i] = false; setRegisterPin(i, HIGH); writeRegisters(); delay(20); grpBtnVal[i] = analogRead(grpBtnPin); setRegisterPin(i, LOW); writeRegisters(); if (grpBtnVal[i] > 500) { grpBtnState[i] = true; if (oldGrpBtnState[i] != grpBtnState[i]) { Serial.print(F("Btn ")); Serial.print(i); Serial.print(F(" detected -> State = ")); Serial.println(grpBtnVal[i]); } } } }
Resultados
O estado do botão é actualizado cada vez que passa pela memória de registo correspondente e é possível ler 8 botões com uma única entrada analógica.
Aplicações
- Gerir até 8 sensores com três pinos digitais e um pino analógico de um microcontrolador
- Criar um dispositivo HID com múltiplas chaves
Encontre o nosso módulo de expansão de registo de turnos com conectividade simplificada, compatível com todos os tipos de microcontroladores (Arduino, ESP8266, ESP32, Raspberry Pi, etc.)
Fontes
- https://fr.wikipedia.org/wiki/Registre_%C3%A0_d%C3%A9calage
- https://fr.wikipedia.org/wiki/Bascule_(circuit_logique)
- Utilização de um registo de turnos
- Utilização de um Multiplexer
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie