Skip to the content
PCBKitNew board
2 layersFluidSim2d, the printed circuit board in 3D

A real‑time FLIP fluid simulation for a 2‑inch round LED pocket watch.

Copper layers
2
Thickness
1.6 mm
Parts
14
Nets
25
Pads
56
Tracks, vias
93, 19
Pours
2
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
20 Jun 2026
Updated
27 Oct 2026

Overview

FluidSim2d is an open-source printed circuit board by laizie, from the laizie/FluidSim2d repository on GitHub, published under the MIT licence. It is a 2-layer board with 14 parts on 25 nets, routed with 93 tracks and 19 vias.

It is built around the TP4056. Its parts include 5 capacitors and 5 connectors. It belongs with the wearables boards of this library.

Main components

1

README

README.md

FluidSim2d

A real‑time FLIP fluid simulation for a 2‑inch round LED pocket watch. Water that sloshes, pools, and beads up as you tilt it, running on a microcontroller you can fit under a coin.

The solver started in the browser, where the physics is easy to watch and tune, then moved to a Waveshare RA4M1‑Zero Mini driving a round display on a custom PCB.

  • The solver is mine. Written from scratch in JavaScript (src/sim.js) and hand‑translated to C++ (src/main.cpp) for the hardware.
  • Claude helped build the browser harness: the HTML panel that draws the LED matrix and lets me change parameters live while the sim runs.
  • Built to leave the browser. Fixed grid, particle count that scales with grid area, and a 60 Hz step, all sized to survive on the real hardware rather than only in a tab.

See it running

No build step. learn/led-matrix-10.html loads the solver from src/sim.js and the harness from src/engine.js.

  • Quickest: open learn/led-matrix-10.html in a browser and pull the rotate slider around. That's the watch being tilted, and the fluid follows.
  • With live‑reload while editing: run npx live-server from the repo root (so the src/ scripts resolve), then open /learn/led-matrix-10.html.

Speed, rotate, and grid are all live. Grid runs from 10×10 up to 24×24, and the LED layout, the serpentine data chain, and the particle count all rebuild to match, so you can see what the sim looks like at the resolution the real panel will run.

How it works

It's a FLIP (Fluid‑Implicit‑Particle) solver:

  1. Forces + advect: add gravity (in the direction the watch is tilted), move the particles, and bounce them off the circular wall.
  2. Push‑apart: a light pass so particles don't sit on top of each other.
  3. P2G: splat particle velocities onto a staggered grid and mark each cell as fluid, air, or wall.
  4. Pressure solve: adjust the grid until every fluid cell has as much flow out as in, so the water can't be squashed. This is what makes it slosh and curl up the walls instead of piling like sand.
  5. G2P: read velocities back to the particles (FLIP/PIC blend).

This runs twice per frame (two substeps) at 60 Hz. The constants at the top of src/sim.js are the knobs that decide how the water feels: the FLIP/PIC blend, bounciness off the wall, and how stiff the pressure solve is.

While learning this, I had Claude help write up an explanation of FLIP fluids pitched at exactly what I needed to understand: learn/physics-and-code.html. learn/porting-guide.html walks through the current solver function by function, how to port each part to C++ for the RA4M1, and how and why it changed from the first version.

