Olhos Ultrassônicos: Sensor de Distância Interativo com Matriz LED 8x8
Componentes e Materiais
| Sensor Ultrassônico HC-SR04 (genérico) | 2 |
| Arduino Nano R3 | 1 |
| Fotorresistor (LDR) | 1 |
| Matriz LED 8x8 MAX7219 (Maxim Integrated) | 2 |
| Protoboard meia | 1 |
| Fios jumpers (genéricos) | 1 |
| Resistor 330 ohm | 1 |
Aplicativos e Serviços Online
- Arduino IDE
Sobre o Projeto
Queria fazer um projeto peculiar usando matrizes LED 8x8 e sensores ultrassônicos... algo diferente do que as pessoas costumam fazer com ultrassônicos - e queria que fosse divertido e lúdico.
Então criei o que chamo de UltrasonicEyes - um projeto divertido que você coloca onde pessoas circulam e ele "olha" para onde as pessoas estão, pisca e, bem, assusta de um jeito divertido e creepy!
O que vamos precisar?
Módulos de sensor ultrassônico são projetados para detectar obstáculos e determinar a distância, geralmente com alcance de 3-4 metros, boa distância para colocar numa sala ou escritório.

Uso 2 módulos HC-SR04 comprados no e-Bay. São super baratos.
Módulos são simples, precisam só 3 ou 4 fios para conectar ao Arduino.
Os módulos de matriz LED 8x8 que escolhi permitem encadeamento, então só um precisa conectar ao Arduino, e o segundo conecta ao primeiro.

Usam SPI, então só 5 fios para o Arduino controlar imagens nos dois displays. Precisamos de dois, claro!
NOTA: O código usa Hardware SPI, então se usar placa diferente do Nano, verifique quais pinos são Hardware SPI para MOSI e SCK e ligue accordingly!

Também precisa de microcontrolador compatível com Arduino. Uso Nano (compatível) por ser pequeno, ter USB para alimentação/programação e muitos GPIOs.

Soldei tudo em uma protoboard do tamanho de meia protoboard, mas recomendo montar tudo na meia protoboard primeiro, assim não precisa soldar e pode desmontar/mudar fácil.
Por fim, precisa de um LDR (fotorresistor) para detectar luz, resistor 330ohm e muitos fios de protoboard, macho-fêmea e fêmea-fêmea.
NOTA: Pode usar fios de qualquer cor... não há exigência de usar as mesmas cores que eu, mas, é boa prática usar vermelho e preto para ALIMENTAÇÃO e GND, e outras cores para dados/sinais, facilitando identificar quais fios têm energia.
Montando Tudo
Alimentação e GND
Conecte fio preto do GND do Nano ao trilho GND da protoboard. Mesmo com fio vermelho, ligando 3,3V (ou 5V se só tiver) ao trilho POWER.

Conecte fio preto entre os dois trilhos GND dos lados da protoboard. Mesmo com vermelho nos dois trilhos POWER.
Nota: Alguns painéis LED matrix podem precisar 5V em vez de 3,3V dependendo da marca. Se tiver resultados instáveis, tente usar o pino 5V do Arduino.
Ligando os Sensores Ultrassônicos
Conecte fio preto entre pinos GND de cada sensor ultrassônico ao trilho GND. Mesmo com vermelho nos pinos VCC (POWER) dos sensores ao trilho POWER.

Agora conecte fios brancos e azuis:
- Branco do TRIG do sensor 1 ao pino digital 2 do Arduino
- Azul do ECHO do sensor 1 ao pino digital 3 do Arduino
- Branco do TRIG do sensor 2 ao pino digital 4 do Arduino
- Azul do ECHO do sensor 2 ao pino digital 5 do Arduino
Ótimo! Sensores ultrassônicos prontos!
Conectando as Duas Matrizes LED 8x8
Conecte fio preto entre pino GND de entrada de uma matriz LED ao trilho GND. Mesmo com vermelho no pino VCC de entrada ao trilho POWER.

Conecte fio preto entre pino GND de saída do display 1 e pino GND de entrada do display 2. Mesmo com vermelho entre pino VCC de saída do display 1 e VCC de entrada do display 2.
Enquanto conectamos fios entre os 2 displays, vamos terminar essa parte:
- Amarelo entre pino SCK (Clock) de saída do display 1 e SCK de entrada do display 2.
- Azul entre pino MOSI (Data) de saída do display 1 e MOSI de entrada do display 2.
- Branco entre pino CS (Select) de saída do display 1 e CS de entrada do display 2.
Ótimo! Agora conecte o resto do display 1 à protoboard:
- Amarelo entre pino SCK de entrada do display 1 e pino digital 13 do Arduino.
- Azul entre pino MOSI de entrada do display 1 e pino digital 11 do Arduino.
- Branco entre pino CS de entrada do display 1 e pino digital 10 do Arduino.
LEMBRE-SE: O código usa Hardware SPI, então se usar placa diferente do Nano, verifique pinos Hardware SPI para MOSI e SCK e ligue accordingly!
Conectando LDR e Resistor para Detectar Luz Ambiente
Antes de conectar, por que este passo? O LDR conectado ao Arduino permite detectar se está claro ou escuro ao redor do UltrasonicEyes e usamos isso para aumentar ou diminuir o brilho dos displays.

