This tutorial is part of: ESP32-S3 RGB LED-matrix
Een gaaf project om te maken voor de lol en voor praktische toepassingen met de ESP32-S3 RGB-matrixmodule. Links naar andere video's vind je onderaan dit artikel.
ESP32-S3 RGB LED-matrixproject 4 - Kantelpunt
Project 4 – Tilt Dot (Verplaats de stip door de ESP32-S3 RGB LED Matrix te kantelen)
Project 4 introduceert de bewegingssensor die is ingebouwd in de ESP32-S3 RGB LED Matrix-module. In plaats van de stip automatisch te verplaatsen (zoals in Project 1) of tekst te scrollen (Projecten 2 en 3), kun je met dit project de positie van de stip bepalen door simpelweg het bord te kantelen. De stip beweegt soepel over het 8×8 RGB-display op basis van live metingen van de QMI8658C-versnellingsmeter aan de achterkant van de module.
Alle zes projecten in deze serie worden gedemonstreerd in één YouTube-video. Dezelfde video is op deze pagina ingebed, zodat je precies kunt zien hoe de stip in realtime beweegt terwijl het bord kantelt. De volledige code voor dit project wordt automatisch onder het artikel geladen, en affiliate-aankooplinks voor de module verschijnen onder het codegedeelte.


Overzicht van de ESP32-S3 RGB LED Matrix-module
Dit project maakt gebruik van de ESP32-S3 RGB LED Matrix-module, die het volgende bevat:

