diff --git a/.github/ISSUE_TEMPLATE/guide_stuck.yml b/.github/ISSUE_TEMPLATE/guide_stuck.yml index 4d704b37..9249797d 100644 --- a/.github/ISSUE_TEMPLATE/guide_stuck.yml +++ b/.github/ISSUE_TEMPLATE/guide_stuck.yml @@ -13,8 +13,8 @@ body: id: where attributes: label: Where in the guide - description: The chapter and step. Filled in for you if you came from the guide. - placeholder: "01 Flash, step 3 — Hold BOOT, tap RST, let go." + description: The guide (Build, Play or Make), the chapter and the step. Filled in for you if you came from the guide. + placeholder: "Play · 01 Flash, step 5 — Hold BOOT, tap RST, let go." validations: required: true - type: textarea diff --git a/.gitignore b/.gitignore index 8e84e5ef..e6ccd81c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,12 @@ node_modules/ dist/ build/ out/ -# Keep the /build app route (source, not a build artifact) +# Keep the /build app route (source, not a build artifact), and every other +# folder called build/ in the web source — the guide's /guide/build route. !web/src/app/build/ +!web/src/**/build/ +# The Build guide's models (case halves, print plates) are served from here. +!web/public/guide/build/ # Arduino build artifacts *.hex diff --git a/BUILD_GUIDE.md b/BUILD_GUIDE.md index fedb1b51..de619ea5 100644 --- a/BUILD_GUIDE.md +++ b/BUILD_GUIDE.md @@ -78,7 +78,7 @@ Key sourcing rules (details in the BOM README): > > **What happened** ([#221](https://github.com/engmung/Patternflow/issues/221)): a board powered through USB-C ran **completely fine for 20–30+ minutes** — no heat, no symptoms — and then suddenly started **smoking at one of the connector pins**, rapidly frying the receptacle and the power path around it. Whether that was a hand-soldering defect on those tight-pitch pins or a structural limit of the 14-pin THT part under the LED matrix's peak current was never settled — so rather than ship an input nobody should populate, **v3.9 removed the footprint entirely.** > -> ⚠️ **This is why "it seems to work" proves nothing here.** The failure is *delayed* — passing your multimeter checks and running for half an hour does not mean the joint is safe. +> ⚠️ **This is why "it seems to work" proves nothing here.** The failure is *delayed* — running fine for half an hour does not mean the joint is safe. > > The screw terminal has none of this history — it's the original, proven Patternflow power input, and it's exactly as capable. @@ -108,8 +108,8 @@ Any fab works, though — upload **`hardware/pcb/gerber/patternflow_v3.9_gerber. | Your printer bed | Print | Notes | |---|---|---| -| **256 mm** (P1S / X1C / A1 class) | `bed_256mm/encloser.stl` | Body frame, back panels, and LED-panel mount in one STL. **White PLA.** ~10 h total. | -| **~330 mm+** (H2S class) | `bed_330mm/encloser.stl` | The one-piece original — body, closing part, and LED-panel mount in one STL, **no bonding at all**. **White PLA.** Adds a USB pass-through to the DevKit and a cable exit slot — **for wired MIDI/OSC and flashing, not for power** (power is always `J4`, Section 2). | +| **256 mm** (P1S / X1C / A1 class) | `bed_256mm/encloser.stl` | Body frame (the LED panel's mounting tabs are part of it), back panels and covers in one STL. **White PLA.** ~10 h total. | +| **~330 mm+** (H2S class) | `bed_330mm/encloser.stl` | The one-piece original — body (panel-mounting tabs built in) and closing part in one STL, **no bonding at all**. **White PLA.** Adds a USB pass-through to the DevKit and a cable exit slot — **for wired MIDI/OSC and flashing, not for power** (power is always `J4`, Section 2). | | **Everyone** | `knobs/knobs_20mm.stl` | **Required for every build** — all four knobs in one plate, as its own separate print job. **Black PLA.** (15 mm-shaft encoders → `knobs_15mm.stl`.) | Two colors, on purpose: **body in white, knobs in black** — that contrast is the Patternflow look. Printing the knob plate as a separate job keeps it simple (no color changes mid-print). @@ -122,7 +122,7 @@ Two colors, on purpose: **body in white, knobs in black** — that contrast is t -*Left: `encloser.stl` on a P1S bed. Right: everything that comes out of the one print — body frame, back panels, battery cover, and the LED-panel mounting part.* +*Left: `encloser.stl` on a P1S bed. Right: everything that comes out of the one print — the body frame with its panel-mounting tabs, the back panels and the covers.* ### Bond the printed halves — right after printing @@ -152,12 +152,6 @@ All parts are through-hole, and the video covers the complete order. > |---|---| > | | | -Before first power, go over your joints with a multimeter: - - - -Don't plug the ESP32 DevKit in until after the first power check (Section 7). -
ESP32 pin reference — the full 44-pin map. You don't need it for a normal build; it's here for debugging and derivative designs. @@ -206,9 +200,9 @@ By now the enclosure halves you bonded in Section 4 have cured and the board is > Printed the **330 mm one-piece body**? Everything in this section is identical — the only thing you skipped is the bonding step in Section 4. -1. **Seat the LED panel in the enclosure with its `HUB-75E IN` connector toward the top** — that's the side the ribbon reaches `J1` from. ⚠️ The panel insertion is very tight — near-zero clearance. Work it in slowly. +1. **Seat the LED panel in the enclosure from the front, with its `HUB-75E IN` connector toward the top** — that's the side the ribbon reaches `J1` from. ⚠️ The panel insertion is very tight — near-zero clearance. Work it in slowly. -2. **Fit the LED-panel mounting part and tighten the screws.** The mounting part is a separate piece precisely because panel bolt-hole positions vary between suppliers — match it to your panel first. +2. **Screw the panel to the frame's mounting tabs from behind.** On the standard print the tabs are part of the frame and line up with the BOM-linked panel's holes. Printed the `for_other_panels/` variant (Section 4)? Its mount is a separate, adjustable piece, because bolt-hole positions vary between suppliers — match it to your panel first, then screw. 3. **Set the board into its bay and secure the encoders from the front**: attach each encoder's nut and tighten with a wrench or pliers — this locks the board against the front face. @@ -233,8 +227,7 @@ By now the enclosure halves you bonded in Section 4 have cured and the board is *Cable already through the enclosure hole, wires clamped into `J4`, board about to go in.* -4. **Before inserting the ESP32:** with power disconnected, continuity-check +5V↔GND at the `J3` terminals (open = good, like the Section 5 check). Then power up once and confirm ~5V across `J3`. -5. Power off, seat the ESP32 DevKit in its sockets (orientation per silkscreen), power on. +4. With power off, seat the ESP32 DevKit in its sockets (orientation per silkscreen), then power on. ## 8. Firmware @@ -244,7 +237,7 @@ The ESP32-S3 module is flashed **separately, outside the PCB**. Already seated i No installation required — desktop **Chrome or Edge** only (Web Serial; Firefox/Safari won't work). -> 🎬 **See it before you do it.** [patternflow.work/guide](https://patternflow.work/guide) walks through this section — the port, BOOT and RST, the Wi-Fi step, the Basics pack — on a Patternflow you can turn, and every step has a link for telling us where you got stuck. +> 🎬 **See it before you do it.** [patternflow.work/guide/play](https://patternflow.work/guide/play) walks through this section — the port, BOOT and RST, the Wi-Fi step, the Basics pack — on a Patternflow you can turn, and every step has a link for telling us where you got stuck. > 🔌 **Use the LEFT USB-C port** — the one on your left when the two ports face you. On the ESP32-S3 DevKit that's the board's **native USB** port (labeled `USB`); the browser flasher (Web Serial + Improv) talks to it directly. The right-hand port goes through a separate USB-to-UART bridge chip and is the one Arduino IDE uses (§8.2) — the flasher may still write the firmware through it, but the Wi-Fi step never appears there, because the firmware only listens for it on the left port. diff --git a/CHANGELOG.md b/CHANGELOG.md index eb34f42c..a5e2471a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ All notable changes to Patternflow will be documented in this file, newest first ### Web -- **A guide you can play along with, at [/guide](https://patternflow.work/guide)** (work in progress, marked WIP). The first page is the first hour, 01 Flash, 02 Knobs, 03 Patterns, 04 Console, on the real v3.9 hardware in 3D, running a port of the firmware's input logic and screens, with the real flasher dialogs and a live copy of the device console. The second, [/guide/make](https://patternflow.work/guide/make), is 05 Community and 06 Pattern Lab: the community's real screens, and a board that plays your own Pattern Lab draft (read, never written) while the real Lab opens in a window beside it. English and Korean. Every step has a "Stuck here?" link to a GitHub issue that already says where (`guide_stuck.yml`). +- **A guide you can play along with, in three parts, at [/guide](https://patternflow.work/guide)** (work in progress, marked WIP). `/guide` is where you pick one by where your Patternflow is, each with its chapters, in order. **Build**, at [/guide/build](https://patternflow.work/guide/build), is for soldering one from bare parts: 01 Gather (the parts list is `bom_v3.9.csv` itself), 02 Order & print, 03 Solder, 04 Into the case, 05 Wire & power, 06 Firmware (which hands over to Play's 01 Flash) and 07 Check & close, each step played on the real v3.9 board and case in 3D, in the order the build happens; the board's known issues stay in `BUILD_GUIDE.md` §10, linked. **Play**, at [/guide/play](https://patternflow.work/guide/play), is the first hour with a built one, 01 Flash, 02 Knobs, 03 Patterns, 04 Console, on the real v3.9 hardware in 3D, running a port of the firmware's input logic and screens, with the real flasher dialogs and a live copy of the device console. **Make**, at [/guide/make](https://patternflow.work/guide/make), is 01 Community and 02 Pattern Lab, done by hand: on a big enough screen your own Pattern Lab, a practice community (placeholder patterns, connected to nothing) and a practice AI with set answers sit beside the steps, and a pointer shows each move and waits for yours; phones get the real screens. Sound, MIDI & OSC, MQTT, Clock, Performance and Editions join Make as they are written. Each guide numbers its own chapters from 01. Links into the first version, when Play was `/guide` itself (`/guide#flash`, `/guide#knobs-3`), land on the same step under `/guide/play`. English and Korean. Every step has a "Stuck here?" link to a GitHub issue that already says which guide, chapter and step (`guide_stuck.yml`). - **The community's Performances note says .pfs**, which is what the Director saves, instead of "Save-JSON". - **A moderator can take a pattern or deck off the wall without deleting it.** Somebody else's public pattern or deck now offers moderators *Make private*, with an optional reason: the softer removal, for things like the same pattern posted a fifth time. Nothing about the work changes and its author keeps it — they can still open it, edit it, take it into the lab — it just stops being shown to anyone else. On a pattern the reason is posted underneath as the moderator's comment, where the author can answer it; either way the author is told in their alerts. While the take-down stands the author cannot make it public again (a take-down its subject can undo in one click is a request); *Restore to public* puts it back exactly as it was. A moderator still cannot publish what an author made private themselves. A deck slot left empty by a take-down reads "made private by a moderator", not "by its author". Moderators can now comment on private patterns and keep their alerts about them, so the thread under a take-down works both ways. Migration `0025` adds `hidden_at` to patterns and decks; `check:hidemod` drives it all through the real routes. - **One press of Publish is one post.** A double-click on *Publish to the wall*, or a mouse switch that bounces, could put the same pattern on the wall twice in the same second ([#455](https://github.com/engmung/Patternflow/issues/455)). The button's disabled state was React state, a render too late for the second click, and after a successful publish it came back enabled while the page changed. The publish, thread, reply, deck, header, performance and report forms now refuse a second press in the same tick (`useSubmitLatch`), and a published pattern keeps its button down until the page changes; a thread whose files failed to attach offers *Open the thread* instead of posting it again. Behind them the server answers an identical submission from the same account within a minute with the post it already made, looked up and inserted in one synchronous transaction so two requests arriving together cannot both get through. `check:publish` fires two identical publishes into the route at the same instant; a version that awaits between the lookup and the insert fails it. diff --git a/README.md b/README.md index c5012907..f4726cb0 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ What a knob does to a running pattern is the pattern's own decision, so the same The device functions themselves are fixed. Encoder 1 is brightness. Encoder 4 opens the pattern list, where you turn to browse the names and long-press again to load one, choosing from whatever is installed at the time. Encoder 2 puts the board's IP address on the panel, and typing that into a browser opens the web console, which carries every feature the device has and works from a phone. -[patternflow.work/guide](https://patternflow.work/guide) has all of this on a Patternflow you can turn, press and hold, from flashing the ESP32 to the console. +[patternflow.work/guide/play](https://patternflow.work/guide/play) has all of this on a Patternflow you can turn, press and hold, from flashing the ESP32 to the console. ## On the device diff --git a/firmware/toolchain/console_demo.py b/firmware/toolchain/console_demo.py index dad45d86..a44db1ec 100644 --- a/firmware/toolchain/console_demo.py +++ b/firmware/toolchain/console_demo.py @@ -1231,6 +1231,19 @@ def main(): L.replace(BASE + 'index.html?v=' + load().build); } }, true); + // The chrome hands the site this panel's address on every link there + // (?device=), and the site keeps it as the reader's own panel. This panel + // is simulated: its address must never be saved as theirs. Bubbling, so it + // runs after the chrome's capture-phase listener has added it. + D.addEventListener('click', function (e) { + var p = e.composedPath ? e.composedPath() : [], a = null, i, u; + for (i = 0; i < p.length; i++) if (p[i].tagName === 'A' && p[i].href) { a = p[i]; break; } + if (!a) return; + try { u = new URL(a.href); } catch (x) { return; } + if (!/(^|\.)patternflow\.work$/.test(u.hostname) || !u.searchParams.has('device')) return; + u.searchParams.delete('device'); + a.href = u.href; + }); D.addEventListener('keydown', function (e) { if (e.key === 'Escape' && !e.defaultPrevented) tell({ action: 'escape' }); }); diff --git a/hardware/case/README.md b/hardware/case/README.md index a7298ce1..cce08070 100644 --- a/hardware/case/README.md +++ b/hardware/case/README.md @@ -10,8 +10,8 @@ | Your printer bed | Print | Design | Status | |---|---|---|---| -| **256 mm** (Bambu P1S / X1C / A1 class) | [`bed_256mm/encloser.stl`](bed_256mm/) | The snap-fit design split for a 256 mm bed — body frame, back panels, and LED-panel mount in one STL | ✅ Standard option, ~10 h total | -| **~330 mm+** (Bambu H2S-class) | [`bed_330mm/encloser.stl`](bed_330mm/) | The one-piece original — body, closing part, and LED-panel mount in one STL, no bonding at all. Also has a **USB pass-through to the DevKit and a cable exit slot** (data only — see below) | ✅ Main design ([#113](https://github.com/engmung/Patternflow/issues/113)) | +| **256 mm** (Bambu P1S / X1C / A1 class) | [`bed_256mm/encloser.stl`](bed_256mm/) | The snap-fit design split for a 256 mm bed — body frame (LED-panel mounting tabs built in), back panels and covers in one STL | ✅ Standard option, ~10 h total | +| **~330 mm+** (Bambu H2S-class) | [`bed_330mm/encloser.stl`](bed_330mm/) | The one-piece original — body (LED-panel mounting tabs built in) and closing part in one STL, no bonding at all. Also has a **USB pass-through to the DevKit and a cable exit slot** (data only — see below) | ✅ Main design ([#113](https://github.com/engmung/Patternflow/issues/113)) | **Whichever body you print, also print [`knobs/knobs_20mm.stl`](knobs/) — required for every build.** Knobs go in **black**, everything else in **white**; run the knob plate as its own print job. (15 mm-shaft encoders → `knobs_15mm.stl`; 15 mm and 20 mm shafts are functionally identical, and the [BOM](../bom/)'s reference part, PEC11R-4220F-S0024, is 20 mm.) @@ -19,7 +19,7 @@ The original mass-production-oriented design: a single-piece body plus a snap-fit closing part, wall-mount hanger hole included. No bonding step at all. Does **not** fit a 256 mm bed. -**`encloser.stl`** — everything in one STL (body, closing part, LED-panel mount), all **white** PLA; knobs from [`knobs/`](knobs/) in black. Same design as the print-&-assembly-verified 256 mm kit, just uncut. +**`encloser.stl`** — everything in one STL (body with its LED-panel mounting tabs, closing part), all **white** PLA; knobs from [`knobs/`](knobs/) in black. Same design as the print-&-assembly-verified 256 mm version, just uncut. **Wired access to the DevKit (330 mm only).** Two openings the 256 mm variant doesn't have yet: a **pass-through between the power-bank bay and the ESP32**, so a USB-C lead reaches the DevKit's own port with the case shut — that's for wired features like MIDI and OSC, and for flashing — and a **cable exit slot below the battery compartment**, so a cable leaves the enclosure instead of being pinched under the back panel. @@ -27,9 +27,9 @@ The original mass-production-oriented design: a single-piece body plus a snap-fi ## `bed_256mm/` — the standard build -**`patternflow_v3.3mf`** is the Bambu Studio project for this kit — four pre-arranged plates with the print settings below, the same file the MakerWorld listing serves. Open it and print; the STL is for every other slicer. +**`patternflow_v3.3mf`** is the Bambu Studio project for this print — four pre-arranged plates with the print settings below, the same file the MakerWorld listing serves. Open it and print; the STL is for every other slicer. -**`encloser.stl`** puts the whole body in one file: frame and back-panel halves plus the LED-panel mounting part, all in **white** PLA. ~10 hours total on a P1S. Print the knobs separately from [`knobs/`](knobs/), in **black**. The LED-panel mount is sized for the panel linked in the [BOM](../bom/). **Print & assembly verified** — the [assembly video](https://youtu.be/J9C9bZgkNKs) builds from this exact file. +**`encloser.stl`** puts the whole body in one file: frame halves (the LED panel's mounting tabs are part of them), back-panel halves and covers, all in **white** PLA. ~10 hours total on a P1S. Print the knobs separately from [`knobs/`](knobs/), in **black**. The tabs are placed for the panel linked in the [BOM](../bom/). **Print & assembly verified** — the [assembly video](https://youtu.be/J9C9bZgkNKs) builds from this exact file. Design perks: **two wall-mount holes**, a **snap-fit back panel**, and recesses for the LED matrix's alignment bumps — **no more nipper-trimming** the panel back (the old [#19](https://github.com/engmung/Patternflow/issues/19) workaround). @@ -41,7 +41,7 @@ Design perks: **two wall-mount holes**, a **snap-fit back panel**, and recesses ### Assembly notes (both 256 mm variants) -The full photo sequence lives in the [build guide](../../BUILD_GUIDE.md) — §4 (bond the printed halves right after printing) and §6 (panel in with `HUB-75E IN` toward the top → mounting part + screws → board in, encoder nuts from the front). Two watch-outs: the panel insertion is very tight (near-zero clearance) — work it in slowly — and bonded seams can show a hairline gap, fillable with putty or baking soda + CA. +The full photo sequence lives in the [build guide](../../BUILD_GUIDE.md) — §4 (bond the printed halves right after printing) and §6 (panel in from the front with `HUB-75E IN` toward the top → screws into the frame's tabs from behind → board in, encoder nuts from the front). Two watch-outs: the panel insertion is very tight (near-zero clearance) — work it in slowly — and bonded seams can show a hairline gap, fillable with putty or baking soda + CA. ## `legacy_v2/` — v2.x boards only diff --git a/web/public/guide/build/case-split.glb b/web/public/guide/build/case-split.glb new file mode 100644 index 00000000..36017763 Binary files /dev/null and b/web/public/guide/build/case-split.glb differ diff --git a/web/public/guide/build/plates.glb b/web/public/guide/build/plates.glb new file mode 100644 index 00000000..df3883ec Binary files /dev/null and b/web/public/guide/build/plates.glb differ diff --git a/web/public/guide/console-demo/index.html b/web/public/guide/console-demo/index.html index 6709dd43..280f8d21 100644 --- a/web/public/guide/console-demo/index.html +++ b/web/public/guide/console-demo/index.html @@ -2,7 +2,7 @@ - + Patternflow diff --git a/web/public/guide/console-demo/knobs.html b/web/public/guide/console-demo/knobs.html index 28fe630e..3521e587 100644 --- a/web/public/guide/console-demo/knobs.html +++ b/web/public/guide/console-demo/knobs.html @@ -1,7 +1,7 @@ - + Patternflow - Knobs