Não queremos displays super brilhantes à noite; no escuro, vemos bem com brilho ~30%, mas em luz dia ou sala clara, precisamos aumentar brilho para visibilidade.
Conecte o LDR em duas fileiras de pinos na protoboard, como no diagrama. Deixe espaço para resistor e fio ao Arduino.
Conecte resistor 330ohm entre uma fileira de um lado do LDR e trilho GND.
Conecte fio vermelho entre fileira do outro lado do LDR ao trilho POWER.
Por fim, conecte fio marrom entre a fileira onde o resistor 330ohm está conectado e pino Analógico 5 (A5) no Arduino. Precisa ser analógico para ler valor 0-255 (intensidade luz) em vez de só 0 e 1 como pino digital.
Ligue e Carregue o Código
Pronto, tudo ligado. Conecte cabo USB entre Arduino e computador, e carregue o sketch UltrasonicEyes abaixo para ver funcionando.
Após ligar e carregar, ande na frente dos sensores ou mova as mãos e veja o que acontece!
Quer Tornar Mais Permanente?
Quer tornar seu UltrasonicEyes mais permanente? Veja meu vídeo cobrindo a versão protoboard soldada em protoboard aqui...
Depois imprima as 2 partes da caixa em qualquer impressora 3D e monte como no vídeo!
Também estou expandindo UltrasonicEyes para ter botão capacitivo (ou normal) para alternar formatos de olhos... veja meus experimentos aqui...
Confira meus outros projetos e vídeos em unexpectedmaker.com
Siga no Twitter, Facebook, Instagram e Tindie
Patreon
Código
Ultrasonic Eyes C/C++
#include <MD_MAX72xx.h> // Biblioteca para controlar displays LED 8x8 - instale via Gerenciador de Bibliotecas
#include <NewPing.h> // Biblioteca para sensores ultrassônicos - instale via Gerenciador de Bibliotecas
// Pinos do display LED matrix 1
//#define CLK_PIN 13 // Hardware SPI - conecte CLK ao pino CLK hardware do seu dispositivo
//#define DATA_PIN 11 // Hardware SPI - conecte MOSI ao pino MOSI hardware do seu dispositivo
#define CS_PIN 10 // Chip Select
#define MAX_DEVICES 2 // número de displays - precisamos de 2, um para cada olho
#define LIGHT A5 // Pino analógico 5 para ler valor do LDR
// Hardware SPI - inicializa automaticamente
MD_MAX72XX mx = MD_MAX72XX(CS_PIN, MAX_DEVICES);
#define t1 2 // Trigger sensor ultrassônico 1
#define e1 3 // Echo sensor ultrassônico 1
#define t2 4 // Trigger sensor ultrassônico 2
#define e2 5 // Echo sensor ultrassônico 2
#define maxDist 400 // distância máxima para pulso ultrassônico
NewPing eyeR(t2, e2, maxDist); // Inicializa sensor ultrassônico 2
NewPing eyeL(t1, e1, maxDist); // Inicializa sensor ultrassônico 1
// Rastreia estado atual do sistema para, após piscar, voltar a olhar na última direção
// Estados possíveis:
// 0: Olhando frente
// 1: Olhando direita
// 2: Olhando esquerda
int currentState = -1;
long duration1, duration2;
int distance1, distance2;
float nextBlink = millis() + 1000; // Próximo piscar aleatório
float lightAmount = 0; // Intensidade luminosa atual
uint8_t eye_forward[COL_SIZE] = {
0b00111100, 0b01000010, 0b01011010, 0b10101101,
0b10111101, 0b10011001, 0b01000010, 0b00111100
};
uint8_t eye_right[COL_SIZE] = {
0b00111100, 0b01000010, 0b01110010, 0b11011001,
0b11111001, 0b10110001, 0b01000010, 0b00111100
};
uint8_t eye_left[COL_SIZE] = {
0b00111100, 0b01000010, 0b01001110, 0b10010111,
0b10011111, 0b10001101, 0b01000010, 0b00111100
};
uint8_t eye_blink[COL_SIZE] = {
0b00000000, 0b00111100, 0b01111110, 0b11111111,
0b10111101, 0b11000011, 0b01111110, 0b00111100
};
void setup() {
mx.begin(); // Inicializa biblioteca Matrix Display
// Modos pinos sensor ultrassônico 1
pinMode(t1, OUTPUT);
pinMode(e1, INPUT);
// Modos pinos sensor ultrassônico 2
pinMode(t2, OUTPUT);
pinMode(e2, INPUT);
// Pinos trigger começam LOW
digitalWrite(t1, LOW);
digitalWrite(t2, LOW);
// Modo pino LDR como INPUT
pinMode(LIGHT, INPUT);
// Começa com olhos olhando frente
ShowEye_Forward();
currentState = 0;
}
void loop() {
// Lê nível de luz atual
lightAmount = analogRead(LIGHT);
// Ajusta valor dentro da faixa de intensidade máxima dos displays
lightAmount = (lightAmount / 255) * MAX_INTENSITY;
// Define intensidade
mx.control(MD_MAX72XX::INTENSITY, lightAmount);
// Ping olho esquerdo com 5 repetições
distance1 = eyeL.ping_median(5);
// Atraso 500ms antes de pingar olho direito para evitar conflitos
delay(500);
// Ping olho direito com 5 repetições
distance2 = eyeR.ping_median(5);
// Verifica se é hora de tentar inserir um piscar
if (nextBlink < millis()) {
// Próximo piscar em tempo aleatório entre agora + 2s e 10s
nextBlink = millis() + random(2000, 10000);
// Decide se piscar simples ou duplo
// Número aleatório 1-13, se <= 6 é piscar duplo
if (random(1, 13) <= 6) ShowEye_Blink_Dbl();
else ShowEye_Blink();
// Pausa 250ms para garantir piscar antes de voltar a olhar
delay(250);
return; // Sai desta iteração do loop
}
// Verifica se diferença entre distâncias é < 250 ou ambas 0 (nada detectado)
float difference = (distance2 - distance1);
if (abs(difference) < 250 || (distance1 == 0 && distance2 == 0)) {
ShowEye_Forward();
currentState = 0;
}
// Se distance1 > distance2 e distance1 > 0, olha direita
else if (distance2 < distance1 && distance1 > 0) {
ShowEye_Right();
currentState = 1;
}
// Se distance2 > distance1 e distance2 > 0, olha esquerda
else if (distance1 < distance2 && distance2 > 0) {
ShowEye_Left();
currentState = 2;
}
// Atraso 250ms para olhos exibirem corretamente
delay(250);
}
/***************************************/
/************ Funções MAX7219 ************/
/***************************************/
void ShowEye_Right() {
mx.clear();
mx.control(MD_MAX72XX::INTENSITY, lightAmount);
for (uint8_t row = 0; row < ROW_SIZE; row++) {
mx.setColumn(row, eye_right[row]);
mx.setColumn(row + 8, eye_right[row]);
}
}
void ShowEye_Left() {
mx.clear();
mx.control(MD_MAX72XX::INTENSITY, lightAmount);
for (uint8_t row = 0; row < ROW_SIZE; row++) {
mx.setColumn(row, eye_left[row]);
mx.setColumn(row + 8, eye_left[row]);
}
}
void ShowEye_Forward() {
mx.clear();
mx.control(MD_MAX72XX::INTENSITY, lightAmount);
for (uint8_t row = 0; row < ROW_SIZE; row++) {
mx.setColumn(row, eye_forward[row]);
mx.setColumn(row + 8, eye_forward[row]);
}
}
void ShowEye_Blink() {
mx.clear();
mx.control(MD_MAX72XX::INTENSITY, lightAmount);
for (uint8_t row = 0; row < ROW_SIZE; row++) {
mx.setColumn(row, eye_blink[row]);
mx.setColumn(row + 8, eye_blink[row]);
}
delay(150); // Mantém piscar por 150ms
// Volta estado dos olhos ao que era
if (currentState == 0) ShowEye_Forward();
else if (currentState == 1) ShowEye_Right();
else if (currentState == 2) ShowEye_Left();
}
void ShowEye_Blink_Dbl() {
mx.clear();
mx.control(MD_MAX72XX::INTENSITY, lightAmount);
for (uint8_t row = 0; row < ROW_SIZE; row++) {
mx.setColumn(row, eye_blink[row]);
mx.setColumn(row + 8, eye_blink[row]);
}
delay(75);
// Volta estado brevemente
if (currentState == 0) ShowEye_Forward();
else if (currentState == 1) ShowEye_Right();
else if (currentState == 2) ShowEye_Left();
delay(75);
// Pisca novamente
ShowEye_Blink();
}
Peças Personalizadas e Gabinetes
Imprima com qualquer impressora 3D, sem configurações específicas necessárias.
Esquemáticos
ultrsoniceyes_final_Th84xpUyB2.fzz
Processo de manufatura
- Construa seu Próprio Jogo UFO Attack com Arduino UNO e Display MAX7219
- Persianas Inteligentes: Controle Automático de Luz com Arduino e Energia Solar
- Relógio 3D RGB Arduclock – Bluetooth, LEDs Endereçáveis e RTC
- Monitor de Saúde de Rios: Sistema de Qualidade da Água Baseado em Arduino
- Construa um Homem de Ferro com Arduino: Componentes, Sensores e Guia Passo a Passo
- Construa um Sensor de Obstáculos Simples com Arduino – Tutorial Fácil com LED IR e Fotodiodo
- Jogo Interativo com Joystick e Arduino – Feedback com LEDs
- Find Me: Localizador Inteligente de Objetos com Arduino e Bluetooth
- Controlador de Umidificador DIY com Arduino e Relé – Configuração Segura de Alta Tensão
- Pequeno Rover com Arduino: Construa seu Próprio Robô Autônomo