Hardware plan

  • MCU: Waveshare RA4M1‑Zero Mini (Renesas RA4M1: 48 MHz Arm Cortex‑M4 with a single‑precision FPU, 256 KB flash, 32 KB SRAM). RAM is the tight budget: the grid, particles, and render state all have to fit in 32 KB, and math should stay in float (0.5f, not 0.5) because the FPU doesn't do double.
  • Display: GC9A01A 1.28″ round TFT LCD, 240×240 (SPI)
  • Tilt: MPU6050 accelerometer/IMU (its gravity vector feeds the sim's gravityDir directly)
  • Board: custom round PCB (KiCad project in pcb/)

Pinout / wiring

All parts run at 3.3 V, so power them from the RA4M1‑Zero's 3V3 pin (not 5 V) and tie all grounds together. The board's logic level defaults to 3.3 V (set by a jumper resistor); leave it there. Pins below match the #defines and begin() calls in src/main.cpp.

GC9A01A round TFT → RA4M1‑Zero (hardware SPI)

Display pinSignalRA4M1‑Zero
SCLSPI clock (SCK)D13
SDASPI data (MOSI)D11
CSChip selectD10
DCData/commandD5
RESResetD4
BLKBacklight3V3
VINPower3V3
GNDGroundGND

MPU6050 accelerometer → RA4M1‑Zero (I²C)

MPU6050 pinSignalRA4M1‑Zero
SDAI²C dataA4
SCLI²C clockA5
VCCPower3V3
GNDGroundGND

SPI (D13/D11) and I²C (A4/A5) are fixed hardware pins on the RA4M1, so SPI.begin() and Wire.begin() take no pin arguments. This leaves D6 (the onboard WS2812 RGB LED) free. The RA4M1‑Zero's pins match the Arduino UNO R4 Minima's, so that board in the Arduino "UNO R4" (Renesas) core works for uploading. Most MPU6050 breakouts have onboard I²C pull‑ups, so no extra resistors are needed; leave AD0 unconnected for the default address 0x68.

Status

Complete:

  • Solver working in the browser, tunable live
  • C++ port written: solver, accelerometer, and display render all in src/main.cpp
  • Brought it up on real hardware (see test/ for the display and screen test sketches)

In Progress:

  • Custom round PCB in KiCad (pcb/)

Credit

Idea credit fully given to mitxela. First given the idea from his video here.

The physics comes from the standard PIC/FLIP literature: Bridson's Fluid Simulation for Computer Graphics, Zhu & Bridson's Animating Sand as a Fluid, and Matthias Müller's "Ten Minute Physics" FLIP video. The implementation here is my own.

License

MIT. Copyright (c) 2026 laizie.

This is a personal build I'm sharing so people can read it and learn from it. If it's useful to you, keep the copyright notice with it, and I'd appreciate a link back.

Parts

14
QtyValueFootprintReferences
3100nFCapacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderC1, C2, C3
210uFCapacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderC4, C5
1Conn_01x02Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_HorizontalJ4
1Conn_02x09_Odd_EvenFootprints:RA4M1_Zero_SMDJ5
1GC9A01 DisplayConnector_PinHeader_2.54mm:PinHeader_1x08_P2.54mm_VerticalJ1
1MPU6050Connector_PinHeader_2.54mm:PinHeader_1x08_P2.54mm_VerticalJ2
1TP4056Footprints:TP4056J3

The 10 most common of 14 parts.

Questions

What parts does the FluidSim2d use?

14 parts, built around the TP4056. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the FluidSim2d KiCad files?

From the laizie/FluidSim2d repository on GitHub, at the commit this page was made from: the board is pcb/fluidsim2d/fluidsim2d.kicad_pcb and its schematic pcb/fluidsim2d/fluidsim2d.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the FluidSim2d design in my own project?

Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

Similar boards

  • 2 layers80 × 129.1 mmSmart Plant, the printed circuit board in 3D

    Smart Plant

    JGAguado/Smart_Plant

    The Smart Plant is a board that can be plugged directly on the soil, close to the plant, that allows the measurement of the environment (soil moisture, environment temperature & illuminance), and presents the…

    75 parts303
  • 2 layers129.5 × 50.8 mmLilka, the printed circuit board in 3D

    Lilka

    lilka-dev/lilka

    Схема та документація ігрової консолі Lilka

    39 parts234GPL-2.0
  • 2 layers110 × 115 mmEsp32 keyboard v0.1, the printed circuit board in 3D

    Esp32 keyboard v0.1

    hhuysqt/esp32s3-keyboard

    USB/BLE keyboard driver based on ESP32S3-WROOM-1

    230 parts168GPL-3.0
  • 2 layers192.4 × 50 mmOmote, the printed circuit board in 3D

    Omote

    OMOTE-Community/OMOTE-Hardware

    Open Source Remote - Hardware

    187 parts157GPL-3.0
  • 2 layers316 × 119 mmTeensy Grovebox, the printed circuit board in 3D

    Teensy Grovebox

    jerry20091103/Teensy_Grovebox

    A portable synth and music multi-tool made with Teensy 4.1

    142 parts150MIT
  • 4 layers43 × 49 mmEsppdp, the printed circuit board in 3D

    Esppdp

    Spritetm/esppdp

    ESP32-based PDP11 simulator, based onSimH

    55 parts141
  • 2 layersCharger stepup, the printed circuit board in 3D

    Charger stepup

    Aplyard/Oled-Clicker

    Clicker Counter for Arduino Nano

    19 parts117BSD-3-Clause
  • 6 layers64.8 × 69.9 mmEzDV, the printed circuit board in 3D

    EzDV

    tmiw/ezDV

    A FreeDV device based on the ESP32.

    130 parts114