- ESP32-S3-microcontroller met Wi-Fi en Bluetooth
- 8×8 RGB LED-matrix (64 individueel adresseerbare LED's)
- QMI8658C-versnellingsmeter aan de achterkant voor kantel- en bewegingsdetectie
- USB-poort voor programmeren en voeding
- Boot-/Reset-knoppen
- Bruikbare GPIO-pinnen voor toekomstige uitbreiding
De QMI8658C-sensor leest X-, Y- en Z-versnellings- en oriëntatiewaarden, waardoor de stip omhoog/omlaag/links/rechts kan bewegen op basis van hoe het bord wordt gekanteld.

Projecten in de video (tijdstempels)
- 00:00 – Introductie
- 02:01 – ESP32-boards installeren
- 03:32 – Bibliotheken installeren
- 05:32 – Project 1: Beweegbare stip
- 11:11 – Project 2: Tekst scrollen
- 12:59 – Project 3: HTTP-tekst
- 16:41 – Project 4: Tilt Dot (dit project)
- 18:55 – Project 5: Pijl omhoog
- 20:02 – Project 6: Doelspel
Het bekijken van de kanteldemonstratie in de video wordt sterk aanbevolen, omdat je kunt zien hoe de stip soepel reageert op de oriëntatie van het bord.

ESP32-boards installeren in Arduino IDE
Als je een eerder project hebt voltooid, is de boardondersteuning al geïnstalleerd. Volg anders deze stappen:
- Open
Bestand > Voorkeuren→ voeg de ESP32-boards-URL toe. - Ga naar
Extra > Board > Boards Manager…en installeer ESP32. - Selecteer je ESP32-S3-board onder
Extra > Board. - Selecteer de juiste COM-poort onder
Extra > Poort.
Vereiste bibliotheken installeren
Dit project vereist de volgende bibliotheken:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFX LibraryQMI8658(bewegingssensor)
Installeer ze in de Bibliotheekbeheer:
- Open
Sketch > Bibliotheek gebruiken > Bibliotheken beheren…. - Zoek naar Adafruit NeoMatrix → Installeer.
- Sta automatische installatie van Adafruit GFX en Adafruit NeoPixel toe.
- Zoek naar QMI8658 op de vermelde auteur → Installeer.
Hoe Project 4 werkt
De QMI8658C-sensor levert continu versnellingsgegevens langs de X-, Y- en Z-assen. Voor dit project gebruiken we alleen de X- en Y-assen om te bepalen:
- Hoe ver de stip naar links of rechts moet bewegen (X-as)
- Hoe ver de stip omhoog of omlaag moet bewegen (Y-as)
De sensorwaarden worden omgezet naar een coördinatenbereik van 0 tot 7 (voor de 8×8 LED-matrix). De stippositie wordt vele keren per seconde bijgewerkt, wat het soepele glij-effect geeft wanneer je de module kantelt.
Project 4 – Code-instellingen (Tilt Dot)
Hieronder staan de door de gebruiker bewerkbare instellingen die bovenaan de projectcode staan. De volledige sketch verschijnt automatisch onder het artikel.
Matrixpin en -grootte
// 8×8 RGB-matrixconfiguratie
const int MATRIX_PIN = 14; // vaste pin voor dit bord
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
Laat MATRIX_PIN op 14 staan. Deze is vast verbonden met de ingebouwde matrix.
Helderheid
// Algehele helderheid (0–255)
uint8_t matrixBrightness = 40;
Verhoog indien nodig, maar vermijd extreme helderheid bij het van dichtbij bekijken.
Stipkleur
// Stipkleur (R, G, B)
uint8_t dotRed = 0;
uint8_t dotGreen = 200; // lichtgroen (standaard)
uint8_t dotBlue = 0;
Wijzig deze waarden om elke kleur te creëren. Voorbeelden:
- Rood:
(255, 0, 0) - Geel:
(255, 255, 0) - Wit:
(255, 255, 255)
Bewegingsgevoeligheid
Om extreme sprongen te voorkomen, worden versnellingsmeterwaarden meestal begrensd of geschaald. Een typische instelling ziet er zo uit:
// Hoe agressief kantelen de beweging beïnvloedt
float sensitivity = 4.0f; // groter = snellere beweging over het scherm
Als de stip te langzaam beweegt → verhoog de waarde. Als de stip te abrupt beweegt → verlaag deze.
Updatesnelheid (verversingssnelheid)
U kunt een kleine vertraging tussen updates toevoegen om beweging vloeiender te maken:
// Vertraging tussen positie-updates (ms)
int refreshDelayMs = 20; // lager = vloeiender en snellere respons
Waarden tussen 10–30 ms voelen zeer responsief aan.
Samenvatting
Project 4 brengt de ingebouwde QMI8658C-versnellingsmeter van de ESP32-S3 tot leven door u de LED-matrix te laten besturen met fysieke beweging. Een kleine kanteling van het bord verplaatst de stip in dezelfde richting, waardoor dit project een perfecte opstap is voor de meer geavanceerde “Arrow Up”- en “Target Game”-projecten.
De volledige Tilt Dot-schets wordt onder dit artikel geladen (automatisch). Voor het beste begrip bekijkt u de kanteldemonstratie in de video, waar u kunt zien hoe vloeiend de stip beweegt terwijl het bord wordt geroteerd. Links om de ESP32-S3 RGB LED Matrix-module te kopen zijn opgenomen onder het codegedeelte.
This tutorial is part of: ESP32-S3 RGB LED-matrix
- ESP32-S3 RGB LED-matrixproject 1- Basispunt
- ESP32-S3 RGB LED-matrixproject 2 - Scrollende tekst
- ESP32-S3 RGB LED-matrixproject 3 - Tekst vanaf mobiele telefoon
- ESP32-S3 RGB LED-matrixproject 5 - Pijl altijd omhoog
- ESP32-S3 RGB LED-matrixproject 6 - Cible-spel
- ESP32-S3 RGB LED-matrix Wi-Fi + NTP-tijdklokproject -1 Basisklok
- ESP32-S3 RGB LED-matrix internetklokproject - 2 klokken multi-kleur tijd- en datumweergave
- ESP32-S3 RGB LED-matrix internetklokproject - 3 nachtkleuren met datum
- ESP32-S3 RGB LED-matrix internetklokproject - 5 Regenboogkleur
- ESP32-S3 RGB LED-matrix internetklokproject - 4 willekeurige kleuren
- ESP32-S3 RGB LED Matrix test for RGB, GRB setting
/*
Project 4: Tilt Dot – ESP32-S3 RGB LED Matrix (Waveshare)
This sketch reads tilt from the QMI8658C IMU and smoothly moves a dot
on the 8×8 RGB LED matrix based on board orientation.
▶️ Video Tutorial:
https://youtu.be/JKLuYrRcLMI
📚⬇️ Resources & Code Page:
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> // by Lahav Gahali
// -------- LED MATRIX SETUP --------
#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
);
// -------- QMI8658 IMU SETUP --------
QMI8658 imu;
QMI8658_Data imuData;
// -------- USER SETTINGS --------
// true -> dot on opposite side: USB↔OUSB, 34↔15
// false -> dot on same side as UP
bool useOppositeMapping = false;
// Dot color (0–255 each)
uint8_t dotRed = 0;
uint8_t dotGreen = 100;
uint8_t dotBlue = 0;
// Board sides
enum Side {
SIDE_CENTER = 0,
SIDE_USB,
SIDE_OUSB,
SIDE_15,
SIDE_34
};
// Smooth dot position (in pixel coordinates, but kept as float for easing)
float dotPosX = 3.0f; // start at center
float dotPosY = 3.0f;
// Smoothing factor: smaller = slower movement (0.1 very slow, 0.5 faster)
const float dotSmooth = 0.25f;
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 "?";
}
}
// Detect which side is UP using calibrated axes:
// +X = USB, -X = OUSB, +Y = 34, -Y = 15
Side detectSideUp(float ax_g, float ay_g, float az_g) {
// Flat detection
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;
// Thresholds to say "this axis is really tilted"
const float tiltThreshY = 0.5f;
const float tiltThreshX = 0.5f;
// 1) Prefer Y axis for 15 / 34 if it's clearly tilted
if (fabs(ay_g) >= tiltThreshY) {
if (ay_g > 0) {
return SIDE_15; // +Y = 34 up
} else {
return SIDE_34; // -Y = 15 up
}
}
// 2) Otherwise, check X axis for USB / OUSB
if (fabs(ax_g) >= tiltThreshX) {
if (ax_g > 0) {
return SIDE_USB; // +X = USB up
} else {
return SIDE_OUSB; // -X = OUSB up
}
}
// 3) If nothing is strongly tilted, just call it CENTER
return SIDE_CENTER;
}
// Map from UP side to where the dot should go
Side dotSideFromUpSide(Side upSide) {
switch (upSide) {
case SIDE_USB:
return useOppositeMapping ? SIDE_OUSB : SIDE_USB;
case SIDE_OUSB:
return useOppositeMapping ? SIDE_USB : SIDE_OUSB;
case SIDE_34:
return useOppositeMapping ? SIDE_15 : SIDE_34;
case SIDE_15:
return useOppositeMapping ? SIDE_34 : SIDE_15;
case SIDE_CENTER:
default:
return SIDE_CENTER;
}
}
// Convert dot side to matrix coordinates
void getDotPixel(Side dotSide, int &px, int &py) {
// Matrix (0,0) = top-left
// top center: (3,0) → USB
// bottom center: (3,7) → OUSB
// left center: (0,3) → 15
// right center: (7,3) → 34
// center: (3,3)
switch (dotSide) {
case SIDE_USB: px = 3; py = 0; break;
case SIDE_OUSB: px = 3; py = 7; break;
case SIDE_15: px = 0; py = 3; break;
case SIDE_34: px = 7; py = 3; break;
case SIDE_CENTER:
default: px = 3; py = 3; break;
}
}
void setup() {
Serial.begin(115200);
delay(500);
matrix.begin();
matrix.setBrightness(20);
matrix.fillScreen(0);
matrix.show();
// IMU: SDA=11, SCL=12 for 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 dotSide = dotSideFromUpSide(upSide);
int targetX, targetY;
getDotPixel(dotSide, targetX, targetY);
// --- Smooth movement toward target ---
dotPosX += (targetX - dotPosX) * dotSmooth;
dotPosY += (targetY - dotPosY) * dotSmooth;
// Convert to integer pixel coordinates
int px = (int)round(dotPosX);
int py = (int)round(dotPosY);
// Clamp just in case
if (px < 0) px = 0;
if (px > 7) px = 7;
if (py < 0) py = 0;
if (py > 7) py = 7;
// --- Draw dot ---
matrix.fillScreen(0);
uint16_t color = matrix.Color(dotRed, dotGreen, dotBlue);
matrix.drawPixel(px, py, color);
matrix.show();
// Debug
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(" | DOT="); Serial.print(sideName(dotSide));
Serial.print(" | px="); Serial.print(px);
Serial.print(" py="); Serial.println(py);
delay(80);
}
Dingen die je misschien nodig hebt
-
Amazon
-
eBay
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
Hulpmiddelen en referenties
-
Intern🎨 Color picker Toolrobojax.com
Bestanden📁
Fritzing-bestand
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB