Cube 3D

Wireframe 3D cube driven by the QMI8658 IMU — tilt the board to rotate the cube in real time via a complementary filter.

Arduino_GFX QMI8658 IMU Complementary filter Canvas double-buffer Perspective projection

What it does

Reads 6-axis data (accelerometer + gyroscope) from the QMI8658 at 250 Hz. A complementary filter (α = 0.96) fuses gyro integration with accelerometer tilt to produce stable pitch, roll, and yaw angles.

Each frame rotates eight unit-cube vertices through Euler angles, projects them with a simple perspective divide, then draws 12 edges in depth-shaded cyan and 8 vertices as yellow dots — all into an off-screen Arduino_Canvas that flushes atomically.

# Algorithm

StepDetail
IMU read12 bytes from 0x35 (AX_L…GZ_H), big-endian int16 → float. Accel scale: ÷8192 (±4 g). Gyro scale: ÷64 (±512 dps).
Complementary filterangle = 0.96 × (angle + gyro × dt) + 0.04 × accel_angle. Yaw is gyro-only (no magnetometer).
Euler rotationRx (pitch) → Ry (roll) → Rz (yaw) applied per vertex.
Perspective projectsx = x × 90 / (z + 4) + 120. Focal length 90 px, eye 4 units back.
Depth shadingEdge brightness: (depth + 2) × 50 + 55. Edges = cyan channel, vertices = red+green (yellow).
Flushcanvas→flush() pushes the full frame to the ST7789V2 via SPI in one DMA burst.

# Geometry

Vertices (±1 unit cube)

(-1,-1,-1)  ( 1,-1,-1)
( 1, 1,-1)  (-1, 1,-1)
(-1,-1, 1)  ( 1,-1, 1)
( 1, 1, 1)  (-1, 1, 1)

Edges (12)

Bottom face:  0-1, 1-2, 2-3, 3-0
Top face:     4-5, 5-6, 6-7, 7-4
Pillars:      0-4, 1-5, 2-6, 3-7

# IMU Configuration

RegisterValueEffect
CTRL1 (0x02)0x40Address auto-increment on burst reads
CTRL2 (0x03)0x13Accelerometer ±4 g, 250 Hz ODR
CTRL3 (0x04)0x53Gyroscope ±512 dps, 250 Hz ODR
CTRL7 (0x08)0x03Enable both accel and gyro

# Display Library

This sketch uses Arduino_GFX (not TFT_eSPI) with the pin mapping from the submodule's User_Setup.h:

SPI bus (Arduino_GFX)

DC=4, CS=5, SCK=6, MOSI=7
SPI host: SPI2_HOST
RST=8, BL=15 (HIGH = on)

Display init

Arduino_ST7789(bus, RST=8,
  rotation=0, IPS=true,
  W=240, H=280,
  col_offset=0, row_offset=20)

Row offset 20 — the ST7789V2 240×280 panel sits at rows 20–299 inside a 320-row controller.

# Source

Full sketch in the ESP32-S3-LCD reposketches/cube_3d/cube_3d.ino.

git clone https://github.com/binRick/ESP32-S3-LCD
bash flash-sketch-001-cube-3d.sh