Este tutorial faz parte de: Matriz de LEDs RGB ESP32-S3
Projeto bacana para criar com aplicações práticas e divertidas usando o módulo ESP32-S3 RGB Matrix. Links para outros vídeos estão abaixo deste artigo.
Projeto de Matriz de LED RGB ESP32-S3 5 - Setas sempre para cima
Projeto 5 - Seta Sempre Para Cima (Indicador de Orientação usando QMI8658C)
O Projeto 5 utiliza o sensor de movimento QMI8658C para detectar a orientação da Matriz de LEDs RGB ESP32-S3 e sempre exibir uma seta apontando para CIMA em relação à gravidade. Não importa como você gire a placa - lado USB para cima, lado OUSB para cima, lado "15" ou lado "34" - a seta automaticamente se gira e aponta para a direção fisicamente para cima.
Esta é uma demonstração poderosa de detecção de orientação em tempo real usando o acelerômetro embarcado. Todos os seis projetos deste módulo são demonstrados em um vídeo no YouTube, que também está incorporado nesta página. O código completo do Projeto 5 é carregado automaticamente abaixo do artigo, e os links de afiliados aparecem na seção de código.

Visão Geral do Módulo de Matriz de LEDs RGB ESP32-S3
O módulo de matriz LED RGB ESP32-S3 inclui vários componentes que tornam este projeto possível:

- Microcontrolador ESP32-S3- fornece Wi-Fi, BLE e executa a lógica LED/IMU.
- Matriz LED RGB 8×8- exibe a seta em qualquer uma das quatro orientações.
- acelerômetro QMI8658C- detecta inclinação, movimento e orientação.:contentReference[oaicite:0]{index=0}
- porta USB-Cpara alimentação e programação no Arduino IDE.
- Botões de Redefinição e Iníciopara enviar esboços.
- Pinos GPIOdisponível em toda a empresa para projetos adicionais.
A direção da seta é determinada inteiramente pelas leituras do acelerômetro. Quando a placa é girada, o QMI8658C detecta os novos valores de X/Y/Z, e o sketch escolhe qual padrão de seta (↑, ↓, ←, →) deve ser desenhado.

Projetos Abordados no Vídeo (Marcos de Tempo)
- 00:00- Introdução
- 02:01- Instalando placas ESP32
- 03:32- Instalando bibliotecas
- 05:32- Projeto 1: Ponto Móvel
- 11:11- Projeto 2: Rolagem de Texto
- 12:59- Projeto 3: Texto HTTP
- 16:41- Projeto 4: Tilt Dot
- 18:55-Projeto 5: Seta Sempre Para Cima (este projeto)
- 20:02- Projeto 6: Jogo de Alvo
O vídeo mostra claramente como a seta muda de direção instantaneamente com base em como o módulo é girado. Assistir a este segmento é fortemente recomendado.:contentReference[oaicite:1]{index=1}

Instalando as Placas ESP32 no Arduino IDE
Se você completou algum projeto anterior, a configuração da placa já está feita. Caso contrário:
File > Preferences→ Adicione a URL da placa ESP32Tools > Board > Boards Manager…→ Instale "ESP32"- Selecione a placa ESP32-S3 em
Tools > Board - Selecione a porta USB COM correta em
Tools > Port
Instalando Bibliotecas Necessárias
O Projeto 5 utiliza:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFXQMI8658(sensor de movimento)
Sketch > Include Library > Manage Libraries…- Pesquisar:NeoMatrix→ Instalar
- Instale as dependências:NeoPixel+GFX
- Pesquisar e instalarQMI8658por seu autor
Como o Projeto 5 Funciona
O QMI8658C mede a gravidade nos eixos X, Y e Z. Ao comparar esses valores, o esboço determina qual lado físico da placa está voltado para cima:
- USB para cima
- Lado OUSB para cima(oposto do USB)
- Lado "15" para cima
- Lado "34" para cima
Cada orientação corresponde a um padrão de seta diferente na matriz 8×8. O mapeamento segue sua lógica de orientação confirmada de sessões de depuração anteriores. A rotação do tabuleiro é lida continuamente, e a seta é atualizada assim que o lado voltado para cima muda.
Projeto 5 - Configurações de Código (Seta Sempre Para Cima)
Abaixo estão os valores ajustáveis pelo usuário na área de configuração. O código completo do projeto aparece automaticamente abaixo do artigo.
Configuração da Matriz
// Matrix configuration
const int MATRIX_PIN = 14; // fixed for this module
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Recommended orientation: Top-Left origin, progressive mode
// (actual constructor is inside the code loaded below)
Este projeto utilizaNEO_MATRIZ_PROGRESSIVAlayout para garantir que a seta aponte corretamente com base no movimento real.
Brilho
uint8_t matrixBrightness = 40; // 0–255
Você pode aumentar esse valor para ambientes mais claros. Para uso interno, 30-60 é confortável.
Cor da seta
// Arrow color
uint8_t arrowRed = 255;
uint8_t arrowGreen = 0;
uint8_t arrowBlue = 0;
Altere esses valores para modificar a cor da seta. Por exemplo:
- Seta verde:
(0, 255, 0) - Seta azul:
(0, 0, 255) - Seta branca:
(255, 255, 255)
Sensibilidade e Suavização
Para evitar o tremor, o código inclui lógica de suavização e limiar. Nas configurações, você pode encontrar algo como:
// Sensitivity / smoothing adjustment
float tiltThreshold = 0.30f; // adjust if arrow changes too easily
- Se sua seta vira muito facilmente →aumentarlimite.
- Se a seta estiver muito lenta para mudar →diminuiçãolimite.
Padrões de Flechas
O esboço inclui padrões de bitmap de setas para:
- ↑ cima
- baixo
- ← esquerda
- → direito
Você não precisa modificar isso, mas pode mudar as formas dentro do código se quiser um estilo diferente.
Resumo
O Projeto 5 demonstra como a Matriz de LED RGB ESP32-S3 e o acelerômetro QMI8658C trabalham juntos para detectar a orientação e exibir uma seta que sempre aponta para cima. Este projeto se baseia no Tilt Dot (Projeto 4) e prepara você para o jogo interativo final no Projeto 6.
O esboço completo "Arrow Always Up" está disponível abaixo deste artigo (carregado automaticamente). É altamente recomendável assistir à parte correspondente do vídeo para ver como a seta responde instantaneamente à rotação do painel. Se você deseja construir este projeto em casa, links de afiliados para o módulo de matriz de LED RGB ESP32-S3 aparecem na seção de código.
Imagens
Este tutorial é parte de: Matriz de LEDs RGB ESP32-S3
- Projetos de Matriz de LED RGB ESP32-S3 (Jogo de Inclinação, Texto, Seta, Demonstração WiFi)
- Projeto de Matriz de LED RGB ESP32-S3 2 - Texto Rolante
- Projeto de Matriz LED RGB ESP32-S3 3 - Texto do telefone móvel
- Projeto de Matriz LED RGB ESP32-S3 4 - Ponto Inclinado
- Projeto de Matriz de LED RGB ESP32-S3 6 - Jogo de Cible
- Projeto de Relógio Básico ESP32-S3 Matriz de LED RGB Wi-Fi + Relógio NTP -1
- Projeto de Relógio da Internet com Matriz de LED RGB ESP32-S3 - Exibição de Hora e Data em Multi Cor para 2 Relógios
- Projeto de Relógio da Internet com Matriz de LED RGB ESP32-S3 - 3 Cores Noturnas com Data
- Projeto de Relógio Internet com Matriz LED RGB ESP32-S3 - 5 Cores do Arco-íris
- Projeto de Relógio de Internet com Matriz de LED RGB ESP32-S3 - 4 Cores Aleatórias
- Teste de Matriz de LED RGB ESP32-S3 para configuração RGB, GRB
/*
* Projeto 5: Setas Sempre para Cima - Matriz LED RGB ESP32-S3 (Waveshare)
* Este esboço lê a inclinação do IMU QMI8658C e move suavemente um ponto na matriz LED RGB 8×8 com base na orientação da placa.
*
* ▶️ Vídeo Tutorial:
* https://youtu.be/JKLuYrRcLMI
*
* 📚⬇️ Recursos e Página de Código:
* https://robojax.com/RJT829
*
* QMI8658_RGB_2
*/
#include <Arduino.h>
#include <math.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#include <QMI8658.h> // por Lahav Gahali
// -------- CONFIGURAÇÃO DO MATRIZ DE LED --------
#define MATRIX_PIN 14
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN,
NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
NEO_RGB + NEO_KHZ800
);
// -------- CONFIGURAÇÃO DO IMU QMI8658 --------
QMI8658 imu;
QMI8658_Data imuData;
// -------- CONFIGURAÇÕES DO USUÁRIO --------
// verdadeiro -> seta aponta para o lado oposto
// USB↔OUSB, 34↔15
// falso -> a seta aponta para o mesmo lado que está para CIMA
bool useOppositeMapping = false;
// Cor da seta (0-255 cada)
uint8_t dotRed = 0;
uint8_t dotGreen = 150;
uint8_t dotBlue = 0;
// Lados da prancha
enum Side {
SIDE_CENTER = 0,
SIDE_USB,
SIDE_OUSB,
SIDE_15,
SIDE_34
};
// Direção para desenho de setas
enum ArrowDir {
ARROW_CENTER,
ARROW_UP,
ARROW_DOWN,
ARROW_LEFT,
ARROW_RIGHT
};
bool isFlat = false;
const char* sideName(Side s) {
switch (s) {
case SIDE_CENTER: return "CENTER";
case SIDE_USB: return "USB";
case SIDE_OUSB: return "OUSB";
case SIDE_15: return "15";
case SIDE_34: return "34";
default: return "?";
}
}
// -------- DESENHO DE FLECHA (SEU CÓDIGO, INALTERADO) --------
// Desenhe uma seta simples em uma matriz 8x8 apontando na direção dada.
void drawArrow(ArrowDir dir, uint16_t color) {
matrix.fillScreen(0);
switch (dir) {
case ARROW_UP:
// Dica
matrix.drawPixel(3, 0, color);
matrix.drawPixel(4, 0, color);
// Segunda fila
matrix.drawPixel(2, 1, color);
matrix.drawPixel(3, 1, color);
matrix.drawPixel(4, 1, color);
matrix.drawPixel(5, 1, color);
// Eixo
matrix.drawLine(3, 2, 3, 6, color);
matrix.drawLine(4, 2, 4, 6, color);
break;
case ARROW_DOWN:
// Dica
matrix.drawPixel(3, 7, color);
matrix.drawPixel(4, 7, color);
// Linha acima da dica
matrix.drawPixel(2, 6, color);
matrix.drawPixel(3, 6, color);
matrix.drawPixel(4, 6, color);
matrix.drawPixel(5, 6, color);
// Eixo
matrix.drawLine(3, 1, 3, 5, color);
matrix.drawLine(4, 1, 4, 5, color);
break;
case ARROW_LEFT:
// Dica
matrix.drawPixel(0, 3, color);
matrix.drawPixel(0, 4, color);
// Coluna após a dica
matrix.drawPixel(1, 2, color);
matrix.drawPixel(1, 3, color);
matrix.drawPixel(1, 4, color);
matrix.drawPixel(1, 5, color);
// Eixo
matrix.drawLine(2, 3, 6, 3, color);
matrix.drawLine(2, 4, 6, 4, color);
break;
case ARROW_RIGHT:
// Dica
matrix.drawPixel(7, 3, color);
matrix.drawPixel(7, 4, color);
// Coluna antes da gorjeta
matrix.drawPixel(6, 2, color);
matrix.drawPixel(6, 3, color);
matrix.drawPixel(6, 4, color);
matrix.drawPixel(6, 5, color);
// Eixo
matrix.drawLine(1, 3, 5, 3, color);
matrix.drawLine(1, 4, 5, 4, color);
break;
case ARROW_CENTER:
default:
// Simples mais no centro
matrix.drawLine(3, 3, 4, 3, color);
matrix.drawLine(3, 4, 4, 4, color);
matrix.drawLine(3, 3, 3, 4, color);
matrix.drawLine(4, 3, 4, 4, color);
break;
}
matrix.show();
}
// -------- IMU → DETECÇÃO LATERAL --------
// Calibramos anteriormente:
// +X = USB, -X = OUSB
// +Y = 15, -Y = 34 (após sua correção)
Side detectSideUp(float ax_g, float ay_g, float az_g) {
// Detecção de falhas
const float flatThreshXY = 0.15f;
const float flatThreshZ = 0.15f;
if (fabs(ax_g) < flatThreshXY &&
fabs(ay_g) < flatThreshXY &&
fabs(az_g - 1.0f) < flatThreshZ) {
isFlat = true;
return SIDE_CENTER;
}
isFlat = false;
// Limiares para dizer "este eixo está realmente inclinado"
const float tiltThreshY = 0.5f;
const float tiltThreshX = 0.5f;
// Prefira o eixo Y para 15 / 34
if (fabs(ay_g) >= tiltThreshY) {
if (ay_g > 0) {
return SIDE_34; // +Y = 34 para cima
} else {
return SIDE_15; // -Y = 15 para cima
}
}
// Caso contrário, use o eixo X para USB / OUSB
if (fabs(ax_g) >= tiltThreshX) {
if (ax_g > 0) {
return SIDE_USB; // +X = USB para cima
} else {
return SIDE_OUSB; // -X = OUSB para cima
}
}
// Não claramente inclinado → tratar como centro
return SIDE_CENTER;
}
// Mapa do lado UP para onde a seta deve apontar
Side arrowSideFromUpSide(Side upSide) {
if (!useOppositeMapping) {
// A seta mostra o lado que está PARA CIMA
return upSide;
}
// A seta mostra o lado oposto
switch (upSide) {
case SIDE_USB: return SIDE_OUSB;
case SIDE_OUSB: return SIDE_USB;
case SIDE_15: return SIDE_34;
case SIDE_34: return SIDE_15;
case SIDE_CENTER:
default: return SIDE_CENTER;
}
}
// Converter SIDE para ArrowDir
ArrowDir arrowDirFromSide(Side s) {
switch (s) {
case SIDE_USB: return ARROW_UP;
case SIDE_OUSB: return ARROW_DOWN;
case SIDE_15: return ARROW_LEFT;
case SIDE_34: return ARROW_RIGHT;
case SIDE_CENTER:
default: return ARROW_CENTER;
}
}
// ---------------- CONFIGURAÇÃO & LOOP ----------------
void setup() {
Serial.begin(115200);
delay(500);
matrix.begin();
matrix.setBrightness(20);
matrix.fillScreen(0);
matrix.show();
// IMU: SDA=11, SCL=12 no ESP32-S3-Matrix
if (!imu.begin(11, 12)) {
Serial.println("Failed to initialize QMI8658!");
while (1) { delay(1000); }
}
imu.setAccelUnit_mg(true);
imu.setGyroUnit_dps(true);
imu.setDisplayPrecision(4);
Serial.print("QMI8658 initialized. useOppositeMapping = ");
Serial.println(useOppositeMapping ? "TRUE" : "FALSE");
}
void loop() {
if (!imu.readSensorData(imuData)) {
return;
}
float ax_g = imuData.accelX / 1000.0f;
float ay_g = imuData.accelY / 1000.0f;
float az_g = imuData.accelZ / 1000.0f;
Side upSide = detectSideUp(ax_g, ay_g, az_g);
Side arrowSide = arrowSideFromUpSide(upSide);
ArrowDir dir = arrowDirFromSide(arrowSide);
uint16_t color = matrix.Color(dotRed, dotGreen, dotBlue);
drawArrow(dir, color);
// Depurar
Serial.print("AX="); Serial.print(ax_g, 3);
Serial.print(" AY="); Serial.print(ay_g, 3);
Serial.print(" AZ="); Serial.print(az_g, 3);
Serial.print(" | UP="); Serial.print(sideName(upSide));
Serial.print(" | ARROW="); Serial.println(sideName(arrowSide));
delay(80);
}
Coisas que você pode precisar
-
Amazonas
-
eBay
-
AliExpressCompre a matriz RGB ESP32-S3 na AliExpress (2)s.click.aliexpress.com
-
AliExpressCompre a matriz RGB ESP32-S3 na AliExpress.s.click.aliexpress.com
Recursos e referências
-
InternoFerramenta de seleção de coresrobojax.com
Arquivos📁
Arquivo Fritzing
-
esp32-S3-supermini-tht peça fritzing
esp32-S3-supermini-tht.fzpz0.02 MB