Escrevi 2 artigos sobre esse multiplexador; o primeiro, fazendo leitura analógica; o segundo, leitura digital. Acontece que estava convicto de que o Arduino Pro Micro teria a mesma disposição do Arduino Leonardo, mas ledo engano, já que com isso tenho a oportunidade de mostrar a migração do código feito no Arduino Leonardo. Como faltou o GPIO 11 no Arduino Pro Micro, tive que reavaliar a situação.
Table of Contents
Datasheet do Atmega32u4
Arduino é o nome da placa de prototipagem, infelizmente confundido até os dias de hoje com a MCU, que é Atmel. Sabendo o nome da MCU (está escrito sobre ela, seja qual for), basta procurar no Google pelo datasheet. O link do datasheet, para os interessados.
De PORTB para PORTF
O grande susto foi quando, ao perceber a diferença, ter olhado para o pinout do Arduino Pro Micro, e perceber que o número de GPIO é menor, além de distribuídos em poucos bits. Por sorte, os pinos analógicos estão na sequência, do 0 ao 3 – digo, no registrador PORTF. Desse modo foi possível manter o código “econômico” dos artigos anteriores, mudando apenas o registrador. Mas primeiro tive que me certificar de que seria possível utilizar o ADC como pino de saída digital. No datasheet:
A importância dos bits em sequência se dá ao fato de estarmos utilizando bitwise para configurar os pinos, e também para selecionar o canal do CD74HC4067. De outro modo, seria mais viável utilizar as funções da API do Arduino, mas o código cresceria um bocado.
Quando procurei pela sequência de pinos no mesmo registrador, me deparei também com a ausência de dois bits: PF2 e PF3.
É a primeira vez que preciso ler o datasheet de um Atmega, no caso, para me certificar do fato de não ter os bits PF2 e PF3. No datasheet está claro que não está no pinout, mas o bit obviamente existe, senão o registrador não iria até PF7.
Tendo resolvido essas questões, e coincidentemente a sequência sendo a mesma do PORTB (os 4 bits mais significativos), só tive que mudar a nomenclatura. Daqui em diante, os artigos relacionados serão feitos no Arduino Pro Micro, com base no código que segue:
#define READ_MUX_PIN 9 uint16_t pb_values = 0; void handler(uint8_t value){ //agora não tem propósito, mas essa função fará sentido em outro artigo Serial.print(value,BIN); Serial.print(" - "); Serial.println(pb_values); } uint8_t getValues(){ for (uint8_t i=0;i<16;i++){ PORTF |= (i<<4); delay(1); pb_values = digitalRead(READ_MUX_PIN); Serial.print("C"); Serial.print(i); Serial.print(":"); handler(pb_values); PORTF &= ~(i<<4); delay(1); } } void setup() { DDRF = 0xF<<4; PORTF &= ~(0xF<<4); pinMode(READ_MUX_PIN,INPUT_PULLUP); Serial.begin(9600); } void loop() { getValues(); delay(2000); }
Como usar o CD74HC4067 no Arduino UNO?
Pode usar o PORTB tranquilamente, o registrador é o mesmo para o atmega328p:
Onde comprar o CD74HC4067?
Esse multiplexador extremamente barato você encontra na Eletrônica Mangili, que tem outros itens interessantes em sua lista, mas o link direto para o multiplexador é esse.
CD74HC4067 como OUTPUT
Para fazer o teste de OUTPUT, coloquei um LED em VCC e GND ao pino 0 do multiplexador. Criei um código simples incrementado ao disposto mais acima, com a função handler fazendo a interação. Ao abrir o monitor serial, coloque “nenhum final de linha” na caixa de seleção do rodapé. Se digitar 0, o LED deve se acender. Se digitar outro número (até 9), devolverá o estado do pino. Se não tiver colocado GND em nenhum pino, qualquer número maior que 0 deve retornar 1. Se estiver com algum pino menor que 9 deve retornar 0.
Como coloquei apenas o pino 0 com um LED, fiz uma lógica na função loop() para acender o LED se digitar 0. Quando o número for maior que 0, o LED se apagará.
#define ENABLE_MUX_PIN 8 #define READ_MUX_PIN 9 uint16_t pb_values = 0; void handler(bool do_read,uint8_t channel, bool turn_on){ if (do_read){ Serial.println("reading..."); pinMode(READ_MUX_PIN,INPUT_PULLUP); //pinMode(ENABLE_MUX_PIN,INPUT); //digitalWrite(ENABLE_MUX_PIN,LOW); PORTF |= (channel<<4); delay(1); pb_values = digitalRead(READ_MUX_PIN); Serial.println(pb_values); PORTF &= ~(channel<<4); return; } if (!turn_on){ PORTF |= (channel); } else{ PORTF &= ~(channel); } pinMode(READ_MUX_PIN,OUTPUT); digitalWrite(READ_MUX_PIN,LOW); pinMode(ENABLE_MUX_PIN,OUTPUT); digitalWrite(ENABLE_MUX_PIN,LOW); } uint8_t getValues(){ for (uint8_t i=0;i<16;i++){ PORTF |= (i<<4); delay(1); pb_values = digitalRead(READ_MUX_PIN); Serial.print("C"); Serial.print(i); Serial.print(":"); Serial.println(pb_values); PORTF &= ~(i<<4); delay(1); } } void setup() { DDRF = 0xF<<4; PORTF &= ~(0xF<<4); pinMode(READ_MUX_PIN,INPUT_PULLUP); pinMode(ENABLE_MUX_PIN,OUTPUT); Serial.begin(9600); delay(1000); } void loop() { //getValues(); if (Serial.available()){ uint8_t value = Serial.read()-48; if (value == 0){ handler(false, 0, true); } else{ handler(true, value, false); } } delay(2000); }
Acender vários LEDs de uma vez
Primeiro, não é possível acionar mais de um pino de uma vez. Lembre-se que essa placa é um multiplexador. Se houver a necessidade de manter continuamente o estado de mais de um pino, use um PCF8574, por exemplo.
Já se a intenção é só ligar diversos LEDs de uma vez, basta fazer um loop nos canais desejados com delay bem baixo. É como fazemos no display de 7 segmentos. A impressão de que estarão ligados todos ao mesmo tempo se chama POV (Persistence Of Vision).
Pin map Atmega32u4
Como deixei o mapa de pinos do Leonardo, fica como referência também o do Arduino Pro Micro:
Revisão: Ricardo Amaral de Andrade
Artigos relacionados
Stone HMI – Adeus, Nextion!
Serial com Python, Arduino e HC12
Sensor capacitivo – dois tipos diferentes