Skip to content

Documenting a successful external pattern port to Patternflow hardware — and an important JS→firmware color conversion issue #67

@engmung

Description

@engmung

Summary

I recently ported an external JavaScript LED pattern onto Patternflow hardware and wanted to document the process, the original credit, and one important conversion issue that came up along the way.

The original pattern was created by zhuo-ran-liu and shared here:

https://github.com/zhuo-ran-liu/pixelgarden/tree/main

I adapted that pattern for Patternflow’s ESP32-S3 HUB75 LED matrix firmware, using the Patternflow web converter prompt as the starting point for generating the Arduino-compatible C++ header.

The port is now working correctly on the physical hardware.


Credit

This Patternflow version is a hardware port of zhuo-ran-liu’s original JavaScript pattern.


What happened

1. Original JavaScript pattern worked beautifully in the web preview

The JS version displayed a rich, animated, multicolor gradient effect with pulsing tile-based imagery.

2. I converted it with the Patternflow web prompt

I copied the current Patternflow JS → firmware conversion prompt and used it to generate a C++ header for the ESP32-S3 firmware.

The structure of the pattern converted correctly, but the first hardware result was visually wrong:

  • the animation was present,
  • the tile layout was present,
  • but the color field collapsed into a mostly single-color look,
  • losing the vivid multicolor gradient behavior from the JS preview.

3. The issue was eventually traced to RGB output handling

The original JavaScript color function can produce RGB channel values that go outside the normal 0–255 range after the hue-style transformation.

In the first firmware conversion, those transformed values were simply clamped to:

0..255

That looked reasonable at first, but it destroyed the visual behavior of the original preview.
The rich gradient-like color variation became much flatter and almost monochromatic.

The correct fix was to preserve the effective 8-bit byte behavior of the preview output rather than aggressively clamping those transformed RGB values.

Once that was changed, the hardware output immediately recovered the intended multicolor gradient look.


Additional hardware-side optimization

After restoring the correct color behavior, the LED panel showed a slight instability on the left side.

That was fixed separately by simplifying the drawing path:

  • instead of drawing source cells as repeated filled rectangles,
  • the renderer was changed to a per-pixel sampling approach,
  • so each physical LED pixel is evaluated and written exactly once per frame.

This kept the corrected visual result while improving stability on the HUB75 panel.


Why this is worth documenting

This was a useful real-world validation of the Patternflow workflow:

External artist's JavaScript pattern
→ Patternflow web conversion prompt
→ ESP32-S3 C++ firmware header
→ Physical Patternflow LED hardware

The pipeline works, but this case revealed an edge case that is important for future conversions:

When translating JavaScript visual code to firmware, RGB values produced by artistic color transforms should not always be blindly clamped to 0–255.
If the preview’s final appearance depends on the effective byte conversion behavior of those values, the firmware port needs to preserve that behavior.


Suggested improvement for the conversion prompt

It may be worth adding a note to the Patternflow conversion prompt along these lines:

If the JavaScript pattern’s color logic can generate RGB values below 0 or above 255, do not automatically assume hard clamping is visually correct. Preserve the preview’s effective channel behavior whenever possible, especially when matching the original output is the goal.

This would help prevent future ports from accidentally losing intended color behavior.


Closing note

Thanks to zhuo-ran-liu for creating and sharing the original pattern.

This was a nice example of what I want Patternflow to support:
taking expressive browser-based visual code from other artists and bringing it onto a standalone, tactile LED instrument.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions