Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
380629e382 | ||
|
|
9b0c7b42f5 | ||
|
|
c8ffe42125 | ||
|
|
4728a821f2 | ||
|
|
f39b175948 | ||
|
|
22f04ee9a1 | ||
|
|
3d9bb9af53 | ||
|
|
15d28d2e0b | ||
|
|
d36a6fdd02 | ||
|
|
793ea02c22 | ||
|
|
7fca116edb | ||
|
|
39342f3a7e | ||
|
|
d968ee5b08 | ||
|
|
f6829417a0 | ||
|
|
1f532d0c85 | ||
|
|
1829dd2aec | ||
|
|
967e6b1c76 | ||
|
|
744a56d22b | ||
|
|
c8307f9d5e | ||
|
|
81de64c8a1 | ||
|
|
995bb4ba60 | ||
|
|
40c049ae15 | ||
|
|
7d6a47e6d0 | ||
|
|
69f8392a23 | ||
|
|
5bdb013449 | ||
|
|
c939ba1fbb | ||
|
|
face699a28 | ||
|
|
d26ed7ab3c | ||
|
|
ba1f5fc3a9 | ||
|
|
cf900cf3a4 | ||
|
|
9d8a1a1fb8 | ||
|
|
8c2143630c | ||
|
|
9ffcfe62f1 | ||
|
|
705690eb99 | ||
|
|
e8674795f5 | ||
|
|
609424b598 | ||
|
|
5207808b57 | ||
|
|
984ced2485 | ||
|
|
9ff5feef11 | ||
|
|
ab303618d8 | ||
|
|
3f33babdaa | ||
|
|
ffc6cedbca | ||
|
|
bd357ab03f | ||
|
|
f2ff1eac1f | ||
|
|
f7e20e1015 | ||
|
|
3f1e4452b8 | ||
|
|
b3e8e4272b | ||
|
|
d8b2c1e2db | ||
|
|
4beda7f27a | ||
|
|
8e4559ee36 | ||
|
|
073f20a132 | ||
|
|
d7380919e4 | ||
|
|
71e30b0633 | ||
|
|
485b3b630a | ||
|
|
d42e99389b | ||
|
|
794cde228c | ||
|
|
7344f12dc8 | ||
|
|
553b4a93d1 | ||
|
|
07ef9c0b9a | ||
|
|
5c303dfc61 | ||
|
|
a101c9f7db | ||
|
|
e12ad2ed7b | ||
|
|
655d5705c4 | ||
|
|
4f02d9a7a9 | ||
|
|
475623e9f2 | ||
|
|
1cceedc8a4 | ||
|
|
f9b8407561 | ||
|
|
dd7b749af9 | ||
|
|
9ed51f4b22 | ||
|
|
5090609df3 | ||
|
|
83f1aa94dc | ||
|
|
e36d7b00a0 | ||
|
|
6a62505aa6 | ||
|
|
4b20ca4f48 | ||
|
|
607f6631a7 | ||
|
|
5daf54a90b | ||
|
|
e49abf89d3 | ||
|
|
7688d03be6 | ||
|
|
1946553dd1 | ||
|
|
2a3da0778f | ||
|
|
a07faf6ef0 | ||
|
|
b650503ea1 | ||
|
|
3984d0c93b | ||
|
|
cb5809e73c | ||
|
|
b1c18cb040 | ||
|
|
eb0039179b | ||
|
|
7af5d89dd0 | ||
|
|
9b03e4de07 | ||
|
|
f776025b58 | ||
|
|
53f3a07a45 | ||
|
|
8032e0ea47 | ||
|
|
1a368287f8 | ||
|
|
eac45eb234 | ||
|
|
ce1d71e0b5 | ||
|
|
7d7a378c8b | ||
|
|
6df1301fb9 | ||
|
|
c6bec71442 | ||
|
|
68539d563c | ||
|
|
90697c8cac | ||
|
|
7da64088ce | ||
|
|
83840d45dc | ||
|
|
d9f3a4b88e | ||
|
|
0700c14b5c | ||
|
|
4263fbbd9b | ||
|
|
9e0c5d4045 | ||
|
|
f2bb7f3d85 | ||
|
|
3a758fcffb | ||
|
|
c50417668b | ||
|
|
f1334f4756 | ||
|
|
90d8a3778a | ||
|
|
21419145f8 | ||
|
|
4fec258f15 | ||
|
|
47e5f9e458 | ||
|
|
9640a4f075 | ||
|
|
79e8cddcff | ||
|
|
856e0a2ccf | ||
|
|
6888abe602 | ||
|
|
b672c58e34 | ||
|
|
9b26cfbf7c | ||
|
|
c56d403da0 | ||
|
|
ffbc46782a | ||
|
|
31d89faf03 | ||
|
|
81f3279efd | ||
|
|
293979bef8 | ||
|
|
88220bcd1f | ||
|
|
725f0cc9d1 | ||
|
|
e23be20b13 | ||
|
|
52bf35f183 | ||
|
|
560d073019 | ||
|
|
0e033784a2 | ||
|
|
4607a4da58 | ||
|
|
917a3eb933 | ||
|
|
81185d8013 | ||
|
|
ffcce42a51 | ||
|
|
0fb60bcbb5 | ||
|
|
122d908862 | ||
|
|
c8482b7a76 | ||
|
|
ed0260d476 | ||
|
|
fbe6a97e39 | ||
|
|
3934dc1dc4 | ||
|
|
1bbef055c4 | ||
|
|
8c8e1be451 | ||
|
|
caa38dcd0b | ||
|
|
4deaa2c57c | ||
|
|
20c8d283d5 | ||
|
|
9d5d695855 | ||
|
|
bbeaed7e87 |
No files matched your search
@@ -0,0 +1,2 @@
|
||||
# Shell scripts run on the Linux CI runner and in git-bash: keep LF.
|
||||
*.sh text eol=lf
|
||||
@@ -0,0 +1,76 @@
|
||||
name: Deploy test site
|
||||
|
||||
# Builds site/dist (site/public/ plus demo pages copied out of docs/, see
|
||||
# site/build.sh) and publishes it to the B4L package registry as the generic
|
||||
# package B4L/cnxvinyl.lol. bkk01 serves https://cnxvinyl.lol/ from those
|
||||
# releases (cnx-network-clan, docs/src/s1-migration.md): the registry's
|
||||
# package event makes it fetch a new version within seconds, and a timer
|
||||
# there fetches every 15 minutes as a backstop.
|
||||
#
|
||||
# Secrets (organization level): REGISTRY_USER, REGISTRY_TOKEN, an account with
|
||||
# a write:package token in a B4L team that may write packages (b4l-ci). The
|
||||
# job's own token only reads the repository: the registry refuses it.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- "site/**"
|
||||
- "docs/**/*.html"
|
||||
- "docs/pitch/**"
|
||||
- ".gitea/workflows/deploy-site.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
# A newer push supersedes a running deploy; bkk01 serves whichever version
|
||||
# the registry lists as the latest.
|
||||
concurrency:
|
||||
group: deploy-cnxvinyl-lol
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
SITE_URL: https://cnxvinyl.lol
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build site/dist
|
||||
run: bash site/build.sh
|
||||
|
||||
- name: Publish to the package registry
|
||||
# The version joins the UTC time and the commit, so versions never
|
||||
# collide. The archive holds the site's root itself.
|
||||
env:
|
||||
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: |
|
||||
if [ -z "$REGISTRY_USER" ] || [ -z "$REGISTRY_TOKEN" ]; then
|
||||
echo "::error::REGISTRY_USER and REGISTRY_TOKEN must be set as organization secrets"
|
||||
exit 1
|
||||
fi
|
||||
version="$(date -u +%Y%m%dT%H%M%S)-${GITHUB_SHA::12}"
|
||||
tar -czf site.tar.gz -C site/dist .
|
||||
curl -fsS --user "$REGISTRY_USER:$REGISTRY_TOKEN" --upload-file site.tar.gz \
|
||||
"${{ github.server_url }}/api/packages/${{ github.repository_owner }}/generic/cnxvinyl.lol/$version/site.tar.gz"
|
||||
echo "published cnxvinyl.lol $version ($(du -h site.tar.gz | cut -f1))"
|
||||
|
||||
- name: Check the public URL
|
||||
# bkk01 fetches the release a few seconds after the upload; give it up
|
||||
# to two minutes. Warning only: the release is in the registry either
|
||||
# way, and the timer on bkk01 picks it up.
|
||||
run: |
|
||||
expected=$(cat site/dist/version.txt)
|
||||
for i in $(seq 1 24); do
|
||||
got=$(curl -sS --max-time 20 "$SITE_URL/version.txt?nocache=$expected" || true)
|
||||
if [ "$got" = "$expected" ]; then
|
||||
echo "$SITE_URL serves $expected"
|
||||
exit 0
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
echo "::warning::$SITE_URL/version.txt returned '${got:0:80}', expected $expected"
|
||||
@@ -23,3 +23,6 @@ node_modules/
|
||||
|
||||
# Playwright MCP session output
|
||||
.playwright-mcp/
|
||||
|
||||
# Test site build output (site/build.sh)
|
||||
site/dist/
|
||||
@@ -1,15 +1,18 @@
|
||||
# CNX Vinyl / Poy Records
|
||||
|
||||
<img src="docs/brand/poyrecord-logo-1536x1536.png" alt="Poy Records logo" width="160">
|
||||
|
||||
A vinyl record factory in planning for the Chiang Mai area of northern
|
||||
Thailand (site candidates include Lamphun and Lampang provinces). This
|
||||
repository is the source of truth for the project: planning documents and
|
||||
cost data today. As the factory takes shape it will also hold the data and
|
||||
software used to run it.
|
||||
Thailand (site candidates include Lamphun and Lampang provinces and, since
|
||||
October 2026, Payap University land in Chiang Mai). This repository is
|
||||
the source of truth for the project: planning documents and cost data
|
||||
today. As the factory takes shape it will also hold the data and software
|
||||
used to run it.
|
||||
|
||||
## Team
|
||||
|
||||
- **Simona Meesaiyati**, Project Lead
|
||||
- **Alexander Grabowski**, Technical Consultant
|
||||
- **Simona Meesaiyati**, Project Lead: management and the audio side
|
||||
- **Alexander Grabowski**, Technical Consultant: the technical side
|
||||
|
||||
[buildfor.life](https://buildfor.life) supports the project in a consulting
|
||||
capacity.
|
||||
@@ -23,8 +26,9 @@ file to delivered record:
|
||||
2. **Lathe cutting**: cutting the master disc
|
||||
3. **Silvering**: metallizing the cut master
|
||||
4. **Stamper production**: electroforming nickel stampers in-house
|
||||
5. **Pressing**: extrusion and pressing of the finished records
|
||||
6. **Finishing**: trimming, labels, shrink wrapping
|
||||
5. **Pressing**: extrusion and pressing of the records, with the labels
|
||||
pressed in
|
||||
6. **Finishing**: trimming, sleeving, shrink wrapping
|
||||
7. **Packaging**: folded paper cartons (jackets and sleeves), produced in
|
||||
collaboration with local packaging manufacturers
|
||||
8. **Fulfillment**: dropshipping directly to end customers on behalf of
|
||||
@@ -34,20 +38,70 @@ In-house galvanics (steps 3 and 4) removes the dependency on overseas stamper
|
||||
suppliers, a common bottleneck for pressing plants, and shortens turnaround
|
||||
for clients. Partnering with local carton manufacturers keeps packaging
|
||||
sourcing close to the plant, in line with the local-sourcing preference for
|
||||
materials. The pressing line is documented in detail; equipment, partners,
|
||||
and budgets for the other steps are open planning items.
|
||||
materials. The pressing line is documented in detail, galvanics and stamper
|
||||
prep from vendor datasheets; equipment, partners, and budgets for the other
|
||||
steps are open planning items.
|
||||
|
||||
## Project Status
|
||||
|
||||
**Planning stage** (as of mid-2026).
|
||||
**Planning stage** (as of October 2026).
|
||||
|
||||
- Industry outreach has been ongoing for several years: equipment vendors,
|
||||
material suppliers, and independent consultants.
|
||||
- Alexander and Simona will soon travel to
|
||||
[Making Vinyl](https://makingvinyl.com/) in Haarlem, Netherlands, to gather
|
||||
further insights from the pressing industry.
|
||||
- A collaboration with [Resurrec](https://www.resurrec.com/) is under
|
||||
discussion.
|
||||
- Alexander and Simona attended
|
||||
[Making Vinyl Europe 2026](https://makingvinyl.com/) in Haarlem (30
|
||||
September to 2 October). Most people they talked to were strongly
|
||||
interested in the full-traceability approach, and for Sibert it was a
|
||||
reason to engage at all (notes in the
|
||||
[exhibitor briefing](docs/suppliers/making-vinyl-europe-2026-exhibitors.md#after-the-show)).
|
||||
- Payap University (Chiang Mai) has offered land on lease and wants to
|
||||
build joint student programmes with the plant. The point it gave for the
|
||||
land is zoned very high density residential in the Chiang Mai city plan,
|
||||
where record pressing is not permitted (checked October 2026). Payap
|
||||
says the land can be rezoned (20 October 2026), so it stays an option;
|
||||
a rezoning is a city-plan amendment the planning department schedules
|
||||
at ~16 to 19 months
|
||||
([what it takes](docs/land-listings/payap/rezoning-2026-10-20.md)); other
|
||||
Payap land would need checking
|
||||
([site candidates](docs/site-candidates.md),
|
||||
[Payap partnership](docs/payap-partnership.md)).
|
||||
- A second company, separate from the plant company, is to hold a record
|
||||
catalogue (owned and licensed titles) and have it pressed at the plant
|
||||
as a customer; language models in the project are self-hosted on
|
||||
premises (decided October 2026;
|
||||
[own catalogue](docs/catalogue-intelligence.md)).
|
||||
- A collaboration with [ResurRec](https://www.resurrec.com/) is under
|
||||
discussion. ResurRec has since opened a plant in Japan with automatic
|
||||
presses, identified from photos as new Pheenix AD12s (October 2026;
|
||||
[revenue model](docs/finance/revenue-model.md#resurrec-japan-october-2026)).
|
||||
- Back from Haarlem, the team is preparing a meeting with the project's
|
||||
investor (October 2026). Post-show follow-ups with Pheenix, Sibert, OMS
|
||||
and SST are in the
|
||||
[exhibitor briefing](docs/suppliers/making-vinyl-europe-2026-exhibitors.md#after-the-show).
|
||||
- The plant now launches with everything in one capital round (October
|
||||
2026): one Newbilt Duplex system and one Classic, a Pheenix galvanics
|
||||
line, the Sibert stamper-prep line, a Sillitoe cutting room and the
|
||||
modular boiler and chiller plant: ~168M to 296M THB with contingency
|
||||
(midpoint ~232M; biomass steam, PV on the factory roof), the Pheenix line priced at OMS's reference plus 20 %
|
||||
([total investment](docs/finance/total-investment.md#launch-plant-october-2026)).
|
||||
For the investor the business plan comes in two versions, priced
|
||||
without contingency and with the ramp-up reserve
|
||||
([two plans](docs/finance/total-investment.md#two-plans-a-at-180m-thb-and-b-at-215m-thb-october-2026)):
|
||||
**Plan A, ~182M THB** (~2M above 180M since steam went biomass), the
|
||||
launch plant with six cost levers, and **Plan B, ~217M THB**, the same
|
||||
launch plant with everything in. **The main investor wants to go with
|
||||
Plan B** (19 October 2026); the investor deck leads with it. The
|
||||
shareholders fund the whole plant as share capital, no bank loan
|
||||
planned (20 October 2026). The main
|
||||
investor holds **at least 60 % of the company** (~130M THB of Plan B's
|
||||
~217M), so at most 40 % (~87M) is for
|
||||
sale to co-investors (Ploy Printing, the founders, others;
|
||||
[possible share prices](docs/finance/share-price.md);
|
||||
[shareholding](docs/finance/total-investment.md#two-plans-a-at-180m-thb-and-b-at-215m-thb-october-2026),
|
||||
20 October 2026).
|
||||
Chinese boilers, compressor and hydraulics save about 2M THB of that
|
||||
([Chinese suppliers](docs/suppliers/china-utilities.md)).
|
||||
The business plan is re-based on it (draft 0.2).
|
||||
|
||||
## Planning Documents
|
||||
|
||||
@@ -57,23 +111,44 @@ The detail lives in dedicated documents:
|
||||
three current gates (market validation, BOI, land title check) through
|
||||
quotes, commitment, build, launch, and expansion
|
||||
- [Pressing line equipment plan](docs/equipment/pressing-line.md): the
|
||||
50/50 automated/semi-automatic fleet strategy, the Newbilt system under
|
||||
evaluation (≈ €200,500 quoted scope), and site requirements
|
||||
current all-Newbilt fleet (two Duplex systems, each with an EX 50 main
|
||||
and an EX 35 colour extruder, plus one Classic automatic press), the 2024
|
||||
Newbilt quote (~USD 232k,
|
||||
expired), the 2026 product flyers, and site requirements
|
||||
- [Galvanics and stamper prep equipment plan](docs/equipment/galvanics.md):
|
||||
the metal path from lacquer to press-ready stamper, from vendor
|
||||
datasheets: Pheenix Alpha's electroforming range as a second turnkey
|
||||
vendor next to Digital Matrix, OMS as a third named by Sibert (reference
|
||||
prices for a 4-cell wet room, EUR 224k to 311k), Sibert's
|
||||
VSP/VSF/VSC stamper prep line (USD 250k budget for the three confirmed),
|
||||
the utilities they need, a first cell-count estimate, and Sibert's
|
||||
optical-disc reference material
|
||||
- [Vendor landscape](docs/suppliers/vendor-landscape.md): researched
|
||||
candidates for mastering and cutting (Agnew Analog), galvanics equipment
|
||||
(Plating Power / Digital Matrix), stamper preparation (Sibert), bridge
|
||||
stamper service (Stamper Discs), and automated presses (Pheenix Alpha)
|
||||
candidates for mastering and cutting (Agnew Analog, and the Sillitoe
|
||||
SDMS with integrated cutting automation at a published USD 125k),
|
||||
galvanics equipment
|
||||
(Plating Power / Digital Matrix, Pheenix Alpha, Optical Media Services),
|
||||
used lathes and cutting-room contacts (via OMS),
|
||||
stamper preparation
|
||||
(Sibert), bridge stamper service (Stamper Discs), and automated presses
|
||||
(Pheenix Alpha, the comparison for the Classic)
|
||||
- [Equipment needs and supplier map](docs/suppliers/equipment-suppliers.md):
|
||||
the full needs list per production step with supplier tables and contacts
|
||||
- [Chinese suppliers](docs/suppliers/china-utilities.md): boilers,
|
||||
compressed air and hydraulics from China (makers, published prices,
|
||||
Thai offices, Thai boiler rules for imports); saves about 2M THB, ~1 %
|
||||
of the budget
|
||||
- [Sustainability](docs/sustainability.md): the solar installation (Deye
|
||||
inverters, 271 kWh Gobel Power battery stack), the zero contaminated water
|
||||
commitment, and the materials strategy
|
||||
inverters, 271 kWh Gobel Power battery stack), the PEA grid tariff and
|
||||
what it decides (biomass steam at a quarter to a tenth of the cost of
|
||||
electric, PV rather than solar thermal), the zero contaminated water commitment,
|
||||
and the materials strategy
|
||||
- [Worker safety](docs/worker-safety.md): safety training, galvanics clean
|
||||
rooms and decontamination, PPE
|
||||
- [Biomass fuel strategy](docs/biomass.md): the 60 rai own-grown coppice
|
||||
idea (with the forestry-classification check that comes first), northern
|
||||
agricultural waste as the main supply, and the staged electric-to-biomass
|
||||
path
|
||||
agricultural waste as the main supply, reported northern fuel prices
|
||||
(October 2026) and who sets them, and the staged electric-to-biomass path
|
||||
- [BOI investment promotion](docs/boi.md): the promotion strategy (Group B
|
||||
base activity plus solar, automation, and R&D measures for the tax value),
|
||||
requirements, Northern-region angle, and why BOI approval precedes
|
||||
@@ -82,9 +157,67 @@ The detail lives in dedicated documents:
|
||||
control, CCTV, whole-factory HVAC (temperature, humidity, PM), archive and
|
||||
audio protection, fire and life safety, plant monitoring, Thai compliance
|
||||
anchors
|
||||
- [Overhead crane, workshop and visitor corridor](docs/crane-workshop-tours.md):
|
||||
a 5 t crane over the whole production floor to move machines in and
|
||||
out, a crane-served maintenance workshop and machine bay at the ramp
|
||||
end, and a glazed ground-level corridor for guided tours without noise,
|
||||
dust or plating chemistry; what each changes in the building and what
|
||||
it costs
|
||||
- [Production hall layout sketch](docs/production-hall-layout-sketch.png):
|
||||
a rough BIM sketch in FreeCAD (`docs/production-hall-layout-sketch.FCStd`)
|
||||
of the 60 x 25 m phase 1 hall at Mueang Chi, with the fleet before
|
||||
October 2026: zones in process order along the visitor corridor, the
|
||||
crane zone, room-in-room boxes and the main equipment; every position is
|
||||
an estimate
|
||||
- [Payap scenario model](docs/cnx_vinyl_parametric_payap.png): a parametric
|
||||
BIM model in FreeCAD 26.3 (`docs/cnx_vinyl_parametric_payap.FCStd`,
|
||||
[isometric](docs/cnx_vinyl_parametric_payap-iso.png)) of the whole plant
|
||||
on a square placeholder plot of Payap land: a 128 x 25 m production-only
|
||||
factory with the five-press fleet, room for ten more Classics (drawn
|
||||
before the October 2026 decision to lay the hall out for Duplex
|
||||
systems: five Duplex bays and four Classic positions), one
|
||||
shared hydraulic and air plant, a colour store with outdoor silos and a
|
||||
two-storey finishing and print block
|
||||
([plans](docs/cnx_vinyl_parametric_payap-block.png)), a separate
|
||||
two-storey office building
|
||||
([floor plans](docs/cnx_vinyl_parametric_payap-office.png): canteen,
|
||||
changing rooms and showers, mastering and listening below; ~150 m² of
|
||||
offices, training room and IT above), a separate water treatment
|
||||
building next to galvanics, the utility yard and site access, all
|
||||
driven by one parameter sheet
|
||||
- [Process logging and traceability](docs/traceability.md): end-to-end
|
||||
per-order traceability for customers, batch genealogy from audio file to
|
||||
shipment, and the requirements this sets for the factory software
|
||||
- [Digital factory systems plan](docs/digital-factory.md): every system
|
||||
that has to exist for environment, machine, QC and genealogy data to land
|
||||
in one place keyed to one record identity, with ERPNext as the plant's
|
||||
only system of record (every tool we build reads and writes it; only
|
||||
machine data stays outside), everything open source with our own code
|
||||
published and, later, the stack and automation services offered to
|
||||
other pressing plants: the plant as one more site in B4L's
|
||||
existing NixOS fleet (the cnx-network clan: mesh, DNS, fleet
|
||||
monitoring, site gateway module, public proxy), what changes in that
|
||||
repo, VLAN zoning, Telegraf/MQTT acquisition source by source, QC
|
||||
instrument integration, the factory application, alerting, backup,
|
||||
security, the data clauses for every RFQ, build order and rough cost
|
||||
- [Plant assistant](docs/plant-assistant.md): an agent management and
|
||||
operators ask in Thai or English, at a press kiosk, a desk or a phone;
|
||||
it answers from the procedures, vendor manuals and this repository and
|
||||
from ERPNext and the machine data, with sources on every answer, sees
|
||||
only what the asker may see, drafts but never submits, never touches a
|
||||
machine, and runs on site on an open-weights model
|
||||
- [Inline optical QC](docs/equipment/inline-optical-qc.md): devices for
|
||||
the 100% record inspection station (line-scan cameras with dark-field
|
||||
and transmitted light, label camera, laser warp sensors, centring
|
||||
turntable), CD-scanner and PRP precedents, smart-camera versus open
|
||||
NixOS software, specials, prices and a two-station cost estimate, and
|
||||
a FreeCAD concept model of the station (aluminium profile frame,
|
||||
rim-belt conveyor, chuck, sensors) with a sourced bill of materials
|
||||
- [QC station control plan](docs/equipment/inline-qc-control-plan.md):
|
||||
EtherCAT with two 100 W servo kits, Beckhoff I/O and an N100 mini PC
|
||||
running QiTech's open-source EtherCAT library on NixOS; bus layout, I/O
|
||||
list, geizhals.de and QiTech shop prices, safety circuit, bench test and
|
||||
build order
|
||||
- [Quality automation](docs/quality-automation.md): stamper metrology
|
||||
(Keyence-class confocal, profiler, XRF), layered pressed-record QC (100%
|
||||
optical inspection, per-cycle press telemetry, sampled automated audio
|
||||
@@ -92,37 +225,255 @@ The detail lives in dedicated documents:
|
||||
- [Process flow](docs/process-flow.md): the whole chain from audio file to
|
||||
delivered record as a chart and stage table, with every check and the
|
||||
three artist approval gates (printable diagram alongside)
|
||||
- [Artist platform](docs/artist-platform.md): upload a master and
|
||||
artwork, get a transparent itemised offer from the price calculator
|
||||
(for artists, labels and any other customer), and optionally launch a
|
||||
fan-funded campaign that the plant presses and ships to each fan once
|
||||
enough have pre-ordered, with refunds if not
|
||||
- [Own catalogue](docs/catalogue-intelligence.md): a second company, not
|
||||
the plant company, owns and licenses a record catalogue and has it
|
||||
pressed at the plant as a customer at arm's length (standby runs in
|
||||
idle press time); its catalogue dashboard, map of where the records
|
||||
sell, demand model for what to repress and how many, and an advisor
|
||||
agent on a self-hosted, on-premises model; not in the plant's
|
||||
business plan
|
||||
- [Order a record](docs/order.html): the order tool as a step-by-step
|
||||
configurator after the Mobineko pattern (step rail, choices, a large live
|
||||
record picture, running price and ship date, a "how to pay" step with
|
||||
direct payment or a fan-funded campaign on make-a-record's calculator,
|
||||
review with what is missing); same price list as the artist demos
|
||||
- [Artist ordering demo](docs/artist-order.html): the artist platform as a
|
||||
clickable single page: configure a record (jacket with a 3 or 5 mm
|
||||
spine), type the track list or drop the master files and artwork
|
||||
(checked in the browser, never uploaded: format, sample rate, bit
|
||||
depth, clipping, side length against the format; artwork as PDF, AI or
|
||||
image against the downloadable jacket and label templates: size and
|
||||
spine, bleed, resolution, colour, fonts), approve gate 1, get the itemised offer with
|
||||
its price curve and lead time, then order directly or run a fan-funded
|
||||
campaign to a funded or missed end (refund, or go ahead at the
|
||||
minimum) and follow the production through the three artist gates
|
||||
- [Make a record](docs/make-a-record.html): the investor demo of the same
|
||||
platform as a customer sees it, in one polished flow: design the record
|
||||
against a to-scale mock-up, check the music and artwork, see the price,
|
||||
let fans fund it, follow the production and open the record passport
|
||||
(the traceability record of one copy); investor notes on every step, a
|
||||
one-minute guided tour (`#tour`), prices in THB, USD or EUR and the whole
|
||||
page in English or Thai (draft translation, `#cur=EUR&lang=th`)
|
||||
- [Factory console and order status](docs/factory-console.html): the
|
||||
factory application of the [digital factory](docs/digital-factory.md)
|
||||
plan as a demo on a simulated plant day: the press floor with live
|
||||
counters, work orders per station (kiosk steps: badge in, scan,
|
||||
confirm), the inspection stream, audio samples, the material lab gate,
|
||||
stamper metrology, the hash-chained event log, and the customer portal
|
||||
for the same orders (steps, copies pressed so far, lab and inspection
|
||||
results, approving a test pressing)
|
||||
- [Plant assistant mockup](docs/plant-assistant.html): the
|
||||
[plant assistant](docs/plant-assistant.md) on `vinyl-ai` as an operator
|
||||
at the press kiosk (Thai, push to talk), management at a desk and sales
|
||||
on a phone see it: answers with their sources, the tool calls beside
|
||||
each answer, drafts that a person submits, safety steps quoted word for
|
||||
word and the questions it refuses
|
||||
- [Steam and cooling](docs/steam-cooling.html): the utility plant for the
|
||||
launch plant (one Duplex system and one Classic; rooms built for four
|
||||
modules, the five-press growth case one click away) as a clickable
|
||||
process diagram: water treatment, feed tank and heat recovery, a bank of
|
||||
two 500 kg/h boilers, the steam header and condensate return, and
|
||||
process cooling with two 250 kW chillers (a third with the second Duplex),
|
||||
a plate heat exchanger, warm and cold tanks and a branch to every press,
|
||||
extruder and the hydraulic oil cooler; operating cases from the launch plant
|
||||
and its commissioning to one module down, the design basis, an equipment schedule and
|
||||
the open questions for the boiler and chiller RFQs
|
||||
- [Plant operation page](docs/plant-operation.html): a single static page
|
||||
animating the launch plant as a simulated SCADA overview at real cycle
|
||||
times: the Newbilt Duplex system and the Classic, the Pheenix Alpha
|
||||
electroforming line and Sibert stamper prep, from PVC intake and the
|
||||
material lab through pressing, inspection, packaging and fulfillment,
|
||||
with the three artist gates, the mother archive, utilities and energy;
|
||||
1× is real time, up to 3600× (a day in 24 s); every station is
|
||||
clickable and names the source of its figures; on phones and tablets
|
||||
held sideways it pinch-zooms and opens station details in a side sheet
|
||||
- [Plant and business plan calculator](docs/fleet-calculator.html): a
|
||||
single static page for the business plan: choose the plant
|
||||
configuration (presses, galvanics in-house or bought stampers, cutting
|
||||
in-house or outsourced, metrology tier, cassette and CD-R, solar bought,
|
||||
PPA or none, steam fuel, Thai or Chinese utilities, crane, visitor
|
||||
corridor) and it builds the investment from the cost blocks of the
|
||||
total investment, checks it against the investor's 180M and 216M THB,
|
||||
and runs the money a year and a ten-year cash view (payback, NPV, IRR,
|
||||
pre-tax sketch), with presets from the launch plant to a full hall. Set
|
||||
the records a year and the share of splatter and specials, and it sizes
|
||||
the mix of Duplex systems (3 records a minute each) and Classics (2 a
|
||||
minute) from the launch plant of one Duplex and one Classic up to a
|
||||
full press hall, with the people,
|
||||
power, central hydraulics, steam, cooling, air, floor, compound and
|
||||
stampers that fleet needs, drawn as a live schematic of the machine
|
||||
park with the stamper line (lathe, Pheenix galvanics, Sibert prep)
|
||||
feeding it, each station counted from the galvanics cycle times;
|
||||
plus the money a year: revenue (standard, specials, title services),
|
||||
PVC, labels, sleeves, jackets, cartons, lacquers, plating chemistry,
|
||||
electricity and steam, labour from base salaries with social security,
|
||||
on-costs and health care for all staff, overheads, EBITDA, depreciation
|
||||
and payback, with the revenue model's adverse, central and favourable
|
||||
cases, BOI promotion on or off (machinery import duty and import VAT,
|
||||
PVC duty relief) and USD, THB or EUR; every assumption is editable, with its
|
||||
source, and a scenario can be shared by link
|
||||
- [Test site](site/README.md): `site/` builds https://cnxvinyl.lol/, the
|
||||
internal test site with demo pages from `docs/` (the plant operation
|
||||
page first) and any static site we want to share by link; Gitea Actions
|
||||
deploys it to the buildfor.life web server on every push that touches it
|
||||
- [Production timeline](docs/production-timeline.md): how long an order
|
||||
takes stage by stage, launch vs mature configuration, the repress fast
|
||||
path, and what lead time can honestly be quoted to a customer
|
||||
- [Project timeline](docs/project-timeline.md): the calendar from today to
|
||||
first paying release, the BOI-to-machinery critical path, and where the
|
||||
float actually sits
|
||||
- [Site candidates](docs/site-candidates.md): the land options side by
|
||||
side (the Mueang Chi lease, the Northern Region Industrial Estate, and
|
||||
Payap University's offer of land next to a pharmaceutical facility under
|
||||
construction) and what has to be checked before any of them is chosen
|
||||
- [Payap University partnership](docs/payap-partnership.md): joint student
|
||||
programmes in audio engineering (mastering, lathe cutting), IT and
|
||||
business built around the plant, what they change in the plan (cutting
|
||||
room earlier, pre-release security, student access) and what to agree
|
||||
- [Project scale](docs/scale.md): rough numbers for everything on one page:
|
||||
output capacity, building area, land, electrical demand, solar and
|
||||
storage, steam and fuel, headcount, and money cross-references
|
||||
- [Total investment](docs/finance/total-investment.md): the full-vision
|
||||
roll-up (~4M to 7.7M EUR) and the ~1.5M to 2.5M EUR phased entry, with
|
||||
the basis of every block
|
||||
- [Revenue model](docs/finance/revenue-model.md): rough full-capacity
|
||||
revenue (~3.2M to 5.9M EUR/yr), direct cost and margin per record, and
|
||||
the levers and caveats behind the numbers
|
||||
- [Total investment](docs/finance/total-investment.md): the launch plant
|
||||
decided in October 2026 (~168M to 296M THB, ~5.1M to 9.0M USD, midpoint
|
||||
~232M THB) with the basis of every block, the two plans for the investor
|
||||
(Plan A ~180M, Plan B ~215M THB, without contingency), and the earlier
|
||||
answer to the 180M / 216M question; the earlier full vision and phased
|
||||
entry are kept as superseded
|
||||
- [Phase 1 construction RFQ](docs/finance/phase1-construction-rfq.md):
|
||||
the spec sheet for asking a contractor to price the phase 1 buildings
|
||||
and site works, with quantities taken from the parametric BIM model
|
||||
- [Revenue model](docs/finance/revenue-model.md): pricing, direct cost
|
||||
and margin per record, the launch plant's operating picture at the
|
||||
planned 60 % specials (central revenue ~3.65M USD a year on ~0.74M
|
||||
records, EBITDA ~1.7M; the adverse case loses money), the operating
|
||||
pictures of Plan A (payback ~3.2 years on ~182M THB) and Plan B (the
|
||||
same output, payback ~3.8 years on ~217M THB: its extra pays back
|
||||
through what the table leaves out), the five-press table, and the levers and
|
||||
caveats behind the numbers
|
||||
- [Share price](docs/finance/share-price.md): possible prices for the 40 %
|
||||
of the company open to co-investors (the lead investor holds at least
|
||||
60 %), from market data (Damodaran industry multiples, the Thai risk
|
||||
premium and bond yield, illiquidity discounts, venture target returns,
|
||||
Thai listed peers), on the decision that the shareholders fund the
|
||||
whole plant as share capital: the founding round at par (Plan B's ~217M
|
||||
as 2,170,000 shares of 100 THB, the 40 % ~86.8M THB, called in
|
||||
instalments against the tranches), a premium only for documented
|
||||
pre-round costs, and what a share could be worth once the plant runs
|
||||
(adverse 11 to 42 THB per 100 THB paid, central 80 to 314 THB)
|
||||
- [Investor deck](docs/pitch/index.html) (October 2026): the plant in 17
|
||||
web slides for BOI, bank and institutional readers, proposing Plan B
|
||||
(~215M THB) with Plan A as the comparison, in a light and a dark theme
|
||||
(press T), with a presenter view (press P) and a PDF of each theme
|
||||
([dark](docs/pitch/CNX-Vinyl-Investor-Deck.pdf),
|
||||
[light](docs/pitch/CNX-Vinyl-Investor-Deck-light.pdf)); every figure carries its
|
||||
source in the business plan or the owning doc
|
||||
- Business plan, draft 0.3 (October 2026), in two versions:
|
||||
[Plan A, ~180M THB](docs/business-plan/CNX-Vinyl-Business-Plan-A.pdf)
|
||||
([docx](docs/business-plan/CNX-Vinyl-Business-Plan-A.docx)) and
|
||||
[Plan B, ~215M THB](docs/business-plan/CNX-Vinyl-Business-Plan-B.pdf)
|
||||
([docx](docs/business-plan/CNX-Vinyl-Business-Plan-B.docx)): the
|
||||
investor-facing roll-up of everything above, each a complete plan with
|
||||
one table comparing it with the other, both priced without contingency
|
||||
and with the ramp-up reserve. Each carries renders of the
|
||||
[plant and business plan calculator](docs/fleet-calculator.html) with
|
||||
its own preset (the isometric plant view on the cover and in section 6,
|
||||
the budget check, ten years of cash; in `docs/renders/calculator/`) and
|
||||
a software section (5.5) with screenshots of the plant overview, the
|
||||
factory console with its ERPNext link, the artist ordering demo, fan
|
||||
funding and the record passport (`docs/renders/demos/`). Built from `docs/business-plan/build/`
|
||||
(`python build_plan.py` makes both versions; the PDFs are exported with
|
||||
LibreOffice so the table of contents is filled in). Draft 0.2, a single
|
||||
launch-plant plan with contingency, is in the git history
|
||||
|
||||
## Repository Layout
|
||||
|
||||
```
|
||||
docs/
|
||||
├── brand/ Poy Records logo (1536 px PNG)
|
||||
├── business-plan/
|
||||
│ ├── CNX-Vinyl-Business-Plan-A.docx / .pdf Investor business plan, Plan A (generated)
|
||||
│ ├── CNX-Vinyl-Business-Plan-B.docx / .pdf Investor business plan, Plan B (generated)
|
||||
│ └── build/ Python source of the plan; regenerate with
|
||||
│ build_plan.py
|
||||
├── pitch/ Investor deck: web slides (index.html, presenter
|
||||
│ view), images in img/, PDF export
|
||||
├── consulting/ Consultancy proposals and overviews
|
||||
├── equipment/
|
||||
│ ├── newbilt/ Offers, site requirements, process schematic,
|
||||
│ │ service rates (vendor PDFs)
|
||||
│ │ service rates, 2026 product flyers (vendor PDFs)
|
||||
│ ├── oms/ OMS introduction letter: wet-room units, reference
|
||||
│ │ prices, capacities, lathe contacts (vendor docx)
|
||||
│ ├── pheenix-alpha/ Electroforming range flyers (vendor PDFs)
|
||||
│ ├── sibert/ Stamper prep specifications and line-up drawing
|
||||
│ │ (2021 issues in specs-2021/), 2008-09
|
||||
│ │ optical-disc literature (vendor PDFs)
|
||||
│ ├── duplex-cell-layout-sketch.png Duplex cell arrangement (sketch, not to scale)
|
||||
│ ├── galvanics.md Electroforming and stamper prep equipment plan
|
||||
│ ├── inline-optical-qc.md Devices for the record inspection station
|
||||
│ ├── inline-qc-control-plan.md EtherCAT control plan for the station
|
||||
│ ├── inline-qc-station/ Concept model of the station (FreeCAD script,
|
||||
│ │ .FCStd, renders, labelled investor view,
|
||||
│ │ bill of materials)
|
||||
│ └── pressing-line.md Press fleet strategy and equipment plan
|
||||
├── finance/ Project cost overviews
|
||||
├── suppliers/ Supplier contacts, vendor landscape, supplier map
|
||||
├── finance/ Project cost overviews, revenue model,
|
||||
│ share price, construction RFQ, PEA electricity tariff
|
||||
│ schedule (pea/), biomass fuel market
|
||||
│ reports (biomass/), photos of ResurRec's
|
||||
│ Japan plant (resurrec-japan/)
|
||||
├── suppliers/ Supplier contacts, vendor landscape, supplier map,
|
||||
│ Chinese utility suppliers (china-utilities.md)
|
||||
├── order.html Step-by-step order configurator demo page
|
||||
├── artist-order.html Artist ordering and fan-funding demo page
|
||||
├── artist-platform.md Upload, price calculator, fan-funded pressing
|
||||
├── biomass.md Biomass fuel strategy and the 60 rai coppice idea
|
||||
├── boi.md BOI promotion strategy and requirements
|
||||
├── catalogue-intelligence.md Own catalogue: sales map, demand model, advisor
|
||||
├── cnx_vinyl_parametric_payap.FCStd Payap scenario parametric BIM model
|
||||
├── cnx_vinyl_parametric_payap.png Top view of the Payap model
|
||||
├── cnx_vinyl_parametric_payap-iso.png Isometric view of the Payap model
|
||||
├── cnx_vinyl_parametric_payap-office.png Office building floor plans
|
||||
├── cnx_vinyl_parametric_payap-block.png Finishing and print block plans
|
||||
├── cnx_vinyl_parametric_payap_parts.FCStd Payap model in Part/Draft: roof, PV, parking canopies
|
||||
├── cnx_vinyl_parametric_payap_parts.png Isometric view of the parts model
|
||||
├── cnx_vinyl_parametric_payap_parts-top.png Top view of the parts model
|
||||
├── CNX_apply_Params.FCMacro Pushes Params edits to the model (FreeCAD 26.3 RC1)
|
||||
├── crane-workshop-tours.md Overhead crane, workshop, visitor corridor
|
||||
├── digital-factory.md Data platform, NixOS/Clan fleet, acquisition, app
|
||||
├── facility-security.md Security, HVAC, fire and life safety, compliance
|
||||
├── factory-console.html Factory application and customer portal demo
|
||||
├── fleet-calculator.html Press fleet calculator: output, mix, requirements
|
||||
├── land-listings/ Land offers and zoning records (Mueang Chi, Payap,
|
||||
│ Payap rezoning route)
|
||||
├── make-a-record.html Artist platform investor demo (end-user flow)
|
||||
├── payap-partnership.md Joint student programmes with Payap University
|
||||
├── plant-assistant.html Plant assistant (vinyl-ai) mockup: operator, management, sales
|
||||
├── plant-assistant.md Ask the plant: assistant on knowledge base and data
|
||||
├── plant-operation.html Animated plant overview (simulated SCADA)
|
||||
├── process-flow.md Audio file to delivered record, with all checks
|
||||
├── production-hall-layout-sketch.FCStd Rough BIM sketch, Mueang Chi hall (earlier fleet)
|
||||
├── production-hall-layout-sketch.png Top view of the sketch
|
||||
├── production-timeline.md Order turnaround, stage by stage
|
||||
├── project-timeline.md Calendar to first paying release, critical path
|
||||
├── quality-automation.md Stamper metrology and layered record QC
|
||||
├── roadmap.md Next steps in dependency order
|
||||
├── scale.md Rough project sizing on one page
|
||||
├── site-candidates.md Land options and the checks before choosing
|
||||
├── steam-cooling.html Steam and cooling plant diagram, launch plant
|
||||
├── sustainability.md Energy, water, materials commitments
|
||||
├── traceability.md Process logging and per-order traceability
|
||||
└── worker-safety.md Training, clean rooms, PPE
|
||||
site/ Internal test site https://cnxvinyl.lol/
|
||||
├── public/ Served as is: landing page, static sites
|
||||
├── build.sh Builds site/dist: public/ plus demo pages from docs/
|
||||
├── Caddyfile Virtual host for the web server (applied by hand)
|
||||
└── README.md Build, deploy and one-time setup
|
||||
.gitea/workflows/
|
||||
└── deploy-site.yml Builds site/ and deploys it on push to master
|
||||
```
|
||||
|
||||
Vendor PDFs and spreadsheets are primary sources and reflect the state of
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# CNX: apply Params
|
||||
# FreeCAD 26.3 RC1 does not pass spreadsheet edits on to the objects that read them
|
||||
# (a normal recompute only recomputes the sheet). Run this macro after editing Params:
|
||||
# it touches every object whose expressions read the sheet, then recomputes; anything
|
||||
# further down the chain (arrays, dimensions) follows normally.
|
||||
import FreeCAD as App
|
||||
|
||||
doc = App.ActiveDocument
|
||||
sheet = doc.getObject("Params") if doc else None
|
||||
if sheet is None:
|
||||
App.Console.PrintError("CNX apply Params: the active document has no Params sheet\n")
|
||||
else:
|
||||
sheet.recompute()
|
||||
deps = [o for o in sheet.InList if o is not sheet]
|
||||
for o in deps:
|
||||
o.touch()
|
||||
n = doc.recompute()
|
||||
bad = [o.Label for o in doc.Objects if "Invalid" in o.State or "Error" in o.State]
|
||||
App.Console.PrintMessage(f"CNX apply Params: {len(deps)} objects read Params, {n} recomputed, errors: {bad[:10]}\n")
|
||||
@@ -0,0 +1,595 @@
|
||||
# Artist Platform: Upload, Price Calculator and Fan-Funded Pressing
|
||||
|
||||
A web platform where anyone who wants records made, from a bedroom
|
||||
artist to a label, can:
|
||||
|
||||
1. **Configure a record in a calculator** and get a transparent,
|
||||
itemised offer: what every line costs, which costs are per title and
|
||||
which per copy, how the price per copy falls with quantity, and when
|
||||
it ships.
|
||||
2. **Upload the master and the artwork**, and have both checked before
|
||||
anyone pays for anything.
|
||||
3. **Either order directly**, as any label would, **or launch a
|
||||
fan-funded campaign**: a page the artist shares with fans, who
|
||||
pre-order their copy. If enough fans commit before the deadline, the
|
||||
plant presses and ships each fan's copy. If not, every fan is
|
||||
refunded and nobody is left with a garage full of records.
|
||||
|
||||
The calculator is for every customer. The campaign is the part that
|
||||
opens vinyl to artists who could never front the cost of a run. Both sit
|
||||
on top of what the plan already has: the stages and the three artist
|
||||
gates in [process flow](process-flow.md), the lead times in
|
||||
[production timeline](production-timeline.md), the order intake, client
|
||||
vault and customer portal in [digital factory](digital-factory.md), and
|
||||
the dropshipping already in the fulfillment step. Every figure on this
|
||||
page without a source is an estimate.
|
||||
|
||||
**Demo.** The [artist ordering demo](artist-order.html) (test site
|
||||
`/demos/artist-order/`) walks this whole flow on one static page:
|
||||
configure a record, type the track list or drop the master files and
|
||||
artwork (read in the browser and never uploaded: format, sample rate, bit
|
||||
depth, sample peak and clipping, side length against the format, print
|
||||
resolution and colour space), approve gate 1, get the itemised offer with
|
||||
its price curve and lead time, then order directly or set up a campaign
|
||||
and run it to a funded or a missed end, with the production steps and the
|
||||
three gates after it. Its price list (version `demo-0.1`) splits the
|
||||
illustration rates below into lines; every split is an estimate and the
|
||||
page lists each rate with its basis.
|
||||
|
||||
**Investor demo.** [Make a record](make-a-record.html) (test site
|
||||
`/demos/make-a-record/`) is the same flow as a customer would see it,
|
||||
built for presenting: a to-scale mock-up with a record that spins at the
|
||||
chosen speed, the checks in plain words, one price with the itemised
|
||||
lines folded under it, the fan campaign on a phone, the production
|
||||
timeline, and a **record passport** for one delivered copy (stamper,
|
||||
press, cycle time and side, per [traceability](traceability.md) and
|
||||
[quality automation](quality-automation.md)). An "Investor notes" switch
|
||||
adds the business case to each step, sourced from this page, the
|
||||
[revenue model](finance/revenue-model.md) and the
|
||||
[production timeline](production-timeline.md); a guided tour (`#tour`
|
||||
after the URL, `#notes` for the notes) walks the whole flow in about a
|
||||
minute. It uses the same price list and stage table as the detailed
|
||||
demo, so a rate change goes into both pages.
|
||||
|
||||
**Step-by-step order tool.** [Order a record](order.html) (test site
|
||||
`/demos/order/`, October 2026, after the configurator at
|
||||
[mobineko.com/order](https://mobineko.com/order)) is the order flow as a
|
||||
plant's online order form: a rail of numbered steps (order type, size,
|
||||
discs, vinyl colour and effects, labels, inner sleeves, jacket and
|
||||
finish, extras, mastering and cutting, test pressings, shipping, track
|
||||
list, artwork, how to pay, review), each step's choices beside a large
|
||||
live picture of the record, and a running price and ship date. The review
|
||||
lists what is still missing before an order can be placed. It carries the
|
||||
same price list, so a rate change goes into all three pages.
|
||||
|
||||
**Fan funding in the order tool** (user, 20 October 2026: the new tool
|
||||
offers fan funding too, so the investor deck's platform pictures come
|
||||
from one tool and one calculator). Step 15 "How to pay" chooses between
|
||||
paying the plant directly (the deposit, the rest before dispatch) and a
|
||||
fan-funded campaign with the same inputs and the same campaign maths as
|
||||
[make-a-record](make-a-record.html): the artist sets the fan price
|
||||
(default 1,200 THB) and the campaign length, the fans needed are the
|
||||
larger of break-even and the 100-copy minimum run, and the tool shows
|
||||
what the artist keeps at the goal and with more fans, after the payment
|
||||
fees (~3.5 %, to confirm with the provider), the one-off setup and the
|
||||
pressing. Step 16 becomes "Review & launch" and simulates the campaign's
|
||||
outcome. For the same record both pages give the same numbers (checked
|
||||
headless over 40 combinations, October 2026): the default record at
|
||||
1,200 THB needs 100 fans (break-even 41) and keeps ~548 THB a copy; the
|
||||
Splatter 12" preset needs 100 fans (break-even 46) and keeps ~480 THB a
|
||||
copy. Indicative demo prices.
|
||||
|
||||
**Mastering as a choice** (user, October 2026): the order tool lets the
|
||||
customer pick the mastering: none (the master is final and only prepared
|
||||
for the lathe), CNX vinyl mastering in-house per side, or full mastering
|
||||
by a partner studio at **60 USD a track** (team figure, about 1,980 THB).
|
||||
The example partner is [Brandenburg Mastering](https://www.brandenburgmastering.com)
|
||||
in Amsterdam, which quotes on request and publishes no price list
|
||||
(checked October 2026); it is not contracted. Partner mastering replaces
|
||||
the in-house line rather than adding to it, and keeps gate 2: the artist
|
||||
approves the master before cutting.
|
||||
|
||||
## Why it fits this plant
|
||||
|
||||
- **The bottom of the Thai market is unserved.** The one Thai plant we
|
||||
have seen quotes a 150-unit minimum that is "rarely accepted because
|
||||
the cost is way too high", so runs under 300 are effectively
|
||||
unavailable ([revenue model](finance/revenue-model.md)). The reason is
|
||||
a per-title cost (imported stampers, outsourced cutting) that does not
|
||||
shrink with the run. In-house cutting and plating collapses it, which
|
||||
makes short runs viable for CNX in a way they are not for an importer
|
||||
of metalwork. Short runs need a channel; this is it.
|
||||
- **Fan funding removes the artist's risk.** What stops an indie artist
|
||||
ordering 200 records is not the price per copy, it is paying for all
|
||||
200 up front without knowing whether they sell. A campaign turns that
|
||||
around: the fans pay first, the run is exactly as big as the demand.
|
||||
- **CNX owns the presses.** The known platforms of this kind are brokers
|
||||
over a network of other people's plants. A plant-owned platform
|
||||
controls its own price, schedule and quality, and keeps the margin on
|
||||
manufacturing instead of a commission.
|
||||
- **Transparency is already the brand.** The plan is built on
|
||||
traceability that customers can see. The same event log can tell a fan
|
||||
"cut on 12 March, plated, test pressing approved by the artist,
|
||||
pressing now, ships next week", automatically and truthfully.
|
||||
|
||||
## Who else does this, and the lesson
|
||||
|
||||
| | Model | Notes |
|
||||
|---|---|---|
|
||||
| **Qrates** (Japan, global) | Crowdfunding plus pressing through partner plants, with a profit calculator for the artist | Its site carries a notice (October 2026) that the service is suspended "due to unforeseen financial difficulties"; artists report funded projects caught in the wind-down |
|
||||
| **Diggers Factory** (France) | Upload tracks and artwork, set a sales goal; if missed, the project is cancelled and everyone refunded, or the artist funds the rest; about 8 weeks of manufacturing after success (2023 description); also sells direct pressing paid up front | An on-demand network rather than a single plant |
|
||||
| **elasticStage** (UK) | Each record made when it is ordered, no minimum, no campaign | Its own on-demand production technology; a different answer to the same problem |
|
||||
|
||||
**The Qrates lesson is the design rule for the money**: fan payments are
|
||||
held apart from the company's own money and are never working capital,
|
||||
so that if anything goes wrong, fans can be refunded and artists keep
|
||||
their projects. See "Payments" below.
|
||||
|
||||
## The calculator
|
||||
|
||||
### What the customer chooses
|
||||
|
||||
| Choice | Options |
|
||||
|---|---|
|
||||
| Format | 12" LP, 10", 7"; single or double disc; 33⅓ or 45 rpm; 7" with a small or a large (dinked) centre hole |
|
||||
| Weight | 140 g, 180 g |
|
||||
| Colour | Black, solid colour, marbled or splatter (the semi-automatic line's speciality); for colour, whether the press is cleaned first |
|
||||
| Quantity | Free entry, with the price-per-copy curve shown live |
|
||||
| Labels | Paper labels pressed into the record: printed, or plain white or black (white labels for promos and DJ copies) |
|
||||
| Run-out inscription | The customer's catalogue number or text, scribed next to the run-out groove of every side (letters and numbers, up to 15) |
|
||||
| Inner sleeve | Paper, poly-lined |
|
||||
| Jacket | None (customer supplies), plain, printed single, printed gatefold; printed by the local packaging partner |
|
||||
| Extras | Insert, hype sticker, shrink wrap, numbered edition, download card, barcode sticker |
|
||||
| Audio source | Digital files, analog tape (transferred in-house), or a lacquer cut by the customer's studio (straight to plating; must arrive within days of cutting) |
|
||||
| Audio services | Customer supplies a vinyl-ready master, or CNX vinyl mastering per side, or full mastering by a partner studio per track |
|
||||
| Metal | Lacquer cutting and stampers (in-house; bridge stampers from Stamper Discs until the galvanics line exists) |
|
||||
| Test pressings | Number of copies for the artist |
|
||||
| Delivery | Bulk to one address, dropship to each buyer, or collect at the plant |
|
||||
|
||||
### Benchmark: Record Industry's calculator (October 2026)
|
||||
|
||||
Record Industry (Haarlem, NL; host plant of Making Vinyl Europe 2026)
|
||||
runs a public calculator
|
||||
(https://www.recordindustry.com/calculator/, checked October 2026): seven
|
||||
steps (pre-production, vinyl, labels, inner sleeve, outer sleeve, extras,
|
||||
quote or order) with an itemised cost list beside the form that updates
|
||||
on every choice, an info box under each question, and a draft order
|
||||
that the plant confirms by hand before the pre-payment invoice. Prices
|
||||
are computed on its server. What it shows that this plan had not
|
||||
covered, and what the demos took from it:
|
||||
|
||||
- **Taken into both demos:** audio arriving as tape or as a supplied
|
||||
lacquer (it charges 470 EUR for cutting plus stampers from a digital
|
||||
master, 570 from tape, 240 for plating a supplied lacquer), plain white
|
||||
or black labels, press cleaning before a colour run (60 EUR, with the
|
||||
warning that without it records can carry the previous colour), the
|
||||
dinked 7", download cards and barcode stickers, and a catalogue number
|
||||
scribed in the run-out (letters and numbers, up to 15). The new rates
|
||||
are estimates with its prices as the basis, listed in the detailed
|
||||
demo.
|
||||
- **Left out for now:** label print modes (CMYK, Pantone, one colour),
|
||||
board grades and finishes (kraft, Hansaboard, matt or gloss varnish,
|
||||
laminates), die-cut holes, spines other than 3 and 5 mm, booklets, foil numbering,
|
||||
sticker position, protective outer sleeves, BIO PVC and a recycled
|
||||
colour mix, and multi-address shipping. Each is a price-list line once
|
||||
the packaging partner and the compound suppliers quote.
|
||||
- **Commercial terms worth deciding for CNX:** a flat order set-up fee
|
||||
(60 EUR) and a small-run surcharge (60 EUR under 300, 40 under 500);
|
||||
20 copies over the order invoiced to cover under- or over-production,
|
||||
credited if fewer are delivered; customers asked to accept about 2 %
|
||||
rejects; full pre-payment for new customers; minimum 200 copies.
|
||||
|
||||
Its prices and lead times are recorded as a benchmark in the
|
||||
[revenue model](finance/revenue-model.md) and the
|
||||
[production timeline](production-timeline.md).
|
||||
|
||||
### What the customer gets back
|
||||
|
||||
- **Every line itemised**, grouped into **per title** (mastering,
|
||||
cutting, stampers, test pressings, setup) and **per copy** (pressing,
|
||||
labels, sleeve, jacket, extras), with pass-through items such as the
|
||||
printed jacket marked as such.
|
||||
- **The price per copy against quantity** as a curve, so it is obvious
|
||||
why 100 copies cost more each than 500, and where the steps are.
|
||||
- **A lead time in weeks** from the quote table in
|
||||
[production timeline](production-timeline.md): counted from
|
||||
test-pressing approval, with the stages before it shown separately as
|
||||
"typically X weeks, subject to your approvals", exactly as that page
|
||||
says a quote should be made.
|
||||
- **An offer** with a validity date and the price-list version it was
|
||||
computed from.
|
||||
|
||||
### How it computes
|
||||
|
||||
Price = sum of the per-title lines + quantity × sum of the per-copy lines,
|
||||
with quantity tiers where a supplier's price steps (jacket print runs).
|
||||
All rates come from **one versioned price list** in the factory
|
||||
application, and every offer records the version it used, so any old
|
||||
offer can be reproduced to the baht. That follows the append-only rule
|
||||
the factory application already applies to everything else.
|
||||
|
||||
Transparency rules, so the word means something:
|
||||
|
||||
- every line visible, no fees that appear later;
|
||||
- pass-through costs (the jacket) shown at what the partner charges plus
|
||||
a stated handling margin;
|
||||
- quoted in THB for Thai customers and in USD for export customers, the
|
||||
currency choice the [revenue model](finance/revenue-model.md) already
|
||||
recommends deciding early.
|
||||
|
||||
### Side length per format
|
||||
|
||||
The audio check compares each side with the format's limit. Until the
|
||||
cutting engineer sets CNX's own figures, the demos use these (October
|
||||
2026):
|
||||
|
||||
| Format | Comfortable | At most | Songs a side, at most |
|
||||
|---|---|---|---|
|
||||
| 12", 33⅓ rpm | 18 min | 22 min | ~4.9 |
|
||||
| 12", 45 rpm | 12 min | 15 min | ~3.3 |
|
||||
| 10", 33⅓ rpm | 12 min | 15 min | ~3.3 |
|
||||
| 10", 45 rpm | 8 min | 12 min | ~2.6 |
|
||||
| 7", 33⅓ rpm | 5 min | 7 min | ~1.5 |
|
||||
| 7", 45 rpm | 4.5 min | 5 min | ~1.1 |
|
||||
|
||||
**At most** and **songs** are the table the team supplied in October
|
||||
2026, from recordplayerexpert.com ("How much can a vinyl record hold",
|
||||
https://recordplayerexpert.com/vinyl-record-capacity, checked October
|
||||
2026), which counts songs at an average length of 4:32. **Comfortable**
|
||||
is the lower end of each range in the microcut.studio format guide
|
||||
(https://microcut.studio/guides/vinyl-format-guide-12-10-7/).
|
||||
|
||||
The published cutting-room figures disagree with the at-most column in
|
||||
three places, so treat those as re-check points for the cutting engineer:
|
||||
10" at 33⅓ rpm (15 min here; microcut.studio up to 16, Diggers Factory
|
||||
17), 10" at 45 rpm (12 min here; microcut.studio 11, Diggers Factory 10,
|
||||
so this table is the most generous) and 7" at 45 rpm (5 min here, as
|
||||
Diggers Factory; microcut.studio 6). Diggers Factory lists hard maxima of
|
||||
22, 12, 17, 10, 6 and 5 minutes for the six formats (stricter on 12" at
|
||||
45 rpm), and A to Z Media 14 to 18 minutes as ideal on a 12" LP. Loud or bass-heavy music needs
|
||||
shorter sides: Diggers Factory's dance-music figures are about 60 % of its
|
||||
standard ones (11:27 against 19:23 on a 12" LP), which the demo applies as
|
||||
a factor of 0.6. The engineer check, not this table, decides whether a
|
||||
side is cuttable.
|
||||
|
||||
### What it looks like with numbers
|
||||
|
||||
An illustration of the **shape**, using the midpoints of the working
|
||||
assumptions in the revenue model: **38,000 THB per title** (mastering,
|
||||
cutting, stampers, test pressings; range 19,000 to 57,000), **132 THB per
|
||||
copy** for pressing, labels, inner sleeve and assembly (range 115 to 150),
|
||||
plus **~100 THB per copy for a printed jacket and shrink** at short run
|
||||
(estimate, until the packaging partner quotes). Black 12", 140 g:
|
||||
|
||||
| Copies | Per-title share per copy | Per copy | Per copy, all in | Order total |
|
||||
|---|---|---|---|---|
|
||||
| 100 | 380 | 232 | **~612 THB** | ~61,200 THB |
|
||||
| 200 | 190 | 232 | **~422 THB** | ~84,400 THB |
|
||||
| 300 | 127 | 232 | **~359 THB** | ~107,600 THB |
|
||||
| 500 | 76 | 232 | **~308 THB** | ~154,000 THB |
|
||||
| 1,000 | 38 | 232 | **~270 THB** | ~270,000 THB |
|
||||
|
||||
**Do not read the level off this table.** At these Western-benchmark
|
||||
rates the 300-copy price lands near 360 THB, while the Thai market pays
|
||||
650 to 950 THB for 300 today. That is the very gap the revenue model
|
||||
flags as its biggest open question. The real price list is set after
|
||||
market validation ([roadmap](roadmap.md) item 1); the calculator only
|
||||
makes whatever prices are chosen legible.
|
||||
|
||||
## Artwork templates and files
|
||||
|
||||
Decided for the demos (user, October 2026): the order tool offers a
|
||||
**spine choice** and **templates to download**, and accepts the files
|
||||
designers actually deliver, **PDF and Illustrator (AI)** as well as
|
||||
images.
|
||||
|
||||
- **Spine.** Thin, 3 mm, holds one record in its inner sleeve; thick,
|
||||
5 mm, holds two, or one with a thick insert or a poster. Plants publish
|
||||
templates for both, and for 7 or 9 mm on a gatefold (Mighty Media Discs:
|
||||
12" sleeve 633 x 315 mm with a 3 mm spine, 635 x 315 mm with 5 mm;
|
||||
Implant: 5 mm for two records; RPM Records: gatefold with a 7 mm spine;
|
||||
XVinylX: 9 mm gatefold; all checked October 2026). A double album in a
|
||||
single jacket takes the 5 mm spine without asking. The thick spine is
|
||||
an extra line on the quote, an estimate until the packaging partner
|
||||
quotes: Quality Record Pressings (US) lists a generic wide-spine jacket
|
||||
at 0.90 USD against 0.55 for a standard one, and Kudos (UK) charges
|
||||
137.50 GBP per order for an extra wide spine (price lists, checked
|
||||
October 2026). A 7" jacket keeps the 3 mm spine.
|
||||
- **Templates** follow the format, the jacket type and the spine chosen:
|
||||
the jacket spread (back, spine, front) with 3 mm bleed, a 5 mm safe
|
||||
area and the folds marked, a second page for the inside of a gatefold,
|
||||
and a label template with one page per side (centre hole, and the
|
||||
large hole of a dinked 7"). They are vector PDFs with trim and bleed
|
||||
boxes set, so they open in Illustrator, InDesign and Affinity. Until
|
||||
the packaging partner supplies its dielines the sizes come from the
|
||||
published templates above; 10" and 7" panels are the mock-up's sizes.
|
||||
- **Files accepted:** PDF (PDF/X-4 preferred), Illustrator files saved
|
||||
with PDF compatibility (an AI file without it is refused with
|
||||
instructions), and 300 dpi images. Plants ask for the same: Mobineko
|
||||
publishes PSD, AI and PDF templates, New Orleans Record Press takes
|
||||
print PDFs and refuses flattened images (checked October 2026). The
|
||||
preflight reads the page boxes, colour spaces and fonts from the file,
|
||||
checks the trim against the chosen spine (a spread made for a 5 mm
|
||||
spine is flagged on a 3 mm order), the bleed, CMYK against RGB, and
|
||||
whether fonts are embedded or outlined, and renders the front panel
|
||||
into the mock-up.
|
||||
|
||||
## Fan-funded campaigns
|
||||
|
||||
### Before the campaign goes live
|
||||
|
||||
Nothing goes in front of fans that the plant cannot make:
|
||||
|
||||
1. **Upload**: master files (WAV/FLAC/AIFF) with checksums at both ends,
|
||||
resumable for album-size uploads, straight into the encrypted client
|
||||
vault (module 2 of the factory application).
|
||||
2. **Automatic audio checks**, reported to the artist within minutes:
|
||||
format, sample rate and bit depth, clipping and true peak, **side
|
||||
length against the chosen format**, and low-frequency phase problems
|
||||
that make a groove hard to cut.
|
||||
3. **Automatic artwork preflight**: label and jacket files against the
|
||||
templates (size, centre hole and safe area for the pressed-in label,
|
||||
bleed, resolution, colour space), with a rendered mock-up of the
|
||||
jacket and the vinyl colour; templates and accepted files in
|
||||
[Artwork templates and files](#artwork-templates-and-files).
|
||||
4. **Engineer check**: a cutting engineer confirms side length and level
|
||||
are cuttable. On a Sillitoe lathe this is a number from the software's
|
||||
virtual groove (disk capacity in percent) without a test cut; see
|
||||
[vendor landscape](suppliers/vendor-landscape.md).
|
||||
5. **Rights**: the artist confirms they own or have licensed the
|
||||
recordings and the compositions (covers need a mechanical licence),
|
||||
and an automatic audio fingerprint check (open tools such as
|
||||
Chromaprint/AcoustID) catches obvious bootlegs before a person looks.
|
||||
6. **Gate 1, master plan approved**, recorded as the event the
|
||||
[process flow](process-flow.md) already defines, plus the approved
|
||||
artwork proof that packaging QC later checks print against.
|
||||
|
||||
### The campaign page
|
||||
|
||||
- Artwork mock-up, story, track list, **short audio previews** (a few
|
||||
seconds to a minute per track at reduced quality, rendered by the plant
|
||||
from the master; the full master never leaves the vault, which matters
|
||||
because pre-release audio is a leak target per
|
||||
[facility security](facility-security.md))
|
||||
- Price per copy, shipping by destination, goal, progress, deadline,
|
||||
**estimated ship month** (campaign close plus the quoted lead time),
|
||||
and what happens if the goal is missed
|
||||
- Sharing built for where the fans are: a link, a QR code for gigs and
|
||||
merch tables, and **LINE** alongside the international networks; Thai
|
||||
and English
|
||||
- Duration chosen by the artist, **14 to 45 days** (estimate)
|
||||
|
||||
### The goal
|
||||
|
||||
The artist sets only the fan price; the goal, the number of fans
|
||||
needed, follows from it (decided October 2026). It is the larger of two
|
||||
numbers:
|
||||
|
||||
- **the plant's minimum campaign run**, set by setup and stamper
|
||||
economics on the semi-automatic line (**100 copies** as a planning
|
||||
figure, to be decided), and
|
||||
- **the artist's break-even**: the copies at which the fan price covers
|
||||
the per-title costs, the per-copy costs and the payment fees.
|
||||
|
||||
Both demos show it in fans and as the pre-order amount (fans × fan
|
||||
price); the investor demo also says from which fan price the 100-copy
|
||||
minimum is enough (about 640 THB in the illustration; below it the
|
||||
break-even sets the goal).
|
||||
|
||||
With the illustration above and a fan price of 1,200 THB (an example,
|
||||
not a recommendation) and payment fees of about 3.5%: break-even is
|
||||
38,000 / (1,200 − 42 − 232) ≈ **41 copies**, so the goal is the 100-copy
|
||||
minimum. At 100 copies the artist keeps about **546 THB a copy**, at 300
|
||||
about **799 THB**, because the per-title cost spreads. The calculator
|
||||
shows the artist this before launch, for any price they type in. Shipping
|
||||
is charged to the fan separately at checkout, at cost.
|
||||
|
||||
VAT is not in this example. With CNX as seller of record (open decision
|
||||
1), a 1,200 THB fan price includes about 79 THB of VAT (7/107), which
|
||||
comes out of the artist's margin; the demo can show the numbers with and
|
||||
without it.
|
||||
|
||||
Over-subscription is good news: the run is pressed at the final number
|
||||
plus the artist's own copies and the spares the reject allowance already
|
||||
covers. An artist can cap a campaign for a limited, numbered edition.
|
||||
|
||||
### Payments
|
||||
|
||||
The decision that matters most, and the one Qrates got wrong.
|
||||
|
||||
| | A. Charge at pledge, refund on failure | B. Save card, charge at success |
|
||||
|---|---|---|
|
||||
| How | Fan pays when pledging; money held in a ring-fenced account; automatic refund if the goal is missed | Card stored by the payment provider; charged only when the campaign succeeds |
|
||||
| Thai fit | Works with **PromptPay QR**, cards and wallets, which is how Thai fans pay | Cards only; excludes PromptPay |
|
||||
| Risk | CNX holds fan money for the campaign's length: must be ring-fenced and legally clean | Some charges fail at the end, so a campaign that "succeeded" can come up short |
|
||||
| Note | Refund paths differ by payment method; confirm each with the provider | A card authorisation cannot simply be held: Opn (Omise) allows an authorise-and-capture pause of up to 7 days, far short of a campaign |
|
||||
|
||||
**Recommended: A**, with three rules. Fan money sits in a **separate
|
||||
account** and is never used for operations until the campaign succeeds.
|
||||
**CNX is the seller of record** to the fan (CNX makes and sells the
|
||||
record, the artist licenses the music and receives the margin), which
|
||||
keeps VAT, consumer protection and refunds in one place. And before the
|
||||
first campaign, **a Thai legal opinion** on whether holding pre-order
|
||||
money for a third party's project needs anything beyond that, for
|
||||
example under the Bank of Thailand's payment-service rules. Card data
|
||||
never touches CNX servers: the provider's hosted payment page or fields
|
||||
keep it out of scope.
|
||||
|
||||
### When the campaign succeeds
|
||||
|
||||
The campaign becomes a production order and runs the normal chain:
|
||||
vinyl mastering if ordered and **gate 2** (master approved by the
|
||||
artist), cutting (only now, because a lacquer has to be plated within
|
||||
one to three days), stampers, test pressings and **gate 3** (artist
|
||||
approves the test pressing; a photo or short video of it to the fans is
|
||||
cheap marketing), the run, packaging, and **dropshipping one parcel per
|
||||
fan** with tracking, which is fulfillment step 9 as already planned.
|
||||
|
||||
Fans follow it on the campaign page, fed from the order's records in
|
||||
ERPNext and the plant's event log: the progress is the plant's own record, not a status someone
|
||||
remembers to update. If a stage slips, the estimated ship month moves
|
||||
and every fan is told.
|
||||
|
||||
An optional **"test pressing first"** campaign does mastering, cutting and
|
||||
test pressings before launch, so fans hear and see the real record. The
|
||||
artist pays the per-title services up front for it; it suits artists
|
||||
with an audience but no track record.
|
||||
|
||||
### When it does not succeed
|
||||
|
||||
Automatic refunds to every fan, or, if the artist chooses, the artist
|
||||
pays the shortfall and the run goes ahead at the minimum (the Diggers
|
||||
Factory option). The artist's uploaded master and artwork stay in the
|
||||
vault for a second attempt.
|
||||
|
||||
### After the first run: repress on demand
|
||||
|
||||
Once a title exists, its father and mother sit in the archive (a mother
|
||||
gives about ten stamper sets, and a worn one is replaced from the father
|
||||
without a new cut) and a repress takes
|
||||
**1.5 to 2.5 weeks** of plant time
|
||||
([production timeline](production-timeline.md)). The campaign page can
|
||||
reopen as "pre-order the repress, pressed when 100 more are in", which
|
||||
turns one release into a recurring one. This is the part a plant with
|
||||
in-house plating can offer and a broker cannot. The planned catalogue
|
||||
company can use the same pre-order as the market test for its titles, on
|
||||
the same terms as any label ([own catalogue](catalogue-intelligence.md)).
|
||||
|
||||
## For labels and regular customers
|
||||
|
||||
The same calculator and upload path, with an account:
|
||||
|
||||
- negotiated rates as a customer-specific price-list version;
|
||||
- direct orders with a deposit instead of a campaign;
|
||||
- the three gates approved in the customer portal
|
||||
([digital factory](digital-factory.md), modules 1 to 3 and 10);
|
||||
- bulk delivery, dropshipping, or both;
|
||||
- standby pressing (proposal, October 2026): a flexible date scheduled
|
||||
into idle press time at a lower price, on the same terms for every
|
||||
customer, the related catalogue company included
|
||||
([own catalogue](catalogue-intelligence.md#arms-length-between-the-two-companies)).
|
||||
|
||||
## How it is built
|
||||
|
||||
Same stack and same rules as the factory application in
|
||||
[digital factory](digital-factory.md): Rust (axum, SQLx, minijinja,
|
||||
HTMX) on PostgreSQL, in the `cnx-factory` repository, packaged as a
|
||||
flake, deployed by the clan. The platform extends modules 1 (orders and
|
||||
releases), 2 (audio intake and the client vault), 3 (the gates) and 10
|
||||
(customer portal) with a price list and calculator, campaigns, pledges,
|
||||
payments and per-fan shipments.
|
||||
|
||||
**Where the public side runs.** The digital factory plan accepts that a
|
||||
WAN outage at the plant stops the customer portal. That is acceptable for
|
||||
a label checking an order, not for a campaign page in the hour an artist
|
||||
posts it, or for payment-provider webhooks. Proposal:
|
||||
|
||||
- the **public process** (calculator, campaign pages, checkout, payment
|
||||
webhooks, upload staging) runs on a fleet machine with a public
|
||||
address, `web01` or a sibling declared in the clan the same way, with
|
||||
its own small PostgreSQL for campaigns and pledges;
|
||||
- the **plant core stays the authority** for everything with a
|
||||
production identity: when a campaign succeeds it becomes an order on
|
||||
`vinyl-core`, and from then on the fan-facing progress is read through
|
||||
the plant, as the portal is. Design decision 7 ("the portal is a view,
|
||||
not a copy") still holds for production data; campaigns and pledges are
|
||||
new data that start life in public;
|
||||
- **uploads** land encrypted in a staging area on the public machine, are
|
||||
pulled over the mesh into the client vault, checksum-verified on both
|
||||
sides, and deleted from staging; **previews** are rendered on the plant
|
||||
and published outwards, so a full master never rests outside the
|
||||
vault.
|
||||
|
||||
No SaaS beyond the payment provider (Opn/Omise, 2C2P or a bank gateway,
|
||||
to be chosen), in line with the plan's standing rule that every plant
|
||||
service runs on the NixOS fleet.
|
||||
|
||||
**ERPNext** (decided October 2026: the plant runs ERPNext as its only
|
||||
system of record, and what we build are tools and interfaces on it;
|
||||
[digital factory](digital-factory.md#erpnext-the-plants-erp)). The
|
||||
platform keeps no business records of its own. For the platform that
|
||||
means:
|
||||
|
||||
- the **price list** behind the calculator is an ERPNext price list
|
||||
(the demos' `R` list is its prototype), synced out to the public
|
||||
process, so the calculator and the invoice never disagree;
|
||||
- an artist or label account is linked to one ERPNext **customer**; a
|
||||
direct order becomes a **sales order** when it is confirmed;
|
||||
- a **campaign** is a custom Campaign document in ERPNext from launch;
|
||||
each pledge is posted as an advance **payment entry** into the
|
||||
ring-fenced account as it arrives, with the fan as a customer; when the
|
||||
campaign succeeds it becomes a sales order the advances are allocated
|
||||
to, and fan shipments become delivery notes; the refunds of a missed
|
||||
campaign are posted as payment entries too. The public process holds
|
||||
sessions and a cache of what it shows, nothing else;
|
||||
- every posting goes through the plant's integration layer and its
|
||||
outbox over the mesh; the public side never talks to ERPNext directly.
|
||||
|
||||
**Personal data.** Fans' names and addresses are personal data under
|
||||
PDPA, with CNX as controller as the seller of record. An artist gets
|
||||
fan contact details only where the fan ticked a consent box; that list
|
||||
is worth a lot to an artist, and consent is what makes it legal to hand
|
||||
over.
|
||||
|
||||
## The calculator is also a research instrument
|
||||
|
||||
Every configuration anyone builds, anonymously logged, is a data point on
|
||||
what people actually want to order: run size, colour, weight, packaging,
|
||||
how many walk away at which price. The revenue model's open **run-size**
|
||||
question ([roadmap](roadmap.md) item 1) is exactly that distribution. So
|
||||
the calculator should go public **long before the plant exists**, with
|
||||
indicative prices and a "tell me when it opens" list, and no payments.
|
||||
|
||||
## Phasing
|
||||
|
||||
| Roadmap phase | Platform step |
|
||||
|---|---|
|
||||
| 0 to 1, validate | Public calculator with indicative prices and an interest list; configuration logging feeds market validation |
|
||||
| 3, build | Direct orders, uploads, automatic checks and gates, as part of factory application v1 |
|
||||
| 4, launch | Campaigns go live **after** the first paying releases have shipped and lead times have been measured. No fan money is taken against a plant that has not yet delivered |
|
||||
| 5, expand | Repress pre-orders, numbered editions, international shipping at scale, cassette and CD formats from the business plan's scope |
|
||||
|
||||
## Rough cost (estimate)
|
||||
|
||||
| Item | THB | USD |
|
||||
|---|---|---|
|
||||
| Public side on top of the factory application: calculator, campaigns, payments, uploads and previews, preflight, fan accounts | 1.3M – 3.0M | 40k – 90k |
|
||||
| Hosting | on the existing fleet | negligible |
|
||||
| Payment fees | per transaction, inside the fan price | about 3 to 4% on cards, less on PromptPay (to be confirmed with the provider) |
|
||||
|
||||
Not yet in the roll-up in
|
||||
[total investment](finance/total-investment.md); listed there as added
|
||||
scope.
|
||||
|
||||
## Risks
|
||||
|
||||
- **Most crowdfunding campaigns fail**, and each failed one still costs
|
||||
CNX checking and setup time. A small non-refundable setup fee, credited
|
||||
against the order if the campaign succeeds, is one answer; decide it
|
||||
before launch.
|
||||
- **Lumpy demand.** Campaigns end on dates nobody controls. The scheduler
|
||||
in the factory application should see live campaigns, weighted by how
|
||||
close they are to their goal, and cap how many can close in the same
|
||||
week.
|
||||
- **Fans are not labels.** They expect a perfect record and a date.
|
||||
Clear wording on what vinyl sounds like, the artist's test-pressing
|
||||
approval, and honest ship months carry most of this.
|
||||
- **Rights.** Someone will upload music that is not theirs. Warranty,
|
||||
fingerprint check, a human look, and a takedown route.
|
||||
- **Money.** Covered by the payment rules above; the legal opinion comes
|
||||
before the first campaign, not after.
|
||||
|
||||
## Open decisions
|
||||
|
||||
1. **Seller of record**: CNX (recommended) or the artist.
|
||||
2. **Payment model**: charge-and-refund into a ring-fenced account
|
||||
(recommended) or save-card-and-charge; legal opinion either way.
|
||||
3. **Fee model**: margin inside the published price list only
|
||||
(recommended, it is what "transparent" means) or a separate platform
|
||||
commission.
|
||||
4. **Minimum campaign run**: 100 copies as the planning figure.
|
||||
5. **Public price list**: fully public rates, or public list prices with
|
||||
account-specific rates for labels.
|
||||
6. **Hosting split**: public process on a fleet machine as proposed, or
|
||||
everything on the plant core at launch volumes.
|
||||
7. **Name**: under CNX Vinyl, Poy Records, or its own brand.
|
||||
@@ -1,23 +1,52 @@
|
||||
# Biomass Fuel Strategy
|
||||
|
||||
If the steam boiler goes the biomass route (see the options in
|
||||
[sustainability](sustainability.md) and the Getabec candidate in the
|
||||
[utilities CSV](finance/utilities-investment.csv)), the fuel comes from two
|
||||
sources: the team's own 60 rai of currently unused land, and northern
|
||||
**Decided 17 October 2026 (user): both business plan versions run on
|
||||
biomass steam** ("option a and b should operate on biomass"): two 500 kg/h
|
||||
biomass modules (or one ~1 t/h package, Getabec class, 6M to 10M THB
|
||||
installed with fuel feed, grate and dust control) plus a fuel store and
|
||||
handling block (1M to 2M THB, estimate) in the
|
||||
[utilities CSV](finance/utilities-investment.csv). The launch plant at
|
||||
~850k records burns ~954 MWh of heat a year, about 300 t of air-dry wood
|
||||
or ~460 t of fresh chips, ~0.67M THB at 0.7 THB/kWh, against ~4.9M THB a
|
||||
year for electric steam with its demand charge (calculator, estimates).
|
||||
The electric-first staged path under Decision framing is dropped; the
|
||||
electric bank stays the alternative.
|
||||
|
||||
The fuel comes from two sources: the team's own 60 rai of currently unused land, and northern
|
||||
Thailand's agricultural waste market. Figures below are planning estimates,
|
||||
plus or minus a wide margin, to be refined against the actual boiler choice
|
||||
and duty cycle.
|
||||
|
||||
## Demand: what the boiler would burn
|
||||
|
||||
The 400 kg/h boiler is roughly 300 kW thermal at full fire. With the heat
|
||||
recovery architecture trimming the load and realistic duty cycles:
|
||||
The five-press fleet draws 750 to 900 kg/h of steam at full demand, ~510
|
||||
to 610 kW thermal, from a proposed bank of two 500 kg/h boilers
|
||||
([steam and cooling](steam-cooling.html)). Fuel follows records pressed,
|
||||
not presses installed. With the heat recovery architecture trimming the
|
||||
load and realistic duty cycles:
|
||||
|
||||
- Mature plant (semi-auto plus automated lines, two shifts, ~300 days/yr):
|
||||
roughly **350 to 400 tonnes of air-dry wood per year** (at ~80% boiler
|
||||
efficiency and ~4 kWh/kg air-dry wood)
|
||||
- Mature plant (two shifts, ~300 days/yr, about 1.0 to 1.1 million
|
||||
records): roughly **350 to 400 tonnes of air-dry wood per year** (at
|
||||
~80% boiler efficiency and ~4 kWh/kg air-dry wood); the start fleet at
|
||||
its full ~1.5 million records needs up to **~550 t/yr**
|
||||
- Early operations (one press line, single shift): roughly a quarter of
|
||||
that, **~90 to 100 t/yr**
|
||||
- Bought as fresh wood chips (~45 % moisture, ~2.6 kWh/kg) the same heat
|
||||
is **~540 to 620 t/yr**, up to ~840 t/yr at 1.5 million records, which
|
||||
is what the fuel store and the monsoon
|
||||
stock have to be sized for (estimate)
|
||||
|
||||
### Recovering heat at the boiler
|
||||
|
||||
A fired boiler loses heat up its stack, so an economizer that preheats the
|
||||
boiler feedwater with the flue gas is the first heat-recovery measure to
|
||||
investigate, ahead of condensate return and the feedwater heat pump
|
||||
([sustainability](sustainability.md#energy-efficiency-architecture-recover-before-generating)).
|
||||
How far the flue gas can be cooled is the vendor's figure: it depends on
|
||||
the flue-gas temperature, the corrosion limit and the fuel. Rice husk ash
|
||||
is high in silica and abrasive, so the RFQ asks for fouling and cleaning
|
||||
provisions, wear protection and a bypass rather than a clean-gas
|
||||
economizer ([steam and cooling](steam-cooling.html)).
|
||||
|
||||
## The 60 rai: own-grown fuelwood
|
||||
|
||||
@@ -28,11 +57,14 @@ proven in Thailand (eucalyptus, acacia, leucaena, bamboo) yield roughly 8 to
|
||||
about **80 to 135 t/yr**:
|
||||
|
||||
- Enough to cover **most or all of early operations**
|
||||
- About **a quarter to a third of mature two-shift demand**
|
||||
- About **a fifth to a third of mature two-shift demand** at ~1.0 million
|
||||
records, a seventh to a quarter at the start fleet's full 1.5 million
|
||||
|
||||
That makes the land a meaningful supplement and a strong brand story
|
||||
("records pressed with steam from our own trees"), not a complete fuel
|
||||
supply.
|
||||
supply. At the market prices below, 80 to 135 t of air-dry wood is worth
|
||||
only ~0.1M to 0.25M THB a year (estimate): the land's value is supply
|
||||
security and the story, not the fuel bill.
|
||||
|
||||
### The classification check comes first
|
||||
|
||||
@@ -62,6 +94,60 @@ The region fills the remainder easily and cheaply:
|
||||
- Buying from local farmers also strengthens the local-sourcing story that
|
||||
already runs through packaging and PVC
|
||||
|
||||
## Fuel prices (market check, October 2026)
|
||||
|
||||
There is no public price index for biomass fuel in northern Thailand. DEDE
|
||||
publishes lists of buyers and sellers (February 2026: 42 registered buyers
|
||||
wanting 2.09M t a year), not prices, so the figures below are reported
|
||||
market prices from bank research, a government industry unit and the
|
||||
press, all checked 7 October 2026. None is a quote to this plant.
|
||||
|
||||
| Fuel | Reported price | Source | Heat cost (estimate) |
|
||||
|---|---|---|---|
|
||||
| Wood chips, fresh (45 to 50 % moisture) | 1,350 to 1,800 THB/t delivered | [LH Bank Research, wood pellet outlook](finance/biomass/LHBank_Wood_Pellets_Industry_Outlook_2026-03.pdf), 9 March 2026: 1,700 to 1,800 THB per fresh tonne for export; a power-plant chip quota in Nakhon Ratchasima at 1,350 THB/t, at most 45 % moisture (undated trader post) | ~0.65 to 0.85 THB/kWh |
|
||||
| Firewood and rubberwood offcuts, air-dry | over 1 THB/kg at the farm gate, up from 0.55 to 0.70 before late 2025 | [OIE Rubber Intelligence Unit](https://rubber.oie.go.th/Article.aspx?id=66365), 2026; southern rubber belt, so chipping and haulage to Lamphun come on top | ~0.3 to 0.5 THB/kWh before chipping and haulage |
|
||||
| Corn cobs and stalk residue | 2 THB/kg, bought from farmers in Mae Chaem (Chiang Mai) | Sunsweet's "no burning, we buy" programme, [Prachachat](https://www.prachachat.net/economic/local-economy/news-1498508), February 2024; an incentive price set to stop field burning | ~0.6 THB/kWh |
|
||||
| Rice husk | ~1.5 THB/kg at past demand peaks | [FTI renewable energy group](https://re-fti.org/%E0%B9%84%E0%B8%9F%E0%B8%9F%E0%B9%89%E0%B8%B2%E0%B8%8A%E0%B8%B5%E0%B8%A7%E0%B8%A1%E0%B8%A7%E0%B8%A5%E0%B8%A3%E0%B8%B0%E0%B8%AA%E0%B9%88%E0%B8%B3%E0%B8%A3%E0%B8%B2%E0%B8%84%E0%B8%B2%E0%B9%81%E0%B8%81%E0%B8%A5%E0%B8%9A%E0%B8%9E%E0%B8%B8%E0%B9%88%E0%B8%87/) (undated); power plants compete for it and northern milling volumes are small | ~0.5 THB/kWh |
|
||||
| Wood pellets, domestic | 3,000 to 5,000 THB/t | LH Bank Research, March 2026; export FOB averaged 4,482 THB/t in 2025 | ~0.75 to 1.25 THB/kWh |
|
||||
|
||||
Heat cost assumes an 80 % boiler (85 % on pellets) and ~2.6 kWh/kg for
|
||||
fresh chips, ~4 for air-dry wood, ~4.2 for corn cobs, ~3.75 for rice husk
|
||||
and ~4.7 for pellets (estimates).
|
||||
|
||||
What it means for the plan:
|
||||
|
||||
- **Planning price: 1.35 to 2 THB/kg delivered**, which is ~0.5 to 0.9 THB
|
||||
per kWh of heat. The earlier assumption of 1 to 2 THB/kg of air-dry wood
|
||||
(~0.3 to 0.6 THB/kWh) was too low at the bottom: the cheap end is
|
||||
farm-gate wood, not chipped fuel at the plant gate. At maturity the fuel
|
||||
bill is **~0.6M to 1.2M THB a year** (~0.15M to 0.3M early), still a
|
||||
quarter to a tenth of electric steam (see
|
||||
[grid tariff](sustainability.md#grid-tariff-pea-and-what-it-decides))
|
||||
- **Prices are rising and follow diesel.** With diesel near 40 THB/L in
|
||||
2026, chip traders feeding power plants parked trucks and cut purchases
|
||||
([Thai Post](https://www.thaipost.net/district-news/971839/), 30 March
|
||||
2026), and rubberwood firewood roughly doubled since late 2025. Haulage
|
||||
is a large share of a delivered tonne, so source within ~50 km and write
|
||||
a diesel clause into the fuel contract rather than a fixed price
|
||||
- **Supply is not the constraint.** Lamphun alone produces more than
|
||||
900,000 t of farm residues a year (Maejo University, via
|
||||
[ThaiPublica](https://thaipublica.org/2026/08/lamphun-reduce-pm2-5-agricultural-waste-biomass-fuel/),
|
||||
August 2026) against the plant's ~600 t. Buying them also counts against
|
||||
the burning season, which is part of the story
|
||||
- **The local price-setter is in Mueang Lamphun.** Ratch Pathana's
|
||||
[biomass buying centre](https://www.ratchpathana.com/th/our-businesses/related-and-other-businesses/biomass-business)
|
||||
at Pa Sak, Mueang Lamphun, buys wood waste, sawdust and corn cobs from
|
||||
farmers for Saha Cogen Green's 9.6 MW, 25 t/h steam cogeneration plant
|
||||
in the Saha Group Lamphun industrial park. It is the reference price to
|
||||
ask for and the main competitor for the same fuel. Further out, Clover
|
||||
Power at Wang Chin (Phrae) buys chips, corn husks and cobs, and bamboo
|
||||
([DEDE buyer list](finance/biomass/DEDE_biomass_buyers_2026-02.pdf),
|
||||
February 2026)
|
||||
- **Next step:** written quotes from the Pa Sak centre and two or three
|
||||
chip suppliers within 50 km, priced by moisture content (an oven-dry
|
||||
tonne carries roughly twice the heat of a fresh one), before the boiler
|
||||
decision
|
||||
|
||||
## Logistics on site
|
||||
|
||||
To reflect in the facility planning: a fuel storage shed (biomass
|
||||
@@ -80,8 +166,18 @@ storage are additional.
|
||||
- The 60 rai tilts the economics and the story further toward biomass, but
|
||||
only after the land-title check clears
|
||||
- The electric boiler remains the alternative: cleanest permitting, no fuel
|
||||
logistics, but effectively grid-powered steam at a ~300 kW draw
|
||||
- A staged path is possible: start electric (fast, clean permitting), plant
|
||||
logistics, but effectively grid-powered steam at a ~520 to 625 kW draw
|
||||
for the five presses. On PEA's time-of-use tariff that costs ~5.2M to
|
||||
6.0M THB a year at mature load against ~0.6M to 1.2M of fuel for
|
||||
biomass, and ~1.6M to 1.8M (one 500 kg/h module) against ~0.15M to 0.3M at early load, because the demand charge follows
|
||||
the boiler's full-power draw (estimates; see the
|
||||
[grid tariff](sustainability.md#grid-tariff-pea-and-what-it-decides)).
|
||||
The electric boiler is the more efficient machine; biomass is the far
|
||||
cheaper heat
|
||||
- (Superseded 17 October 2026: biomass from the launch.) A staged path is possible: start electric (fast, clean permitting), plant
|
||||
the coppice now (first harvest in 2 to 4 years), and add the biomass
|
||||
boiler at the automated-line expansion when demand and the fuel supply
|
||||
have both matured
|
||||
have both matured. At the tariff above that is a permitting and logistics
|
||||
choice, not a cost one: every year on electric steam costs roughly 1.4M
|
||||
to 5.4M THB more than biomass, so the switch should come as soon as the
|
||||
permit and a fuel contract are in place
|
||||
@@ -15,13 +15,25 @@ no corporate income tax holiday on the core pressing activity, but the full
|
||||
non-tax package and machinery duty exemption. The tax value is engineered on
|
||||
top through the upgrade measures, where this project happens to be strong:
|
||||
|
||||
- **Solar and battery**: the alternative-energy measure (Announcement
|
||||
2/2568, April 2025, under the Smart and Sustainable Industry framework)
|
||||
grants CIT exemption based on the solar investment. Eligible spend
|
||||
explicitly includes PV modules, inverters, BESS and BESS inverters, and
|
||||
mounting structures, capped at THB 12M/30M/40M of investment value per MW
|
||||
depending on investment type. The planned Deye + Gobel installation
|
||||
converts directly into CIT-exemption headroom.
|
||||
- **Solar: no longer promoted; the battery may be.** The alternative-energy
|
||||
measure (Announcement 2/2568, April 2025, under the Smart and Sustainable
|
||||
Industry framework) granted a CIT exemption on the solar investment,
|
||||
capped at THB 12M/30M/40M per MW. **Announcement 3/2568** (5 June 2025,
|
||||
in force 1 July 2025) ended promotion for installing solar power
|
||||
generation under that measure for applications from 1 July 2025; what
|
||||
remains is machinery modified to use other renewable energy, and battery
|
||||
storage (BESS) with its inverters, the eligible investment capped at
|
||||
THB 12M per MW
|
||||
([B Global Law](https://bgloballaw.com/2026/01/18/boi-announcement-no-3-2568-amendment-to-renewable-energy-efficiency-enhancement-measures),
|
||||
[Smarter Energy Solution](https://smarterenergysolution.com/blog/boi-solar-thailand-2026),
|
||||
checked October 2026). So owning the ~520 kWp factory-roof array earns no BOI
|
||||
benefit; its case is the bill (see [sustainability](sustainability.md)).
|
||||
Whether the 271 kWh battery qualifies is for the BOI consultant. A PPA
|
||||
developer selling solar power (200 kW or more per distribution point)
|
||||
can still be promoted under activity 7.1.2 (8-year CIT exemption); that
|
||||
benefit is the developer's, and how much of it reaches the PPA price is
|
||||
a negotiation
|
||||
([CapSolar](https://capsolar.co.th/en/knowledge/boi-solar-incentives-2026)).
|
||||
- **Automation and metrology**: the Smart and Sustainable Industry upgrade
|
||||
measure (Announcement 15/2565, refreshed July 2025) rewards automation,
|
||||
smart machinery, and energy efficiency, typically 3 years of CIT
|
||||
@@ -33,15 +45,37 @@ top through the upgrade measures, where this project happens to be strong:
|
||||
galvanics process development, and recycled-PVC work could be framed as
|
||||
qualifying development.
|
||||
|
||||
So the application is pitched on solar, automation, and technology content,
|
||||
not on "we press plastic discs."
|
||||
So the application is pitched on automation and technology content (and
|
||||
the battery, if it qualifies), not on "we press plastic discs."
|
||||
|
||||
## What Group B still delivers (the core value)
|
||||
|
||||
- **Machinery import duty exemption**: significant with the entire equipment
|
||||
list imported (Germany, Sweden, USA, Japan)
|
||||
list imported (Germany, Sweden, USA, Japan). **Import VAT goes with it:**
|
||||
machinery or raw material imported with the duty exemption is exempt
|
||||
from VAT at import as well (Revenue Department answer on the
|
||||
[BOI OSOS FAQ](https://osos.boi.go.th/One-Stop/faq-group/205/FAQ-about-VAT--BOI),
|
||||
checked October 2026); otherwise a BOI company is treated like any other
|
||||
for VAT. What it is worth: the capex blocks in
|
||||
[total investment](finance/total-investment.md) are vendor prices
|
||||
without duty or VAT, so they already assume promotion. Without it, the
|
||||
~2.3M USD of imported machinery in the launch plant (presses, galvanics
|
||||
line, Sibert, cutting room, metrology; block midpoints, as
|
||||
[total investment](finance/total-investment.md#launch-plant-october-2026)
|
||||
states it) would carry import duty, roughly 5 % (Thailand's MFN averages
|
||||
4.1 % on HS 8477 plastics machinery, 0 to 10 % across HS 84; estimate
|
||||
until the HS codes are set), ~0.11M USD, and 7 % import VAT, ~0.17M USD
|
||||
paid at the border and only recovered later as input tax, mostly as a
|
||||
refund claim because exports are zero-rated. The
|
||||
[plant and business plan calculator](fleet-calculator.html) shows both
|
||||
cases; its BOI switch also counts the water treatment (ZLD/DI) as
|
||||
imported, ~2.5M USD at the midpoint (figures re-based October 2026; the
|
||||
earlier ~2.75M was the superseded start fleet).
|
||||
- **100% foreign ownership** of the promoted manufacturing company,
|
||||
overriding Foreign Business Act restrictions for the promoted activity
|
||||
overriding Foreign Business Act restrictions for the promoted activity.
|
||||
The intended split: the main investor holds at least 60 %, at most
|
||||
40 % goes to co-investors (user, October 2026;
|
||||
[total investment](finance/total-investment.md#two-plans-a-at-180m-thb-and-b-at-215m-thb-october-2026))
|
||||
- **Land ownership** for the promoted operation despite foreign
|
||||
shareholding, plus a small allowance for office/residential use; note the
|
||||
privilege is tied to the promotion, which matters for the buy-vs-lease
|
||||
@@ -57,8 +91,10 @@ not on "we press plastic discs."
|
||||
- Minimum investment THB 1,000,000 excluding land and working capital
|
||||
(comfortably cleared by the first pressing line alone)
|
||||
- Debt-to-equity ratio no higher than 3:1, maintained for the life of the
|
||||
privileges; plan the equity/loan mix for the machinery and solar capex
|
||||
accordingly
|
||||
privileges. Met with room to spare: the shareholders fund the whole
|
||||
plant as share capital and no bank loan is planned (user, October 2026;
|
||||
[total investment](finance/total-investment.md#two-plans-a-at-180m-thb-and-b-at-215m-thb-october-2026)),
|
||||
so any later loan keeps the same ceiling
|
||||
- Modern machinery and process expected; ISO/environmental compliance for
|
||||
larger projects
|
||||
- BOI promotion does not replace the factory license (Ror.Ngor. 4),
|
||||
@@ -104,11 +140,16 @@ project timeline, ahead of equipment contracts.
|
||||
|
||||
- Confirm the exact activity sub-code and tier for vinyl/PVC consumer-goods
|
||||
pressing (Group B assumption is well supported but not code-verified)
|
||||
- Confirm the live versions and per-MW caps of the solar and
|
||||
smart-and-sustainable measures at filing time
|
||||
- Confirm the live version of the smart-and-sustainable measures at
|
||||
filing time, and whether the battery qualifies under the BESS part of
|
||||
the alternative-energy measure (THB 12M per MW cap); solar itself is out
|
||||
since 1 July 2025 (Announcement 3/2568)
|
||||
- Confirm current NEC/Lamphun area add-ons
|
||||
- Engage a BOI-registered consultant to structure the application so the
|
||||
solar, automation, and R&D measures stack on the base promotion
|
||||
automation and R&D measures (and the battery) stack on the base promotion
|
||||
- Check whether R&D contracted with Payap University and the joint student
|
||||
programmes ([Payap partnership](payap-partnership.md)) count toward the
|
||||
R&D merit or a skills-development measure
|
||||
- Keep any future label/content/retail arm in a separate entity: media and
|
||||
service activities carry different (and sometimes Thai-ownership)
|
||||
conditions, and mixing them muddies a clean manufacturing application
|
||||
|
After Width: | Height: | Size: 45 KiB |
@@ -0,0 +1,46 @@
|
||||
"""Build the CNX Vinyl business plan .docx, in its two versions (October 2026).
|
||||
|
||||
python build_plan.py -> ../CNX-Vinyl-Business-Plan-A.docx and -B.docx
|
||||
python build_plan.py A -> ../CNX-Vinyl-Business-Plan-A.docx
|
||||
python build_plan.py B out.docx -> Plan B to a custom path
|
||||
|
||||
Plan A (~180M THB) and Plan B (~215M THB) share every chapter; the content modules
|
||||
switch the plan-specific text with plan_variant.pick(). Images are resolved relative
|
||||
to docs/ (the parent of business-plan/).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(HERE))
|
||||
|
||||
from plan_lib import Renderer # noqa: E402
|
||||
import plan_variant # noqa: E402
|
||||
import content_a, content_b, content_c # noqa: E402
|
||||
|
||||
DOCS = HERE.parent.parent # .../docs
|
||||
VERSION = "draft 0.3, October 2026"
|
||||
|
||||
|
||||
def out_path(plan: str) -> Path:
|
||||
return HERE.parent / f"CNX-Vinyl-Business-Plan-{plan}.docx"
|
||||
|
||||
|
||||
def main(plan: str = "A", out: Path | None = None) -> Path:
|
||||
plan_variant.PLAN = plan
|
||||
out = out or out_path(plan)
|
||||
r = Renderer(DOCS, header_text=f"CNX Vinyl / Poy Records: Business plan, {plan_variant.label()}, {VERSION}",
|
||||
footer_text="Confidential")
|
||||
r.render(content_a.blocks() + content_b.blocks() + content_c.blocks())
|
||||
r.save(out)
|
||||
return out
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = sys.argv[1:]
|
||||
plans = [args.pop(0).upper()] if args and args[0].upper() in ("A", "B") else ["A", "B"]
|
||||
target = Path(args[0]) if args else None
|
||||
for p in plans:
|
||||
print(main(p, target if len(plans) == 1 else None))
|
||||
@@ -0,0 +1,973 @@
|
||||
"""Part A: cover, reading guide, executive summary, opportunity, anatomy of the plant.
|
||||
|
||||
Builds Plan A (~180M THB) or Plan B (~215M THB): plan-specific text is switched with
|
||||
plan_variant.pick() inside blocks(), never at import time.
|
||||
"""
|
||||
from plan_lib import H1, H2, H3, P, B, N, T, KV, IMG, CALL, PB, TOC, COVER
|
||||
from plan_variant import pick, is_a, is_b, label, name
|
||||
|
||||
|
||||
def blocks():
|
||||
out = []
|
||||
LP = pick("Launch plant", "At launch") # 'When' column of the 4.0 checklist
|
||||
|
||||
# ------------------------------------------------------------ cover
|
||||
out.append(COVER(
|
||||
kicker="CNX VINYL / POY RECORDS",
|
||||
title="What It Takes to Build a Top-Notch Vinyl Plant",
|
||||
subtitle="Business plan for a full-service vinyl, cassette and CD manufacturing plant "
|
||||
"in the Chiang Mai region, Northern Thailand",
|
||||
image=pick("renders/calculator/plan-a-cover.png", "renders/calculator/plan-b-cover.png"),
|
||||
lines=[
|
||||
"**Prepared for:** the project's lead investor",
|
||||
"**Prepared by:** Simona Meesaiyati (Project Lead) and Alexander Grabowski (Technical Consultant), "
|
||||
"supported by buildfor.life, with Ploy Printing (Chiang Mai) as packaging partner and "
|
||||
"strategic co-investor",
|
||||
f"**Version:** Draft 0.3, October 2026: **{name()}, {pick('~180M THB', '~215M THB')}**",
|
||||
],
|
||||
note="Confidential. All figures in USD and THB at 1 USD = 33 THB (August 2026). Vendor quotes are "
|
||||
"snapshots at their file dates, not commitments. Every number in this plan is labelled as quoted, "
|
||||
"researched, or estimated; see section 2. " + pick(
|
||||
"This version is Plan A: the launch plant with the whole chain, cutting and galvanics "
|
||||
"included, three presses, with six cost levers taken: labelled ~180M THB, it comes to "
|
||||
"~182M at the midpoint, about 2M above 180M. A second version, Plan B (~215M THB), builds "
|
||||
"the same plant and takes none of the levers. ",
|
||||
"This version is Plan B: the launch plant with the whole chain, cutting and galvanics "
|
||||
"included, three presses, with everything in and none of the cost levers taken, at ~215M "
|
||||
"THB (~217M). A second version, Plan A (~180M THB), builds the same plant with six cost "
|
||||
"levers. ")
|
||||
+ "The plan price includes the ramp-up reserve and carries no contingency. Cover picture: the "
|
||||
"plant as the plant and business plan calculator draws this plan (schematic, Payap scenario "
|
||||
"layout, section 6.2). Draft 0.3 replaces "
|
||||
"draft 0.2 (October 2026), which described a single launch plant priced with a contingency.",
|
||||
))
|
||||
out.append(TOC())
|
||||
|
||||
# ------------------------------------------------ 1 executive summary
|
||||
out += [
|
||||
H1("1. Executive summary"),
|
||||
P("CNX Vinyl (label name Poy Records) is a planned record manufacturing plant for the Chiang Mai "
|
||||
"region of Northern Thailand. Its premise is simple: a label or artist in Asia-Pacific should be "
|
||||
"able to send an audio file to one place and receive finished, packaged, fully traceable records at "
|
||||
"their door, without shipping a fragile lacquer disc across the world and without waiting for metal "
|
||||
"stampers to come back from Europe. Today that customer presses in Europe, the United States or "
|
||||
"Japan. The one Thai pressing shop we have seen presses only: it buys its stampers abroad, runs "
|
||||
"without climate control, and cannot economically serve runs under 300 units."),
|
||||
P("This document explains, for a reader who is not a vinyl specialist, what a top-notch plant "
|
||||
"consists of, why each part matters, what it costs, what it can earn, how long it takes, and what "
|
||||
"could go wrong. It is built from the project's planning repository and vendor documents, and it "
|
||||
"keeps the honest parts: where a number is an estimate, it says so; where the evidence is thin, it "
|
||||
"says that too."),
|
||||
P("**What changed since the earlier drafts.** In October 2026 the plan moved from a phased entry (one "
|
||||
"press at launch, stampers bought in from the UK, cutting bought in from Europe) to a **launch plant** "
|
||||
"that has the whole chain from the first day, bought in one capital round and commissioned in "
|
||||
"sequence. There are no bridge stampers and no outsourced cutting in the plan any more. Draft 0.3 "
|
||||
"prices that plant in **two versions**, both including the ramp-up reserve and neither carrying a "
|
||||
"contingency: **Plan A (~180M THB)**, the launch plant's three presses with six cost levers, and "
|
||||
"**Plan B (~215M THB)**, the same three presses with everything in. " + pick(
|
||||
"**This document is Plan A**, and every section below is written for it; a short table after "
|
||||
"the numbers compares the two versions.",
|
||||
"**This document is Plan B**, and every section below is written for it; a short table after "
|
||||
"the numbers compares the two versions.")),
|
||||
H2("What we will build"),
|
||||
B([
|
||||
"**The complete vinyl chain under one roof:** mastering, lacquer cutting, galvanics (growing the "
|
||||
"nickel stampers), stamper preparation, pressing, finishing, packaging with our Chiang Mai print "
|
||||
"partner Ploy Printing, and fulfilment including direct-to-fan dropshipping.",
|
||||
"**Three presses at launch:** one Newbilt Duplex system (two semi-automatic presses with a main "
|
||||
"and a colour extruder, for colour, splatter and short runs) and one Newbilt Classic fully "
|
||||
"automatic press for long standard runs. Special prints are the focus (60 % and more of the "
|
||||
"records), and specials run only on the Duplex, so together they make about 0.58 to 0.90 "
|
||||
"million records a year on two shifts (0.71 to 0.97 million at a standard-heavy mix; "
|
||||
"estimates). A second Duplex system is a growth step from revenue, with its floor, utility "
|
||||
"positions and pipe connections reserved, not part of the investment.",
|
||||
"**The metal path in-house:** a Sillitoe SDMS cutting room, a Pheenix Alpha galvanics line with "
|
||||
"zero-discharge water treatment, and the Sibert stamper-prep line. The father and the mother of "
|
||||
"every side are archived, so represses start from our own metal.",
|
||||
"**A modular utility plant:** a boiler hall and a chiller compound built once for four modules "
|
||||
"each, with two 500 kg/h biomass boiler modules (B-1, B-2) and two 250 kW chiller modules "
|
||||
"(CH-1, CH-2) installed at launch; further presses add modules, not rooms. **Steam is biomass "
|
||||
"from launch in both versions of this plan**, fired with wood chips from a covered fuel "
|
||||
"store: ~0.67M THB of fuel a year against ~4.9M THB for electric steam (estimates). Electric "
|
||||
"boilers are the alternative, not the plan.",
|
||||
pick("**Cassette duplication and CD-R duplication as a growth step** after launch, not in the "
|
||||
"plan price; both fit inside the building programme. ",
|
||||
"**Cassette duplication and CD-R duplication in-house** from launch. ")
|
||||
+ "Full CD replication "
|
||||
"(injection-moulded discs) is a separate, much larger decision, outside the totals; both CD "
|
||||
"routes are set out in section 4.10 for the investor to decide.",
|
||||
"**A purpose-built ~1,500 m² plant on long-term leased land**, with a detached utility yard, "
|
||||
+ pick("solar on the factory roof (~520 kWp, estimate) through a solar power purchase "
|
||||
"agreement (PPA)",
|
||||
"owned solar on the factory roof (~520 kWp, estimate) with a battery")
|
||||
+ ", the office roof and the car and scooter canopies built PV-ready for later panels, and "
|
||||
"room for a second building.",
|
||||
"**Open source throughout:** every plant server runs NixOS, declared in one repository in the "
|
||||
"fleet B4L already operates, so any machine is rebuilt from it; ERPNext (no licence fee) is the "
|
||||
"only system of record; and our own code (the factory console, the plant overview, the artist "
|
||||
"platform, the calculator) is published as open source, licence to be chosen. The exception is "
|
||||
"the vendors' own firmware and control software in the machines, instruments and inverters, "
|
||||
"kept as appliances that export data into our systems and run none of our services. Once the "
|
||||
"plant has run this stack in production for at least a year, it and our factory-automation "
|
||||
"services can be offered to other pressing plants; that is not in the revenue (section 5.6).",
|
||||
"**Commissioned in sequence:** the cutting room and galvanics first (the presses need their "
|
||||
"stampers), then " + pick("the Duplex system, then the Classic",
|
||||
"the Duplex system, then the Classic, with cassette and CD-R "
|
||||
"duplication alongside")
|
||||
+ ". That puts galvanics, the hardest skill to "
|
||||
"hire, on the path to the first paying release. Sibert, the stamper-prep supplier in the plan, "
|
||||
"advised after the Haarlem trade show to get presses, boilers, operators and feedback loops "
|
||||
"right first; " + pick("the launch plant", "the whole chain at launch")
|
||||
+ " was decided anyway, and that advice is carried as a risk (sections 11.2 and 13).",
|
||||
pick(
|
||||
"**Six cost levers bring the plant to ~182M THB: labelled ~180M, it is about 2M above 180M "
|
||||
"at the midpoint** (177M with the low end of the ramp-up reserve), from ~201.6M to ~167.1M "
|
||||
"THB at the midpoint before the reserve (estimates, section 8): solar on the factory roof "
|
||||
"(~520 kWp) and the battery through a solar PPA (the installer owns and finances the array, "
|
||||
"the plant buys the power); metrology in two steps (XRF, inline vision and the audio "
|
||||
"station at launch, the laser confocal and the "
|
||||
"wide-area profiler bought from revenue); the visitor corridor built later, so no public tours "
|
||||
"at first; cassette and CD-R duplication later; a mobile crane rented for the installations, "
|
||||
"with frame, runway and machine door kept crane-ready; the compressor through the Chinese "
|
||||
"route. Every press, the cutting room, the galvanics line, the stamper-prep line and the "
|
||||
"biomass boilers stay in. The Chinese route priced only electric boilers; a Chinese biomass "
|
||||
"boiler is not yet quoted, and one ~2M THB or more below the Thai package would bring the "
|
||||
"midpoint back to 180M.",
|
||||
"**Everything in, none of the cost levers: ~215M THB** (~217M at the midpoint with the "
|
||||
"ramp-up reserve, ~201.6M THB before it) and ~35M THB more than Plan A (estimates, section "
|
||||
"8): owned solar on the factory roof (~520 kWp) and the battery, so no PPA power bill (~1.9M "
|
||||
"THB a year in Plan A, estimate); the full metrology stack from launch (XRF, "
|
||||
"laser confocal, wide-area profiler, inline vision, audio station); the visitor corridor and "
|
||||
"accessible entrance, so public tours and the Payap student programmes are possible from the "
|
||||
"start; cassette and CD-R duplication; a bought 5 t overhead crane; the compressor from a "
|
||||
"Thai supplier, with local service. Every press, the cutting room, the galvanics line, the "
|
||||
"stamper-prep line and the biomass boilers are the same as in Plan A."),
|
||||
]),
|
||||
H2("What makes it top-notch"),
|
||||
P("Four things separate this plant from a pressing shop, and they are the reason it can charge "
|
||||
"export-grade prices in a region that currently has none:"),
|
||||
N([
|
||||
"**Traceability from audio file to shipment.** Every lacquer, father, mother, stamper, press "
|
||||
"cycle, compound lot and carton lot gets an identity that knows its parents; a pressed record is "
|
||||
"identified by its stamper, press, cycle time and side. The plant runs **ERPNext as its only "
|
||||
"system of record** (orders, invoices, stock, job cards, batches, inspections, metal-part "
|
||||
"genealogy); machine data (press cycles, instrument files, audio captures) sits beside it, keyed "
|
||||
"to the same ERPNext names. A customer sees their order's full chain; a complaint resolves to one "
|
||||
"stamper, one press, one shift and one material lot. The **father and the mother of every side "
|
||||
"are archived**: a mother gives about ten stamper sets and a father five to ten mothers "
|
||||
"(industry rules of thumb), so a repress starts from the archived mother and a worn mother is "
|
||||
"regrown from the father without a new cut. At Making Vinyl Europe in Haarlem this was what the "
|
||||
"industry responded to most.",
|
||||
"**Metrology and layered quality control.** The nickel parts are measured without contact "
|
||||
+ pick("and logged per serial, which is ahead of current industry practice: XRF thickness from "
|
||||
"launch, the laser confocal and the wide-area profiler bought from revenue. ",
|
||||
"(laser confocal, wide-area profiler, XRF thickness) and logged per serial, which is ahead "
|
||||
"of current industry practice. ")
|
||||
+ "Every pressed record passes 100% inline optical inspection, every "
|
||||
"press cycle is logged, and sampled records are compared automatically against the source "
|
||||
"master.",
|
||||
"**Efficiency designed in.** Heat is recovered before energy is generated: in order, a flue-gas "
|
||||
"economiser on the biomass boilers, as much condensate back to the feed tank as possible, then "
|
||||
"a heat pump that lifts the presses' ~60 °C cooling return into boiler feedwater. Solar goes on "
|
||||
"the factory roof: **~520 kWp** on the Payap scenario layout, about 730 to 780 MWh a year, of "
|
||||
"which ~87 % is used on site (~633 MWh, ~61 % of the launch plant's ~1,036 MWh a year of "
|
||||
"electricity); the rest is curtailed, because a factory on PEA's grid runs zero export and is "
|
||||
"not paid for surplus. With biomass steam the running load is ~230 kW, and an hourly sketch "
|
||||
"puts the best array for it at ~500 to 550 kWp, so the factory roof sits at that optimum "
|
||||
"(estimates). The office roof (~65 kWp) and the car and scooter canopies (~54 kWp) are built "
|
||||
"PV-ready (structure rated for panels, conduit to the main board) and take panels when the "
|
||||
"load rises with the second Duplex system: ~120 kWp for ~2.4M to 3.1M THB (estimate). On the "
|
||||
"Mueang Chi hall the factory roof takes ~247 kWp and its canopies are PV-ready too. A 271 kWh "
|
||||
"battery gives ride-through"
|
||||
+ pick(
|
||||
"; array and battery come through the solar PPA: the installer owns and finances them, the "
|
||||
"plant buys the power. ",
|
||||
"; array and battery are owned by the plant. ")
|
||||
+ "Cooling runs as a closed loop, no process water is discharged, "
|
||||
"galvanics rinse water goes through a zero-discharge evaporator, and 20% of the feedstock is "
|
||||
"in-house regrind. Boilers and chillers come in identical modules, so spares and service are one "
|
||||
"routine. At reported northern fuel prices biomass heat costs a quarter to a tenth of electric "
|
||||
"steam, which is why steam is biomass from launch: it saves ~4.2M THB (~USD 0.13M) a year "
|
||||
"against electric boilers and keeps the grid demand at ~264 kW instead of ~980 kW (estimates).",
|
||||
"**Climate control as product quality.** The whole plant runs at 20 to 26 °C, 35 to 60% "
|
||||
"relative humidity, with particulate filtration sized for Northern Thailand's burning season. "
|
||||
"Moisture and dust are the two classic causes of noisy records; the plant we visited has "
|
||||
"neither control.",
|
||||
]),
|
||||
H2("The numbers"),
|
||||
KV([
|
||||
["Capacity", pick(
|
||||
"~0.58M to 0.90M records/yr at 60 % specials (2 semi-automatic presses + 1 Classic, 2 shifts; "
|
||||
"the Duplex sets the pace; estimate; the press fleet calculator gives ~0.94M at our planning "
|
||||
"rates). Second Duplex as a growth step from revenue: ~1.0M to 1.5M",
|
||||
"~0.58M to 0.90M records/yr at 60 % specials, central 0.74M (2 semi-automatic presses + 1 "
|
||||
"Classic, 2 shifts; the Duplex sets the pace; estimate; the press fleet calculator gives ~0.94M "
|
||||
"at our planning rates). Second Duplex as a growth step from revenue (section 4.4); full hall "
|
||||
"as a later option: ~2.9M to 4.4M")],
|
||||
["Site", "~1,500 m² main building plus a ~379 m² utility yard built for four boiler and four "
|
||||
"chiller modules and a covered biomass fuel store, on leased land (~4 rai minimum, "
|
||||
"6 to 8 rai with expansion); second "
|
||||
"building as expansion"],
|
||||
[pick("Investment, Plan A", "Investment, Plan B"), pick(
|
||||
"**~THB 182M (~USD 5.52M), labelled ~180M THB**: the plan investment, ~THB 167.1M (~USD "
|
||||
"5.06M) at the midpoint with the six levers taken, plus a ramp-up reserve of ~THB 10M to 20M "
|
||||
"(staff and overheads before volume covers them). **At the midpoint that is about 2M above "
|
||||
"180M**; with the low end of the reserve (~177M) it fits. From the low to the high end of "
|
||||
"every block: ~THB 132M to 233M. Estimates: no quote yet for the Classic, the galvanics line "
|
||||
"(priced at OMS's reference plus 20 %) or the building",
|
||||
"**~THB 217M (~USD 6.56M), labelled ~215M THB**: the plan investment, ~THB 201.6M (~USD "
|
||||
"6.11M) at the midpoint with everything in, plus a ramp-up reserve of ~THB 10M to 20M (staff "
|
||||
"and overheads before volume covers them); at the midpoint ~0.6M above the investor's 180M "
|
||||
"THB plus 20 % (216M), inside 225M. From the low to the high end of every block: ~THB 156M "
|
||||
"to 277M. "
|
||||
"Estimates: no "
|
||||
"quote yet for the Classic, the galvanics line (priced at OMS's reference plus 20 %) or the "
|
||||
"building")],
|
||||
["Not in the plan price", "**No contingency** (at the 15 % used in the cost documents, ~THB "
|
||||
+ pick("25M", "30M") + " at the midpoint): quotes that land high are "
|
||||
"funded outside the plan or by scope steps (section 8). Also not in "
|
||||
"it: the central hydraulic plant (not yet costed), the archive's mobile "
|
||||
"shelving (to quote), CD replication, financing costs, currency moves, "
|
||||
"and Thai duty and import VAT (the blocks assume BOI promotion)"],
|
||||
["Land lease", "Not negotiated; the plan carries an estimated THB 0.3M to 1.0M per year "
|
||||
"(USD 9k to 30k), section 6.1"],
|
||||
["Operating result, mature year", pick(
|
||||
"Central case at 60 % specials: revenue ~USD 3.65M (~THB 120M), EBITDA ~USD 1.73M (~THB "
|
||||
"57M), operating profit ~USD 1.33M (~THB 44M); break-even on operating profit at ~0.2M "
|
||||
"records a year. **The adverse case loses money:** EBITDA ~USD 0.23M, operating loss ~USD "
|
||||
"0.41M (~THB 14M); it would need ~1.0M records a year to cover depreciation and the three "
|
||||
"presses make 0.58M at that rate. The solar PPA's power price (~USD 0.06M a year in the "
|
||||
"calculator) is not in these figures. Utilisation and price decide the outcome, not upside "
|
||||
"(section 9)",
|
||||
"Central case at 60 % specials: revenue ~USD 3.65M (~THB 120M), EBITDA ~USD 1.73M (~THB "
|
||||
"57M), operating profit ~USD 1.24M (~THB 41M); break-even on operating profit at ~0.24M "
|
||||
"records a year. **The adverse case loses money:** EBITDA ~USD 0.23M, operating loss ~USD "
|
||||
"0.55M (~THB 18M); it would need ~1.1M records a year to cover depreciation and the three "
|
||||
"presses make 0.58M at that rate. Cassette, CD-R and tour revenue are not in these figures. "
|
||||
"Utilisation and price decide the outcome, not upside (section 9)")],
|
||||
["Payback", pick(
|
||||
"~3.2 years on the plan price in the central case (2.3 to 4.1 from the low to the high end of "
|
||||
"the price); ~1.1 years in the favourable case, ~31 years in the adverse case (EBITDA, mature "
|
||||
"year, ramp-up reserve included; estimates)",
|
||||
"~3.8 years on the plan price in the central case (2.7 to 4.9 from the low to the high end of "
|
||||
"the price); ~1.2 years in the favourable case, ~37 years in the adverse case (EBITDA, mature "
|
||||
"year, ramp-up reserve included; estimates)")],
|
||||
["First paying release", "**Open.** The August 2026 calendar gives Q4 2028 to mid-2029 (27 to 33 "
|
||||
"months from the start of phase 0), but it was drawn for a one-press "
|
||||
"launch. Commissioning the cutting room and galvanics before the presses "
|
||||
"is not yet in it, and the lathe, galvanics line and stamper-prep build "
|
||||
"times are not on file, so the date stays open until those vendors "
|
||||
"quote. Ordering machinery before the BOI certificate, if allowed, could "
|
||||
"still pull it forward by 6 to 9 months (section 10)"],
|
||||
["People", "~15 to 25 across shifts at volume (estimate); the launch plant needs most of that "
|
||||
"crew, because two shifts still need press, finishing, galvanics, QC and maintenance "
|
||||
"staff (13 to 19 direct production staff in the revenue model)"],
|
||||
["The ask", pick(
|
||||
"~THB 182M (~USD 5.52M), the plan labelled ~180M THB (about 2M above 180M at the midpoint), "
|
||||
"released in tranches against milestones (section 8), starting with phase 0 (~THB 1.3M to "
|
||||
"2.6M). Funded entirely by the shareholders as share capital, no bank loan planned: the "
|
||||
"lead investor's 60 % is at least ~THB 109M, the 40 % open to co-investors at most ~THB 73M "
|
||||
"(arithmetic at one share price)",
|
||||
"~THB 217M (~USD 6.56M), the ~215M THB plan, released in tranches against milestones "
|
||||
"(section 8), starting with phase 0 (~THB 1.3M to 2.6M). Funded entirely by the shareholders as "
|
||||
"share capital, no bank loan planned: the lead investor's 60 % is at least ~THB 130M, the 40 % "
|
||||
"open to co-investors at most ~THB 87M (arithmetic at one share price)")],
|
||||
]),
|
||||
H2("Two versions of this plan"),
|
||||
P("This plan comes in two versions, built from the same documents and the same machine choices. " + pick(
|
||||
"This document is **Plan A**. The other version, **Plan B (~215M THB)**, builds the same three "
|
||||
"presses and takes none of the six levers. ",
|
||||
"This document is **Plan B**. The other version, **Plan A (~180M THB)**, builds the same three "
|
||||
"presses (one Duplex system and the Classic) and takes six cost levers. ")
|
||||
+ "Both carry the ramp-up reserve and neither carries a contingency, and in both the second Duplex "
|
||||
"system is a growth step from revenue. What decides between them is no longer demand, because both "
|
||||
"make the same records: it is whether the investor funds ~THB 35M (~19 %) more at launch for what "
|
||||
"Plan A leases or buys from revenue. Plan B owns its solar array (no PPA power bill), measures "
|
||||
"every stamper fully from the first release, makes tours and the Payap "
|
||||
"programmes possible from the start, sells cassette and CD-R from launch, owns its crane and buys "
|
||||
"its compressor with local service; both run on biomass steam. On the modelled numbers that extra "
|
||||
"earns little (the same EBITDA in the revenue model, ~USD 0.06M a year more in the calculator for "
|
||||
"the PPA power bill the "
|
||||
"owned array avoids; more depreciation, a longer payback, a deeper adverse case), so Plan A has "
|
||||
"the better modelled return and Plan B the more complete plant. Most of Plan B's items can be added to Plan A "
|
||||
"later from revenue; the corridor is cheaper to build in from the start, and owning the array "
|
||||
"saves the PPA bill from the first year. BOI no longer promotes solar installations (since 1 July "
|
||||
"2025, section 7.1), so neither plan earns a tax benefit on the array. "
|
||||
"Section 8 sets the two side by side."),
|
||||
T(["", "Plan A", "Plan B"], [
|
||||
["Plan price (ramp-up reserve in, no contingency)", "~THB 182M (~USD 5.52M), ~2M above 180M at "
|
||||
"the midpoint; ~132M to 233M from the low to the high end", "~THB 217M (~USD 6.56M); ~156M to "
|
||||
"277M from the low to the high end"],
|
||||
["Presses", "3: one Duplex system (2 semi-automatic) and one Classic", "The same 3"],
|
||||
["Records a year at 60 % specials", "~0.58M to 0.90M (central 0.74M)", "The same"],
|
||||
["Steam", "Biomass from launch: two 500 kg/h modules and a covered fuel store", "The same"],
|
||||
["EBITDA, central case", "~USD 1.73M (~THB 57M)", "~USD 1.73M (~THB 57M); cassette and CD-R "
|
||||
"not modelled"],
|
||||
["Operating profit, central case", "~USD 1.33M (~THB 44M)", "~USD 1.24M (~THB 41M)"],
|
||||
["Payback on the plan price, central case", "~3.2 years (2.3 to 4.1)", "~3.8 years (2.7 to 4.9)"],
|
||||
["Adverse case", "Loses money: EBITDA ~USD 0.23M, operating loss ~USD 0.41M",
|
||||
"Loses money: EBITDA ~USD 0.23M, operating loss ~USD 0.55M"],
|
||||
["What Plan A gives up, what Plan B buys", "At launch: solar through a PPA (a power bill of "
|
||||
"~USD 0.06M a year instead of owning the array), no confocal or profiler, no visitor corridor "
|
||||
"or tours, no cassette or CD-R, a rented crane; a Chinese-made compressor",
|
||||
"~THB 35M more at launch: owned solar (~520 kWp on the factory roof) and battery, "
|
||||
"so no PPA bill, the full "
|
||||
"metrology stack, the visitor corridor and tours, cassette and CD-R, a bought crane; "
|
||||
"a Thai-supplied compressor"],
|
||||
], widths_mm=[42, 64, 64], font_pt=8.5,
|
||||
caption="Estimates: mature year at 60 % specials, from the revenue model; payback counted on the "
|
||||
"whole plan price including the reserve. A central EBITDA margin of ~47 % (both plans) is "
|
||||
"far above the 15 to 25 % pressing plants earn; read the adverse case as the honest one. "
|
||||
"The revenue model does not split energy cost by plan or fuel, so the PPA bill and the "
|
||||
"biomass saving show only in the calculator."),
|
||||
H2("Where we are, and what we ask"),
|
||||
P("The project is at the planning stage. Industry outreach has run for several years. Alexander and "
|
||||
"Simona attended **Making Vinyl Europe in Haarlem** (30 September to 2 October 2026): most people "
|
||||
"they talked to were strongly interested in the full-traceability approach, and for Sibert it was "
|
||||
"the reason to engage at all. Since the show Sibert has confirmed a **USD 250k budget** for its "
|
||||
"three stamper-prep machines; Pheenix Alpha's CEO has offered a call, reference clients and a "
|
||||
"factory visit (the next Europe trip is planned for February 2027); OMS has sent reference prices "
|
||||
"for a galvanics wet room; and SST in Frankfurt, which already cuts Poy Records' lacquers, has "
|
||||
"offered help. This is supplier-side evidence, not buyer price validation."),
|
||||
P("Vendor quotes exist for the pressing line (2024, expired), utilities have been costed with Thai "
|
||||
"suppliers, and a parametric building model has produced quantities for a construction price "
|
||||
"request. **Site:** a leased parcel in Mueang Chi, Lamphun, is the working candidate the design is "
|
||||
"tested against; Payap University in Chiang Mai has offered land on lease and joint student "
|
||||
"programmes, but the point it gave fails zoning (zoned very high density residential, where "
|
||||
"record pressing is not permitted; checked October 2026), and its other plots are not yet "
|
||||
"checked. Nothing has been re-sited and **nothing has been ordered**."),
|
||||
P("Three gates run now and in parallel: **market validation** (buyer prices from regional labels; "
|
||||
"none yet); the **BOI investment promotion** track with a registered consultant; and **land**: "
|
||||
"zoning, lease terms and a soil test. Nothing large is spent until its gate clears."),
|
||||
CALL("What the investor is asked to fund now", [
|
||||
"**Phase 0 (next 3 to 6 months): ~USD 40k to 80k (~THB 1.3M to 2.6M)** for the BOI consultant, "
|
||||
"Thai legal work on the lease and zoning, a soil boring test, and the requests that settle most "
|
||||
"of the investment band: " + pick(
|
||||
"the Newbilt re-quote for the Duplex system (with an EX 35 price) and the Classic, a Pheenix "
|
||||
"quote for the galvanics line, the building price request with the soil test, metrology "
|
||||
"distributor quotes, a solar PPA offer and a Chinese biomass-boiler quote (one ~2M THB or "
|
||||
"more below the Thai package brings Plan A's midpoint back to 180M).",
|
||||
"the Newbilt re-quote for the Duplex system (with an EX 35 price) and the Classic, a Pheenix "
|
||||
"quote for the galvanics line, the building price request with the soil test, and metrology "
|
||||
"distributor quotes."),
|
||||
pick(
|
||||
"**Then the Plan A round, ~THB 182M (~USD 5.52M), labelled ~180M THB**, about 2M above 180M "
|
||||
"at the midpoint, including the "
|
||||
"ramp-up reserve and without contingency, released in tranches against milestones: BOI "
|
||||
"certificate and lease signed, long-lead orders (lathe, galvanics, stamper prep, presses, "
|
||||
"boiler and chiller modules), building contract, fit-out, commissioning in sequence "
|
||||
"(section 8). From the low to the high end of every block the plan runs from ~THB 132M to "
|
||||
"233M; quotes that land high are funded outside the plan or by scope steps.",
|
||||
"**Then the Plan B round, ~THB 217M (~USD 6.56M), labelled ~215M THB**, including the "
|
||||
"ramp-up reserve and without contingency, at the midpoint ~0.6M above the investor's 180M "
|
||||
"THB plus 20 % (216M) and inside 225M, released in tranches against milestones: BOI "
|
||||
"certificate and lease signed, "
|
||||
"long-lead orders (lathe, galvanics, stamper prep, presses, boiler and chiller modules), "
|
||||
"building contract, fit-out, commissioning in sequence (section 8). From the low to the high "
|
||||
"end of every block the plan runs from ~THB 156M to 277M; quotes that land high are funded "
|
||||
"outside the plan or by scope steps."),
|
||||
"**Decisions needed from the investor:** which version to fund, Plan A or Plan B (both make the "
|
||||
"same records, so the choice is ~THB 35M more at launch for what Plan A leases or defers; the "
|
||||
"Classic, Pheenix and EX 35 quotes, the solar PPA offer and the building quote settle the "
|
||||
"numbers); the share capital's call schedule against the tranches (the shareholders fund the whole "
|
||||
"plant, no bank loan planned, so BOI's 3:1 debt-to-equity ceiling is met with no debt); and CD "
|
||||
"replication, yes or no (it must be in the BOI application from the start). The steam fuel is "
|
||||
"no longer open: both versions run on biomass steam from launch.",
|
||||
"**Co-investment:** Ploy Printing, the Chiang Mai print and packaging house that will produce "
|
||||
"the plant's jackets and sleeves, has expressed the intention to invest alongside the lead "
|
||||
"investor. The lead investor holds at least 60 % of the company, so at most 40 % is open to "
|
||||
"Ploy Printing, the founders and any further co-investor. Terms are not yet discussed; the "
|
||||
"intended structure is described in section 12.2.",
|
||||
]),
|
||||
|
||||
# ----------------------------------------------- 2 reading guide
|
||||
H1("2. How to read the numbers"),
|
||||
P("**Two versions.** This business plan comes in two versions, built from the same documents: "
|
||||
"**Plan A (~180M THB)**, the launch plant's three presses with six cost levers, and **Plan B "
|
||||
"(~215M THB)**, the same three presses with everything in. Both plan prices include the ramp-up "
|
||||
"reserve and neither carries a contingency. This document is **" + label() + "**. Chapters that "
|
||||
"do not depend on the choice read the same in both; where the plans differ, this version gives "
|
||||
"its own figures, and sections 1 and 8 compare the two."),
|
||||
P("Every figure in this plan carries one of three confidence levels. Where a table does not say, "
|
||||
"the basis column or caption does."),
|
||||
T(["Label", "Meaning", "Examples"], [
|
||||
["Quoted", "A vendor document exists, in its original currency: a quote, a budget confirmation "
|
||||
"or a published list price. Quotes may have expired and need re-confirmation.",
|
||||
"Newbilt pressing line (EUR 200,500, June 2024, expired); Sibert's USD 250k budget confirmation "
|
||||
"for the stamper-prep line (October 2026); Sillitoe SDMS list price USD 125k (ex tax and "
|
||||
"shipping); OMS reference prices for a galvanics wet room; Newbilt service rates"],
|
||||
["Researched", "Published or market data gathered by the team, including one set of real Thai "
|
||||
"invoices.", "Record Industry's online price calculator (October 2026); Thai "
|
||||
"pressing invoices (August 2026); the PEA electricity tariff; vendor "
|
||||
"flyers and datasheets; reported biomass fuel prices; BOI measures"],
|
||||
["Estimate", "Engineering ratio or industry norm with no vendor confirmation. Treat as "
|
||||
"plus or minus 30 to 50%.", "Building cost per m²; the Pheenix galvanics line (no "
|
||||
"Pheenix price on file; priced at OMS's reference plus "
|
||||
"20 %) and the Newbilt Classic (no price on file); the "
|
||||
"cutting room beyond the lathe; metrology stack; land "
|
||||
"lease; the solar yield and the share used on "
|
||||
"site; " + pick("the solar PPA power price; ", "")
|
||||
+ "all cassette and CD figures"],
|
||||
], widths_mm=[22, 70, 78]),
|
||||
P("Currency: USD and THB at 1 USD = 33 THB (5 August 2026). Vendor quotes issued in EUR or GBP are "
|
||||
"kept in their currency next to their source and converted at 1 EUR = 1.155 USD and "
|
||||
"1 GBP = 1.35 USD. Currency exposure is real and is discussed in section 8.5."),
|
||||
P("Deliberately **not** in this plan: a contingency in the plan price (section 8); bank debt (the "
|
||||
"shareholders fund the whole plant as share capital; the share price and call schedule are to be "
|
||||
"agreed, section 12.2); "
|
||||
"a signed customer; a signed lease; firm quotes for the Classic, the galvanics line, the metrology "
|
||||
"stack or the building; a price for the central hydraulic plant; and a year-by-year cash model. "
|
||||
"Each of these is a named next step in section 14. The revenue also leaves out two upsides that "
|
||||
"have no price or volume yet: supplying stampers to other plants (section 3.3), and services to "
|
||||
"other pressing plants built on the plant's open-source software and factory automation "
|
||||
"(section 5.6)."),
|
||||
|
||||
# ------------------------------------------------- 3 opportunity
|
||||
H1("3. The opportunity"),
|
||||
H2("3.1 The product"),
|
||||
P("A vinyl record is made by cutting the audio into a soft lacquer disc, growing a set of nickel "
|
||||
"metal parts from that lacquer by electroplating (the 'stampers'), and pressing hot PVC between two "
|
||||
"stampers under about 150 tonnes of force with steam heating and water cooling. The record is then "
|
||||
"trimmed, sleeved, put into a printed jacket, shrink-wrapped and shipped. Each of these "
|
||||
"steps has its own equipment, skills and failure modes, and most plants in the world do only some "
|
||||
"of them, sending the rest out to specialists, often on other continents."),
|
||||
P("Demand for vinyl has grown for well over a decade from a small base. The 2021 to 2022 boom "
|
||||
"pushed lead times at European and US plants to six to nine months; they have since normalised to "
|
||||
"roughly 10 to 16 weeks for a standard black LP, and global capacity has been added. Demand is "
|
||||
"cyclical and this plan does not assume it only rises; it assumes the plant can sell what it "
|
||||
"presses, which is the single assumption most worth testing (section 3.3)."),
|
||||
H2("3.2 Where regional labels press today"),
|
||||
P("Labels and artists in Southeast Asia, Australia and much of East Asia ship their masters to "
|
||||
"Europe, the United States or Japan, wait in those plants' queues, and pay freight and time zones "
|
||||
"on top. We know of no industrial-grade, climate-controlled, full-service plant in the region. That "
|
||||
"is the gap. It is also the plan's biggest assumption: that enough regional customers will pay for "
|
||||
"a closer, faster, more accountable plant at a price that works. That pricing power is unproven. "
|
||||
"The Haarlem trade show produced strong supplier interest but no buyer prices, and the market "
|
||||
"validation gate exists to test it before capital is committed."),
|
||||
H2("3.3 What the market shows: two price points"),
|
||||
P("Two sets of real prices now exist: invoices from the one Thai pressing shop we have seen, and the "
|
||||
"published calculator of a European plant. Neither is used to re-base the financial model, which "
|
||||
"keeps its assumed price until buyers have been asked. Together they bracket that assumption."),
|
||||
H3("The Thai market: one buyer, one plant"),
|
||||
P("In August 2026 the team compared real invoices from ResurRec in Bangkok (with whom a "
|
||||
"collaboration is also under discussion), and toured its plant. This is one buyer, one plant, one "
|
||||
"afternoon, but it is the only domestic market evidence so far."),
|
||||
T(["Item", "THB", "USD", "Note"], [
|
||||
["Audio mastering", "5,000 to 20,000 per song", "150 to 605", "Market range from several engineers"],
|
||||
["Stamper set (father, mother, silvering)", "up to 22,000 per title", "up to 665",
|
||||
"Residual between a full-service and a pressing-only invoice; an upper bound that also carries "
|
||||
"cutting, test pressings and margin"],
|
||||
["All-in per 12-inch record at 300 units", "650 to 950", "19.70 to 28.80",
|
||||
"Includes a printed jacket; discounts of 5% at 500, 15% at 1,000 to 3,000, 30% above 3,000, "
|
||||
"with 2 to 4 weeks added lead time above 3,000"],
|
||||
["Minimum run", "150 units, 'rarely accepted'", "", "Sub-300 runs are effectively unavailable "
|
||||
"in Thailand"],
|
||||
], widths_mm=[42, 36, 24, 68],
|
||||
caption="Researched: buy-side invoices and published discount ladder, August 2026."),
|
||||
P("What the tour showed: the shop operates from a small non-industrial premises; it does not plate "
|
||||
"(stampers are bought in from abroad and resold); there is no temperature, humidity or particulate "
|
||||
"control on the pressing floor; and it runs two Newbilt presses, a Classic fully automatic and one "
|
||||
"semi-automatic, about 190 to 210 records an hour at nameplate. That is a real capital fleet. "
|
||||
"Our launch plant's three presses (248 to 288 records an hour at nameplate, planned for two "
|
||||
"shifts) out-press it on paper, which the one-press launch of draft 0.1 did not. Neither figure is "
|
||||
"measured output: their shifts and order book were not observed."),
|
||||
H3("A European plant: Record Industry's calculator"),
|
||||
P("Record Industry (Haarlem, Netherlands) publishes an online calculator. For a 12-inch 140 g black "
|
||||
"LP cut from a digital master, with stampers, five test pressings, printed labels, a white paper "
|
||||
"inner sleeve, a printed 3 mm jacket and shrink wrap, ex Dutch VAT and ex freight (checked "
|
||||
"October 2026):"),
|
||||
T(["Copies", "Order total", "Per copy", "Per copy, USD", "Per copy, THB"], [
|
||||
["200", "EUR 1,494.68", "EUR 7.47", "8.63", "~285"],
|
||||
["300", "EUR 1,721.22", "EUR 5.74", "6.63", "~219"],
|
||||
["500", "EUR 2,098.12", "EUR 4.20", "4.85", "~160"],
|
||||
["1,000", "EUR 3,169.78", "EUR 3.17", "3.66", "~121"],
|
||||
], widths_mm=[22, 38, 30, 40, 40],
|
||||
caption="Researched: Record Industry online calculator, October 2026; converted at 1 EUR = 1.155 USD "
|
||||
"and 1 USD = 33 THB."),
|
||||
P("Its per-title items (set-up, small-run charge, cutting, stampers, test pressings) come to about "
|
||||
"EUR 580 to 600 (~THB 22,000 to 23,000), at the low end of our per-title assumption. Black "
|
||||
"pressing with labels and a paper inner sleeve comes to about USD 2.43 a copy at 300 (2.09 at "
|
||||
"1,000). The Thai price at 300 copies is about 3 to 4.3 times this plant's ex-works price, before "
|
||||
"the freight, Thai import duty and VAT a Thai buyer pays on an import. Our own artist ordering "
|
||||
"demo's price list comes to about 343 THB a copy at 300 with vinyl mastering: above the European "
|
||||
"ex-works price and well below the Thai market. These price levels stay open until buyers have "
|
||||
"been asked (roadmap item 1)."),
|
||||
P("Four readings follow, each with its caveat:"),
|
||||
B([
|
||||
"**Our assumed price sits between the two markets.** The plan prices a record at USD 3.76 to 5.27 "
|
||||
"blended at 60 % specials (124 to 174 THB; 3.50 to 4.60 at a standard-heavy mix). The Thai market pays 535 to 780 THB on a comparable scope, several "
|
||||
"times more, even after allowing 100 to 150 THB for the jacket. A European plant's published "
|
||||
"price for black pressing with labels and an inner sleeve (~USD 2.43 at 300) is below our "
|
||||
"assumption, though our blend also carries colour work and assembly. Two caveats: a sole "
|
||||
"domestic supplier can hold an import-parity price that a second entrant compresses, and against "
|
||||
"Europe our assumption is not conservative. We keep it until buyer prices exist.",
|
||||
"**The floor of the market is unserved.** Runs under 300 are uneconomic for a shop whose "
|
||||
"per-title cost is an imported stamper plus outsourced mastering. In-house cutting and plating "
|
||||
"collapse that fixed cost, which makes short runs viable for CNX in a way they structurally are "
|
||||
"not for the incumbent. The artist platform (section 4.8) is the channel for them.",
|
||||
"**Lead time degrades with run size, probably because of metalwork.** Three thousand units is "
|
||||
"about two days of pressing on their fleet, yet they add two to four weeks. A stamper lasts "
|
||||
"1,000 to 2,000 pressings, so a 3,000-unit run needs two or three sets, each an overseas order. "
|
||||
"Jacket printing or floor space could produce the same symptom, and the cause should be "
|
||||
"confirmed before it is treated as a structural weakness.",
|
||||
"**The gap we close is capability, not only capacity.** No plating, no climate control, no "
|
||||
"metrology, no traceability. The incumbent sells commercially from that room today, which bounds "
|
||||
"how much the Thai market currently pays for the difference. Our bet is on export-grade customers "
|
||||
"and on regional labels who currently ship to Europe.",
|
||||
]),
|
||||
CALL("Investor takeaway", "CNX should not fight a price war at 200-unit runs against an operator "
|
||||
"with low rent and no climate-control load. It competes on what a non-plating, unconditioned "
|
||||
"shop cannot offer at any run size: export-grade quality control and traceability, titles that "
|
||||
"need plating, consistent output through the burning season, a repress in two to three weeks "
|
||||
"from an archived mother, and short runs. A collaboration with the incumbent is under "
|
||||
"discussion; supplying stampers into its presses is one plausible shape for it, and is not in "
|
||||
"the revenue model."),
|
||||
H2("3.4 Cassettes and CDs"),
|
||||
P("The investor has asked for cassette and CD capability on the site. Both fit the same customer: "
|
||||
"the independent label that presses 300 to 2,000 records also orders 100 to 500 cassettes and a "
|
||||
"short run of CDs for the same release, and prefers one supplier, one artwork approval and one "
|
||||
"shipment. Cassette sales have grown from a very low base in the US and UK over the last decade; "
|
||||
"volumes are small and the equipment market is mostly refurbished, but the format is a natural "
|
||||
"add-on with modest capital. CDs remain a large format in Asia (Japan and Korea in particular), "
|
||||
"but industrial CD replication is an established, price-competitive business with existing "
|
||||
"capacity across the region. Sections 4.9 and 4.10 lay out both formats and the two very "
|
||||
"different CD routes; " + pick(
|
||||
"Plan A adds cassette and CD-R duplication after launch, as a growth step outside its price.",
|
||||
"cassette and CD-R duplication are in Plan B from launch.")),
|
||||
|
||||
# ------------------------------------------ 4 anatomy of the plant
|
||||
H1("4. Anatomy of a top-notch plant: the full chain"),
|
||||
P("The chain from audio file to delivered record has nine stages and three points where the artist or "
|
||||
"label must approve before work continues. Every stage records its events in ERPNext and its "
|
||||
"machine data in the plant's data store, and the instruments behind every check are specified in "
|
||||
"section 5. The chart on the next page shows the whole chain; the table after it is the checklist "
|
||||
"of what a top-notch plant needs and where this plan puts each item."),
|
||||
PB(),
|
||||
IMG("process-flow.png", 138, "Figure 1. Process flow from audio file to delivered product, with every "
|
||||
"check and the three artist approval gates. Source: project repository."),
|
||||
PB(),
|
||||
H2("4.0 The checklist"),
|
||||
T(["What a top-notch plant needs", "Why it matters", "This plan", "When"], [
|
||||
["A quiet, vibration-free cutting room with a modern lathe", "The groove is born here; every "
|
||||
"defect propagates to every record", "Sillitoe SDMS complete cutting system in-house; Agnew "
|
||||
"Type 612 as the other candidate", LP + ", commissioned first"],
|
||||
["In-house galvanics with zero-discharge water", "The regional bottleneck; enables represses in "
|
||||
"days and short runs", "Pheenix Alpha line (PASU, PPPU, one PDPU, PMPB); evaporator-based "
|
||||
"zero discharge and DI water in a treatment building next to it",
|
||||
LP + ", commissioned first"],
|
||||
["Stamper preparation machines", "Turns a raw nickel shell into a press-ready part",
|
||||
"Sibert back-finisher, punch, coiner (USD 250k budget confirmed)", LP + ", with galvanics"],
|
||||
["A mixed press fleet", "Semi-automatic for colour and short runs, automatic for long runs",
|
||||
"Newbilt Duplex system (2 presses, main + colour extruder) and one Newbilt Classic",
|
||||
pick("Launch plant; second Duplex as growth option", "At launch; second Duplex as growth option")],
|
||||
["Steam, cooling and compressed air engineered locally", "The largest energy loads; efficiency "
|
||||
"lives here", "Boiler hall and chiller compound for four modules each; 2 x 500 kg/h biomass "
|
||||
"boilers with a covered fuel store and 2 x 250 kW chillers; heat recovery designed in",
|
||||
LP + "; modules added with presses"],
|
||||
["Whole-plant climate and particulate control", "Moisture and dust are the two classic record "
|
||||
"defects", "20 to 26 °C, 35 to 60% RH, filtration for the burning season, tighter in clean "
|
||||
"zones", LP],
|
||||
["Metrology for the metal parts", "Data-backed accept/reject before a stamper is mounted",
|
||||
pick("XRF thickness and inline vision at launch; laser confocal and wide-area profiler from "
|
||||
"revenue",
|
||||
"Laser confocal, wide-area profiler, XRF thickness, inline vision"),
|
||||
pick("Launch plant (confocal and profiler from revenue)", "At launch, full stack")],
|
||||
["Layered QC for every record", "Catch defects at line speed without playing every record",
|
||||
"100% optical inspection, per-cycle telemetry, sampled audio comparison", LP],
|
||||
["Traceability from file to shipment", "Complaints resolve backwards; customers see their "
|
||||
"order; machine data access is a purchasing condition", "ERPNext as the only system of record, "
|
||||
"machine data keyed to it, customer "
|
||||
"portal", LP + " (v1 before the "
|
||||
"machines arrive)"],
|
||||
["A materials lab", "PVC lots differ; a bad lot is a noisy run", "Per-lot gate: moisture, heat "
|
||||
"stability, colour, density, granulate; release by test pressing", LP + " (day-one tier)"],
|
||||
["A packaging partner and packaging QC", "Jackets are the path that slips; the wrong "
|
||||
"record in the right jacket is the classic error", "Ploy Printing (Chiang Mai) for jackets, "
|
||||
"sleeves, J-cards; matrix code scanned "
|
||||
"against jacket barcode", LP],
|
||||
["An archive for fathers and mothers", "Irreplaceable metal; repress economics",
|
||||
"Father and mother of every side; fire-rated, climate-controlled room, clean-agent suppression, "
|
||||
"mobile shelving (to quote)", LP],
|
||||
["Renewable energy and closed-loop water", "Cost, resilience, brand" + pick(
|
||||
"", "; the owned battery may qualify for BOI as storage"),
|
||||
pick("PV on the factory roof (~520 kWp; office roof and canopies PV-ready) and a 271 kWh "
|
||||
"battery through a solar PPA (installer-owned), biomass steam, closed cooling loop, zero "
|
||||
"process discharge",
|
||||
"PV on the factory roof (~520 kWp; office roof and canopies PV-ready) and a 271 kWh "
|
||||
"battery (owned), biomass steam, closed cooling loop, zero process discharge"),
|
||||
pick("Launch plant (PV and battery through a solar PPA)", "At launch")],
|
||||
["Trained people and a safety program", "Steam at 10 bar, hydraulics at 180 bar, plating "
|
||||
"chemistry", "Vendor commissioning training, in-house program, PPE, clean rooms",
|
||||
LP + "; galvanics hiring first"],
|
||||
["An ordering platform for every customer", "Short runs need a channel; transparency is the "
|
||||
"brand", "Itemised price calculator, upload checks, fan-funded campaigns (section 4.8)",
|
||||
"Calculator early; campaigns after first releases ship"],
|
||||
["Cassette and CD lines", "Same customers, one order, one shipment", "In-house cassette "
|
||||
"duplication; CD-R duplication; CD replication as a separate option",
|
||||
pick("Growth step after launch, not in the plan price (replication only if chosen)",
|
||||
"At launch (replication only if chosen)")],
|
||||
], widths_mm=[40, 45, 55, 30], font_pt=8.5),
|
||||
|
||||
H2("4.1 Mastering and lacquer cutting"),
|
||||
P("**What happens.** A mastering engineer prepares the audio for vinyl (levels, side length, "
|
||||
"low-frequency handling), then a cutting lathe drives a heated stylus into a lacquer-coated "
|
||||
"aluminium disc, cutting the groove in real time. The lacquer is soft nitrocellulose: heat- and "
|
||||
"shock-sensitive, and it wants plating within one to three days. Lacquers do not travel well, "
|
||||
"which is the reason to cut and plate under the same roof."),
|
||||
P("**What it needs.** A disk mastering lathe and stereo cutter head, matched cutting amplifiers, a "
|
||||
"mastering console and chain, monitoring, pitch and depth automation, vacuum for platter hold-down "
|
||||
"and chip suction, a groove inspection microscope, and a low-vibration, temperature-controlled "
|
||||
"room away from the presses and compressor. Consumables are lacquer blanks and styli."),
|
||||
P("**Who supplies it.** The plan is a **Sillitoe Disk Mastering System (SDMS)** from Sillitoe Audio "
|
||||
"Technology (Australia), a complete cutting system rather than a bare lathe: direct-drive "
|
||||
"turntable with a vacuum platter for 7- to 14-inch disks, a feedback cutterhead, a 350 W per "
|
||||
"channel cutting amplifier, vacuum and a groove microscope in the box. Its Space / Time Control "
|
||||
"software computes a virtual groove from the audio before anything is cut and drives pitch, depth "
|
||||
"and head lift automatically (vendor claim: no capacity tests or dry runs). It also exports a cue "
|
||||
"sheet, an open-format groove file and stylus hours, which the cutting record in ERPNext can "
|
||||
"attach instead of manual entry. The weaknesses: it is a closed system (the head works only with "
|
||||
"Sillitoe's amplifier and is factory calibrated), the install base is small, and service depends "
|
||||
"on one small company, so a spare cutterhead and support terms belong in the quote. **Agnew "
|
||||
"Analog** (Greece) and its Type 612 lathe, billed as the first all-new lacquer lathe since the "
|
||||
"1960s, is the other candidate: bespoke, unpublished price, long build times, with amplifiers and "
|
||||
"automation sourced around it. Used lathes and complete used studios exist too, through contacts "
|
||||
"OMS passed on; any of them is compared as a whole room."),
|
||||
P("**Cost and people.** The cutting-room block is an estimated USD 200k to 350k (THB 6.6M to "
|
||||
"11.6M): the SDMS at its published list price of USD 125k (ex tax and shipping, built to order), "
|
||||
"plus a spare cutterhead and support, the mastering console and chain, monitoring and the room "
|
||||
"build-out, all estimates. A cutting engineer earns about 50,000 THB a month base (team figure). "
|
||||
"Mastering is labour-bound: an engineer masters perhaps two to four songs a day, which caps the "
|
||||
"title-services line (section 9). Payap University wants joint student programmes in mastering "
|
||||
"and lathe cutting, a possible future source of trained people. SST in Frankfurt, which already "
|
||||
"cuts Poy Records' lacquers, stays a contact for overflow or a slipping commissioning, not part "
|
||||
"of the plan."),
|
||||
|
||||
H2("4.2 Galvanics: silvering and electroforming"),
|
||||
P("**What happens.** The lacquer is cleaned and sprayed with a conductive silver layer, then "
|
||||
"electroplated with nickel to grow a negative metal copy, the 'father'. From the father a positive "
|
||||
"'mother' is grown (playable), and from the mother the working 'stampers' that go into the press. "
|
||||
"This three-step process means a fresh stamper can be grown from an archived mother in a day or "
|
||||
"two; a cheaper one-step stamper is single-use and a repress restarts at cutting. The plant keeps "
|
||||
"the father **and** the mother of every side in its archive, so a worn mother is regrown from the "
|
||||
"father without a recut."),
|
||||
P("**Why it is the key to the region.** We have found no plating capability in Thailand; the one "
|
||||
"plant we have seen buys its stampers abroad (a desk check of Thai electroforming capacity is "
|
||||
"still to be done). Every title it presses therefore waits on an overseas order, which is the most "
|
||||
"plausible cause of its lead-time penalty on larger runs and its inability to take small ones. "
|
||||
"Bringing cutting and plating in-house takes an estimated 1.5 to 5 weeks out of the lead time and "
|
||||
"USD 175 to 665 per title out of the cost."),
|
||||
P("**What it needs.** A lacquer cleaning and silvering station, a low-stress nickel pre-plate, "
|
||||
"production electroforming cells for the three generations, a passivation and cleaning bench, a "
|
||||
"clean room with controlled access, fume extraction, DI water, and a closed-loop rinse-water "
|
||||
"treatment and metal recovery system. The chemistry (silver nitrate, nickel salts) sets the safety "
|
||||
"and permitting requirements: decontamination procedures, PPE, locked chemical storage, eyewash "
|
||||
"and emergency shower, and hazardous-substance registration. Because galvanics is now in the "
|
||||
+ pick("launch plant", "plant from launch")
|
||||
+ ", the site's zoning and the first factory licence have to allow electroplating from "
|
||||
"the start."),
|
||||
P("**Who supplies it.** The plan is a **Pheenix Alpha** line (Sweden): the PASU automatic silvering "
|
||||
"unit, the PPPU pre-plating unit (four masters at once), one PDPU dual plating unit (two cells, up "
|
||||
"to 200 A each) and the PMPB passivation and cleaning bench. The plating units are PLC-controlled "
|
||||
"with recipes and a network connection (the protocol is not stated; data access is a purchasing "
|
||||
"condition). **Digital Matrix / Plating Power** (New York), the long-standing US turnkey vendor, "
|
||||
"is the second turnkey candidate. **OMS** (Optical Media Services, Baarlo, Netherlands), named by "
|
||||
"Sibert, is the third candidate and the price reference: EUR 224,000 for a basic and EUR 311,000 "
|
||||
"for an advanced 4-cell wet room (installation and water treatment extra), 24 and 32 shells in an "
|
||||
"8-hour day. No vendor supplies the water treatment: the zero-discharge evaporator and DI water "
|
||||
"come from an industrial water vendor (an imported core unit with Thai integration), in a small "
|
||||
"treatment building next to the galvanics room (proposed)."),
|
||||
P("**How much line the plant needs.** Pheenix publishes no cycle times. Published plating practice "
|
||||
"gives about 15 to 30 minutes for pre-plate, ~75 minutes for a father, about an hour for a mother "
|
||||
"and ~45 minutes for a stamper (silvering and bench times are estimates). With loading and rinsing, "
|
||||
"a cell turns a part in about 1 to 1.5 hours, so one PDPU makes 20 to 32 parts in a two-shift day "
|
||||
"against 8 to 20 parts a working day "
|
||||
+ pick("even for the larger five-press fleet", "even with the second Duplex system added from revenue")
|
||||
+ ". **One PDPU covers the "
|
||||
"demand; a second would buy redundancy, not capacity.** By OMS's rule of thumb (one person runs "
|
||||
"about 20 stampers a day) that is one galvanics operator per shift."),
|
||||
P("**Cost and risk.** Pheenix has not quoted, so the plan prices its line at **OMS's reference plus "
|
||||
"20 %**: OMS's 4-cell wet room with the EUR 10,000 know-how transfer (nobody on the team has run a "
|
||||
"plating room), EUR 234,000 to 321,000, times 1.2 gives EUR 280,800 to 385,200, ~USD 324k to 445k "
|
||||
"(THB 10.7M to 14.7M; an estimate, replacing the earlier estimate of USD 320k to 650k). The "
|
||||
"zero-discharge and DI water plant adds an estimated USD 97k to 258k "
|
||||
"and its building USD 52k to 87k. Galvanics is the hardest skill to hire and it is now on the "
|
||||
"path to the first release, because the presses need its stampers. Sibert advised getting each "
|
||||
"main step right and earning some return before every manufacturing step is in place; that advice "
|
||||
"and the plan's answer to it are in sections 11.2 and 13. Stamper Discs (UK), a trade stamper "
|
||||
"service, stays a contact for overflow or a slipping commissioning, not part of the plan."),
|
||||
|
||||
H2("4.3 Stamper preparation"),
|
||||
P("A raw electroformed shell is not yet a stamper. It is back-finished flat, centre-punched to the "
|
||||
"groove, and formed ('coined') to the mould. Sibert Instruments (UK, in this niche since the early "
|
||||
"1970s) makes the three machines, run in that order: the **VSF** back-finisher, the **VSP** punch "
|
||||
"and the **VSC** coiner, which forms the centre hole and the edge and punches the outer diameter "
|
||||
"to size. Sibert confirmed in October 2026 that **USD 250k covers all three** (a budget "
|
||||
"confirmation, with an itemised quotation to follow when we go ahead); its engineer's time, spare "
|
||||
"parts, shipping and travel are extra and sit in the freight and spares lines. The machines run "
|
||||
"on single-phase power and compressed air, weigh 200, 250 and 1,000 kg, and stand in a row about "
|
||||
"5.0 x 0.8 m. They list no data interface, and centring on the punch is manual under x100 optics, "
|
||||
"so the concentricity check after it stays and feeds the traceability record. Sibert also builds "
|
||||
"a fully automatic punch (VSPa) and has offered to carry some of its features across to the VSP; "
|
||||
"which ones is a question for the quotation. The coiner needs tooling per mould type, which the "
|
||||
"press vendor has to specify. The back-finisher's water carries nickel fines and goes to the "
|
||||
"galvanics treatment, never the drain. Stamper prep is planned in one clean zone with galvanics."),
|
||||
|
||||
H2("4.4 Pressing"),
|
||||
P("**What happens.** An extruder melts PVC compound into a 'patty', which is placed with two labels "
|
||||
"between two stampers in a steam-heated mould. The press closes at about 150 tonnes, the mould is "
|
||||
"then water-cooled, and the record is ejected and trimmed. A cycle takes about 28 seconds on the "
|
||||
"automatic Classic; on a semi-automatic press an operator handles the patty and the record, which "
|
||||
"is slower but is exactly what colour, splatter and special editions need. The labels are pressed "
|
||||
"into the record, not glued on afterwards: they are pre-dried in an oven (moisture in a label "
|
||||
"causes bubbles) and loaded with the patty every cycle, and the label lot is logged per cycle."),
|
||||
P("**The fleet: all Newbilt, semi-automatic first.** The semi-automatic side carries most of the "
|
||||
"volume: splatter, marble and other colour effects, special editions and small runs are where an "
|
||||
"operator working the mould is an advantage rather than a cost, and the colour extruder on the "
|
||||
"Duplex adds the second colour strand. The Classic takes the long standard runs. Classic and "
|
||||
"Duplex share mould inserts, so the plant runs one mould family, one set of spares and one service "
|
||||
"relationship; the cost is a single-vendor dependency."),
|
||||
T(["Machine", "Role", "Basis", "Cost"], [
|
||||
["Newbilt Duplex system (Alsdorf, Germany)",
|
||||
"Two HRP 12 hydraulic presses (~150 t), EX 50 main "
|
||||
"extruder and EX 35 colour extruder, 12-inch book moulds for 140/180 g, trimmer, label dry oven, "
|
||||
"shrink wrapper, PVC grinder, label punch, spindles and plates; one operator's cell",
|
||||
"Quoted: EUR 200,500 (~USD 232k) for the Single 2.1 system incl. sea freight, June 2024, plus "
|
||||
"the quoted second press and extruder (~USD 115k); expired, re-quote required with build time",
|
||||
"USD 350k to 370k (THB 11.6M to 12.2M)"],
|
||||
["Newbilt Classic", "Fully automatic press with built-in extruder, automatic patty, label and "
|
||||
"record handling; 28 s cycle, ~128 records/h at 180 g; Siemens safety PLC with OPC UA; "
|
||||
"vendor-claimed 95% yield and uptime", "Estimate: placeholder band; **no Newbilt price on "
|
||||
"file**", "USD 290k to 460k (THB 9.6M to 15.2M)"],
|
||||
["Second Duplex system (growth option)", "Two more semi-automatic presses on the same central "
|
||||
"hydraulics; floor, utility positions and ring-main tees reserved", "Estimate; not in the "
|
||||
"investment",
|
||||
"~USD 230k to 300k"],
|
||||
], widths_mm=[34, 66, 42, 28], font_pt=8.5),
|
||||
P("The Pheenix Alpha AD12 automatic press left the plan in October 2026 and stays the comparison if "
|
||||
"the Classic re-quote disappoints."),
|
||||
P("**What Newbilt deliberately excludes**, and what is engineered and sourced locally: steam and "
|
||||
"cooling. At Newbilt's per-machine figures the three presses draw about 450 to 540 kg/h of steam "
|
||||
"at 10 bar / 180 °C and up to ~390 kW of cooling on a hot afternoon (estimates; the Classic is "
|
||||
"counted as one press and extruder until Newbilt states its own figures). They are met by **two "
|
||||
"500 kg/h biomass boiler modules (B-1, B-2) and two 250 kW chiller modules (CH-1, CH-2)**, in a "
|
||||
"boiler hall and an open chiller compound built for four modules each; a second Duplex adds a "
|
||||
"third chiller module, and the fourth positions are reserve and growth. The boilers burn wood "
|
||||
"chips from a covered fuel store, in both versions of the plan: ~6M to 10M THB installed with "
|
||||
"fuel feed, grate and dust control, plus ~1M to 2M THB for the fuel store and handling, and "
|
||||
"~0.67M THB of fuel a year (estimates). " + pick(
|
||||
"Plan A buys the compressor through the Chinese route. That route priced only electric "
|
||||
"boilers; Chinese makers also build biomass boilers but none is priced yet, and a quote ~2M "
|
||||
"THB or more below the Thai package would bring Plan A's midpoint back to 180M (section 5.4). ",
|
||||
"Plan B buys the compressor from a Thai supplier, with local service. ")
|
||||
+ "The presses share one central hydraulic plant and one "
|
||||
"compressed-air plant through ring mains with a valved tee at every press position, so a new press "
|
||||
"is connected without stopping the others; the standby pump set, accumulators and ring main are "
|
||||
"not yet costed. These are the largest energy systems in the plant and the reason the efficiency "
|
||||
"architecture in section 5.4 is ours to design."),
|
||||
P("**Site requirements.** Roughly 200 m² of production floor per Duplex system and an estimated 50 "
|
||||
"to 75 m² for the Classic, saturated steam, compressed air and cooling circuits, and side rooms for "
|
||||
"materials and finished goods. A press weighs 1,350 kg on under one square metre, so the floor slab "
|
||||
"must carry several tonnes per square metre and is a building-selection criterion; the floor must "
|
||||
"be flat, non-slip and solvent-resistant."),
|
||||
T(["Stage", "Fleet", "Rough output per year"], [
|
||||
["Launch plant", "1 Duplex system (2 semi-automatic) + 1 Classic, 2 shifts",
|
||||
"~0.58 to 0.90 million records at 60 % specials (0.71 to 0.97 at ~20 %)"],
|
||||
["Growth option: second Duplex", "4 semi-automatic + 1 Classic, 2 shifts; room reserved, not in "
|
||||
"the investment",
|
||||
"~1.0 to 1.5 million records"],
|
||||
["Full hall (option)", "5 Duplex systems + 4 Classics, the press hall laid out for Duplex "
|
||||
"(special pressings first, ~73/27 by floor); a utility phase of its own",
|
||||
"~2.9 to 4.4 million records at 60 % specials (estimate)"],
|
||||
], widths_mm=[40, 80, 50],
|
||||
caption="Basis: semi-automatic 60 to 80 records/h assumed; Classic ~128/h (vendor flyer); 16 h/day, "
|
||||
"300 days/yr, 60 to 70% overall equipment effectiveness; specials (60 % and more) only on the "
|
||||
"Duplex. The launch plant is 248 to 288 records/h at nameplate, but at 60 % specials the "
|
||||
"Duplex caps it at 200 to 267/h, ~120 to 187/h after effectiveness; the press fleet "
|
||||
"calculator at the team's planning rates gives ~0.94 million. Neither option is in the "
|
||||
"revenue model or the investment."),
|
||||
P("**On the 60 to 70% effectiveness figure.** Newbilt publishes 95% yield and 95% uptime for the "
|
||||
"Classic. We have not adjusted the plan on that basis, deliberately: a vendor's machine uptime "
|
||||
"excludes stamper and mould changes, colour changeovers, compound lot changes, first-article QC "
|
||||
"and breaks, which are exactly the losses that dominate a short-run boutique plant. It would also "
|
||||
"apply only to the Classic, because the semi-automatic rate already includes operator handling. "
|
||||
"Newbilt is being asked for the basis of its figures as part of the re-quote; if they hold, they "
|
||||
"argue for a higher effectiveness on the Classic only."),
|
||||
|
||||
H2("4.5 Finishing, packaging and fulfilment"),
|
||||
P("After pressing, records are trimmed inline, sleeved, assembled into jackets, shrink-wrapped and "
|
||||
"packed; edge trim and rejected records go back through the label punch and grinder as regrind. "
|
||||
"Jackets, sleeves, inserts, J-cards and CD packaging come from **Ploy Printing** (Ploy Karnpim "
|
||||
"Limited Partnership, Pa Daet, Mueang Chiang Mai), an established print house with offset, "
|
||||
"digital, risograph, UV inkjet and latex inkjet presses and vinyl packaging production. That "
|
||||
"keeps a labour-intensive, freight-heavy item within the province, gives the plant a partner who "
|
||||
"already knows record packaging, and, because Ploy Printing intends to co-invest (section 12), "
|
||||
"aligns the two businesses on the same schedule and quality. Risograph and UV print also open "
|
||||
"boutique packaging options (spot colours, special stocks, printed shells and J-cards) that suit "
|
||||
"the short-run and colour-vinyl market the semi-automatic line serves. Two points matter "
|
||||
"commercially:"),
|
||||
B([
|
||||
"**Packaging is the path that slips.** Printed jackets need 10 to 20 working days from approved "
|
||||
"artwork. The metal path and the packaging path run in parallel and converge at assembly; when "
|
||||
"a label delivers artwork late, jackets become the critical path and every day saved on "
|
||||
"metalwork is wasted. Artwork deadline is therefore contracted as a fourth approval gate, and "
|
||||
"the ordering platform checks artwork against our templates at upload (section 4.8).",
|
||||
"**The wrong record in the right jacket is the classic error**, and a misprinted barcode is a "
|
||||
"rejected delivery at the distributor. Each jacket is scanned against the runout matrix code of "
|
||||
"the record going into it, and every unit's barcode is verified.",
|
||||
]),
|
||||
P("**Fulfilment** covers bulk pallet delivery to labels and distributors, and dropshipping single "
|
||||
"parcels directly to end customers on behalf of labels and artists (one parcel per fan for a "
|
||||
"fan-funded campaign), with carrier tracking recorded per shipment. Dropshipping fees are charged "
|
||||
"per parcel and are not in the revenue model."),
|
||||
|
||||
H2("4.6 Materials: PVC compound"),
|
||||
P("Records are pressed from a vinyl chloride / vinyl acetate copolymer compound, about 150 to 160 g "
|
||||
"per 12-inch record. The plant runs an 80% virgin / 20% regrind feed: trimmings and rejects go "
|
||||
"through an in-house grinder and back to the extruder, so scrap is feedstock, not landfill. The "
|
||||
"current supplier list is European (Netherlands, UK, Italy, France, Germany) with one US option; "
|
||||
"the preference is a qualified Thai or regional compound if it meets record specifications, "
|
||||
"which cuts freight, cost and footprint. The incumbent's floor was stacked with sacks marked "
|
||||
"'Made in Thailand', a lead worth following. Special designs will run in tens of colours, so the "
|
||||
"plan keeps a racked colour store, with outdoor silos proposed for black and the standard colours. "
|
||||
"Every incoming lot passes the material lab gate in section 5.3 before it is released to a press."),
|
||||
|
||||
H2("4.7 The order, end to end: what a customer is promised"),
|
||||
P("A defensible lead time is not the sum of process steps: it carries queue and buffer, and it is "
|
||||
"quoted from the last customer approval, because a plant cannot be held to a clock the customer "
|
||||
"keeps stopping. With cutting and plating in-house from the start, there is no external metal "
|
||||
"block in any of these quotes. The plan's quotable lead times, from test-pressing approval:"),
|
||||
T(["Order type", "Quoted lead time", "Basis"], [
|
||||
["New title, full service (cutting, plating and pressing in-house)", "7 to 9 weeks",
|
||||
"Stage sum of 11.5 to 22 plant days plus queue and buffer; Record Industry (NL) quotes 9 to 11 "
|
||||
"weeks after test-pressing and artwork approval; EU/US plants are reported at 10 to 16 weeks"],
|
||||
["Customer supplies jackets", "1 to 2 weeks less", "Removes the print path"],
|
||||
["Repress from an archived mother, no changes", "2 to 3 weeks", "Grow a stamper from the mother "
|
||||
"(1 to 2 days), prep, press, finish: about 7 to 11 working days in the plant; the highest-margin "
|
||||
"order the plant will take"],
|
||||
["Rush slot", "Premium, capped per month", "Only credible with reserved capacity"],
|
||||
], widths_mm=[62, 28, 80],
|
||||
caption="Estimate: planning figures from the stage table; no order has run through this plant."),
|
||||
P("Draft 0.1 quoted 10 to 14 weeks for the launch, when stampers were to come from the UK; that row "
|
||||
"is gone. The figures above are still planning numbers: the first months will run slower while "
|
||||
"the reject rate settles, which is why fan-funded campaigns open only after the first releases "
|
||||
"have shipped and lead times are measured."),
|
||||
P("Lead time is a capacity decision, not a process decision. A plant running at 90% quotes 16 weeks "
|
||||
"with the same equipment that quotes 6 weeks at 50%. Any turnaround promise to the market is a "
|
||||
"promise to hold spare capacity, and the revenue model in section 9 is built on that basis."),
|
||||
|
||||
H2("4.8 The artist platform: ordering and fan-funded pressing"),
|
||||
P("Short runs need a channel, and the plant's transparency needs a front door. The artist platform is "
|
||||
"a web service where anyone who wants records made, from a bedroom artist to a label, configures a "
|
||||
"record and gets a **transparent, itemised offer**: what every line costs, which costs are per "
|
||||
"title and which per copy, how the price per copy falls with quantity, and when it ships. Two "
|
||||
"clickable demos of it exist, one detailed and one built for investors."),
|
||||
B([
|
||||
"**Calculator and uploads.** Format, weight, colour, labels, jacket with a 3 or 5 mm spine, "
|
||||
"extras, mastering and test pressings, priced from one price list that also drives the invoice "
|
||||
"in ERPNext. The master files are checked within minutes (format, sample rate, clipping, side "
|
||||
"length against the format); artwork is checked against downloadable jacket and label templates "
|
||||
"(size, spine, bleed, resolution, colour) and can be delivered as PDF, Illustrator (AI) or image "
|
||||
"files.",
|
||||
"**Fan-funded campaigns.** The artist sets a fan price and shares a campaign page; fans pre-order "
|
||||
"their copy. The goal is the larger of a minimum campaign run (100 copies as the planning figure) "
|
||||
"and the artist's break-even. Fans pay into a **ring-fenced account** that is never working "
|
||||
"capital, and are refunded automatically if the goal is missed; CNX is the seller of record. The "
|
||||
"rule comes from Qrates, a crowdfunded pressing platform whose service was suspended with funded "
|
||||
"projects caught in the wind-down. A Thai legal opinion comes before the first campaign.",
|
||||
"**Timing.** The calculator goes public early with indicative prices and an interest list but no "
|
||||
"payments: every configuration is a data point on the run sizes people actually want, which is "
|
||||
"the open question in market validation. Campaigns open **only after the first paying releases "
|
||||
"have shipped** and lead times are measured; no fan money is taken against a plant that has not "
|
||||
"yet delivered.",
|
||||
]),
|
||||
P("In the platform's illustration, a fan price of 1,200 THB breaks even at about 41 copies, so the "
|
||||
"100-copy minimum sets the goal (an example, not a recommendation). The public side is an estimated "
|
||||
"USD 40k to 90k, inside the software block of the investment; it runs on the plant's own server "
|
||||
"fleet, with a payment provider as the only outside service. Its name is undecided (under CNX "
|
||||
"Vinyl, Poy Records or a brand of its own)."),
|
||||
|
||||
H2("4.9 Cassette duplication"),
|
||||
P("**What happens.** A studio master is duplicated onto tape either in real time on a bank of decks, "
|
||||
"or at high speed on a loop-bin duplicator that copies a running master loop onto reels of blank "
|
||||
"tape ('pancakes') many times faster than real time. The tape is then loaded into empty cassette "
|
||||
"shells ('C-0s') by a loader that cuts to length and splices, shells are printed or labelled, "
|
||||
"J-cards are printed and folded, and the cassette is boxed and shrink-wrapped."),
|
||||
T(["", "Tier A: real-time bank", "Tier B: professional high-speed line"], [
|
||||
["Equipment", "10 to 20 duplicating decks, a cassette loader, shell printer or label printer, "
|
||||
"shrink wrapper", "Loop-bin high-speed duplicator (typically refurbished 1980s to 1990s "
|
||||
"Lyrec, Gauss or similar, or a current Chinese-built unit), 2 to 3 loaders, "
|
||||
"pad printer for on-shell print, imprinter, shrink wrapper"],
|
||||
["Throughput", "~100 to 300 cassettes per day", "~1,000 to 3,000 cassettes per day"],
|
||||
["Space", "~30 to 40 m²", "~60 to 80 m², climate-controlled (tape and PVC are both "
|
||||
"humidity-sensitive)"],
|
||||
["Staff", "1, part time", "1 to 2"],
|
||||
["Capital", "USD 15k to 40k", "USD 40k to 150k"],
|
||||
["Quality", "Adequate for short runs; audio quality is master-limited", "Industry standard; "
|
||||
"chrome or ferric tape"],
|
||||
], widths_mm=[24, 68, 78],
|
||||
caption="Estimate. The professional cassette equipment market is largely refurbished; new "
|
||||
"high-speed lines are rare. Prices to be confirmed with two or three vendors."),
|
||||
P("**Supply chain.** Blank tape pancakes and C-0 shells come from a handful of suppliers worldwide "
|
||||
"(National Audio Company in the US is the largest tape source; shell moulders exist in China and "
|
||||
"should be sought in Thailand). Supply risk is real and the plan is to hold stock. **Positioning:** "
|
||||
"cassettes are a boutique add-on for the same indie customers, with shells in colours that match "
|
||||
"the record. **Effect on the plan:** " + pick(
|
||||
"Plan A adds cassette and CD-R duplication after launch, as a growth step from revenue, "
|
||||
"starting at tier A or a small tier B. Together they are one estimated block of USD 55k to "
|
||||
"190k (~THB 4.0M at the midpoint), not in Plan A's price: moving them later is one of its six "
|
||||
"cost levers. They fit inside the building programme, and the activity can still go into the "
|
||||
"BOI application from the start (to confirm with the BOI consultant).",
|
||||
"in Plan B from launch, starting at tier A or a small tier B; cassette and CD-R together are "
|
||||
"one estimated block of USD 55k to 190k in the investment; schedule-neutral; fits inside the "
|
||||
"building programme; the activity goes into the BOI application. Plan A, the other version, "
|
||||
"moves both to after launch as one of its cost levers.")),
|
||||
|
||||
H2("4.10 CD: two very different routes (investor decision)"),
|
||||
P("'CD manufacturing' can mean two things that differ by two orders of magnitude in capital, and the "
|
||||
"investor is asked to choose."),
|
||||
T(["", "Route 1: CD-R duplication", "Route 2: CD replication"], [
|
||||
["What it is", "Blank recordable discs are burned and printed by robotic duplicators. The "
|
||||
"result is a CD-R, playable in almost all players, with full-colour on-disc print.",
|
||||
"Discs are injection-moulded from polycarbonate against a nickel stamper (made by glass "
|
||||
"mastering and electroforming), metallised, lacquered, and printed. The result is a 'pressed' "
|
||||
"CD identical to major-label product."],
|
||||
["Equipment", "2 to 4 robotic autoloader duplicators with inkjet or thermal print (Rimage, "
|
||||
"Microboards, Primera or Epson class); packaging printed by Ploy Printing; "
|
||||
"shrink wrapper", "Laser beam recorder for glass mastering (or outsourced glass masters), "
|
||||
"electroforming line, one or two injection-moulding lines with inline "
|
||||
"metalliser, lacquer coater and scanner, screen or offset disc printer, "
|
||||
"packaging automation, ISO 7/8 clean room"],
|
||||
["Throughput", "~200 to 800 discs per day per unit", "~10,000 to 30,000 discs per day per line"],
|
||||
["Space", "~20 to 40 m²", "~300 to 600 m² plus clean room; realistically the second building"],
|
||||
["Capital", "USD 15k to 40k", "USD 1.5M to 4.0M (new-build lines); used lines from closed "
|
||||
"plants can halve that at higher risk"],
|
||||
["Staff", "Shared with cassette line", "6 to 10 across shifts, including a process engineer"],
|
||||
["Market fit", "Short runs of 50 to 500 for indie releases, merch and promo; same customers as "
|
||||
"vinyl and cassette", "Volume runs of 1,000+; competes with established replicators in "
|
||||
"Japan, Taiwan, Malaysia and elsewhere on thin margins"],
|
||||
["Regulatory", "No separate BOI activity expected (confirm)", "Separate BOI activity code, "
|
||||
"must be in the application from "
|
||||
"the start; larger factory "
|
||||
"licence scope"],
|
||||
["Effect on timeline", "None", "Substantial: a second commissioning programme and a bigger "
|
||||
"building; would push first CD output well past first vinyl"],
|
||||
["Synergy", "Shares packaging, fulfilment, artwork approval, traceability", "Shares the "
|
||||
"electroforming skill set and the clean-room discipline of the vinyl galvanics room, but not "
|
||||
"the equipment"],
|
||||
], widths_mm=[24, 68, 78], font_pt=8.5,
|
||||
caption="Estimate throughout. Route 2 figures are order-of-magnitude and would need a dedicated "
|
||||
"feasibility study."),
|
||||
P("**Recommendation.** " + pick(
|
||||
"Route 1 is the CD route for this plant: it is cheap, schedule-neutral, and serves the plant's "
|
||||
"customers; Plan A adds it after launch together with the cassette line. ",
|
||||
"Route 1 is in Plan B from launch: it is cheap, schedule-neutral, and serves the plant's "
|
||||
"customers. ")
|
||||
+ "Treat Route 2 as a separate project with its own market study, because CD "
|
||||
"replication is a mature, competitive, declining business outside Asia's strongholds and would "
|
||||
"add USD 1.5M to 4.0M and a second building to a plan whose vinyl economics do not depend on it. "
|
||||
"If the investor wants Route 2, the decision must be taken before the BOI application is filed "
|
||||
"(section 7), and the second building should be designed for it. " + pick(
|
||||
"Plan A's price includes neither route; Route 1 is a growth step and Route 2 a separate line.",
|
||||
"This plan's totals include Route 1 only; Route 2 is shown as a separate line.")),
|
||||
]
|
||||
return out
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
"""Export CNX-Vinyl-Business-Plan-A.docx and -B.docx to PDF with LibreOffice, filling in the table of contents.
|
||||
|
||||
Run with LibreOffice's own Python (it ships the uno module):
|
||||
"C:/Program Files/LibreOffice/program/python.exe" export_pdf.py
|
||||
A plain `soffice --convert-to pdf` leaves the Word TOC field unfilled.
|
||||
"""
|
||||
import uno, sys, time, subprocess, os
|
||||
from pathlib import Path
|
||||
HERE = Path(__file__).resolve().parent
|
||||
DOCXS = [HERE.parent / f"CNX-Vinyl-Business-Plan-{p}.docx" for p in ("A", "B")]
|
||||
DOCXS = [d for d in DOCXS if d.exists()]
|
||||
from com.sun.star.beans import PropertyValue
|
||||
def pv(n, v):
|
||||
p = PropertyValue(); p.Name = n; p.Value = v; return p
|
||||
soffice = r"C:\Program Files\LibreOffice\program\soffice.exe"
|
||||
proc = subprocess.Popen([soffice, "--headless", "--invisible", "--norestore", "--accept=socket,host=localhost,port=2083;urp;"])
|
||||
local = uno.getComponentContext()
|
||||
resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
|
||||
for i in range(60):
|
||||
try:
|
||||
ctx = resolver.resolve("uno:socket,host=localhost,port=2083;urp;StarOffice.ComponentContext"); break
|
||||
except Exception:
|
||||
time.sleep(0.5)
|
||||
smgr = ctx.ServiceManager
|
||||
desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
|
||||
for DOCX in DOCXS:
|
||||
PDF = DOCX.with_suffix(".pdf")
|
||||
src = uno.systemPathToFileUrl(str(DOCX))
|
||||
doc = desktop.loadComponentFromURL(src, "_blank", 0, (pv("Hidden", True),))
|
||||
idx = doc.getDocumentIndexes()
|
||||
print(DOCX.name, "indexes", idx.getCount())
|
||||
for i in range(idx.getCount()):
|
||||
idx.getByIndex(i).update()
|
||||
doc.refresh()
|
||||
# update fields (page numbers)
|
||||
doc.getTextFields().refresh()
|
||||
for i in range(idx.getCount()):
|
||||
idx.getByIndex(i).update()
|
||||
out = uno.systemPathToFileUrl(str(PDF))
|
||||
doc.storeToURL(out, (pv("FilterName", "writer_pdf_Export"),))
|
||||
doc.close(True)
|
||||
try:
|
||||
desktop.terminate()
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(1)
|
||||
proc.kill() if proc.poll() is None else None
|
||||
print("done")
|
||||
@@ -0,0 +1,326 @@
|
||||
"""Tiny document DSL and renderer for the CNX Vinyl business plan.
|
||||
|
||||
Blocks are plain tuples so the content files stay readable:
|
||||
|
||||
H1("text") / H2 / H3 headings
|
||||
P("text with **bold** runs") paragraph
|
||||
B([...]) bullet list
|
||||
N([...]) numbered list (manual numbers, restart per list)
|
||||
T(header, rows, widths_mm=None, caption=None, font_pt=9)
|
||||
KV([[k, v], ...], widths_mm) two-column table without header
|
||||
IMG(path, width_mm, caption) picture
|
||||
CALL(title, body) shaded call-out box; body is str or list
|
||||
PB() page break
|
||||
TOC() table-of-contents field
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from docx import Document
|
||||
from docx.enum.table import WD_TABLE_ALIGNMENT
|
||||
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_BREAK
|
||||
from docx.oxml import OxmlElement
|
||||
from docx.oxml.ns import qn
|
||||
from docx.shared import Mm, Pt, RGBColor
|
||||
|
||||
NAVY = RGBColor(0x1F, 0x38, 0x64)
|
||||
BLUE = RGBColor(0x2E, 0x55, 0x97)
|
||||
GREY = RGBColor(0x59, 0x59, 0x59)
|
||||
HEADER_FILL = "1F3864"
|
||||
CALLOUT_FILL = "DEEAF6"
|
||||
ALT_FILL = "F2F5FA"
|
||||
BODY_FONT = "Calibri"
|
||||
|
||||
|
||||
# ----------------------------------------------------------------- DSL ---
|
||||
def H1(t): return ("h", 1, t)
|
||||
def H2(t): return ("h", 2, t)
|
||||
def H3(t): return ("h", 3, t)
|
||||
def P(t, style=None): return ("p", t, style)
|
||||
def B(items): return ("bullets", items)
|
||||
def N(items): return ("numbers", items)
|
||||
def T(header, rows, widths_mm=None, caption=None, font_pt=9):
|
||||
return ("table", header, rows, widths_mm, caption, font_pt)
|
||||
def KV(rows, widths_mm=(50, 115), font_pt=9.5): return ("kv", rows, widths_mm, font_pt)
|
||||
def IMG(path, width_mm, caption=None): return ("img", path, width_mm, caption)
|
||||
def CALL(title, body): return ("callout", title, body)
|
||||
def PB(): return ("pb",)
|
||||
def TOC(): return ("toc",)
|
||||
def COVER(**kw): return ("cover", kw)
|
||||
|
||||
|
||||
# ------------------------------------------------------------ helpers ---
|
||||
def _shade(cell, fill):
|
||||
tcPr = cell._tc.get_or_add_tcPr()
|
||||
shd = OxmlElement("w:shd")
|
||||
shd.set(qn("w:val"), "clear")
|
||||
shd.set(qn("w:color"), "auto")
|
||||
shd.set(qn("w:fill"), fill)
|
||||
tcPr.append(shd)
|
||||
|
||||
|
||||
def _field(paragraph, instr, placeholder):
|
||||
run = paragraph.add_run()
|
||||
b = OxmlElement("w:fldChar"); b.set(qn("w:fldCharType"), "begin")
|
||||
i = OxmlElement("w:instrText"); i.set(qn("xml:space"), "preserve"); i.text = instr
|
||||
s = OxmlElement("w:fldChar"); s.set(qn("w:fldCharType"), "separate")
|
||||
t = OxmlElement("w:t"); t.text = placeholder
|
||||
e = OxmlElement("w:fldChar"); e.set(qn("w:fldCharType"), "end")
|
||||
for el in (b, i, s, t, e):
|
||||
run._r.append(el)
|
||||
return run
|
||||
|
||||
|
||||
def _set_font(style, name, size=None, bold=None, color=None, italic=None):
|
||||
f = style.font
|
||||
f.name = name
|
||||
rpr = style.element.get_or_add_rPr()
|
||||
rfonts = rpr.find(qn("w:rFonts"))
|
||||
if rfonts is None:
|
||||
rfonts = OxmlElement("w:rFonts"); rpr.append(rfonts)
|
||||
for k in ("w:ascii", "w:hAnsi", "w:eastAsia", "w:cs"):
|
||||
rfonts.set(qn(k), name)
|
||||
if size is not None: f.size = Pt(size)
|
||||
if bold is not None: f.bold = bold
|
||||
if italic is not None: f.italic = italic
|
||||
if color is not None: f.color.rgb = color
|
||||
|
||||
|
||||
_INLINE = re.compile(r"(\*\*.+?\*\*)")
|
||||
|
||||
|
||||
def _runs(paragraph, text, size=None, color=None):
|
||||
for part in _INLINE.split(text):
|
||||
if not part:
|
||||
continue
|
||||
bold = part.startswith("**") and part.endswith("**")
|
||||
run = paragraph.add_run(part[2:-2] if bold else part)
|
||||
run.bold = bold or None
|
||||
if size is not None: run.font.size = Pt(size)
|
||||
if color is not None: run.font.color.rgb = color
|
||||
return paragraph
|
||||
|
||||
|
||||
def _cell_text(cell, text, size, bold=False, color=None, align=None):
|
||||
cell.text = ""
|
||||
para = cell.paragraphs[0]
|
||||
para.paragraph_format.space_after = Pt(1)
|
||||
para.paragraph_format.space_before = Pt(1)
|
||||
if align: para.alignment = align
|
||||
for j, line in enumerate(str(text).split("\n")):
|
||||
if j:
|
||||
para = cell.add_paragraph()
|
||||
para.paragraph_format.space_after = Pt(1)
|
||||
_runs(para, line, size=size, color=color)
|
||||
if bold:
|
||||
for r in para.runs: r.bold = True
|
||||
|
||||
|
||||
def _caption(doc, text):
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.space_before = Pt(2)
|
||||
p.paragraph_format.space_after = Pt(8)
|
||||
r = p.add_run(text)
|
||||
r.italic = True
|
||||
r.font.size = Pt(8.5)
|
||||
r.font.color.rgb = GREY
|
||||
return p
|
||||
|
||||
|
||||
def _keep_rows_together(table):
|
||||
for row in table.rows:
|
||||
trPr = row._tr.get_or_add_trPr()
|
||||
cs = OxmlElement("w:cantSplit"); trPr.append(cs)
|
||||
|
||||
|
||||
# ----------------------------------------------------------- renderer ---
|
||||
class Renderer:
|
||||
def __init__(self, base_dir: Path, header_text: str, footer_text: str):
|
||||
self.base = Path(base_dir)
|
||||
self.doc = Document()
|
||||
self._setup_page()
|
||||
self._setup_styles()
|
||||
self._setup_header_footer(header_text, footer_text)
|
||||
self._update_fields_on_open()
|
||||
|
||||
# -- setup
|
||||
def _setup_page(self):
|
||||
s = self.doc.sections[0]
|
||||
s.page_width, s.page_height = Mm(210), Mm(297)
|
||||
s.top_margin = s.bottom_margin = Mm(22)
|
||||
s.left_margin = s.right_margin = Mm(20)
|
||||
s.header_distance = s.footer_distance = Mm(10)
|
||||
|
||||
def _setup_styles(self):
|
||||
st = self.doc.styles
|
||||
_set_font(st["Normal"], BODY_FONT, 10.5)
|
||||
pf = st["Normal"].paragraph_format
|
||||
pf.space_after = Pt(6); pf.line_spacing = 1.08
|
||||
_set_font(st["Heading 1"], BODY_FONT, 17, True, NAVY)
|
||||
st["Heading 1"].paragraph_format.space_before = Pt(18)
|
||||
st["Heading 1"].paragraph_format.space_after = Pt(8)
|
||||
_set_font(st["Heading 2"], BODY_FONT, 13, True, BLUE)
|
||||
st["Heading 2"].paragraph_format.space_before = Pt(12)
|
||||
st["Heading 2"].paragraph_format.space_after = Pt(4)
|
||||
_set_font(st["Heading 3"], BODY_FONT, 11, True, RGBColor(0x40, 0x40, 0x40))
|
||||
st["Heading 3"].paragraph_format.space_before = Pt(8)
|
||||
st["Heading 3"].paragraph_format.space_after = Pt(3)
|
||||
for name in ("List Bullet", "List Number"):
|
||||
_set_font(st[name], BODY_FONT, 10.5)
|
||||
st[name].paragraph_format.space_after = Pt(3)
|
||||
|
||||
def _setup_header_footer(self, header_text, footer_text):
|
||||
s = self.doc.sections[0]
|
||||
hp = s.header.paragraphs[0]
|
||||
hp.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
r = hp.add_run(header_text); r.font.size = Pt(8.5); r.font.color.rgb = GREY
|
||||
fp = s.footer.paragraphs[0]
|
||||
fp.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
r = fp.add_run(footer_text + " | Page "); r.font.size = Pt(8.5); r.font.color.rgb = GREY
|
||||
r = _field(fp, "PAGE", "1"); r.font.size = Pt(8.5); r.font.color.rgb = GREY
|
||||
r = fp.add_run(" of "); r.font.size = Pt(8.5); r.font.color.rgb = GREY
|
||||
r = _field(fp, "NUMPAGES", "1"); r.font.size = Pt(8.5); r.font.color.rgb = GREY
|
||||
|
||||
def _update_fields_on_open(self):
|
||||
el = OxmlElement("w:updateFields"); el.set(qn("w:val"), "true")
|
||||
self.doc.settings.element.append(el)
|
||||
|
||||
# -- blocks
|
||||
def render(self, blocks):
|
||||
for blk in blocks:
|
||||
kind = blk[0]
|
||||
getattr(self, "_b_" + kind)(*blk[1:])
|
||||
return self.doc
|
||||
|
||||
def _b_cover(self, kw):
|
||||
d = self.doc
|
||||
for _ in range(3): d.add_paragraph()
|
||||
p = d.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
||||
r = p.add_run(kw["kicker"]); r.font.size = Pt(12); r.font.color.rgb = BLUE; r.bold = True
|
||||
p = d.add_paragraph()
|
||||
r = p.add_run(kw["title"]); r.font.size = Pt(30); r.font.color.rgb = NAVY; r.bold = True
|
||||
p.paragraph_format.space_after = Pt(6)
|
||||
p = d.add_paragraph()
|
||||
r = p.add_run(kw["subtitle"]); r.font.size = Pt(13); r.font.color.rgb = GREY
|
||||
p.paragraph_format.space_after = Pt(14)
|
||||
if kw.get("image"):
|
||||
d.add_picture(str(self.base / kw["image"]), width=Mm(170))
|
||||
p = d.add_paragraph(); p.paragraph_format.space_before = Pt(10)
|
||||
for line in kw["lines"]:
|
||||
_runs(p, line, size=10.5); p.add_run().add_break()
|
||||
p = d.add_paragraph()
|
||||
r = p.add_run(kw["note"]); r.font.size = Pt(8.5); r.italic = True; r.font.color.rgb = GREY
|
||||
d.add_paragraph().add_run().add_break(WD_BREAK.PAGE)
|
||||
|
||||
def _b_toc(self):
|
||||
d = self.doc
|
||||
p = d.add_paragraph(); r = p.add_run("Contents"); r.font.size = Pt(17); r.bold = True; r.font.color.rgb = NAVY
|
||||
p = d.add_paragraph()
|
||||
_field(p, 'TOC \\o "1-2" \\h \\z \\u',
|
||||
"Table of contents: open in Word and press F9 (or accept the update prompt) to populate.")
|
||||
d.add_paragraph().add_run().add_break(WD_BREAK.PAGE)
|
||||
|
||||
def _b_h(self, level, text):
|
||||
self.doc.add_heading(text, level=level)
|
||||
|
||||
def _b_p(self, text, style):
|
||||
p = self.doc.add_paragraph(style=style) if style else self.doc.add_paragraph()
|
||||
_runs(p, text)
|
||||
|
||||
def _b_bullets(self, items):
|
||||
for it in items:
|
||||
_runs(self.doc.add_paragraph(style="List Bullet"), it)
|
||||
|
||||
def _b_numbers(self, items):
|
||||
for i, it in enumerate(items, 1):
|
||||
p = self.doc.add_paragraph()
|
||||
p.paragraph_format.left_indent = Mm(8)
|
||||
p.paragraph_format.first_line_indent = Mm(-6)
|
||||
p.paragraph_format.space_after = Pt(3)
|
||||
_runs(p, f"{i}. {it}")
|
||||
|
||||
def _b_table(self, header, rows, widths, caption, font_pt):
|
||||
d = self.doc
|
||||
n = len(header)
|
||||
t = d.add_table(rows=1, cols=n)
|
||||
t.style = d.styles["Table Grid"]
|
||||
t.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||||
for j, h in enumerate(header):
|
||||
c = t.rows[0].cells[j]
|
||||
_shade(c, HEADER_FILL)
|
||||
_cell_text(c, h, font_pt, bold=True, color=RGBColor(0xFF, 0xFF, 0xFF))
|
||||
for i, row in enumerate(rows):
|
||||
cells = t.add_row().cells
|
||||
for j in range(n):
|
||||
val = row[j] if j < len(row) else ""
|
||||
_cell_text(cells[j], val, font_pt)
|
||||
if i % 2 == 1: _shade(cells[j], ALT_FILL)
|
||||
if widths:
|
||||
t.autofit = False
|
||||
for j, w in enumerate(widths):
|
||||
t.columns[j].width = Mm(w) # grid columns: LibreOffice reads these
|
||||
for row in t.rows:
|
||||
for j, w in enumerate(widths):
|
||||
row.cells[j].width = Mm(w)
|
||||
# repeat header row
|
||||
trPr = t.rows[0]._tr.get_or_add_trPr()
|
||||
th = OxmlElement("w:tblHeader"); th.set(qn("w:val"), "true"); trPr.append(th)
|
||||
_keep_rows_together(t)
|
||||
if caption: _caption(d, caption)
|
||||
else: d.add_paragraph().paragraph_format.space_after = Pt(2)
|
||||
|
||||
def _b_kv(self, rows, widths, font_pt):
|
||||
d = self.doc
|
||||
t = d.add_table(rows=0, cols=2)
|
||||
t.style = d.styles["Table Grid"]
|
||||
t.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||||
for k, v in rows:
|
||||
cells = t.add_row().cells
|
||||
_shade(cells[0], ALT_FILL)
|
||||
_cell_text(cells[0], k, font_pt, bold=True)
|
||||
_cell_text(cells[1], v, font_pt)
|
||||
t.autofit = False
|
||||
for j, w in enumerate(widths):
|
||||
t.columns[j].width = Mm(w)
|
||||
for row in t.rows:
|
||||
for j, w in enumerate(widths):
|
||||
row.cells[j].width = Mm(w)
|
||||
_keep_rows_together(t)
|
||||
d.add_paragraph().paragraph_format.space_after = Pt(2)
|
||||
|
||||
def _b_img(self, path, width_mm, caption):
|
||||
self.doc.add_picture(str(self.base / path), width=Mm(width_mm))
|
||||
self.doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
if caption: _caption(self.doc, caption)
|
||||
|
||||
def _b_callout(self, title, body):
|
||||
d = self.doc
|
||||
t = d.add_table(rows=1, cols=1)
|
||||
t.style = d.styles["Table Grid"]
|
||||
t.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||||
c = t.rows[0].cells[0]
|
||||
_shade(c, CALLOUT_FILL)
|
||||
c.width = Mm(170)
|
||||
c.text = ""
|
||||
p = c.paragraphs[0]
|
||||
p.paragraph_format.space_before = Pt(3); p.paragraph_format.space_after = Pt(3)
|
||||
r = p.add_run(title); r.bold = True; r.font.color.rgb = NAVY; r.font.size = Pt(10.5)
|
||||
items = body if isinstance(body, list) else [body]
|
||||
for it in items:
|
||||
q = c.add_paragraph()
|
||||
q.paragraph_format.space_after = Pt(3)
|
||||
if isinstance(body, list):
|
||||
q.paragraph_format.left_indent = Mm(4)
|
||||
_runs(q, "\u2022 " + it, size=10)
|
||||
else:
|
||||
_runs(q, it, size=10)
|
||||
_keep_rows_together(t)
|
||||
d.add_paragraph().paragraph_format.space_after = Pt(2)
|
||||
|
||||
def _b_pb(self):
|
||||
self.doc.add_paragraph().add_run().add_break(WD_BREAK.PAGE)
|
||||
|
||||
def save(self, path):
|
||||
self.doc.save(str(path))
|
||||
@@ -0,0 +1,36 @@
|
||||
"""Which version of the business plan is being built (October 2026).
|
||||
|
||||
Plan A, ~180M THB: the launch plant (1 Duplex system + 1 Classic, every machine) with six cost levers.
|
||||
Plan B, ~215M THB: the same launch plant with everything in (none of the six levers).
|
||||
Both are priced without contingency and with the ramp-up reserve
|
||||
(docs/finance/total-investment.md, "Two plans").
|
||||
|
||||
build_plan.py sets PLAN before it calls the content modules' blocks(); call pick() and the
|
||||
helpers inside blocks(), never at import time.
|
||||
"""
|
||||
PLAN = "A"
|
||||
|
||||
NAME = {"A": "Plan A", "B": "Plan B"}
|
||||
PRICE = {"A": "~180M THB", "B": "~215M THB"}
|
||||
|
||||
|
||||
def is_a() -> bool:
|
||||
return PLAN == "A"
|
||||
|
||||
|
||||
def is_b() -> bool:
|
||||
return PLAN == "B"
|
||||
|
||||
|
||||
def pick(a, b):
|
||||
"""The Plan A or the Plan B variant of a value, text or list of blocks."""
|
||||
return a if PLAN == "A" else b
|
||||
|
||||
|
||||
def name() -> str:
|
||||
return NAME[PLAN]
|
||||
|
||||
|
||||
def label() -> str:
|
||||
"""e.g. 'Plan A (~180M THB)'."""
|
||||
return f"{NAME[PLAN]} ({PRICE[PLAN]})"
|
||||
@@ -0,0 +1,495 @@
|
||||
# Own Catalogue: Sales Map, Demand Forecast and Market Advisor
|
||||
|
||||
The idea (Alexander, 26 October 2026): with a catalogue of its own to
|
||||
press, sales by shop, region and location can drive a model that says
|
||||
what to press next. That needs three things: a **catalogue dashboard**
|
||||
with a **map of where the records sell**, a **demand model** that turns
|
||||
those sales into press decisions, and an **advisor agent** that points at
|
||||
market opportunities.
|
||||
|
||||
**Decided the same day (Alexander):**
|
||||
|
||||
- **A second company holds the catalogue, not the plant company.** It
|
||||
owns titles and licenses titles, and has its records pressed at the
|
||||
plant as a customer.
|
||||
- **It owns and licenses**: owned masters and licensed reissues are both
|
||||
in scope.
|
||||
- **Language models are self-hosted, on premises**, for the catalogue
|
||||
company's advisor as for the [plant assistant](plant-assistant.md); no
|
||||
hosted AI service.
|
||||
|
||||
This document plans the catalogue company's tools on the same open-source
|
||||
stack the plant runs, and the line between the two companies. It is a
|
||||
planning position: every figure without a source is an estimate. Nothing
|
||||
here is in the plant's business plan: the catalogue company's orders
|
||||
would reach the plant as ordinary customer orders, and its capital is its
|
||||
own.
|
||||
|
||||
## Why a catalogue company next to the plant
|
||||
|
||||
- **It can fill press time the plan does not sell.** At the planned 60 %
|
||||
specials, specials run only on the Duplex system, and the Classic runs
|
||||
at about two thirds of its ~128 records an hour
|
||||
([revenue model](finance/revenue-model.md#operating-picture-of-the-launch-plant-october-2026)).
|
||||
The spare third is 21 to 48 records an hour; at the plan's 60 to 70 %
|
||||
effectiveness, 16 hours and 300 days that is **~60,000 to 160,000
|
||||
records a year** (estimate), black and solid colours only. At the
|
||||
calculator's planning rate the launch plant is balanced and that spare
|
||||
time disappears, so the catalogue company's runs are fillers for idle
|
||||
hours, not a reason to buy presses.
|
||||
- **A repress at the plant is short.** The father and mother of every
|
||||
side are archived, so a repress skips cutting and the three artist
|
||||
gates and takes **~7 to 11 working days**; a mother gives about ten
|
||||
stamper sets and a father 5 to 10 mothers
|
||||
([production timeline](production-timeline.md#repress-the-shortest-path-in-the-plant)).
|
||||
A label that orders from a plant abroad presses big runs months ahead
|
||||
and carries the stock. A label next to a plant with its metal in the
|
||||
archive can press **small runs often, against measured demand**. That
|
||||
is what makes a demand model worth having: it is asked every few weeks,
|
||||
for a few hundred records, not once a year for thousands.
|
||||
- **There is a market for Thai catalogue abroad, and it runs through
|
||||
Japan.** EM Records (Osaka) reissues luk thung and molam compiled by
|
||||
Soi48, many of them first official reissues
|
||||
([EM1185LP](https://www.discogs.com/release/14467921-Various-Classic-Productions-by-Surin-Phaksiri-Luk-Thung-Gems-from-the-1960s-80s),
|
||||
[EM1198DLP](https://emrecords.ocnk.net/product/244)); Bangkok's
|
||||
ZudRangMa Records co-released an Angkanang Kunchai compilation with EM
|
||||
Records and Soi48 that launched in Japan with the singer present
|
||||
([Bangkok Post](https://www.bangkokpost.com/life/arts-and-entertainment/419399/legendary-molam-star-unleashed-again)).
|
||||
Japanese labels shipped 3.38 million records in 2025, and Japan is short
|
||||
of pressing capacity ([revenue model](finance/revenue-model.md#resurrec-japan-october-2026)).
|
||||
Contract pressing for Japanese labels now competes with ResurRec's new
|
||||
Japan plant; selling Thai catalogue into Japan does not.
|
||||
- **The reverse has been done.** P-Vine, a Japanese label, built its own
|
||||
plant (VGAP, 2024) because domestic plants took six months to a year
|
||||
and pressing abroad about six months, too slow for new releases. P-Vine
|
||||
also said that, having made records themselves, it found the ~¥4,000 a
|
||||
new record sells for "tight"
|
||||
([Phile-web, 15 October 2024](https://www.phileweb.com/news/audio/202410/15/25744.html),
|
||||
[BRUTUS, 2025](https://brutus.jp/en/post-430468/)). A catalogue earns the
|
||||
retail or wholesale price, and carries stock, rights and marketing in
|
||||
exchange.
|
||||
|
||||
**What the split does (our reading).** Stock, licence advances, royalty
|
||||
accounting and the risk of a title that does not sell sit in the
|
||||
catalogue company, not in the plant company, its BOI promotion or the
|
||||
capital plan its shareholders fund
|
||||
([total investment](finance/total-investment.md)). The plant stays a
|
||||
neutral supplier to every label, including this one.
|
||||
|
||||
## What the catalogue company holds
|
||||
|
||||
| Kind | What it is |
|
||||
|---|---|
|
||||
| Owned titles | Masters the company owns. Poy Records' releases are the obvious first ones (SST in Frankfurt cut lacquers for POY003, 005, 006 and 013, [equipment suppliers](suppliers/equipment-suppliers.md)); whether they move into the new company, or Poy Records becomes that company, is open |
|
||||
| Licensed titles | Masters licensed for vinyl: territories, term, sell-off period, royalty per unit, advance and recoupment |
|
||||
|
||||
Which titles, in which territories and until when, is the first list to
|
||||
write; nothing below can be tested without it.
|
||||
|
||||
## Arm's length between the two companies
|
||||
|
||||
The catalogue company is **a customer of the plant like any label**, and
|
||||
both sides keep it that way:
|
||||
|
||||
- **Orders** go through the plant's order intake and customer portal
|
||||
with a customer account and the same gates
|
||||
([artist platform](artist-platform.md#for-labels-and-regular-customers)).
|
||||
A purchase order in the catalogue company's books becomes a sales order
|
||||
and a work order in the plant's ERPNext; the plant's invoice becomes a
|
||||
purchase invoice on the other side.
|
||||
- **Prices** come from the plant's price list. Runs that fill idle slots
|
||||
can be sold as **standby pressing** (a flexible date, scheduled into
|
||||
idle press time, at a lower price), offered on the same terms to every
|
||||
customer, so the related company gets nothing another label could not
|
||||
(proposal; price and terms open). Thai law lets the Revenue Department
|
||||
adjust prices between related companies to arm's length (Revenue Code
|
||||
section 71 bis), and related companies with more than 200 million THB
|
||||
of revenue a year file a disclosure form
|
||||
([OECD transfer pricing profile, Thailand](https://www.oecd.org/content/dam/oecd/en/topics/policy-sub-issues/transfer-pricing/transfer-pricing-country-profile-thailand.pdf)).
|
||||
Whether the two companies are related in that sense depends on who
|
||||
holds the shares, which is open.
|
||||
- **Press dates.** The plant never moves another customer's date for the
|
||||
catalogue company. A label that suspects its plant favours a related
|
||||
label goes elsewhere.
|
||||
- **Data.** The plant's customers' orders, sizes and addresses never
|
||||
reach the catalogue company, and the catalogue company's sales never
|
||||
reach the plant. In the portal it sees what any customer sees: its own
|
||||
orders, its metal parts in the archive and the standby calendar.
|
||||
- **Metal.** Its fathers and mothers sit in the plant's archive under the
|
||||
same storage and retention terms as every customer's, which the
|
||||
customer contract still has to state
|
||||
([production timeline](production-timeline.md#repress-the-shortest-path-in-the-plant)).
|
||||
|
||||
## The questions the system answers
|
||||
|
||||
1. **What to press next**: which title, before it runs out where it
|
||||
sells.
|
||||
2. **How many**: a run sized to the demand of the next few months, since
|
||||
the next repress is two weeks away.
|
||||
3. **Which variant**: black or a colour, within what the plant can make
|
||||
(specials compete with every customer's specials on the Duplex; black
|
||||
and solid colours suit standby runs on the Classic's idle hours).
|
||||
4. **Where the stock goes**: its own store room, a distributor, or a shop
|
||||
on consignment.
|
||||
5. **Which titles to add**: licensing leads for a person to research.
|
||||
|
||||
## Data sources
|
||||
|
||||
| Source | What it gives | Location detail | Access and terms | Lands in |
|
||||
|---|---|---|---|---|
|
||||
| Own web shop, direct shop accounts, event sales (Poy Festival merch table) | Every sale with its ship-to or the event's place | postcode or city; the event venue | the company's own | its ERPNext: Sales Invoice, POS Invoice, Delivery Note |
|
||||
| Distributor statements | Units per account (shop) and territory per month, returns | shop or territory | the distribution agreement must require monthly sell-through by account, not only sell-in | its ERPNext: Channel Sales Report (new, below) |
|
||||
| Consignment shops | Monthly stock count, so sell-through per shop | the shop | the consignment agreement | its ERPNext: Channel Sales Report, consignment warehouse per shop |
|
||||
| Bandcamp | Raw sales report with the buyer's ship-to city, state, postcode and country for physical items; also as JSON through the Sales API ([help](https://get.bandcamp.help/en/articles/15263368-reading-your-raw-data-sales-report), [API](https://bandcamp.com/developer/sales)) | postcode or city | the label's own account | its ERPNext: Sales Invoice per Bandcamp payout with lines, or Channel Sales Report |
|
||||
| Record passport registrations | A buyer scans the sleeve code and, opting in, gives country and city: the end listener's place even when the record went through a shop or distributor | city | consent on the form; no IP address stored; the plant runs the passport for every customer and passes a customer's registrations on to it as its processor ([traceability](traceability.md)) | its analytics store, per-record rows keyed to the record key |
|
||||
| Streaming of its own artists | Top countries and cities per artist and per song in Spotify for Artists ([Spotify](https://artists.spotify.com/en/blog/how-to-read-your-spotify-for-artists-data)); country totals in the distributor's streaming statements | country, top cities | only for artists it releases | its analytics store, weekly series |
|
||||
| Interest list and pre-orders | "Tell me when it is pressed" sign-ups and pre-orders in its own shop, or through the plant's campaign service on the [artist platform](artist-platform.md) on the same terms as any label | country, city | consent on sign-up | its ERPNext: Lead, Sales Order with advance payments |
|
||||
| Discogs monthly data dumps | Every release, version and pressing in the Discogs database: labels, countries, formats, identifiers ([data.discogs.com](https://data.discogs.com), CC0) | country of release | free to use (CC0) | a local index on its own server, refreshed monthly |
|
||||
| Discogs API: have/want counts, lowest price and copies for sale ([API](https://www.discogs.com/developers)) | The collectors' view of a title | none useful | **Restricted Data** (marketplace data by name; the have/want counts come from users' collections and wantlists, which the terms also restrict): no commercial use, no storage longer than needed, never shown more than six hours old, no marketing analytics without Discogs' written permission ([API Terms of Use](https://support.discogs.com/hc/en-us/articles/360009334593-API-Terms-of-Use), checked October 2026); 60 requests a minute | not stored; live look-ups by a person only, unless Discogs agrees in writing |
|
||||
| Market totals | Country production and sales series, e.g. RIAJ for Japan ([revenue model](finance/revenue-model.md#resurrec-japan-october-2026)) | country | public | a context layer on the map |
|
||||
| Events | Tours, festival slots, film or ad syncs, anniversaries, Record Store Day | city, date | entered by the team | its ERPNext (a dated note on the Release) |
|
||||
|
||||
**Sell-in is not sell-through.** A distributor buying 300 copies says
|
||||
nothing about fans until the shops sell them; returns can come months
|
||||
later. The model uses sell-through wherever an agreement provides it and
|
||||
treats sell-in as a weaker signal.
|
||||
|
||||
**Stockouts hide demand.** Weeks in which a title was out of stock at a
|
||||
shop record zero sales, not zero demand. Those weeks are marked censored,
|
||||
and the interest list and passport registrations carry the demand the
|
||||
till could not.
|
||||
|
||||
## Where the data lives (ERPNext touchpoints)
|
||||
|
||||
The catalogue company follows the rule the plant set for itself: ERPNext
|
||||
is its only system of record, its tools read and write it, and only
|
||||
machine-speed and signal data stays outside
|
||||
([digital factory](digital-factory.md#erpnext-the-plants-erp)). It runs
|
||||
**its own ERPNext site**, not a second company inside the plant's
|
||||
ERPNext: separate books, a separate database and no shared users, so
|
||||
neither company can see the other's records. The packaging the plant
|
||||
plans to use runs several sites from one installation (frappe-nix with
|
||||
per-site systemd units, [hosting on NixOS](digital-factory.md#hosting-on-nixos)).
|
||||
|
||||
| Object | In its ERPNext | Outside (its analytics store) |
|
||||
|---|---|---|
|
||||
| Release, side, item per format and variant | custom Release and Side documents from the same `cnx_erp` app; Item per release, format and variant | none |
|
||||
| Rights | **new** Licence document: licensor, territories, term, sell-off end, royalty basis and rate, advance and recoupment; Release links to it; "owned" or "licensed" on the Release | none |
|
||||
| Royalties | royalty accrual per unit sold, posted as journal entries; a royalty statement print format per licensor | none |
|
||||
| Places | Address gains latitude and longitude of its **postcode or city centroid** (custom fields, filled by the geocoder); shops are Customers in a "Shop" group with their exact location; regions are ERPNext Territories | none |
|
||||
| Sales | Sales Invoice, POS Invoice, Delivery Note | none |
|
||||
| Third-party sales | **new** Channel Sales Report: source (distributor, Bandcamp, consignment count), period, lines of item, place (shop, territory or city), units sold, returned, on hand | none |
|
||||
| Stock | Warehouses: its own store room, each distributor, one per consignment shop | none |
|
||||
| Pressing | Purchase Order to the plant, Purchase Invoice from it; repress-ready status (archived father and mother, stamper sets left) read from the plant's customer portal | none |
|
||||
| Recommendations | **new** Catalogue Recommendation: title and variant, quantity, the forecast quantiles it rests on, the reason, status (proposed, accepted, rejected), link to the Purchase Order it became | the full forecast rows per title, place and month |
|
||||
| Market opportunities | CRM Opportunity and Lead (new shop, distributor, territory, licensing lead) | none |
|
||||
| External signals | none | weekly streams per country and city, passport registrations, Discogs dump index, map aggregates |
|
||||
|
||||
The forecast rows and map aggregates are derived and can be rebuilt from
|
||||
ERPNext and the signal series at any time; nobody types into them.
|
||||
Decisions and their outcomes are ERPNext documents, which is what lets
|
||||
the model and the advisor be scored later.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph S[Sources]
|
||||
SHOP[Web shop, shop accounts,<br/>event POS]
|
||||
DIST[Distributor and<br/>consignment statements]
|
||||
BC[Bandcamp sales report]
|
||||
INT[Interest list,<br/>pre-orders]
|
||||
PP[Record passport<br/>registrations, opt-in]
|
||||
STR[Streaming by country<br/>and city, own artists]
|
||||
DG[Discogs CC0 dump]
|
||||
end
|
||||
subgraph C[Catalogue company, on premises]
|
||||
ERP[(Its ERPNext<br/>releases, licences, sales,<br/>stock, channel reports)]
|
||||
MD[(Analytics store<br/>signal series, forecast rows)]
|
||||
FC[Forecast job]
|
||||
DASH[Catalogue dashboard<br/>and sales map]
|
||||
AG[Market advisor,<br/>self-hosted model]
|
||||
TEAM[Team decides]
|
||||
end
|
||||
subgraph P[Plant company]
|
||||
PORTAL[Order intake and<br/>customer portal]
|
||||
end
|
||||
SHOP --> ERP
|
||||
DIST --> ERP
|
||||
BC --> ERP
|
||||
INT --> ERP
|
||||
PP --> MD
|
||||
STR --> MD
|
||||
DG --> MD
|
||||
ERP --> FC
|
||||
MD --> FC
|
||||
FC --> MD
|
||||
FC -->|recommendations| ERP
|
||||
ERP --> DASH
|
||||
MD --> DASH
|
||||
DASH --> AG
|
||||
AG -->|drafts: recommendations,<br/>opportunities| ERP
|
||||
ERP --> TEAM
|
||||
TEAM -->|purchase order| PORTAL
|
||||
PORTAL -->|order status, archive,<br/>standby calendar, invoice| ERP
|
||||
```
|
||||
|
||||
## Personal data
|
||||
|
||||
Buyers' names and addresses are personal data under Thailand's PDPA
|
||||
(B.E. 2562, fully in force since 1 June 2022;
|
||||
[overview](https://pacmap.dev/regulation/th-pdpa-2019)), and so is a sales
|
||||
location fine enough to point at one buyer. The catalogue company is the
|
||||
controller of its buyers' data; the plant handles passport registrations
|
||||
for it as a processor, under a processing agreement. The map is built so
|
||||
that it never needs a person:
|
||||
|
||||
- addresses are geocoded to the **postcode or city centroid**, never to
|
||||
the house;
|
||||
- a map cell shows a count only when it holds at least five buyers;
|
||||
smaller cells merge into the surrounding region;
|
||||
- only shops and venues, which are businesses, appear as points;
|
||||
- passport registrations ask for country and city, with consent, and
|
||||
store no name, e-mail or IP address unless the fan asks to be told
|
||||
about represses;
|
||||
- the advisor sees aggregates only; no personal data goes into a prompt.
|
||||
|
||||
## The catalogue dashboard
|
||||
|
||||
One internal tool for the catalogue company's team, with five views.
|
||||
|
||||
1. **Catalogue.** Every title and variant: owned or licensed, licence
|
||||
territories and expiry, stock by place (store room, distributors, each
|
||||
consignment shop), sell-through over 4, 13 and 52 weeks, weeks of
|
||||
cover at the current rate, repress-ready (from the plant's portal),
|
||||
last pressing, royalties accrued, and a flag when a recommendation is
|
||||
open.
|
||||
2. **Sales map.** Sales density by city or hexagon over time, with a
|
||||
time slider and filters by title, genre, variant and channel. Layers:
|
||||
own sales; shops with its stock (pins sized by stock, coloured by
|
||||
weeks of cover); distributor territories; streaming listeners of its
|
||||
artists; passport registrations; interest-list sign-ups; country
|
||||
totals (RIAJ and others) as context. A **white-space layer** marks
|
||||
places where listeners, sign-ups or registrations are high and sales
|
||||
or stock are low: the map's version of a market opportunity.
|
||||
3. **Title page.** The sales curve with out-of-stock weeks shaded, the
|
||||
forecast fan for the next months, the title's own map, its archived
|
||||
metal and its licence clock.
|
||||
4. **Repress planner.** Proposed runs against the plant's standby
|
||||
calendar (the idle slots the plant publishes to every customer) and
|
||||
normal lead times, with the Classic's idle hours as the default for
|
||||
black and solid colours.
|
||||
5. **Advisor inbox.** The advisor's notes, each with its numbers linked
|
||||
to the rows they came from, and accept or reject buttons that create
|
||||
or close the ERPNext document.
|
||||
|
||||
**How it is built.** The same open-source stack as the plant's tools
|
||||
([digital factory](digital-factory.md#the-factory-application)): Rust
|
||||
(axum, minijinja, HTMX), its own ERPNext integration user, NixOS, managed
|
||||
like the plant's machines but on the catalogue company's own server and
|
||||
disks; internal only, not public. The map is open source and
|
||||
self-hosted, in line with the plant's open-source decision
|
||||
([digital factory](digital-factory.md#open-source-throughout-and-working-with-other-plants)):
|
||||
|
||||
- **MapLibre GL JS** (BSD-3-Clause) in the browser;
|
||||
- **vector tiles from OpenStreetMap data** (ODbL, attribution on the map)
|
||||
as one Protomaps PMTiles file (BSD-3-Clause tooling) served from its
|
||||
own server, so no Google Maps or Mapbox account;
|
||||
- **H3** hexagons (Apache-2.0) for binning;
|
||||
- **geocoding offline**: postcode and city centroids from GeoNames
|
||||
(CC BY 4.0), with a self-hosted Nominatim only if centroids prove too
|
||||
coarse.
|
||||
|
||||
## The demand model
|
||||
|
||||
The model grows with the data. Each stage has to beat the simpler one
|
||||
before it is allowed to decide anything.
|
||||
|
||||
**Stage 0: no sales history (a new title or a reissue candidate).**
|
||||
Demand is borrowed from comparable titles (genre, era, the artist's
|
||||
streaming, how many pressings already exist per the Discogs dump) and
|
||||
tested cheaply with a **pre-order**: in the company's own shop, or
|
||||
through the plant's campaign service on the
|
||||
[artist platform](artist-platform.md#fan-funded-campaigns) on the same
|
||||
terms as any label. If the pre-orders reach the minimum run, press; if
|
||||
not, refund and learn.
|
||||
|
||||
**Stage 1: the first months of sales.** A reorder rule, not a model:
|
||||
sell-through per title and place per week, with out-of-stock weeks left
|
||||
out of the rate. Repress when the stock that will be left at the end of
|
||||
the repress lead time (~7 to 11 working days at the plant, plus transport
|
||||
to where it sells) falls below a safety stock. Dashboard view 1 shows
|
||||
this from the first sale.
|
||||
|
||||
**Stage 2: a year of data and a few dozen titles (thresholds are
|
||||
estimates).** A hierarchical count model of weekly sales per title and
|
||||
place (negative binomial, with partial pooling across titles of the same
|
||||
genre and across nearby places), so a title with three months of history
|
||||
borrows strength from its neighbours. Inputs: past sales with censoring
|
||||
for stockouts, the artist's streaming in that place with a lag, price,
|
||||
variant, season (year-end, Record Store Day), events, age since release,
|
||||
passport registrations and sign-ups. Output: a forecast **distribution**
|
||||
(quantiles), never a single number. Runs as a nightly batch job on its
|
||||
server (Python with statsmodels or PyMC from nixpkgs, as a systemd
|
||||
timer).
|
||||
|
||||
**How many to press.** With a two-week repress the run only has to cover
|
||||
the next few months, so it is sized by the classic stocking rule: press
|
||||
the quantile of next-period demand at which the margin lost on a missed
|
||||
sale balances the cost of a record left unsold.
|
||||
|
||||
- Missed-sale cost: net selling price after the channel's margin, minus
|
||||
what the record costs the catalogue company (the plant's price, 3.40
|
||||
to 4.25 USD a standard record in the
|
||||
[revenue model](finance/revenue-model.md#operating-picture-of-the-launch-plant-october-2026)
|
||||
before any standby discount, plus jacket, sleeve and freight), minus
|
||||
royalty.
|
||||
- Unsold-record cost: that cost plus storage and the money tied up,
|
||||
minus any salvage value (an unsold record can be label-punched and
|
||||
granulated into regrind,
|
||||
[pressing line](equipment/pressing-line.md#newbilt-range-making-vinyl-europe-2026-flyers),
|
||||
if the plant takes it back; terms open).
|
||||
- Floor: the plant's minimum run and setup terms, and within one
|
||||
stamper's life (1,000 to 2,000 pressings,
|
||||
[production timeline](production-timeline.md#repress-the-shortest-path-in-the-plant)).
|
||||
|
||||
The catalogue company's wholesale and retail prices, the standby price
|
||||
and the packaging cost are not in any document yet; they are inputs to
|
||||
fill before the rule produces a number.
|
||||
|
||||
**How it is checked.** Rolling back-tests on its own history: do the
|
||||
80 % intervals contain about 80 % of outcomes, and does following the
|
||||
model give fewer out-of-stock weeks and less stock unsold after a year
|
||||
than the Stage 1 rule did? Accepted and rejected recommendations, with
|
||||
what then sold, are ERPNext records, so this is a report, not a project.
|
||||
|
||||
## The market advisor
|
||||
|
||||
An agent that reads the dashboard's data and writes a **weekly note**
|
||||
plus answers to questions ("where does molam sell outside Thailand?",
|
||||
"which shops stock out fastest?"). It **proposes and never acts**: it
|
||||
places no order with the plant, sends no e-mail to a shop or licensor and
|
||||
changes no price. An accepted proposal becomes an ERPNext document
|
||||
created by a person.
|
||||
|
||||
What it looks for:
|
||||
|
||||
- **Repress now**: weeks of cover below the repress lead time plus
|
||||
safety, with the run size from the model.
|
||||
- **Move stock**: a shop out of stock while another sits on months of
|
||||
cover.
|
||||
- **White space**: places with listeners, sign-ups or registrations and
|
||||
no shop or distributor; proposed as a CRM Lead for a shop or
|
||||
distributor to approach.
|
||||
- **Variants**: colours that sell faster in a region than black, within
|
||||
what the plant's standby calendar offers.
|
||||
- **Events**: an artist's tour or festival date in a city where stock is
|
||||
thin.
|
||||
- **Licensing leads**: titles in genres that sell for the company that,
|
||||
per the Discogs dump, were never reissued or not for decades, with the
|
||||
original label named. A lead for a person to research; the advisor
|
||||
never says that rights are available.
|
||||
|
||||
How it is kept honest:
|
||||
|
||||
- the numbers come from the model and the database, the words from the
|
||||
agent; every figure in a note links to its row and date;
|
||||
- it separates the company's own data from outside signals and says how
|
||||
sure it is;
|
||||
- it has read-only tools: the dashboard API, the forecast rows, ERPNext
|
||||
reports through a read-only integration user, the local Discogs dump
|
||||
index, market notes, and web search through a self-hosted SearXNG for
|
||||
news (tours, syncs, competing reissues); it has no access to the
|
||||
plant's systems beyond the customer portal;
|
||||
- every suggestion and its outcome is logged, and after six months it is
|
||||
scored against the plain reorder rule; if it does not beat it, it
|
||||
becomes a report instead of an agent.
|
||||
|
||||
**Which model runs it** (decided: self-hosted, on premises). The same
|
||||
software as the [plant assistant](plant-assistant.md), as the catalogue
|
||||
company's own instance with its own data and permissions, and an
|
||||
open-weights model on hardware it controls. The forecasting is ordinary
|
||||
statistics, so the language model only reads, searches and writes; a
|
||||
mixture-of-experts model such as Typhoon 2.5 may run on a CPU server
|
||||
(to be measured, as for the plant). Running it on the plant's `vinyl-ai`
|
||||
instead would put the catalogue company's sales data into prompts on the
|
||||
plant company's hardware; that needs a written hosting agreement and is
|
||||
an open decision, not the default.
|
||||
|
||||
## How it works with the plant
|
||||
|
||||
- **Scheduling.** Its orders enter the plant's schedule like any
|
||||
customer's; standby runs go into idle slots, the Classic's first, and
|
||||
never move another customer's date.
|
||||
- **Metal archive.** Its fathers and mothers sit in the archive room with
|
||||
every customer's ([facility security](facility-security.md)); the
|
||||
portal shows it what is archived and how many stamper sets are left.
|
||||
- **Traceability.** Its sleeves carry the record passport code like every
|
||||
other record, which is what makes the registration layer of the map
|
||||
possible ([traceability](traceability.md)).
|
||||
- **Artist platform.** It can use the plant's campaign service on the
|
||||
same terms as any label; its own web shop is its own.
|
||||
- **Money.** The plant's [revenue model](finance/revenue-model.md) does
|
||||
not count on its orders. Its working capital (stock, licence advances)
|
||||
and its systems are its own, outside the plant's
|
||||
[total investment](finance/total-investment.md).
|
||||
|
||||
## Phasing
|
||||
|
||||
| Roadmap phase | Step |
|
||||
|---|---|
|
||||
| 0, validate (now) | List the titles to own and to license, with rights and territories; collect Poy Records' existing sales (Bandcamp report, shops, festival) into one sheet and draw the first map by hand; decide whether to ask Discogs for written permission |
|
||||
| 1 to 2, quotes and commit | Found the catalogue company (shareholders, name, whether Poy Records is it or moves into it); the plant's customer terms with standby pressing, data and archive clauses |
|
||||
| 3, build | Its ERPNext site with Licence, Channel Sales Report, Catalogue Recommendation, geocode fields, consignment warehouses; dashboard views 1 and 2; geocoder and tiles on its own server |
|
||||
| 4, launch | First standby runs at the plant on the Stage 1 rule; passport registrations live; advisor version 0 (rule-based notes written up by the self-hosted model) |
|
||||
| 5, expand | Stage 2 model once there is a year of data; licensing leads; the software offered to other labels, open source like the plant stack |
|
||||
|
||||
## Rough cost (estimates)
|
||||
|
||||
All of it borne by the catalogue company.
|
||||
|
||||
| Item | Effort or cost |
|
||||
|---|---|
|
||||
| Company setup, its ERPNext site with Thai tax, the catalogue documents and royalty statement | 1 to 2 person-months, or a partner quote for the ERPNext configuration |
|
||||
| Importers (Bandcamp, distributor and consignment statements, streaming exports) | 0.5 to 1 person-month |
|
||||
| Dashboard and sales map | 1.5 to 3 person-months, less where the plant's open-source code is reused |
|
||||
| Forecast job: Stage 1 rule, then the Stage 2 model | 0.5, then 1 to 2 person-months |
|
||||
| Advisor: tools, prompts, logging, scoring on the plant assistant's software | 0.5 to 1 person-month |
|
||||
| On-premises server for ERPNext, dashboard, forecast and model (CPU first) | a few thousand USD; a GPU only if the CPU trial is too slow ([plant assistant](plant-assistant.md#rough-cost-estimates) for the GPU figure) |
|
||||
|
||||
## Risks
|
||||
|
||||
- **Stock is the risk a pressing plant normally avoids.** It now sits in
|
||||
the catalogue company; small, frequent represses keep it small, and the
|
||||
model's job is to keep it smaller.
|
||||
- **Related-party pricing.** Prices between the two companies must be the
|
||||
plant's published terms, documented, or the Revenue Department can
|
||||
adjust them.
|
||||
- **Neutrality.** Other labels must be able to trust that the plant does
|
||||
not favour its neighbour; the arm's-length rules above go into the
|
||||
customer terms, not only into this document.
|
||||
- **Small data.** A few dozen titles is little to learn from; the stages
|
||||
above exist so that no complex model decides before it has beaten a
|
||||
simple rule.
|
||||
- **Data access.** Distributors and shops report sell-through only if the
|
||||
contract says so; that clause goes into every agreement from the
|
||||
first.
|
||||
- **Platform terms.** Discogs' marketplace and wantlist data are
|
||||
restricted; the plan uses its CC0 dumps and live look-ups by a person
|
||||
unless Discogs agrees in writing.
|
||||
- **Distraction.** A label is a second business for the same people. Its
|
||||
runs stay fillers for idle press time until the plant's own order book
|
||||
is validated ([roadmap](roadmap.md) item 1).
|
||||
|
||||
## Open decisions
|
||||
|
||||
1. **The catalogue company**: who holds its shares, its name, and whether
|
||||
Poy Records is that company or its titles move into it.
|
||||
2. **Working capital** for stock and licence advances: how much and from
|
||||
whom.
|
||||
3. **Standby pressing**: price, terms and the minimum run, offered to
|
||||
every customer of the plant.
|
||||
4. **Discogs**: ask for written permission to use have/want and
|
||||
marketplace data commercially, or work from the CC0 dumps alone.
|
||||
5. **Where its systems run**: its own on-premises server (the default
|
||||
here) or hardware at the plant under a written hosting agreement.
|
||||
6. **Other labels**: whether the software is offered to them, and on
|
||||
what terms (it is open source either way).
|
||||
|
After Width: | Height: | Size: 232 KiB |
|
After Width: | Height: | Size: 401 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 318 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 455 KiB |
@@ -0,0 +1,452 @@
|
||||
# Overhead Crane, Maintenance Workshop and Visitor Corridor
|
||||
|
||||
Three additions to the building program, decided in October 2026:
|
||||
|
||||
1. **An overhead crane over the whole factory floor**, so machines can be
|
||||
moved in, out and around without hiring a mobile crane or dragging
|
||||
them on skates.
|
||||
2. **A maintenance workshop** with a crane-served service bay, so a
|
||||
machine can be lifted out of the line and serviced properly instead of
|
||||
in place.
|
||||
3. **A glazed visitor corridor at ground level through the factory**, so
|
||||
guided tours see the whole process without being exposed to noise,
|
||||
dust or plating chemistry, and without production having to stop or
|
||||
escort people across the floor.
|
||||
|
||||
They are planned together because they collide with each other and with
|
||||
the building: the crane decides where walls may go, the workshop sits
|
||||
where the crane parks, and the corridor runs under the crane runway.
|
||||
This page states what each one needs, what it changes in the
|
||||
[construction RFQ](finance/phase1-construction-rfq.md), the
|
||||
[zone table](scale.md) and [facility security](facility-security.md), and
|
||||
what is still open. Every figure without a vendor or contractor behind it
|
||||
is an estimate.
|
||||
|
||||
## 1. Overhead crane
|
||||
|
||||
### What it has to lift
|
||||
|
||||
| Item | Weight | Source |
|
||||
|---|---|---|
|
||||
| Newbilt press (HRP 12) | 1,350 kg | [Newbilt Duplex site requirements](equipment/newbilt/) |
|
||||
| Newbilt extruder | 660 kg | same |
|
||||
| Newbilt hydraulic aggregate (250 L tank, 50 L accumulator) | 600 kg | same, plus the [budgetary offer](equipment/newbilt/) |
|
||||
| Newbilt Classic automatic press | **unknown**, ask Newbilt with the re-quote | not in any document yet (it replaced the Pheenix AD12 in the fleet plan, October 2026) |
|
||||
| Sibert VSP punch / VSF finisher / VSC coiner | 200 / 250 / 1,000 kg; VSP and VSF on castors, the VSC sheet lists none, so it is a lift | [Sibert specifications](equipment/sibert/) (2022 and 2023) |
|
||||
| Pheenix plating units (PPPU, PDPU), silvering unit, prep bench | unknown: dimensions published, weights not; each plating unit carries a 385 L tank, lifted empty | [Pheenix flyers](equipment/pheenix-alpha/), [galvanics and stamper prep](equipment/galvanics.md); ask with the quote |
|
||||
| Water-treatment evaporator | unknown, lifted empty | to be asked with the quote |
|
||||
|
||||
**Planning capacity: 5 t safe working load** (estimate). It covers the
|
||||
heaviest known lift with its lifting beam and slings at a wide margin and
|
||||
leaves room for the automatic press until Newbilt states the Classic's
|
||||
weight. If the Classic turns out under about 2.5 t, price a **3.2 t** crane as the
|
||||
alternative: lighter runway and frame, and possibly a lighter inspection
|
||||
regime. Thai cranes fall under the Ministry of Labour's 2021 Ministerial
|
||||
Regulation on machinery, cranes and boilers (the same regulation that
|
||||
covers the boiler); a crane-industry summary puts cranes above 3 t on an
|
||||
engineer inspection every three months. Confirm the intervals against the
|
||||
regulation text before choosing the capacity.
|
||||
|
||||
The crane does **not** serve the outdoor plant. Boiler, chiller, cooling
|
||||
tower, transformer and the BESS enclosure sit outside the main building
|
||||
and are set by mobile crane as normal.
|
||||
|
||||
### What kind of crane
|
||||
|
||||
- **Single-girder electric overhead travelling (EOT) crane** spanning the
|
||||
building's full 25 m width (about 24 m between rail centres), with an
|
||||
electric wire-rope hoist. This is the default factory crane in the Thai
|
||||
market, where most bridge cranes are imported from China and installed
|
||||
by local firms.
|
||||
- **Inverter drives on hoist and travel** with a slow creep speed, because
|
||||
the job is setting precision machines on levelling pads, not moving
|
||||
steel. Radio remote control, so the operator walks beside the load.
|
||||
- Overload limiter, hoist limit switches, warning horn and light, and
|
||||
**protected zones** (a standard option on modern crane controls) so the
|
||||
hook cannot carry a load over the visitor corridor or over enclosed
|
||||
rooms.
|
||||
- **Light duty class.** Machine moves are a few a year plus occasional
|
||||
maintenance lifts, so a light class (around ISO 4301 M3 to M4, estimate)
|
||||
is enough.
|
||||
- **Clean running.** The crane travels over a press hall where dust in a
|
||||
groove is an audible defect: enclosed gearboxes, lubrication-free wheels
|
||||
and an enclosed conductor rail, and the crane **parks over the
|
||||
workshop**, not over the presses.
|
||||
|
||||
### What "the whole factory" means in practice
|
||||
|
||||
The runway runs the full length of the **production compartment**, wall
|
||||
to wall and end to end: press hall, material area, stamper prep,
|
||||
finishing, the workshop and the machine bay. It stops at the fire wall
|
||||
that separates production from the finished-goods warehouse
|
||||
([RFQ §1a](finance/phase1-construction-rfq.md) requires that wall to be
|
||||
rated EI 60 or EI 120, and a crane cannot run through a fire wall). The
|
||||
warehouse is forklift territory with no heavy lifts, so nothing is lost.
|
||||
With a 300 to 500 m² warehouse at the dock end, the runway is roughly 40
|
||||
to 48 m of the 60 m building (estimate, set by the warehouse depth). If
|
||||
the fire strategy ends up without that wall, the runway can run the full
|
||||
60 m.
|
||||
|
||||
### What it changes in the building
|
||||
|
||||
This is where the cost is, and it has to go into the shell price before
|
||||
the contractor quotes. The RFQ currently says **"no crane"**.
|
||||
|
||||
1. **Frame designed for crane loads.** Crane brackets or stepped columns,
|
||||
runway beams and rails along both long walls, end stops, and a frame
|
||||
sized for the wheel loads and braking forces. In a PEB this is a known
|
||||
option, but it is a different frame from the one priced so far.
|
||||
2. **Hook height under the 7.0 m low eave.** The roof falls across the
|
||||
25 m width, so the low side governs. With a single-girder hoist the
|
||||
rail would sit somewhere around 5.5 to 6 m and the hook around 5 m
|
||||
(estimate; it depends on the haunch depth at the low eave). That is
|
||||
enough to lift a press and carry it low along a clear aisle, which is
|
||||
the right way to move a machine anyway, but not to carry it over other
|
||||
machines or rooms. Ask the contractor for the achievable hook height at
|
||||
7.0 m and price **+1.0 m on the low eave as an option**. The option
|
||||
costs wall cladding and about 10% more conditioned volume, so take it
|
||||
only if the quoted hook height falls short.
|
||||
3. **No full-height cross walls inside the crane zone.** A wall across
|
||||
the building would stop the bridge. Partitions inside the zone stop
|
||||
below the bridge, and where a load has to pass (press hall to
|
||||
workshop), the partition has a **full-height opening closed by a
|
||||
high-speed door**, because the hoist rope comes down from above and
|
||||
needs a slot all the way up. Separation between zones is then by air
|
||||
pressure, not by a sealed wall (see the workshop below).
|
||||
4. **Rooms inside the crane zone are boxes with lids.** Galvanics, stamper
|
||||
prep and any other enclosed room in the zone are built room-in-room
|
||||
with their own ceilings below the bridge. Where heavy kit has to go in
|
||||
(electroforming cells, the water-treatment evaporator), the ceiling
|
||||
gets a **removable crane hatch**. The bridge passes over the lids;
|
||||
loads do not (protected zones).
|
||||
5. **The roof space belongs to the crane first.** HVAC ducts, sprinkler
|
||||
mains, cable trays and lighting run above the crane envelope or along
|
||||
the walls, never through the band the bridge travels in. Sprinkler
|
||||
coverage under the bridge is an item for the fire designer.
|
||||
6. **Vibration and the cutting room.** The crane runs on the building
|
||||
frame. Keep the mastering and cutting room outside the crane zone (it
|
||||
belongs at the quiet front of the building with the offices and
|
||||
archive anyway), on a slab isolated from the frame columns, and do not
|
||||
run the crane during a cutting session.
|
||||
|
||||
### Machine door: how machines get in and out
|
||||
|
||||
The vehicle ramp in the RFQ (10.5 m at 1:10, 4.5 m wide) already sits at
|
||||
the far end of the building, opposite the loading docks. That end gets
|
||||
the **machine door** and the **machine bay**:
|
||||
|
||||
- An insulated sectional door of about **4.5 m wide × 5.0 m high**
|
||||
(estimate) with full seals. It opens only for machine moves, a few
|
||||
times a year, so it does not undermine the airtight envelope the HVAC
|
||||
and the burning-season PM design depend on; schedule moves outside
|
||||
February to April where possible.
|
||||
- The crane runway runs right up to the inside face of the door.
|
||||
- **Method:** a rigid truck reverses up the ramp and through the door
|
||||
into the machine bay, and the crane lifts the machine off the bed
|
||||
inside the building. Three checks for the contractor: the ramp
|
||||
transitions against the truck's ground clearance, door headroom for the
|
||||
truck, and the machine-bay slab rated for **truck wheel loads**, which
|
||||
are point loads and not covered by the 30 kN/m² distributed rating.
|
||||
- **Fallback:** a truck-mounted crane sets the machine on skates at the
|
||||
door threshold and the overhead crane takes it from there.
|
||||
|
||||
### Rough cost (estimate)
|
||||
|
||||
| Item | THB | USD |
|
||||
|---|---|---|
|
||||
| 5 t × ~24 m single-girder EOT crane, supplied and installed | 1.0M – 2.5M | 30k – 76k |
|
||||
| Runway beams, rails, end stops, conductor rail, ~2 × 45 m | 0.8M – 1.6M | 24k – 48k |
|
||||
| Frame premium for crane loads (brackets, heavier columns) | 1.0M – 2.5M | 30k – 76k |
|
||||
| Machine door and truck-rated slab in the machine bay | 0.4M – 0.9M | 12k – 27k |
|
||||
| **Crane total** | **~3.2M – 7.5M** | **~97k – 227k** |
|
||||
|
||||
## 2. Maintenance workshop and machine bay
|
||||
|
||||
### Where
|
||||
|
||||
At the ramp end, inside the crane zone, between the machine door and the
|
||||
press hall. One space does two jobs:
|
||||
|
||||
- **Machine bay**: new machines land here, are unpacked, inspected and
|
||||
documented before they go to the floor; machines leaving for vendor
|
||||
repair are crated here.
|
||||
- **Workshop**: a machine is disconnected, lifted out of the line with
|
||||
the crane, set down on the service bay and worked on properly, with
|
||||
tools, light and space around it.
|
||||
|
||||
The crane's parking position is above it, which keeps the idle crane off
|
||||
the press hall.
|
||||
|
||||
### What is in it
|
||||
|
||||
| Area | Contents | Size (estimate) |
|
||||
|---|---|---|
|
||||
| Service bay | Clear crane-served floor for one press-sized machine with about 1.5 m working space all round (a Newbilt press stands on under 1 m², an AD12 on about 3.25 m²); bunded drip-tray floor; 400 V three-phase and 230 V outlets; compressed air drop; task lighting | ~60 m² |
|
||||
| Bench area | Workbenches and vices, pillar drill, hydraulic hose crimper (the press hydraulics run at 180 to 200 bar and hoses are a routine spare), closed-loop parts washer, mould and platen bench, optionally a small lathe and mill for brackets and one-off parts | ~40 m² |
|
||||
| Spares store | Lockable, shelved; every part tracked in ERPNext (stock, reorder level, which machine it fits) | ~20 – 30 m² |
|
||||
| Hot-work corner | Welding screen and fume extractor; hot-work permit, because paper, cartons and hydraulic oil share the building | ~10 m² |
|
||||
| **Total** | | **~100 – 150 m²** |
|
||||
|
||||
**Spares are the uptime lever.** Newbilt service comes from Germany and
|
||||
Pheenix from Sweden; the northern-dispatch service question in the
|
||||
[supplier map](suppliers/equipment-suppliers.md) only partly closes that
|
||||
gap. A press down for a seal or a heater should be back the same day from
|
||||
the shelf, not after a courier.
|
||||
|
||||
### Keeping the workshop's dirt out of the press hall
|
||||
|
||||
Grinding dust, welding fume and oil mist must not reach the presses. Since
|
||||
the crane zone rules out a sealed full-height wall (section 1), the
|
||||
workshop is held at **negative pressure** to the press hall: local
|
||||
extraction at the welding and grinding positions, an exhaust that keeps
|
||||
air flowing from the hall into the workshop over the top of the partition
|
||||
and through the high-speed door, never the other way. The HVAC zoning in
|
||||
[facility security](facility-security.md) gains the workshop as a zone
|
||||
below the press hall in the pressure cascade.
|
||||
|
||||
### Oil, waste and water
|
||||
|
||||
- Hydraulic oil drums on spill pallets, spill kits at the service bay,
|
||||
used oil and oily rags collected by a licensed waste contractor under
|
||||
DIW manifests.
|
||||
- **No floor drain.** A dry workshop keeps the zero contaminated water
|
||||
commitment in [sustainability](sustainability.md) simple: spills are
|
||||
absorbed and collected, never washed down.
|
||||
|
||||
### Safety
|
||||
|
||||
- **Isolation before lifting.** Before a machine is disconnected:
|
||||
electrical lockout, steam isolated and vented, and the hydraulics
|
||||
depressurised, including the aggregate's 50 L gas-loaded accumulator,
|
||||
which holds pressure after the pump stops. Written lockout/tagout per
|
||||
machine.
|
||||
- **A lift plan for every machine move**, a trained crane operator and a
|
||||
trained slinger, and nobody under the load.
|
||||
- **Warranty.** Newbilt's offer requires every installation to be
|
||||
commissioned by an engineer trained on Newbilt machinery, the first one
|
||||
by Newbilt itself, and ties warranty claims to that. Ask Newbilt in
|
||||
writing whether lifting a press into the workshop and back counts as a
|
||||
re-installation during the warranty period.
|
||||
|
||||
### Fit-out (October 2026)
|
||||
|
||||
The workshop is to be fully equipped for maintenance:
|
||||
- workbenches and the mould service bench, tool cabinets, hand and power
|
||||
tools;
|
||||
- a workshop press, parts washer, pillar drill and band saw;
|
||||
- a screened welding bay and a measuring table;
|
||||
- **3D printers** for jigs, guards and small parts;
|
||||
- possibly a **lathe** and a **small CNC mill** to make and repair parts
|
||||
in house.
|
||||
|
||||
The [Payap scenario model](site-candidates.md#payap-scenario-model-october-2026) draws this set in a ~200 m²
|
||||
workshop next to the machine door.
|
||||
|
||||
### Rough cost (estimate)
|
||||
|
||||
Workshop fit-out (benches, hand and power tools, hose crimper, parts
|
||||
washer, welding set and fume extractor, shelving, spill equipment, 3D
|
||||
printers): **1.0M to 2.5M THB (~30k to 76k USD)**. The lathe and the
|
||||
small CNC mill are not yet priced and come on top. The
|
||||
first spares stock sits in the existing working-capital line in
|
||||
[total investment](finance/total-investment.md).
|
||||
|
||||
## 3. Visitor corridor
|
||||
|
||||
### What it is for
|
||||
|
||||
Guided tours for artists, labels, investors, schools and the public that
|
||||
show the whole chain from lacquer to packed record, while visitors:
|
||||
|
||||
- hear nothing louder than conversation, so no hearing protection;
|
||||
- breathe the corridor's own filtered air, never press hall or galvanics
|
||||
air;
|
||||
- need **no PPE** at all, which turns a tour from an escorted, kitted-out
|
||||
floor walk into something that can run several times a day;
|
||||
- cannot touch anything, distract an operator or bring dust onto the
|
||||
floor. The glass protects production as much as it protects visitors.
|
||||
|
||||
ResurRec's new Japan plant shows its press floor the same way, through a
|
||||
window wall beside the brand sign
|
||||
([photo](finance/resurrec-japan/resurrec-japan_visitor-window.jpeg),
|
||||
October 2026; [revenue model](finance/revenue-model.md#resurrec-japan-october-2026)).
|
||||
|
||||
### Route
|
||||
|
||||
At ground level along **one long wall, the car-park elevation**, which is
|
||||
where the RFQ already places the main entrance and a second exit at the
|
||||
far end of the same wall ([RFQ §1b](finance/phase1-construction-rfq.md)).
|
||||
The tour starts at reception and leaves by the far exit, or loops back.
|
||||
|
||||
Along a wall rather than down the middle, for three reasons:
|
||||
|
||||
- it does not cut the production floor in two, so forklift routes and
|
||||
crane moves never cross it;
|
||||
- the strip under the crane runway is where the hook reaches least well
|
||||
anyway, so the corridor uses the least valuable floor;
|
||||
- both ends already have exits.
|
||||
|
||||
**Stations follow the process order**, which means the process layout has
|
||||
to run along the corridor:
|
||||
|
||||
1. Mastering and cutting (window into the cutting room)
|
||||
2. Galvanics (fixed, sealed window in the clean room wall; no opening, no
|
||||
shared air)
|
||||
3. Stamper prep
|
||||
4. Material lab and PVC handling
|
||||
5. **Press hall**, the long glazed stretch and the centre of the tour
|
||||
6. Cooling racks and 100% optical inspection of the cooled records (the
|
||||
presses trim inline)
|
||||
7. QC and listening, with a headphone listening point
|
||||
8. Finishing and packaging, where the records leave production
|
||||
|
||||
Finished goods sit behind the fire wall and are shown from a fire-rated
|
||||
window or not at all. The concept drawing
|
||||
[facility-layout.drawio](facility-layout.drawio) predates this corridor
|
||||
and the detached utility yard and does not yet follow this order; it
|
||||
needs redrawing at the next layout pass.
|
||||
|
||||
A first rough pass that does follow it is the BIM sketch
|
||||
[production-hall-layout-sketch.FCStd](production-hall-layout-sketch.FCStd)
|
||||
(top view: [PNG](production-hall-layout-sketch.png), October 2026): ramp
|
||||
end with machine door, workshop and spares; then mastering, galvanics,
|
||||
stamper prep, PVC lab and material area, the press hall, inspection, QC
|
||||
and packaging along the corridor; the fire wall at 48 m and the warehouse
|
||||
and dispatch at the dock end, with a 4.5 m crane and forklift aisle along
|
||||
the back wall from the machine door to the fire wall. It shows one
|
||||
conflict to resolve: with the workshop at the ramp end, reception and the
|
||||
cutting room sit under the bridge's travel too, against point 6 above
|
||||
(cutting room outside the crane zone).
|
||||
|
||||
The Payap scenario model
|
||||
([cnx_vinyl_parametric_payap.FCStd](cnx_vinyl_parametric_payap.FCStd),
|
||||
[top view](cnx_vinyl_parametric_payap.png); see
|
||||
[site candidates](site-candidates.md#payap-scenario-model-october-2026))
|
||||
resolves that conflict. Mastering and cutting, the offices and IT move
|
||||
into a separate office building, so only production sits under the
|
||||
crane. The tour then starts in the office building, at the cutting-room
|
||||
window and the listening room, and crosses a covered link into a 98 m
|
||||
corridor. That is longer than the 45 to 55 m assumed below, because the
|
||||
press hall keeps room for five Duplex systems and four Classics and a
|
||||
colour store sits before it. In that model the crane runway ends at the press hall:
|
||||
finishing and packaging sit beyond it in a two-storey block with the
|
||||
print room and stocks upstairs, which the crane cannot serve, so loads
|
||||
there move by forklift and goods lift. The model also draws the
|
||||
five-press fleet of October 2026; the sketch above still shows the
|
||||
earlier fleet (one Duplex and two Classics).
|
||||
|
||||
### How it is built
|
||||
|
||||
- **Room-in-room**: a glazed wall on the production side, a solid roof at
|
||||
about 3.0 m (an acoustic lid and protection from anything dropped),
|
||||
floor on the slab.
|
||||
- **Clear width about 2.4 m** (estimate): a group of about 15 with a guide,
|
||||
and room for a wheelchair to pass.
|
||||
- **Length about 45 to 55 m**, so roughly **110 to 130 m²** of floor and
|
||||
**~150 m²** of glazing (estimate).
|
||||
- **Acoustics.** Press halls typically run 80 to 90 dB(A) near the
|
||||
presses (to be measured on this plant). Laminated acoustic double
|
||||
glazing in the Rw 40 to 45 dB class (estimate) brings that down to
|
||||
roughly 40 to 50 dB(A), so a guide can talk without a headset system.
|
||||
Seals, penetrations and door gaskets decide whether that is achieved,
|
||||
more than the glass does.
|
||||
- **Air.** Its own HVAC zone with filtered supply at slight positive
|
||||
pressure to the press hall, so any leak runs from the corridor into the
|
||||
hall. It is the cleanest-air space a visitor enters, which matters in
|
||||
burning season.
|
||||
- **Glass safety.** Toughened laminated glass; a kerb or steel barrier on
|
||||
the production side wherever forklifts run; the crane's protected zone
|
||||
over the whole corridor.
|
||||
- **Fire and escape.** The corridor is an escape route with exits at both
|
||||
ends. Where it runs along a fire compartment wall or the galvanics room,
|
||||
that stretch of glazing must be fire-rated (EI), which costs several
|
||||
times standard glazing, so keep those stretches short.
|
||||
- **Viewing.** Light the production side brighter than the corridor and
|
||||
use low-reflection glass, or the visitors mostly see themselves.
|
||||
|
||||
### Step-free access is now required
|
||||
|
||||
The building floor sits at **+1.2 m** and the RFQ's only ramp is the 1:10
|
||||
vehicle ramp, which it notes is not an accessible gradient and asked to
|
||||
be told now if a step-free entrance is wanted. Public tours make it a
|
||||
requirement: a **1:12 ramp at the main entrance**, about 14.4 m of run
|
||||
for the 1.2 m rise plus intermediate landings, with handrails both sides.
|
||||
|
||||
### Running tours
|
||||
|
||||
- **Visitor screens** at the stations showing live, non-confidential
|
||||
plant data: a read-only visitor view of the factory application in the
|
||||
style of the [plant operation page](plant-operation.html), on kiosk
|
||||
displays wired like the station kiosks. The visitors' own phones stay
|
||||
on the guest Wi-Fi, which reaches the internet only (VLAN plan in
|
||||
[digital factory](digital-factory.md)).
|
||||
- **Confidentiality.** Unreleased artwork and labels are visible on the
|
||||
floor, and some clients will not want that. Options: schedule tours
|
||||
around confidential runs, a no-photography rule, or switchable privacy
|
||||
glass at the label and packaging stations (extra cost, estimate on
|
||||
request).
|
||||
- **CCTV notice** at the corridor entrance; footage of visitors falls
|
||||
under PDPA like staff footage.
|
||||
- **The tour ends where people can buy records.** A small shop or
|
||||
pick-up counter at the exit fits the
|
||||
[artist platform](artist-platform.md) idea of fans collecting their
|
||||
copy at the plant.
|
||||
- **Access control.** The corridor is its own zone. No door leads from it
|
||||
onto the production floor except, if the fire strategy needs one, an
|
||||
access-controlled staff door.
|
||||
|
||||
### Rough cost (estimate)
|
||||
|
||||
| Item | THB | USD |
|
||||
|---|---|---|
|
||||
| Acoustic laminated glazing, ~150 m² at 6,000 – 15,000 THB/m² | 0.9M – 2.3M | 27k – 70k |
|
||||
| Structure, roof, finishes, HVAC zone, lighting, screens | 1.0M – 2.0M | 30k – 61k |
|
||||
| 1:12 accessible entrance ramp with landings and handrails | 0.3M – 0.6M | 9k – 18k |
|
||||
| **Corridor total** | **~2.2M – 4.9M** | **~67k – 148k** |
|
||||
|
||||
## What the three add up to
|
||||
|
||||
| | Area | THB | USD |
|
||||
|---|---|---|---|
|
||||
| Overhead crane and machine door | (in the shell) | 3.2M – 7.5M | 97k – 227k |
|
||||
| Workshop and machine bay | 100 – 150 m² | 1.0M – 2.5M | 30k – 76k |
|
||||
| Visitor corridor and accessible entrance | 110 – 130 m² | 2.2M – 4.9M | 67k – 148k |
|
||||
| **Total** | **~210 – 280 m²** | **~6.4M – 14.9M** | **~195k – 450k** |
|
||||
|
||||
All estimates, not yet in the roll-up in
|
||||
[total investment](finance/total-investment.md); that page lists them as
|
||||
added scope until the next re-base.
|
||||
|
||||
**On area**: the 1,500 m² phase 1 footprint was already tight for the
|
||||
zone table in [scale](scale.md). Moving the boiler and chiller into the
|
||||
detached utility yard freed about 126 m² there, and scale.md left open
|
||||
whether to shrink the building or grow the program into it. These
|
||||
additions answer that: the program grows into it. At the lower half of
|
||||
the zone table everything still fits; at the upper half it does not, and
|
||||
the release valve is the one scale.md already names, moving finished
|
||||
goods into the phase 2 building.
|
||||
|
||||
## Changes made elsewhere
|
||||
|
||||
- [Construction RFQ](finance/phase1-construction-rfq.md): frame type
|
||||
changed from "no crane" to crane-ready, a new section for the crane and
|
||||
the machine door, the accessible entrance ramp made a requirement.
|
||||
- [Scale](scale.md): workshop and corridor added to the zone table.
|
||||
- [Facility security](facility-security.md): visitor management and
|
||||
access zones updated for corridor tours.
|
||||
- [Worker safety](worker-safety.md): lifting operations and the workshop.
|
||||
- [Roadmap](roadmap.md): item 15 (building fit-out).
|
||||
|
||||
## Open decisions
|
||||
|
||||
1. **Crane capacity**: 5 t or 3.2 t, once Newbilt states the Classic's weight
|
||||
and the inspection intervals are confirmed.
|
||||
2. **Low eave**: keep 7.0 m or raise to 8.0 m, once the contractor states
|
||||
the achievable hook height.
|
||||
3. **Runway length**: stop at the warehouse fire wall (recommended) or run
|
||||
the full 60 m if the fire strategy drops the wall.
|
||||
4. **Process layout along the corridor**: the stations above need the
|
||||
layout redrawn in process order along the car-park elevation.
|
||||
5. **Fire-rated glazing extent**, from the fire strategy.
|
||||
6. **Tour policy**: who tours, how often, and the confidentiality rule
|
||||
for client work on the floor.
|
||||
|
After Width: | Height: | Size: 56 KiB |
@@ -0,0 +1,528 @@
|
||||
# Galvanics and Stamper Prep: Equipment Plan
|
||||
|
||||
The metal path turns a cut lacquer into press-ready nickel stampers:
|
||||
silvering, electroforming of father, mother and stampers, passivation
|
||||
between generations, then punching, back-finishing and coining (stages 4
|
||||
and 5 in the [process flow](../process-flow.md)). It is Phase 5 item 23 in
|
||||
the [roadmap](../roadmap.md), with an open case for pulling it forward;
|
||||
until it runs, bridge stampers come from Stamper Discs. This page holds the
|
||||
equipment data for it, the way [pressing-line.md](pressing-line.md) does for
|
||||
the presses.
|
||||
|
||||
Sources are vendor datasheets filed with the Making Vinyl Europe 2026
|
||||
material in October 2026: Pheenix Alpha's electroforming range (four flyers
|
||||
dated September 2024, in [`pheenix-alpha/`](pheenix-alpha/)) and Sibert's
|
||||
vinyl stamper prep line (the current technical specifications and a
|
||||
line-up drawing, sent by Sibert's Ian Locke on 5 October 2026, in
|
||||
[`sibert/`](sibert/); the April 2021 issues they replace are in
|
||||
[`sibert/specs-2021/`](sibert/specs-2021/)), plus Sibert's 2008 to 2009
|
||||
optical-disc literature (below). Every figure here is vendor-published, not
|
||||
quoted; the only prices are Sibert's budget confirmation by email and
|
||||
OMS's reference prices in its introduction letter (both below).
|
||||
Digital Matrix / Plating Power stays the comparison; its datasheets are not
|
||||
in the repo yet (see the
|
||||
[vendor landscape](../suppliers/vendor-landscape.md)).
|
||||
|
||||
## Electroforming: the Pheenix Alpha range
|
||||
|
||||
Pheenix Alpha, the AD12 press maker, also builds the galvanics line. The
|
||||
four flyers:
|
||||
|
||||
| Unit | What it does | Datasheet figures |
|
||||
|---|---|---|
|
||||
| **PASU** Automatic Silvering Unit | Cleaning station plus silver spray unit: the lacquer is cleaned, then silvered by an automatic spray sequence; foot-controlled spray faucet, overspill collection; the silver unit mounts left or right of the cleaning bench | W 2188 × D 715 × H 1835 mm, working height 900 mm; cleaning station up to 120 rpm, spray unit 45 rpm, four nozzles; 100 to 230 VAC single-phase, 10 A; water Ø20 hose, 2 × G3/4"; compressed air G1/2" at 6 bar; exhaust Ø125 mm at 150 m³/h; drain Ø32 mm |
|
||||
| **PPPU** Pre-Plating Unit | First nickel layer on the silvered master: up to four masters at once, each position controlled on its own with its own cathode movement; integrated dummy plating; PID temperature control | W 1062 × D 1245 × H 1750 mm; 400/480 VAC three-phase, 16 A; tank 385 L, pump 10 m³/h, heater 4.5 kW, 2 × 20" filters; up to 15 VDC and 30 A per position; exhaust Ø63 mm; 500 mm service access behind the tank |
|
||||
| **PDPU** Dual Plating Unit | Production electroforming: two cells, each with its own rotating cathode shaft and digitally controlled rectifier; titanium anode baskets; adjustable anode-to-cathode distance; options for a flow meter, automatic lid and selective cleaning | W 1070 × D 1350 × H 1800 mm; 400/480 VAC three-phase, 16 A; tank 385 L, 40 L per cell, pump 10 m³/h, heater 4.5 kW, titanium cooling coil; filters 10 µm pre and 2.5 µm fine; 45 rpm; anode baskets 30 kg each; parts up to Ø355 mm; up to 15 VDC and 200 A per cell; cooling water 12 to 20 °C, 5 bar, 10 L/min; exhaust Ø63 mm; 500 mm service access behind the tank |
|
||||
| **PMPB** Modular Preparation Bench | Passivation, cleaning and drying between generations: removes lacquer residue, anodic passivation and cathodic cleaning for nickel and DMM parts, integrated pump, filtration and temperature control, sink with foot-controlled spray, spin table | W 1588 × D 775 × H 1700 mm, working height 920 mm; spin table up to 120 rpm; 100 to 230 VAC single-phase, 10 A; DI water G3/4"; drain Ø32 mm; exhaust ready |
|
||||
|
||||
All four are built in stainless steel and polypropylene, the bench and
|
||||
plating units with titanium in the wetted parts. The two plating
|
||||
units are PLC-controlled with a 7" touch screen, user-programmable recipes
|
||||
and a network connection for remote access; the range advertises alerts for
|
||||
filter cartridge changes, nickel pellet top-up and anode basket cleaning.
|
||||
|
||||
What this changes in the plan:
|
||||
|
||||
- **A second turnkey galvanics vendor.** Until now Digital Matrix was the
|
||||
only one in the plan ([roadmap](../roadmap.md) item 6, the galvanics block
|
||||
in [total investment](../finance/total-investment.md)). The Pheenix range
|
||||
covers the same four steps: silvering (PASU against Digital Matrix's
|
||||
VLSS), pre-plate (PPPU against VLPP), production electroforming (PDPU
|
||||
against the VLFP 2/4/6-cell system) and passivation (PMPB against the
|
||||
EC-1000). Pheenix calls itself the only manufacturer of both
|
||||
electroforming and pressing systems (vendor claim), so it can quote the
|
||||
whole chain from lacquer to pressed record: AD12 and AD12 Manual for the
|
||||
presses, this range for the metal. One conversation covers roadmap items
|
||||
5 and 6, and the single-vendor risk is the same as for the presses.
|
||||
- **Lacquer and DMM.** The PMPB passivates and cleans DMM parts as well as
|
||||
nickel, and Pheenix describes the range as built for lacquer and DMM
|
||||
families, so a DMM lathe (the open Sillitoe question in the
|
||||
[vendor landscape](../suppliers/vendor-landscape.md)) would not need
|
||||
different galvanics equipment, by the vendor's description.
|
||||
- **No water treatment in the flyers.** None of the four covers rinse-water
|
||||
treatment or metal recovery, the same gap as Digital Matrix. The
|
||||
zero-discharge plant stays a separate vendor
|
||||
([sustainability](../sustainability.md)); ask Pheenix which treatment
|
||||
partner its customers use.
|
||||
- **Utilities the galvanics room needs** (from the datasheets):
|
||||
- Electrical: two 16 A three-phase units (~11 kVA each at 400 V) and two
|
||||
10 A single-phase units (~2.3 kVA each), so **~27 kVA connected** for
|
||||
one line by the rated currents (estimate). Actual draw is lower: at
|
||||
most 6 kW DC in the PDPU (2 cells × 15 V × 200 A) and 1.8 kW in the
|
||||
PPPU (4 × 15 V × 30 A), plus a 4.5 kW heater in each. Thai 400 V / 50
|
||||
Hz three-phase fits. Not in the [scale](../scale.md) electrical table
|
||||
yet, because galvanics is Phase 5.
|
||||
- **DI water** at the PMPB: a deionised (RO plus polishing) water supply
|
||||
belongs in the galvanics utility list. The RO skid in the
|
||||
[utilities CSV](../finance/utilities-investment.csv) is an option row
|
||||
sized for boiler feed, not for this.
|
||||
- **Cooling water** at the PDPU: 12 to 20 °C at 5 bar and 10 L/min
|
||||
through its titanium coil, either a branch of the process chiller loop
|
||||
or a small dedicated chiller. 10 L/min is small next to the press
|
||||
moulds' ~220 L/min peak.
|
||||
- **Extraction**: Ø63 mm on each plating unit, Ø125 mm at 150 m³/h on the
|
||||
silvering unit. The fume-extraction interlock in
|
||||
[facility security](../facility-security.md) (no extraction, no
|
||||
plating) applies to every one.
|
||||
- Compressed air at 6 bar for the PASU; drains Ø32 mm.
|
||||
- **Water treatment in its own building (proposed, October 2026).** The
|
||||
zero-discharge effluent treatment, the DI water plant and the chemical
|
||||
store move out of the factory into a small building next to the
|
||||
galvanics room. A buried service duct carries the effluent by gravity
|
||||
from the galvanics floor at +1.2 m and brings DI water back, and a
|
||||
covered crossing joins the two doors. The galvanics room keeps only a
|
||||
chemical day store at the duct head. The
|
||||
[Payap scenario model](../site-candidates.md#payap-scenario-model-october-2026) draws it as a 12 × 10 m building
|
||||
(estimate).
|
||||
- **Stamper prep open to galvanics (October 2026).** No wall between the
|
||||
galvanics room and stamper prep: stampers go from the last bath straight
|
||||
to the Sibert line inside one clean zone, as the
|
||||
[Payap scenario model](../site-candidates.md#payap-scenario-model-october-2026) draws it.
|
||||
- **Space.** One of each unit is ~5.6 m² of footprint (PASU 1.56, PMPB
|
||||
1.23, PPPU 1.32, PDPU 1.44 m²), plus 500 mm service access behind the two
|
||||
tank units and working space around them: comfortably inside the 80 to
|
||||
150 m² the [zone table](../scale.md) holds for clean room, water
|
||||
treatment and chemical store. At 1.70 to 1.84 m tall they fit under the
|
||||
room-in-room ceilings in the crane zone
|
||||
([crane, workshop and tours](../crane-workshop-tours.md)), and by their
|
||||
published dimensions all four pass through a 1.2 m double door, so the
|
||||
crane hatch in the clean-room lid is for the water-treatment evaporator
|
||||
rather than the plating units (check against crated sizes).
|
||||
- **Weight.** Not published. Each tank unit holds 385 L of electrolyte,
|
||||
roughly half a tonne filled (estimate), plus 60 kg of nickel in the
|
||||
PDPU's anode baskets. Ask for empty and filled weights with the quote,
|
||||
for the slab design and the crane table.
|
||||
- **Data.** PLC, recipes, network connection and maintenance alerts are on
|
||||
the datasheets; the protocol is not. Per the
|
||||
[digital factory](../digital-factory.md) RFQ clauses: read access over
|
||||
Modbus TCP or OPC UA with the tag list, remote support through our mesh,
|
||||
no vendor cloud. The maintenance alerts are the bath events the
|
||||
galvanics record in [traceability](../traceability.md) needs anyway.
|
||||
|
||||
### A third candidate: Optical Media Services (OMS)
|
||||
|
||||
Asked after the show which electroforming route he would take, Sibert's
|
||||
Ian Locke named two (email, 5 October 2026): **OMS through Lou Wullms**, "a
|
||||
long-standing industry colleague who makes good equipment" and very
|
||||
familiar with the Asian market, or **Pheenix** for a full turnkey package
|
||||
with long international experience, electroforming systems and presses
|
||||
together (he calls Pheenix the de facto standard for vinyl presses
|
||||
worldwide; his view, not a market figure).
|
||||
|
||||
OMS is Optical Media Services B.V. in Baarlo, Netherlands, established
|
||||
1996 (vinyl-pressing-plants.com directory and Lou Wullms' own profile): an
|
||||
independent vinyl stamper service from lacquers and DMMs that also builds
|
||||
and refurbishes vinyl electroforming equipment, including conversions of
|
||||
CD/DVD electroforming lines to 14" vinyl. The same directory gives
|
||||
Newbilt's equipment page as OMS's website, and that page announces new
|
||||
Newbilt electroplating equipment with the portfolio "presented here soon";
|
||||
whether OMS builds it is not confirmed, so ask both. OMS's introduction
|
||||
letter (below) presents the units as its own designs (EFS2-200, AEFS4-250)
|
||||
and does not mention Newbilt.
|
||||
|
||||
What it adds: a third galvanics vendor next to Digital Matrix and Pheenix,
|
||||
named by a supplier who knows Lou Wullms and has installed equipment at
|
||||
Pheenix; a stamper service that could
|
||||
also serve as a European bridge supplier next to Stamper Discs; and, if
|
||||
the Newbilt link holds, a galvanics route that pairs with the Newbilt
|
||||
presses the way the Pheenix range pairs with the AD12.
|
||||
|
||||
**First email** (to Alexander in German, 7 October 2026, after meeting in
|
||||
Haarlem). Lou Wullms introduces himself as the Dutchman who works with nickel
|
||||
sulfamate (the electroforming electrolyte), asks Alexander to confirm he
|
||||
received the email, and will then send material so that we can start
|
||||
calculating and see what the line involves. He also asks whether Simona
|
||||
will work on the project. Company details as OMS gives them:
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Company | Optical Media Services B.V., Tangweg 16, 5991 PE Baarlo, Netherlands |
|
||||
| Technical | Lou Wullms, lou.wullms@gmail.com, mobile +31 6 5490 3443 |
|
||||
| Accounting and logistics | Wilma Peeters, wilmapeeters6@gmail.com |
|
||||
| Office phone | +31 77 477 8054 |
|
||||
| Registration | KvK 12037670 (Venlo), VAT NL806459335B01, EORI NL806459335 |
|
||||
|
||||
Alexander has replied to confirm (October 2026), with the split Lou asked
|
||||
about: Simona covers management and the audio side, Alexander the
|
||||
technical side, so galvanics questions go to Alexander.
|
||||
|
||||
#### OMS introduction letter (9 October 2026)
|
||||
|
||||
Lou Wullms sent his material two days later: an introduction letter to
|
||||
Alexander and Simona, filed as
|
||||
[`oms/OMS_Introduction_letter_2026-10-09.docx`](oms/OMS_Introduction_letter_2026-10-09.docx).
|
||||
He asks Alexander to give Simona a copy so that she can work through the
|
||||
figures. **Open:** forward the letter to Simona. It is an introduction,
|
||||
not an offer: the prices are "for reference only", final pricing comes
|
||||
with an official quote, and a dedicated offer needs our plans first. Lou
|
||||
would rather explain the options in Baarlo, where the equipment can be
|
||||
seen.
|
||||
|
||||
Background, as Lou gives it: from 1986 to 1994 at Philips' optical-disc
|
||||
equipment business (ODM, then OD&ME and ODME, the company later called
|
||||
Toolex Alpha); two years setting up a CD plant with mastering and
|
||||
electroforming at WPME in Kaarst, Germany; then OMS, for service to the
|
||||
optical-disc industry; involved in setting up Mimeos, a CD and later DVD
|
||||
stamper service that closed in 2012; in vinyl stamper production since
|
||||
2015. OMS runs an independent stamper service for vinyl plants and builds
|
||||
the wet-room equipment to its own designs.
|
||||
|
||||
The wet room for a turnkey line, with the letter's reference prices:
|
||||
|
||||
| # | Unit | What it does | EUR, reference |
|
||||
|---|---|---|---|
|
||||
| 1 | Wet bench | Cleaning, rinsing, soaking, wetting and pre-treating the lacquer | 20,000 |
|
||||
| 2a | Silvering booth, manual (\*) | Silvering the lacquer | 16,000 |
|
||||
| 2b | Silvering booth, automatic/manual (\*) | The same, automatic | 22,000 |
|
||||
| 3 | Pre-plate, 4 positions (\*) | First plating of the silvered lacquer at lower temperature and current | 45,000 |
|
||||
| 4a | Electroforming unit EFS2-200, 2 cells | Fast plating; the basic unit | 55,000 each |
|
||||
| 4b | Electroforming unit AEFS4-250, 4 cells with PLC | The advanced unit | 155,000 |
|
||||
| 5 | Cleaning / passivation | Extra cleaning of the stamper at high temperature and current; passivation | 25,000 |
|
||||
| 6 | Spin dryer | Spin-drying DMMs, lacquers and stampers; scuffing (pre-treatment) of DMMs and lacquers | 14,000 each |
|
||||
| 7 | Know-how transfer, including training at OMS | | 10,000 |
|
||||
| 8 | Silvering recipe | | 5,000 |
|
||||
|
||||
(\*) Not needed for stampers made only from DMMs: these are the lacquer
|
||||
path. The model names of the electroforming units come from the
|
||||
letter's expansion lines.
|
||||
|
||||
The letter totals two configurations:
|
||||
|
||||
| | Basic | Advanced |
|
||||
|---|---|---|
|
||||
| Units | 1, 2a, 3, 2 × 4a, 2 × 6, 8 | 1, 2b, 3, 1 × 4b, 5, 3 × 6, 8 |
|
||||
| Cells | 4 (two EFS2-200) | 4 (one AEFS4-250, PLC) |
|
||||
| Total in the letter | **EUR 224,000** (~USD 259k) | **EUR 311,000** (~USD 359k) |
|
||||
| One 8-hour day (30 min lunch included) | "7 runs should be possible", then counted with 6: 6 × 4 = **24 shells** | 8 × 4 = **32 shells** |
|
||||
| Doubling | 2 more EFS2-200, EUR 110,000, "over 50 stampers a day" | 1 more AEFS4-250, EUR 155,000, "over 68 stampers a day" |
|
||||
|
||||
USD at the [total investment](../finance/total-investment.md) rate of
|
||||
1 EUR = 1.155 USD. Reading the letter:
|
||||
|
||||
- **The sums.** The basic total adds up; the advanced units add up to EUR
|
||||
314,000, not the 311,000 stated. A re-quote point.
|
||||
- **Know-how transfer is left out of both totals**, with the note that
|
||||
electroplating know-how "is already present at your facility". That is
|
||||
not the case for CNX: nobody on the team has run a plating room. With
|
||||
the EUR 10,000 item (training at OMS included) the totals are EUR
|
||||
234,000 and 321,000, ~USD 270k and 371k (our reading).
|
||||
- **The basic set has no cleaning/passivation unit** (item 5). Ask how
|
||||
parts are passivated between generations without it.
|
||||
- **Installation is extra**: training and start-up on site at EUR 1,200 a
|
||||
day each, travel days at EUR 600, all other costs invoiced on top.
|
||||
- **Used equipment** is also on offer ("good used/pre-owned equipment").
|
||||
- **Finishing is not OMS's scope.** For back-polishing, centre punching and
|
||||
forming/trimming the letter points to Sibert and Ian Locke as the
|
||||
reference, as Sibert pointed to OMS for electroforming.
|
||||
|
||||
What it changes in the plan:
|
||||
|
||||
- **Price.** A complete 4-cell wet room at ~USD 259k to 371k, depending
|
||||
on the configuration and the know-how item, is at or below the low end
|
||||
of the USD 320k to 650k galvanics block in
|
||||
[total investment](../finance/total-investment.md). Neither includes
|
||||
water treatment (its own block) or installation days. Since October
|
||||
2026 the plan prices the Pheenix line at **OMS's reference plus 20 %**
|
||||
(user decision): EUR 280.8k to 385.2k, ~USD 324k to 445k, replacing the
|
||||
320k to 650k estimate until Pheenix quotes.
|
||||
- **Capacity.** 6 to 8 runs in a 7.5-hour working day is roughly an hour a
|
||||
run, which matches the 1 to 1.5 hours per part the cell count below
|
||||
assumes. Full capacity needs 8 to 20 parts a working day, so either
|
||||
4-cell configuration covers it on one shift, and the doubling options
|
||||
buy headroom only. This is the first vendor figure on cycle times.
|
||||
- **Staff.** One person runs about 20 stampers a day; from about 30 a day
|
||||
it takes two. Lou asks for people who work accurately and precisely,
|
||||
attentively, and like clean work. At the plant's 8 to 20 parts a day that
|
||||
is one operator per shift ([scale](../scale.md) people estimate).
|
||||
- **Utilities and rooms.** Compressed air, a demineralised-water system,
|
||||
waste-water collection or treatment, and cooling water, which Lou says
|
||||
can be passive, with no active chiller (he expects this needs more
|
||||
discussion). The Pheenix PDPU asks for 12 to 20 °C cooling water, so
|
||||
whether passive cooling holds at 30 °C and more ambient is a question for
|
||||
Lou. Space beyond the wet room: an acid cabinet with fume extraction for
|
||||
mixing chemicals, storage for stampers, lacquers and DMMs, a quality
|
||||
room with turntable, speakers and inspection microscope, spare parts and
|
||||
consumables. Smaller items: a drill stand for removing lacquer from the
|
||||
back of lacquers, lab ware (glass and PP ware, temperature sensor,
|
||||
density meter, pH meter), and a laundry washing machine and a concrete
|
||||
mixer for cleaning the anode baskets and anode bags.
|
||||
- **Data.** The AEFS4-250 has a PLC: programs of up to 20 steps, each step
|
||||
setting time, voltage, current, flow and rotation; an automatic wake-up
|
||||
function and pump-curve calibration; a modified cell flow that allows
|
||||
higher current "without stretching the bath solution". Lou calls it very
|
||||
energy-efficient with extremely low maintenance (vendor claims). The
|
||||
protocol is not stated, so the [digital factory](../digital-factory.md)
|
||||
RFQ clauses apply. The letter mentions no PLC for the basic EFS2-200,
|
||||
which would keep galvanics a manual check-in station.
|
||||
- **DMM.** The lacquer-path units (2a or 2b, and 3) are EUR 61,000 to
|
||||
67,000 of either configuration; a plant cutting only DMM would not need
|
||||
them, which bears on the Sillitoe DMM question in the
|
||||
[vendor landscape](../suppliers/vendor-landscape.md).
|
||||
- **Cutting lathes.** The letter ends with five contacts for buying a
|
||||
lathe, second-hand included; they are in the
|
||||
[vendor landscape](../suppliers/vendor-landscape.md#used-lathes-and-cutting-room-contacts-via-oms).
|
||||
|
||||
### Cycle times and cell count
|
||||
|
||||
Pheenix publishes no cycle times. Published practice from other plating
|
||||
rooms agrees with Faraday's law at the PDPU's 200 A ceiling (1.095 g of
|
||||
nickel per ampere-hour), and these are the times the
|
||||
[plant operation page](../plant-operation.html) runs on:
|
||||
|
||||
| Step | Time | Source |
|
||||
|---|---|---|
|
||||
| Silvering (clean, sensitise, spray, rinse) | ~15 min | estimate; no published figure |
|
||||
| Pre-plate | 15 to 30 min at 10 to 20 A | ~15 min at 35 °C (flight 13 duplication, Freiburg, in Leuze Verlag's Galvanotechnik report "Of fathers, mothers and sons"); ~20 min at ~20 A (Welcome to 1979, Nashville, on a Digital Matrix line, in Finishing and Coating); 30 min at 10 to 20 A (US patent 4,363,705) |
|
||||
| Father | ~1 h 15 min | ~0.2 mm and ~200 g at 150 A and 11 V (flight 13); 1¼ h with the current raised from 20 to 200 A (US 4,363,705) |
|
||||
| Mother | ~1 to 1¼ h | 1¼ h at 200 A (US 4,363,705); "as little as one hour" (Wikipedia, Production of phonograph records) |
|
||||
| Stamper | ~45 min | a 145 g stamper in 45 min (Wikipedia, same article) |
|
||||
| Separation, passivation, cleaning and drying (PMPB) | ~10 to 15 min | estimate |
|
||||
| Back-finish (VSF), centre punch (VSP), coin (VSC) | ~5 to 10, 3 to 5 and 1 to 2 min | estimate; Sibert publishes none |
|
||||
|
||||
The count, from this repo's own demand figures:
|
||||
|
||||
- At full capacity the [revenue model](../finance/revenue-model.md) assumes
|
||||
300 to 600 titles a year across 1.0 to 1.5 million records, so 2,500 to
|
||||
3,300 records per title.
|
||||
- Each title needs, per side, a father, a mother and two to three stampers
|
||||
(at 1,000 to 2,000 pressings per stamper): 8 to 10 electroformed parts per
|
||||
title, **~2,400 to 6,000 parts a year**, 8 to 20 per working day at 300
|
||||
days, before remakes.
|
||||
- The father and the mother of every side go into the archive (decided
|
||||
October 2026): 4 parts per title, **~1,200 to 2,400 parts a year** at 300
|
||||
to 600 titles. A mother carries about 10 stamper sets and a father about
|
||||
5 to 10 mothers by the industry rule of thumb (sources and the repress
|
||||
arithmetic in the
|
||||
[production timeline](../production-timeline.md#repress-the-shortest-path-in-the-plant)),
|
||||
so a repress normally grows stampers from the archived mother, and a
|
||||
worn mother is replaced from the father without a new cut. The room
|
||||
that holds them is planned in
|
||||
[facility security](../facility-security.md#protecting-the-irreplaceable).
|
||||
- With ~15 minutes of loading, rinsing and unloading on top of 45 to 75
|
||||
minutes of deposition, a cell turns a part in ~1 to 1.5 hours: 10 to 16
|
||||
parts per cell per two-shift day, **20 to 32 per PDPU**.
|
||||
|
||||
So **one PDPU covers full-capacity demand** with headroom for remakes, and
|
||||
a second PDPU buys redundancy rather than capacity, which is how Pheenix
|
||||
itself sells it ("more capacity as well as enhanced redundancy"). The
|
||||
first version of this page assumed 2 to 3 hours per part and concluded
|
||||
that the high end needed two. One PASU, one PPPU (pre-plate is for the
|
||||
masters, 2 to 4 a day at full capacity, and the unit takes four at once)
|
||||
and one PMPB cover the rest. Ask Pheenix for measured cycles at the
|
||||
plant's thickness before this goes into a budget. OMS's letter (above) is
|
||||
the first vendor figure: 6 to 8 runs on 4 cells in a 7.5-hour working day,
|
||||
roughly an hour a run, which fits these times.
|
||||
|
||||
## Stamper prep: the Sibert VS line
|
||||
|
||||
Sibert's three vinyl machines, from the current technical specifications
|
||||
(VSF and VSC dated May 2022, VSP June 2023, by their file dates), sent by
|
||||
Ian Locke on 5 October 2026 together with a line-up drawing of the three
|
||||
(July 2023):
|
||||
|
||||
| Machine | What it does | Specification figures |
|
||||
|---|---|---|
|
||||
| **VSP** Vinyl Stamper Punch | Punches the centre hole after optical centring on the groove | Punch and die M2 high-speed steel, Ø25.4 mm standard (other sizes available), ±0.002 mm; turntable Ø360 mm, 6 mm centring travel, ±0.0015 mm rotational accuracy; pneumatic automatic pre-centring, then manual fine centring; optics ×100, graticule 15 divisions at 0.10 mm, viewing diameter Ø90 to 110 mm (centres on the lead-out groove); pneumatic punch cylinder 100 mm bore, 50 mm stroke; 115 to 230 VAC single-phase, 250 VA; air 6 to 8 bar, 4.5 L/s during the punch stroke; 200 kg; spare punch and die on request |
|
||||
| **VSF** Vinyl Stamper Finisher | Automatic wet back-finishing with automatic stamper cleaning | Turntable up to Ø362 mm, sized to the customer's stamper, vacuum plus mechanical quick-release clamping on moulded rubber mats, 150 to 1500 rpm; head pressure 0 to 30 psi, brushless DC head drive and traverse, 150 to 1500 rpm; 4-station quick-change disc head including a cleaning pad; abrasive grades P120 to P2500 (nine grades); closed water loop, 0.6 µm absolute or 5 µm nominal filtration plus a 10 µm bag in the tank; 115 to 230 VAC single-phase, 1200 VA; air 6 to 8 bar, 3.1 L/s; 250 kg |
|
||||
| **VSC** Vinyl Stamper Coiner | Fully automatic forming of the centre hole (ID) and the edge (OD), with the outer diameter punched to a preset size, so no trimming | Press of 40 mm structural steel plate and pillar box section on four hardened pillars and eight linear ball races; independent twin hydraulic OD forming and adjustable pneumatic ID forming; automatically interchangeable 7", 10" and 12" tooling carriages, up to three stations in the machine, loaded by ball rollers and a brushless DC lead screw; D2 and M2 high-speed steel tools, vacuum hardened three times, tempered and precision ground; removable precision-ground ID spigot with height and pressure adjustment; OD insert made to the customer's mould profile ("quick change tooling to suit all vinyl moulds"); 115 to 230 VAC single-phase, 1 kVA; air 6 to 8 bar, 4.5 L/s during forming; 1000 kg; about 2.0 × 0.8 × 1.6 m (width with the tool carriages × depth × height, from the sheet's render) |
|
||||
|
||||
All three have aluminium frames and 5 mm cast acrylic guarding and ship
|
||||
with a pressure regulator and filter. The VSP and VSF sheets list castors
|
||||
and levelling feet; the current VSC sheet does not.
|
||||
|
||||
Against the 2021 sheets, the VSC is a heavier machine (1000 kg, was 600;
|
||||
40 mm plate, four pillars and eight ball races) with forming split into
|
||||
hydraulic OD and pneumatic ID; the VSF turntable is now sized to the
|
||||
stamper (up to 362 mm, was 365), its head pressure range is 0 to 30 psi
|
||||
(was 0 to 50), its drives are brushless and its disc head has four stations
|
||||
(was five); the VSP sheet changed only a typo.
|
||||
|
||||
What this changes in the plan:
|
||||
|
||||
- **Budget: USD 250k for all three.** Sibert confirmed by email (5 October
|
||||
2026) that a budget of USD 250k covers "all 3 auto-machines"; Ian
|
||||
Locke's own time, spare parts, shipping and travel come on top. This is a
|
||||
budget confirmation, not a quote: Sibert offers a fully itemised
|
||||
quotation once we go ahead. Ian Locke repeated on 9 October 2026 that
|
||||
equipment footprints and formal quotations follow when we are ready, and
|
||||
advised settling the pressing side first. It sits above the 60k to 170k estimate in
|
||||
[total investment](../finance/total-investment.md), which carries the
|
||||
difference in its not-yet-rolled-up table until the next re-base.
|
||||
- **Single-phase power.** All three run on 115 to 230 VAC, 50/60 Hz, ~2.5
|
||||
kVA together, so the three-phase question from the
|
||||
[Haarlem briefing](../suppliers/making-vinyl-europe-2026-exhibitors.md)
|
||||
falls away. Each needs 6 to 8 bar compressed air at ½" BSP minimum, so
|
||||
the air network has to reach the stamper prep room.
|
||||
- **Weights 200, 250 and 1000 kg.** The VSP and VSF stand on castors:
|
||||
pallet-truck moves. The VSC weighs a tonne and its sheet lists no
|
||||
castors, so it is a crane or forklift lift; stamper prep is under the
|
||||
crane runway ([crane table](../crane-workshop-tours.md) updated).
|
||||
- **Line-up: 4958 × 833 mm.** Sibert's drawing sets the machines in a row,
|
||||
VSF, VSP, VSC, 500 mm apart: 4.96 m long overall and 0.83 m deep. With an
|
||||
operator aisle in front and access at the ends, the line needs a strip of
|
||||
roughly 6 × 2.5 m (estimate) in the stamper prep room, before stamper
|
||||
racks and the inspection bench.
|
||||
- **Order of operations: finish, punch, coin.** Gotta Groove's
|
||||
Electromastering Lab in Cleveland, which runs a Sibert VSF and VSP,
|
||||
back-sands first, then centres and punches on the VSP, then trims and
|
||||
coins the edge and forms the centre hole for the press type
|
||||
(recordplating.com). The VSC locates on the punched hole, which fits the
|
||||
same order, and Sibert's line-up drawing places the machines in it. The
|
||||
[process flow](../process-flow.md)'s "punch, back-finish, coin" names
|
||||
the operations, not their sequence.
|
||||
- **Centring is manual.** The VSP pre-centres pneumatically, then the
|
||||
operator centres the lead-out groove under ×100 optics against the
|
||||
graticule. Concentricity depends on the operator, so the stage 5 check
|
||||
stays, and it is the measurement most worth automating. Sibert's 2009
|
||||
optical-disc punch offered automatic centring with a measured centring
|
||||
value, a barcode reader for the stamper card and a LAN connection as
|
||||
options; the VS sheets list none of these. Sibert also builds a fully
|
||||
automatic punch, the **VSPa**; Ian Locke thinks it may not be right for
|
||||
this application and offered to discuss it, or to carry some of its
|
||||
features across to the VSP as a special exception. Which features
|
||||
(automatic centring, a measured centring value written out against a
|
||||
stamper serial) is the question to settle before the quotation: the
|
||||
answer decides whether stamper prep stays a manual check-in station in
|
||||
the [digital factory](../digital-factory.md).
|
||||
- **Mould fit.** The standard punch is Ø25.4 mm, other sizes on request,
|
||||
and the VSC makes its OD insert to each customer mould profile, with
|
||||
interchangeable ID spigots. Gotta Groove keeps nine
|
||||
centre-hole forming tools to fit the presses its customers run, which
|
||||
shows the scale of the question. Which centre hole and
|
||||
edge form each mould needs (Newbilt book mould, Pheenix/Toolex, M-Tech)
|
||||
has to come from the press vendors, and the tooling sets per mould type
|
||||
are a quote line. Whether the VSC duplicates anything a press vendor
|
||||
supplies is still open.
|
||||
- **The finisher's water carries nickel.** The VSF's closed loop collects
|
||||
nickel fines and abrasive in its filters and bag. Spent water and filters
|
||||
go to the galvanics treatment and hazardous-waste route, never the drain
|
||||
([sustainability](../sustainability.md)). Consumables: abrasive discs in
|
||||
up to nine grades, filter cartridges and bags, turntable mats.
|
||||
- **Service model** (from the 2009 optical-disc literature; confirm for the
|
||||
VS line). Sibert services punch-and-die sets at its own works: resharpen,
|
||||
check alignment and vacuum, test-punch the customer's own stampers and
|
||||
issue a certificate (measured ID, ID-to-data concentricity, roundness,
|
||||
surface finish, front and back hardness HV0.3). It advises against local
|
||||
resharpening and sets shot-count warnings in the machine. For a plant in
|
||||
Thailand that means a spare punch and die in rotation (the VSP lists one
|
||||
on request) and a UK freight leg per service. In 2009 Sibert also had a
|
||||
Singapore branch; ask whether regional service still exists. The
|
||||
certificate's fields are a ready list for the stamper prep record in
|
||||
[traceability](../traceability.md). Installation and training are not in
|
||||
the budget: Ian Locke's time and travel are charged on top, so they are
|
||||
a quote line of their own.
|
||||
|
||||
## Optical-disc reference material
|
||||
|
||||
[`sibert/sps-optical-disc-2009/`](sibert/sps-optical-disc-2009/) holds
|
||||
Sibert's SPS (Stamper Preparation System) literature from 2008 and 2009,
|
||||
punching and finishing modules with their workflows, maintenance lists and
|
||||
upgrade options, and the August 2008 Blu-ray stamper characteristics paper
|
||||
by Sony DADC, Singulus, Sibert and technotrans. These are optical-disc
|
||||
documents and their limits are not vinyl specifications. What carries over:
|
||||
|
||||
- **The structure of a stamper acceptance spec**: thickness, flatness,
|
||||
hardness, back roughness before and after finishing, outer diameter,
|
||||
centre hole, eccentricity, burr and visual defect counts, each with a
|
||||
measurement method. CNX has the instruments
|
||||
([quality automation](../quality-automation.md)) but no written limits
|
||||
yet; this paper is the model to write them against.
|
||||
- **Hardness on the centre slug.** Hardness is measured on the disc punched
|
||||
out of the centre, never on the part, and a fresh nickel bath plates soft
|
||||
at first, which changes how stampers punch and finish. Taken into
|
||||
[quality automation](../quality-automation.md).
|
||||
- **Back-finish pattern.** Random crossing scratches, uniform over the
|
||||
surface, worked best for Blu-ray; concentric scratches were not
|
||||
recommended. The SPS finisher reached Ra 0.03 µm. No vinyl figure is on
|
||||
file: ask Sibert what the VSF reaches and what vinyl plants specify.
|
||||
- **Tool wear shows in the hole.** Hole size shrinks by a few microns as
|
||||
the punch and die wear, so a shot count per punch-and-die set belongs in
|
||||
the genealogy record next to each stamper's concentricity.
|
||||
|
||||
The SPS material is directly relevant only if CD replication, the
|
||||
investor's request in the [project timeline](../project-timeline.md), ever
|
||||
goes ahead.
|
||||
|
||||
## Open questions for the quotes
|
||||
|
||||
- **Pheenix Alpha**: price and lead time for one line (PASU, PPPU, PDPU,
|
||||
PMPB) and for a second PDPU, quoted alongside the AD12; empty and filled
|
||||
weights; measured cycle per part per cell at stamper, mother and father
|
||||
thickness; PLC protocol and tag list; DI water quality; which
|
||||
water-treatment partner its customers use; reference plants running the
|
||||
range. CEO Robert Gunnarsson offered a Teams call, reference clients and
|
||||
a factory visit near Stockholm (email, 5 October 2026); the call
|
||||
follows once these questions are ready, and a visit could fit the
|
||||
February 2027 Europe trip
|
||||
([exhibitor briefing](../suppliers/making-vinyl-europe-2026-exhibitors.md#after-the-show)).
|
||||
- **Sibert**: the itemised quotation against the confirmed USD 250k
|
||||
budget, with Ian Locke's time, spare parts, shipping and travel priced,
|
||||
and lead time; tooling sets per mould type and their cost; which VSPa
|
||||
features can move to the VSP (automatic centring, a measured centring
|
||||
value, barcode and network); punch-and-die service from Thailand (UK
|
||||
works or a regional partner); the roughness the VSF reaches; crated
|
||||
sizes and weights (the VSC is now 1 t); what it installed at Pheenix in
|
||||
January 2025, and whether Pheenix sells Sibert machines with its line.
|
||||
- **OMS (Optical Media Services)**: a dedicated offer once we send our
|
||||
plans (lacquer, DMM or both; parts per day; shifts), ideally after seeing
|
||||
the equipment in Baarlo (the February 2027 Europe trip could fit);
|
||||
datasheets for the EFS2-200 and AEFS4-250 (dimensions, empty and filled
|
||||
weights, power, cooling water); how parts are passivated in the basic set
|
||||
without the cleaning/passivation unit; the advanced total (the units add
|
||||
up to EUR 314,000, the letter says 311,000); whether passive cooling holds
|
||||
at Thai ambient; the AEFS4-250's PLC protocol and tag list; the used
|
||||
equipment on offer; installations and service in Asia; stamper service
|
||||
prices and turnaround; which water-treatment partner his customers use;
|
||||
and whether OMS builds the electroplating equipment Newbilt announces.
|
||||
- **All galvanics candidates** (Pheenix, Digital Matrix, OMS): how many
|
||||
stamper sets a mother gives and how many mothers a father gives with
|
||||
their process before quality drops, how they check it (mother playback,
|
||||
metrology), and how they recommend storing archived fathers and mothers
|
||||
(passivation, sleeves, humidity) for years.
|
||||
- **Press vendors** (Newbilt, Pheenix, M-Tech): the stamper centre hole and
|
||||
edge form each mould expects, so the punch size and coiner tooling can be
|
||||
ordered to match ([pressing line](pressing-line.md)).
|
||||
|
||||
## Source documents
|
||||
|
||||
- [`pheenix-alpha/`](pheenix-alpha/): PASU, PPPU, PDPU and PMPB flyers
|
||||
(September 2024; renamed from their download names). The flyers give
|
||||
Pheenix Alpha AB's address as Skepptuna, Märsta, Sweden;
|
||||
info@pheenixalpha.com, helpdesk@pheenixalpha.com.
|
||||
- [`sibert/`](sibert/): VSF and VSC technical specifications (May 2022),
|
||||
VSP technical specification (June 2023) and the VSF/VSP/VSC line-up
|
||||
drawing (July 2023), attached to Ian Locke's email of 5 October 2026;
|
||||
the April 2021 issues they replace are in
|
||||
[`sibert/specs-2021/`](sibert/specs-2021/). Sibert Instruments Ltd,
|
||||
Medstead, Hampshire, UK, by the email signature (the specification
|
||||
sheets still carry the older Alton address); sales@sibert.co.uk,
|
||||
ian.locke@sibert.co.uk.
|
||||
- [`oms/`](oms/): OMS's introduction letter of 9 October 2026 (Word;
|
||||
sent as "Introduction letter BUILDFOR.LIFE.docx", attached to Lou
|
||||
Wullms' email of the same day): wet-room units with reference prices,
|
||||
two configurations, capacities, utilities, staffing, used equipment and
|
||||
lathe contacts. Optical Media Services B.V., Tangweg 16, Baarlo,
|
||||
Netherlands.
|
||||
- [`sibert/sps-optical-disc-2009/`](sibert/sps-optical-disc-2009/): SPS
|
||||
punching and finishing literature (2008 to 2009), the punch-and-die
|
||||
return form, and the Blu-ray stamper characteristics paper (2008).
|
||||
@@ -0,0 +1,659 @@
|
||||
# Inline optical QC: devices for the record inspection station
|
||||
|
||||
Research note, October 2026. This note works out which devices can do
|
||||
layer 1 of [quality automation](../quality-automation.md#layer-1-100-optical-inspection-inline),
|
||||
the optical check of every pressed record. Prices come from vendor shops,
|
||||
vendor pages or third-party listings, and the source is named each time.
|
||||
Anything without a source is marked as an estimate. Nothing here is a
|
||||
quote.
|
||||
|
||||
**Short answer.** Nobody sells a vinyl inspection machine. The template
|
||||
is the CD and DVD in-line scanner: spin the disc once under a line-scan
|
||||
camera that looks along the radius, with angled lights, and measure the
|
||||
height with lasers during the same turn. That can be built from standard
|
||||
parts:
|
||||
|
||||
- a 4k line-scan camera per side, with dark-field and bright-field lights;
|
||||
- a colour area camera per side for the label;
|
||||
- two laser distance sensors for warp;
|
||||
- a servo turntable with a centring chuck;
|
||||
- an edge PC running open-source vision software on NixOS.
|
||||
|
||||
The hardware costs about USD 17k to 33k per station (bill of materials,
|
||||
partly estimates). At launch one station serves both presses, the Duplex
|
||||
system and the Classic, and it checks the records after they have cooled
|
||||
(decided October 2026; see [where it sits](#where-it-sits)). A concept model of the station, an aluminium
|
||||
profile frame with a rim-belt conveyor and all sensors mounted to it, is
|
||||
in [the station setup](#the-station-setup-frame-conveyor-and-sensors).
|
||||
|
||||
## What the station has to catch
|
||||
|
||||
| Defect | How it shows optically | Device | Limit or source |
|
||||
|---|---|---|---|
|
||||
| Non-fill (PVC did not fill the stamper) | dull, matte patches in the groove band, most often at the outer edge of 180 g records ([AnalogPlanet](https://analogplanet.com/content/what-non-fill-looks)) | line-scan camera, low-angle (dark-field) light | any patch; correlates with audible defects |
|
||||
| Stitching and flow lines | lines or streaks in the groove sheen | same | any visible line |
|
||||
| Bubbles, inclusions, black specks | dark or bright points; in clear and translucent colours seen best in transmitted light | line-scan with a back light | size threshold set in trials |
|
||||
| Debris, scratches, scuffs | bright points or lines in dark-field, dark in bright-field | both lights | size threshold set in trials |
|
||||
| Edge trim (burr, wrong diameter) | the record edge in the line-scan image | line-scan | trim drawing |
|
||||
| Label wrong, on the wrong side, off-centre, wrinkled, bubbled, misprinted | colour image of the label against the approved artwork from the order | colour area camera, ring or dome light | artwork in ERPNext |
|
||||
| Off-centre hole (eccentricity) | the groove band edges trace a sine wave in the unwrapped image when the hole sits off the spiral centre | line-scan, fit of the lead-in and the finishing groove | 0.2 mm hole to groove spiral (IEC 98-1987, DIN 45547-1981, as [tabulated here](http://www7a.biglobe.ne.jp/~yosh/standards_table.htm)); Stamper Discs aims below 0.1 mm on the record and 0.05 mm on the stamper ([Stamper Discs, 2025](https://www.stamperdiscs.com/the-physical-attributes-of-a-stamper-eccentricity/)) |
|
||||
| Centre hole size | hole diameter in a backlit image, or a go/no-go mandrel | area camera (optional) | 7.24 mm, -0/+0.09 mm (same table) |
|
||||
| Warp: edge run-out and dish | height change over one turn | two laser distance sensors, or one laser line profiler | Mobineko rejects above 0.5 mm (black), 1.0 mm (colour) or 1.5 mm (special effects) edge run-out per turn, or above 2 mm (black) or 3 mm (colour) between edge and centre ([Mobineko](https://mobineko.com/vinyl-quality-standards)) |
|
||||
| Colour off the approved test pressing | colour values against the first approved records of the job | calibrated colour camera | tolerance set per job |
|
||||
| Record temperature at unload (process signal, optional) | temperature map | thermal camera | trend against warp |
|
||||
|
||||
No camera can see a wrong master cut into good-looking grooves, or clicks
|
||||
from defects smaller than its resolution. Those stay with the sampled
|
||||
audio comparison (layer 3). Optical and audio checks complement each other.
|
||||
|
||||
## Who does this already
|
||||
|
||||
- **No vinyl product.** A search in October 2026 found no inline
|
||||
inspection machine for vinyl records on sale. The presses do not offer
|
||||
one either. The Newbilt Classic's feature list stops at automatic
|
||||
unloading, the spindle stack, cycle recording and OPC UA
|
||||
([Newbilt Classic](https://vinyl-pressing-plants.com/blog/newbilt-classic-12-inch-vinyl-record-press)).
|
||||
- **CD and DVD lines had it, and that is the template.** Dr. Schenk's ISM
|
||||
in-line scanner ([brochure, 2007](https://www.drschenk.com/fileadmin/user_files/brochures/13-other_applications/optical_media_inspection/ism_inline_scanner.pdf)):
|
||||
- a 2048-pixel, 12-bit line-scan camera with LED lights;
|
||||
- one turn in 600 ms or less, 20 µm radial resolution;
|
||||
- radial and tangential disc deformation measured at 1,000 points;
|
||||
- a defect classifier, on embedded Linux.
|
||||
|
||||
Basler began in this market in 1990 for PolyGram in Hanover
|
||||
([IMVE](https://imveurope.com/feature/caught-camera)) and sold the
|
||||
optical-media business to Xiris in 2009
|
||||
([Vision Systems Design](https://vision-systems.com/cameras-accessories/article/16747762/basler-sells-optical-media-business-continues-focus-on-camera-markets)).
|
||||
A vinyl record is a bigger, black, grooved disc, but the method carries
|
||||
over.
|
||||
- **Precision Record Pressing (Ontario), 2023.** Their in-house AQA system
|
||||
takes the first and second record of each order. Surface-scanning
|
||||
cameras built into the lids of modified turntables scan both records,
|
||||
then both are played in sync and compared with the master
|
||||
([PRP](https://www.precisionpressing.com/blog/news-prp-announces-new-automated-quality-assurance-system)).
|
||||
It works on samples and is not for sale, but it is the closest vinyl
|
||||
precedent.
|
||||
- **Czech Technical University, Prague.** A bachelor thesis built an
|
||||
automated optical defect check for LPs in LabVIEW and ran lighting
|
||||
experiments ([CTU thesis](https://dspace.cvut.cz/entities/publication/11505711-6ce1-4b87-904d-a1421d91cf9f)).
|
||||
A 2018 paper from the same faculty identified defects with a wavelet
|
||||
method and classified them with KNN, and got 57 % of records right
|
||||
([CTU, 2018](https://starfos.tacr.cz/en/vysledky-vyzkumu/RIV%2F68407700%3A21230%2F18%3A00321872)).
|
||||
- **Plants check by hand today.** Mobineko measures flatness with a
|
||||
micrometer gauge and a laser level on a modified turntable
|
||||
([Mobineko](https://mobineko.com/vinyl-quality-standards)). Third Man
|
||||
checks flatness and label orientation by eye as records leave the press
|
||||
([WIRED](https://www.wired.com/video/watch/how-vinyl-records-are-made-with-third-man-records)).
|
||||
|
||||
## The station
|
||||
|
||||
**How it works.** The record goes onto a centring chuck: a mandrel
|
||||
expands in the 7.24 mm hole and a ring supports the label area. A servo
|
||||
turntable with an encoder turns it once in about 1 s. Both sides are
|
||||
imaged during that one turn, one camera set above and one below. The
|
||||
lights are strobed on alternate lines, so the same turn gives a
|
||||
dark-field, a bright-field and a transmitted-light image. Stacking line
|
||||
images from one turn into one picture is standard multi-light line-scan
|
||||
practice (estimate for this application; to prove in trials). The PC
|
||||
unwraps each image into a strip of radius against angle, which makes
|
||||
rings straight lines and an off-centre hole a sine wave.
|
||||
|
||||
| Function | Device, per side unless noted | Examples | Price signal |
|
||||
|---|---|---|---|
|
||||
| Surface | 4k monochrome line-scan camera along the radius, with a lens, plus a dark-field and a bright-field line light | Basler racer 2 r2L4096 (GigE, 14 to 29 kHz); Hikrobot MV-CL042-91GM (GigE, 4096 × 7 µm pixels, 28 kHz, 80 kHz in high-bandwidth mode, GenICam, Linux; [datasheet](https://www.innosmart.bg/en/catalog/product/by-id/MV-CL042-91GM)); Cognex In-Sight 3800 Line Scan (smart camera, 4K at 84 kHz, encoder inputs, AI tools on board; [specs](https://www.cognex.com/products/machine-vision/2d-machine-vision-systems/in-sight-3800-line-scan/specifications)) | Basler 4k GigE line-scan from USD 857 to 1,088 in Basler's web shop ([price listing](https://cards.keenable.ai/w/01a14ab8-9648-7191-8286-bc5956857428)); lens USD 300 to 800 and line lights USD 500 to 1,500 each (estimates) |
|
||||
| Transmitted light | a diffuse line light under the record for the top camera | any line-light maker | USD 500 to 1,500 (estimate) |
|
||||
| Label | 5 to 8 MP colour area camera with a ring or dome light | Basler ace 2 a2A2840-14gcPRO | USD 1,119 (Basler web shop, same listing) |
|
||||
| Warp, simple | two laser distance sensors under the record, at the outer edge and at mid radius | Micro-Epsilon optoNCDT 1420 | from EUR 470 list ([Micro-Epsilon](https://www.micro-epsilon.com/insights/optoncdt-1220-1320-1420/)); ILD1420-25 about USD 1,600 at a reseller ([Radwell](https://www.radwell.ca/Buy/MICRO%20EPSILON/MICRO%20EPSILON/ILD1420-25)) |
|
||||
| Warp and thickness, full map (alternative) | laser line profiler across the radius, giving a full height map | Keyence LJ-X8000 (warpage and flatness tools, compensates eccentricity; [Keyence](https://keyence.com/products/measure/laser-2d/lj-x8000)); LMI Gocator 2500 (up to 10 kHz, blue laser; [LMI](https://lmi3d.com/2500-high-speed-3d-laser-profile-sensors/)); Micro-Epsilon scanCONTROL | no list price found; USD 8k to 20k (estimate) |
|
||||
| Thermal (optional) | infrared camera over the unload position | Optris Xi 400 (80 Hz, line-scan mode) | from EUR 1,950 ([Optris](https://optris.com/products/thermal-cameras/compact-line/xi-400/)); USD 2,995 at a US reseller ([moviTHERM](https://movitherm.com/product/optris-xi-400-infrared-camera/)) |
|
||||
| Compute | edge PC with a GPU, NixOS | any industrial PC | USD 2k to 4k (estimate) |
|
||||
| Mechanics | servo turntable, centring chuck, encoder, frame, light shield, reject gate, stack light | local machine builder | USD 4k to 10k (estimate) |
|
||||
|
||||
**Resolution.** These are worked figures for a 160 mm field and a 4,096-pixel line:
|
||||
|
||||
- **Radial:** about 39 µm per pixel.
|
||||
- **Along the groove, at 14 kHz and one turn per second:** about 66 µm per line at the outer edge (146 mm radius) and 22 µm at the label edge. At 28 kHz these halve.
|
||||
- **What that sees:** millimetre-sized non-fill, flow lines and specks of about 0.1 mm and up. It does not resolve single grooves.
|
||||
- **How defects show:** the camera sees how the groove field scatters light, so a defect has to change that scatter. That is why lighting trials come first, as in the CTU thesis.
|
||||
|
||||
**Eccentricity.** At the 0.1 mm target, the sine wave in the unwrapped
|
||||
image is about 2.6 pixels high. A sub-pixel fit along the lead-in edge
|
||||
and the finishing groove (106.4 ± 0.8 mm diameter in IEC 98) over about
|
||||
14,000 lines should repeat within 10 to 20 µm. That figure is an estimate
|
||||
and has to be shown in trials. The chuck has to centre on the hole
|
||||
exactly, because the station measures the groove spiral against the
|
||||
chuck.
|
||||
|
||||
**Throughput.**
|
||||
|
||||
| | Duplex cell | Classic |
|
||||
|---|---|---|
|
||||
| Output | a record every 15 to 20 s from its two presses (at 30 to 40 s per press; Newbilt quotes about 30 s, and the [fleet calculator](../fleet-calculator.html) takes 3 records a minute as 40 s) | a 180 g record every 28 s (Newbilt) |
|
||||
| Station time per record | about 1 s of scan plus 2 to 3 s to load and unload (estimate) | same |
|
||||
|
||||
That leaves slack at both stations. One central station takes the
|
||||
launch plant's 5 to 6 records a minute with room to spare, and that is
|
||||
the launch setup ([where it sits](#where-it-sits)). A station at each
|
||||
cell would catch a non-fill streak within a cycle or two; that stays the
|
||||
option for a larger fleet.
|
||||
|
||||
## The station setup: frame, conveyor and sensors
|
||||
|
||||
A concept model of one station, drawn in FreeCAD from the script
|
||||
[`build_station.py`](inline-qc-station/build_station.py) (views from
|
||||
[`render_station.py`](inline-qc-station/render_station.py); model file
|
||||
[`inline-qc-station.FCStd`](inline-qc-station/inline-qc-station.FCStd)).
|
||||
It is a layout to take to a machine builder, not a fabrication drawing.
|
||||
The frame uses the real 8-slot 40 series section (slots, centre bore,
|
||||
corner cavities) with cast angle brackets in the corners; bought parts
|
||||
are drawn as their outline boxes. The script checks that every part
|
||||
reaches the floor through parts it touches, so nothing floats.
|
||||
|
||||

|
||||
|
||||
*The labelled view for presentations, made with
|
||||
[`render_annotated.py`](inline-qc-station/render_annotated.py) (FreeCAD
|
||||
view and label positions) and
|
||||
[`annotate_render.py`](inline-qc-station/annotate_render.py) (labels,
|
||||
Pillow).*
|
||||
|
||||

|
||||
|
||||
*Records run from the infeed (back left, a translucent red special on
|
||||
the belts) through the light-tight tunnel to the reject pusher and the
|
||||
outfeed stop (front right). The cabinet sits under the outfeed, the
|
||||
reject bin behind it.*
|
||||
|
||||
**Frame.** The frame is built from 40 × 40 mm 8-slot aluminium profile
|
||||
(32 m in 45 pieces) on two 40 × 80 mm base beams, with 24 cast angle
|
||||
brackets in the corners and eight levelling feet. It is 1.9 m long, 0.65 m wide and 1.5 m high, plus the stack
|
||||
light. The reject bin adds 0.4 m behind it. Records travel at 900 mm,
|
||||
a normal working height.
|
||||
|
||||
The middle 0.8 m is a tunnel closed with black panels on all sides
|
||||
(4.3 m²), because the line-scans need their own light only. The front
|
||||
panel is a door with a safety switch. The records enter and leave
|
||||
through low slots in the end walls. The reject zone has a clear polycarbonate guard.
|
||||
All camera and light brackets clamp into the slots, so heights and angles
|
||||
can be moved during the lighting trials.
|
||||
|
||||
**Conveyor.** Two 6 mm PU round belts run under the record's rim, 148.5 mm
|
||||
from the centre line. That is outside the recorded area: a 12" record is
|
||||
301.6 mm across and its grooves end at 292.6 mm at most (IEC 98, as
|
||||
[tabulated here](http://www7a.biglobe.ne.jp/~yosh/standards_table.htm)).
|
||||
The belt therefore touches only the raised edge that records are made to
|
||||
stand on, never a groove. The centre stays open, so cameras and the chuck
|
||||
can reach the record from below.
|
||||
|
||||
The belts run on UHMW slide strips and are driven by one shaft at the
|
||||
outfeed end. Side guides with a flared mouth centre the record at the
|
||||
infeed. Supported on two rim lines, a warm 180 g record sags about 1 mm
|
||||
in the middle (beam estimate). The launch setup feeds cooled records,
|
||||
which are stiffer; the trials should confirm that the sag does no harm. For 10" and 7" records the belt spacing moves in on a slide;
|
||||
the model shows the 12" setting.
|
||||
|
||||
| Station | Position from the infeed end | What happens |
|
||||
|---|---|---|
|
||||
| Infeed | 200 mm | the finishing operator puts each cooled record down (at a press-side station: the press operator or the Classic's unloader); a presence sensor starts the cycle |
|
||||
| Label gate | 520 mm | both colour cameras flash the labels on the fly through the open centre (exposure about 20 µs, under 10 µm blur at 0.5 m/s); the top camera also reads the dead-wax code that ties the record to its stamper, and so to its press and cycle (readability to test, as in [digital factory](../digital-factory.md)) |
|
||||
| Inspection | 880 mm | a through-beam on the leading edge stops the belts; the chuck lifts the record 75 mm off them (the pad waits below the belt plane), expands the mandrel in the 7.24 mm hole and turns it once in about 1 s |
|
||||
| Reject | 1,320 mm | a pneumatic rodless cylinder on a bridge pushes a reject sideways by its edge onto a felt-lined chute at the back and into the bin |
|
||||
| Outfeed | 1,715 mm | good records wait at a soft end stop; the station holds the next one while the outfeed is full |
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
**Inspection zone.** The record is shown lifted on the chuck. The two
|
||||
line-scans look at opposite radii along the conveyor axis, because no
|
||||
belt crosses that line:
|
||||
|
||||
- **Top camera:** reads the downstream radius, from 50 to 155 mm, from
|
||||
330 mm above. A coaxial line light sits under it, two dark-field line
|
||||
lights sit at 20° either side, and a diffuse backlight below the
|
||||
record gives transmitted light for clear colours.
|
||||
- **Bottom camera:** reads the upstream radius from below with the same
|
||||
set of lights.
|
||||
- **Bottom dark-field lights:** these sit outside the record's footprint,
|
||||
above the rails, so the conveyed record passes them. They light the
|
||||
underside at about 8°, true dark-field.
|
||||
- **Warp lasers:** two lasers under the record trace circles at 90 and
|
||||
130 mm radius during the turn.
|
||||
- **Spindle drive:** an encoder on the spindle shaft clocks both
|
||||
line-scans; the lasers are sampled with the servo position (see the
|
||||
spindle servo below).
|
||||
- **Lift drive:** the lift is a guided pneumatic cylinder, and the
|
||||
spindle is belt-driven from a servo set to the side. That keeps the
|
||||
bottom camera's view cone clear, which the elevation shows.
|
||||
- **Thermal camera (option):** hangs at the tunnel entry. It only makes
|
||||
sense at a press-side station; cooled records show no temperature
|
||||
pattern, so the launch setup leaves it out.
|
||||
|
||||
**Spindle servo and camera clock.** The spindle runs on a 100 W EtherCAT
|
||||
servo kit, StepperOnline A6-EC100L2A1-M17: a 40 mm motor (0.32 N·m rated,
|
||||
1.12 N·m peak, 17-bit magnetic encoder, 0.03 kg·cm² rotor) with the
|
||||
A6-200EC drive. It costs USD 123.29 from the China warehouse
|
||||
([StepperOnline](https://www.omc-stepperonline.com/a6-series-100w-ethercat-ac-servo-motor-kit-3000rpm-0-32nm-17-bit-absolute-encoder-ip67-a6-ec100l2a1-m17),
|
||||
October 2026). The conveyor uses the same kit, so one spare covers both.
|
||||
|
||||
- **Belt ratio 1:6** (for example 15 to 90 teeth). The record alone is
|
||||
about 20.5 kg·cm² (180 g at 150.8 mm radius); with the spindle head the
|
||||
load is about 25 to 35 kg·cm² (estimate). That is about 1,000 times the
|
||||
rotor direct; through 1:6 the ratio comes down to about 28, inside the
|
||||
drive's tuning range. The motor then runs at 360 rpm for one turn a
|
||||
second.
|
||||
- **Torque is no limit.** Reaching one turn a second in 0.15 s takes
|
||||
about 0.13 N·m at the spindle and 0.02 N·m at the motor (our
|
||||
arithmetic), well under the rating.
|
||||
- **Camera clock from a spindle encoder.** The A6-EC drive has no
|
||||
divided encoder output: its CN1 port carries five inputs, two of them
|
||||
touch probes, and three outputs
|
||||
([A6-EC manual](https://www.omc-stepperonline.com/download/A6-EC_series_servo_drive_manual.pdf)).
|
||||
So an incremental encoder (RS-422 line driver, 2,000 to 2,500 pulses a
|
||||
turn) sits on the spindle shaft. Its A/B signals clock both line-scans
|
||||
directly (Basler racer 2 encoder control,
|
||||
[Basler](https://docs.baslerweb.com/encoder-control)), so line timing
|
||||
never passes through software, and it measures the spindle itself
|
||||
rather than the motor behind the belt. The same line also runs to an
|
||||
EtherCAT encoder terminal (EL5101), which counts A/B and latches the
|
||||
index once a turn. The scan, the laser traces and the servo then share
|
||||
one angle reference.
|
||||
- **STO version, looked at in October 2026.** StepperOnline sells the
|
||||
A6-EC drive with Safe Torque Off only from 400 W: A6-EC400H2B1-M17-STO
|
||||
with a brake (USD 157.91,
|
||||
[StepperOnline](https://www.omc-stepperonline.com/a6-series-400w-sto-safe-torque-off-ethercat-ac-servo-motor-kit-3000rpm-1-27nm-w-brake-17-bit-absolute-encoder-ip67-a6-ec400h2b1-m17-sto))
|
||||
or the same without a brake, A6-EC400H2A1-M17-STO (USD 129.60). The STO
|
||||
is two 24 V inputs, STO1 and STO2, on CN5, but its manual names no
|
||||
safety rating: no SIL or PL figure and no certificate
|
||||
([A6-EC-STO manual](https://files.omc-stepperonline.com/A6-EC-STO_manual.pdf)).
|
||||
On that document alone it cannot replace the contactor in the safety
|
||||
circuit. The brake holds nothing on a horizontal spindle or conveyor.
|
||||
Recommendation: stay with the 100 W kit. If StepperOnline confirms a
|
||||
rated STO in writing, switch both axes to the version without a brake
|
||||
and drop the contactor; its 0.60 kg·cm² rotor then needs only a 1:2 to
|
||||
1:3 belt.
|
||||
|
||||
**Sensor list.** Everything that measures the record, and everything the
|
||||
station controller needs to run the station. Lights, drives and cylinders are in the
|
||||
[bill of materials](inline-qc-station/inline-qc-station-bom.csv).
|
||||
|
||||
| Sensor | Qty | Example | Where | What it measures | USD each |
|
||||
|---|---|---|---|---|---|
|
||||
| 4k monochrome line-scan camera, GigE, 50 mm lens | 2: top and bottom | Basler racer 2 r2L4096, Hikrobot MV-CL042-91GM | inspection zone, on opposite radii (top 330 mm above the record) | surface: non-fill, stitching, flow lines, specks, bubbles, under dark-field, bright-field and transmitted light on alternate lines; eccentricity from the groove spiral | 857 to 1,088 (Basler web shop); lens 300 to 800 (estimate) |
|
||||
| 8 MP colour area camera, GigE, 16 mm lens, ring light | 2: top and bottom | Basler ace 2 a2A2840-14gcPRO | label gate, 520 mm from the infeed | right label on the right side, print, label centring; the top camera also reads the stamper number in the run-out | 1,119 (Basler web shop); lens and ring light 300 to 800 (estimate) |
|
||||
| Laser distance sensor | 2 | Micro-Epsilon optoNCDT 1420 | under the record, at 90 and 130 mm radius; analog output to the EtherCAT analog input | warp: height traced round two circles during the turn | from EUR 470 list; ILD1420-25 about 1,600 at a reseller |
|
||||
| Servo encoder, 17-bit | 2: spindle and conveyor | StepperOnline A6-EC100L2A1-M17 kit | in each motor; position over EtherCAT | spindle angle for the sequence and the warp traces; conveyor travel | in the kit, 123.29 |
|
||||
| Incremental encoder, RS-422 line driver, 2,000 to 2,500 pulses a turn | 1 | Omron E6B2-CWZ1X class | on the spindle shaft | A/B clock both line-scans; A/B and the index go to the EL5101 encoder terminal, which counts the spindle angle | 53 to 282 (geizhals.de, October 2026) |
|
||||
| Diffuse photoelectric sensor | 3 | any industrial make | looking up through the open centre: infeed, label trigger, outfeed | a record at the infeed starts the cycle; the trigger fires the label cameras; a full outfeed holds the next record | 50 to 150 (estimate) |
|
||||
| Through-beam photoelectric sensor | 1 pair | any industrial make | across the conveyor at the inspection position | the record's leading edge; stops the belts over the chuck | 50 to 150 (estimate) |
|
||||
| Cylinder position switch | 6 | SMC D-M9 class | lift (up, down), reject pusher (home, out), mandrel (open, clamped) | confirms each move before the next step | 25 to 60 (estimate) |
|
||||
| Safety door switch | 1 | any safety-rated make | tunnel door | stops the station when the door opens, through the safety relay with the e-stop | in the door lot, 120 to 350 (estimate) |
|
||||
| Thermal camera (option, not in the launch setup) | 0 or 1 | Optris Xi 400 | over the unload position, at a press-side station only | temperature map of a warm record, trended against warp | from EUR 1,950 |
|
||||
| Laser line profiler (alternative to the two lasers) | 0 or 1 | Keyence LJ-X8000, LMI Gocator 2500, Micro-Epsilon scanCONTROL | across the radius | full height and thickness map | 8k to 20k (estimate) |
|
||||
|
||||
So the launch station carries four cameras, two lasers, two servo
|
||||
encoders and the spindle encoder, four photoelectric sensors, six
|
||||
cylinder switches and the door switch. The cameras go to the edge PC,
|
||||
the spindle encoder straight to the line-scans, and everything else onto
|
||||
EtherCAT.
|
||||
|
||||
**Cycle per record (estimate).**
|
||||
|
||||
| Step | Time |
|
||||
|---|---|
|
||||
| Convey to the inspection position | 1.5 to 2.5 s |
|
||||
| Lift and clamp | 0.5 s |
|
||||
| One turn, with run-up and stop | 1.3 s |
|
||||
| Lower | 0.3 s |
|
||||
| Convey out, with a push if rejected | 1 to 2 s |
|
||||
| **Total** | **about 5 to 6 s** |
|
||||
|
||||
A Duplex cell delivers a record every 15 to 20 s and the Classic one
|
||||
every 28 s; together that is 5 to 6 records a minute, against the 10 to
|
||||
12 the station can take. The PC finishes the verdict while the record is lowered and
|
||||
carried to the pusher.
|
||||
|
||||
**Control: EtherCAT** (decided October 2026; it replaces the small PLC
|
||||
of the first draft). The full plan, with the I/O list, geizhals.de
|
||||
prices, safety circuit, bench test and build order, is in
|
||||
[inline-qc-control-plan.md](inline-qc-control-plan.md).
|
||||
|
||||
- **Station controller:** a fanless mini PC, Intel N100 with Intel
|
||||
i226-V ports, EUR 394 to 456 on
|
||||
[geizhals.de](https://geizhals.de/mini-pc-barebone-netzwerk-pc-intel-n100-a2926989.html)
|
||||
(October 2026). It runs NixOS with the PREEMPT_RT
|
||||
kernel, declared in the plant's clan like the edge PC. It is the
|
||||
EtherCAT master and runs the station sequence, which we write
|
||||
ourselves; there is no PLC.
|
||||
- **Master software,** open source either way:
|
||||
- **QiTech's EtherCAT library on EtherCrab:**
|
||||
[qitech_lib](https://github.com/qitechgmbh/qitech_lib) (LGPL-3.0),
|
||||
the layer under [QiTech Control](https://github.com/qitechgmbh/control),
|
||||
which runs QiTech's own extrusion and winding machines on NixOS. It
|
||||
brings distributed clocks, SDO and PDO handling, Beckhoff drivers and
|
||||
a CiA402 servo driver to copy for the A6-EC; EtherCrab
|
||||
([GitHub](https://github.com/ethercrab-rs/ethercrab), MIT or
|
||||
Apache-2.0) is the pure Rust master underneath. It fits the Rust stack
|
||||
of the factory application, and is the first choice.
|
||||
- **IgH EtherCAT Master:** the mature fallback (GPL-2.0, its library
|
||||
LGPL-2.1), packaged in nixpkgs
|
||||
([MyNixOS](https://mynixos.com/nixpkgs/package/linuxKernel.packages.linux_6_18.ethercat)).
|
||||
Its native igc driver for the i226 is listed for the 6.12 kernel, so
|
||||
with IgH, pin the 6.12 LTS kernel
|
||||
([IgH device drivers](https://docs.etherlab.org/ethercat/1.6/doxygen/devicedrivers.html)).
|
||||
- **On the bus, in one line:** an EK1101 coupler with EL1809 (16
|
||||
inputs: photoelectric sensors, cylinder switches, door and e-stop
|
||||
status), EL2809 (16 outputs: valves, stack light), EL3152 (two 4 to
|
||||
20 mA inputs for the warp lasers) and EL5101 (spindle encoder), then
|
||||
the spindle drive and the conveyor drive at the end of the line. The
|
||||
small A6-200EC takes its control power from the main supply, so it
|
||||
leaves the bus when the safety contactors open; at the end it cuts
|
||||
nothing else off. The cycle is 1 ms with distributed clocks. The
|
||||
spindle runs in cyclic synchronous position mode, the conveyor in
|
||||
cyclic synchronous velocity.
|
||||
- **Warp traces:** the lasers are sampled in the same cycle as the
|
||||
spindle encoder count, so each trace comes with its angles: about
|
||||
1,000 points a turn at 1 ms (our arithmetic). The optoNCDT 1420 has a
|
||||
4 to 20 mA output, hence the EL3152 rather than a voltage terminal.
|
||||
- **Safety stays hardwired:** the e-stop and the door switch sit on a
|
||||
safety relay that drops a contactor in the drive supply. The 100 W kit
|
||||
has no STO input; in the A6-EC list, STO versions start at 400 W.
|
||||
- **Edge PC:** the NixOS edge PC with the GPU, under the outfeed, takes
|
||||
the four GigE cameras on PoE and the light controllers. It talks to the
|
||||
station controller over plain Ethernet (record in place, turn done,
|
||||
verdict with the reason) and sends the result string and images to the
|
||||
factory system (see [digital factory](../digital-factory.md)). Keeping
|
||||
the master off this PC keeps the GPU load away from the real-time loop.
|
||||
- **HMI:** a browser page from the station controller on the 10 inch
|
||||
touch panel.
|
||||
|
||||
Utilities are 230 V single phase at about 1 kW and 6 bar compressed air
|
||||
(estimates).
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
**Bill of materials.** The line-by-line list with sources is in
|
||||
[`inline-qc-station-bom.csv`](inline-qc-station/inline-qc-station-bom.csv).
|
||||
By group, per station:
|
||||
|
||||
| Group | USD | Main parts |
|
||||
|---|---|---|
|
||||
| Frame | 0.8k to 1.6k | 32 m of 40 × 40, 3.8 m of 40 × 80, angle brackets, feet |
|
||||
| Enclosure and guards | 0.3k to 0.7k | black panels, polycarbonate, door switch |
|
||||
| Conveyor | 0.4k to 1.1k | round belts, pulleys, slide strips, 100 W EtherCAT servo drive |
|
||||
| Handling | 1.9k to 4.5k | guided lift cylinder, 100 W EtherCAT spindle servo, spindle head with mandrel, rodless cylinder, pneumatics |
|
||||
| Vision | 7.7k to 12.5k | 2 line-scans, 2 colour cameras, lenses, 2 coaxial, 4 dark-field and 2 backlights, 2 ring lights, controllers |
|
||||
| Sensors | 1.5k to 4.6k | 2 laser distance sensors, presence and stop sensors, cylinder switches, spindle encoder |
|
||||
| Control | 4.2k to 7.7k | EtherCAT controller and I/O, edge PC with GPU, HMI, safety, cabinet and wiring |
|
||||
| **Total** | **17k to 33k (0.55M to 1.08M THB)** | thermal camera (USD 2.1k to 3.0k) not included |
|
||||
|
||||
**Open points for the machine builder.**
|
||||
|
||||
1. **Sag:** confirm that the rim-only support does not mark or bend the
|
||||
records: cooled ones at launch, warm ones at a press-side station.
|
||||
2. **Static:** fresh PVC attracts dust, so an ionising bar at the infeed
|
||||
may be needed. Otherwise the station counts dust it attracted itself.
|
||||
3. **Classic hand-off:** only for a press-side station later; at launch
|
||||
the Classic stacks on its spindle as built.
|
||||
4. **Belt width:** a quick-change spacing for 10" and 7" records.
|
||||
5. **Space:** at launch the station and the cooling racks stand at the
|
||||
start of the finishing block; a press-side station later has to fit the
|
||||
5 × 3 m Duplex cell next to the trimmer.
|
||||
|
||||
## Where it sits
|
||||
|
||||
**Launch setup: one station for both presses, after cooling** (decided
|
||||
October 2026).
|
||||
|
||||
- **To the cooling racks.** The records leave both presses on spindle
|
||||
stacks as they do today: the Classic stacks by itself, with its cooling
|
||||
plates ([pressing line](pressing-line.md)), and the Duplex operator
|
||||
stacks the trimmed records. Each full stack gets a label, scanned at the
|
||||
press, with the press, the stamper set and the first and last cycle. The
|
||||
stacks go into the cooling racks first in, first out.
|
||||
- **The queue.** 24 hours of cooling before sleeving is accepted practice,
|
||||
and some plants cut it to 8 hours
|
||||
([Stamper Discs](https://stamperdiscs.com/horns-and-quality-issues-in-vinyl-record-pressing)).
|
||||
The station takes the stacks at the end of that time. A single record
|
||||
would reach room temperature within minutes in still air (our estimate
|
||||
for a 1.8 mm disc), but records keep settling for hours, so the queue is
|
||||
measured in hours. The racks hold about one day of output: 2,800 to
|
||||
3,100 records at the launch plant (the 850k target to the ~0.94M
|
||||
capacity in the [calculator](../fleet-calculator.html), over 300 days).
|
||||
- **Stacks and cooling plates** (decided October 2026).
|
||||
- **50 records a stack,** about 15 to 25 minutes of one press. Cascade
|
||||
Record Pressing pulls the spindle at 50
|
||||
([VRTX](https://vrtxmag.com/articles/how-to-press-vinyl-locally)).
|
||||
Fifty 180 g records weigh 9 kg; a day of output is about 58 stacks.
|
||||
- **A flat aluminium cooling plate every 5 records** (decided October
|
||||
2026), so 10 plates in a stack of 50. MY45 lays one every ten
|
||||
([oberflaeche.de](https://oberflaeche.de/en/knowledge/topics/electro-plating/a-vinyl-renaissance/the-great-comeback-of-the-record-3)),
|
||||
Mobineko one under every record
|
||||
([Mobineko](https://mobineko.com/vinyl-quality-standards)). The
|
||||
Classic places the plates itself ("automatic cooling plate handling",
|
||||
[Newbilt](https://vinyl-pressing-plants.com/blog/newbilt-classic-12-inch-vinyl-record-press));
|
||||
at the Duplex the operator lays one by hand. Full flat discs, not ring
|
||||
spacers: a warm record held only round the label sags into a dish.
|
||||
A stack then weighs about 15 kg: 9 kg of records and 10 plates of
|
||||
0.6 kg at 3 mm (0.4 kg at 2 mm).
|
||||
- **Plates cut locally.** 5052 aluminium, 3 mm thick, with the centre
|
||||
hole of Newbilt's plate so the Classic's magazine takes them;
|
||||
thickness and alloy are our estimate until Newbilt's drawing arrives.
|
||||
A 1220 × 2440 mm sheet nests 28 discs of up to about 310 mm, and a
|
||||
3 mm sheet costs about THB 8,300 before VAT
|
||||
([OneStockHome](https://www.onestockhome.com/th/product_categories/aluminum-sheet-thickness-3-mm),
|
||||
grade 3003, October 2026): about THB 300 of metal a plate, THB 350 to
|
||||
450 with cutting and deburring (estimate). Cut on a fibre laser or a
|
||||
waterjet. Chiang Mai has several laser shops (SK Laser Cut and Laser
|
||||
CNX on Rattanakosin Road, among others), but many cut only acrylic and
|
||||
wood, so ask for 3 mm aluminium.
|
||||
- **Keeping the plates from scratching the records:**
|
||||
1. **The grooves never touch the plate.** Record dies have a thick
|
||||
label area matched by a thick outer edge, so pressed records stack
|
||||
without the groove area touching while they cool
|
||||
([Quality Record Pressings](http://qualityrecordpressings.com/index.cfm?go=Record-Weights)).
|
||||
A flat plate rests on the same two rings. That holds as long as the
|
||||
plate is flat (checked on a surface plate, no gap over 0.1 mm, our
|
||||
target) and the Newbilt dies have this profile (to confirm).
|
||||
2. **The plate is larger than the record,** about 306 to 310 mm
|
||||
against 302 mm, so the record's rim sits on the flat face and never
|
||||
on the plate's edge. All edges and the centre hole are deburred and
|
||||
rounded; the centre hole sits under the label.
|
||||
3. **Clear anodised** (about 10 to 15 µm): a hard, closed surface
|
||||
that does not smear grey aluminium onto the record and keeps its
|
||||
finish longer. Roughly CNY 16 to 28 a square metre in bulk in China
|
||||
([YF CNC](https://yfcncmachining.com/reference-price-for-domestic-surface-treatment-in-china/));
|
||||
THB 50 to 150 a plate for a small Thai batch (estimate). The first
|
||||
two sheets test bare against anodised.
|
||||
4. **Straight up and down only.** Records and plates go onto the
|
||||
spindle and come off it vertically; nothing slides across a
|
||||
record. Lint-free gloves, plates lifted by the rim that stands out
|
||||
past the record.
|
||||
5. **No grit between them.** Grit trapped under 15 kg is what
|
||||
scratches. Flash from the edge trimmer goes into the trimmer's
|
||||
extraction, not onto the stack. Each plate passes an ionised-air
|
||||
blow-off and a wipe on its way back to the presses, plates travel
|
||||
on a covered spindle cart, and the racks are covered.
|
||||
6. **Plates are numbered** (laser mark on the band outside the
|
||||
record) and looked at under a raking light every month; a dented
|
||||
or scratched plate is taken out.
|
||||
7. **The station proves it.** It knows each record's place in the
|
||||
stack, so it can compare scratch counts on faces that lay on a
|
||||
plate with faces that lay on another record. If the plate faces
|
||||
come out worse, the plates are the cause.
|
||||
- **How many:** one plate per 5 records over the full 24-hour queue
|
||||
needs about 700 plates (25 sheets): THB 245,000 to 315,000 cut, plus
|
||||
THB 35,000 to 105,000 for anodising (estimates). An 8-hour queue
|
||||
needs about 200 to 260. Ask Newbilt how many plates come with the
|
||||
Classic. Two sheets come first, for the plate trial (next steps).
|
||||
|
||||
- **At the station.** The finishing operator takes each record off the
|
||||
cooled stack and puts it on the infeed, and lifts each cooling plate
|
||||
onto the plate cart that goes back to the presses. Good records leave the outfeed
|
||||
into sleeving; a reject goes into the bin, and the HMI shows the reason.
|
||||
Finishing handles every record anyway, so the station adds no handling
|
||||
step.
|
||||
- **What it gains.**
|
||||
- Warp and centring are measured on settled records, so the reading is
|
||||
the release value; no separate sampling of cooled records is needed.
|
||||
- One station instead of two: USD 17k to 33k instead of 50k to 105k
|
||||
(estimates).
|
||||
- The Classic needs no change to its unloader.
|
||||
- The questions about warm records drop out: sag on the rim belts and
|
||||
the thermal camera.
|
||||
- **What it costs.** A defect is found hours after pressing instead of
|
||||
within a cycle or two. Three things cover that gap:
|
||||
1. The Duplex operator still sees every record.
|
||||
2. Press telemetry flags process drift every cycle
|
||||
([layer 2](../quality-automation.md#layer-2-press-telemetry-every-cycle)).
|
||||
3. An early lane: the first records of every run, and the first after
|
||||
each stamper change, go to the station warm, straight from the press.
|
||||
Their surface and label verdicts count; their warp is only an early
|
||||
warning. The station runs at about half its capacity at launch, so
|
||||
there is room for this lane.
|
||||
- **Record key.** Away from the press, the station takes the key from the
|
||||
stack label and the record's place in the stack (the top record is the
|
||||
last one pressed). It checks that against the stamper number read in the
|
||||
run-out; the readability of that code is still to test. Where the check
|
||||
fails, the result stays tied to the stack: press, stamper set and time
|
||||
window ([traceability](../traceability.md)).
|
||||
- **Capacity.** The launch plant makes 5 to 6 records a minute and the
|
||||
station takes 10 to 12. One station covers about two Duplex systems and
|
||||
two Classics at the calculator's planning rates (3 + 3 + 2 + 2 = 10 a
|
||||
minute). Past that, add a second station or move to stations at the
|
||||
presses.
|
||||
|
||||
**Considered, not taken: a spiral cooling tower.** Holding the whole
|
||||
queue on a spiral is out of proportion. Eight hours of output lying
|
||||
single is about 2,900 records, some 300 m of 1 m belt three records
|
||||
across, roughly USD 75k to 120k at USD 250 to 300 per metre for Chinese
|
||||
spiral coolers
|
||||
([listing](https://www.sourcingai.com/smart-products/acebakebreadmachine/flexible-screw-cooling-spiral-tower-conveyor-tower-with-advanced-cooling-technology-for-bakery-BUWkKSqORktM);
|
||||
our arithmetic), for a job the racks do for a few thousand. Bakery
|
||||
spirals are built for 30 to 60 minutes
|
||||
([I.J. White](https://www.ijwhite.com/blog/ultra-series-spiral-cooler-at-klosterman-baking/)).
|
||||
Open on a belt for hours, fresh records also collect dust on both faces,
|
||||
and a record lying alone has no stack weight holding it flat. A short
|
||||
spiral of 30 to 60 minutes (20 to 40 m of belt, about USD 5k to 16k
|
||||
ex-works, estimate) stays a later option: it would hand cooled records
|
||||
to the station one by one and give each its exact pressing time, but
|
||||
warp would then be read after an hour instead of on settled records.
|
||||
The plate trial checks whether the early reading predicts the settled
|
||||
one.
|
||||
|
||||
**Later option: a station at each press.** It finds a defect streak
|
||||
within a cycle or two, at the price of one station per cell, and it reads
|
||||
warm records, so release on warp still needs cooled samples.
|
||||
|
||||
- **Duplex cell.** After the edge trimmer, in front of the operator,
|
||||
before the spindle. The operator puts each trimmed record on the infeed;
|
||||
a stack light and the HMI show green or red; a good record waits at the
|
||||
outfeed for the spindle.
|
||||
- **Classic.** Ask Newbilt whether the unload handling can set the record
|
||||
down on the station's infeed instead of the spindle. If not, a fixed
|
||||
area camera over the unload position covers surface and label, and
|
||||
leaves warp and eccentricity to samples.
|
||||
|
||||
**Plant view.** The [plant and business plan calculator](../fleet-calculator.html)
|
||||
draws the station with the cooling racks in the room at the start of the
|
||||
finishing block.
|
||||
|
||||
## Two software routes
|
||||
|
||||
| | Smart camera or vendor controller | Open, PC-based |
|
||||
|---|---|---|
|
||||
| Examples | Cognex In-Sight 3800 with edge learning (about USD 8,500 a unit in a [third-party listing](https://robotomated.com/explore/manufacturing/cognex-insight-3800)); Keyence CV-X or XG-X with LumiTrax, which separates shape from surface pattern on shiny parts ([Keyence](https://www.keyence.com/landing/vision/lumitrax-lighting.jsp)); CV-X controllers listed at about USD 5,400 to 5,500 on resale sites ([BigGo](https://biggo.com/s/cv-x%20keyence)); Keyence quotes only locally | GenICam cameras (Basler, Hikrobot, or Keyence's VJ series) with:<br>- Aravis for acquisition (LGPL-2.1, GigE Vision and USB3 Vision, packaged in nixpkgs as 0.8.35; [GitHub](https://github.com/AravisProject/aravis), [MyNixOS](https://mynixos.com/nixpkgs/package/aravis)), or Harvester (Apache-2.0, needs the camera maker's GenTL producer; [GitHub](https://github.com/genicam/harvesters));<br>- OpenCV;<br>- anomalib for learned defect detection (Apache-2.0, PatchCore and others; [PyPI](https://pypi.org/project/anomalib/)) |
|
||||
| For | fast set-up, vendor support, tested tools | we own the code and the data, no licence per unit, fits the NixOS stack and the service offer to other plants ([digital factory](../digital-factory.md)) |
|
||||
| Against | closed, Windows set-up tools; the polar unwrap, eccentricity fit and per-job learning still have to be built on top | we build and maintain it; the first station takes longer |
|
||||
|
||||
Keyence's VJ series sits between the two. It sells Keyence GigE cameras
|
||||
and LumiTrax lights for PC-based software, with GenICam, OpenCV and
|
||||
HALCON listed as supported
|
||||
([Keyence VJ](https://keyence.com/ss/products/vision/vj)).
|
||||
|
||||
Recommendation: take the open route for the station itself. Before that,
|
||||
ask Keyence Thailand for its free demo and test report on sample records
|
||||
with LumiTrax. It costs nothing, teaches us the lighting, and gives a
|
||||
benchmark for our own result.
|
||||
|
||||
## Colour and special records
|
||||
|
||||
Specials are planned at 60 % or more of output, and they are the hard
|
||||
part:
|
||||
|
||||
- **Marbled and splatter:** the pattern is random, so a fixed golden image
|
||||
cannot work. The model learns each job from its first approved records
|
||||
and flags what differs. That is few-shot anomaly detection, for example
|
||||
PatchCore in anomalib, with the operator confirming the first flags.
|
||||
- **Clear and translucent colours:** transmitted light shows bubbles and
|
||||
specks well.
|
||||
- **Picture discs:** they need the label-style print comparison over the
|
||||
whole face.
|
||||
- **Black:** the easiest.
|
||||
|
||||
Expect more false rejects on specials in the first months (estimate). The
|
||||
reject rates in the [factory console](../factory-console.html) demo are
|
||||
simulated.
|
||||
|
||||
## Cost
|
||||
|
||||
| Item | Estimate |
|
||||
|---|---|
|
||||
| Hardware per station, from the [bill of materials](inline-qc-station/inline-qc-station-bom.csv) | USD 17k to 33k (0.55M to 1.08M THB) |
|
||||
| First station: frame build and machined parts, lighting trials, software, training data | 2 to 4 person-months, USD 15k to 40k (our own team with a local machine builder) |
|
||||
| Launch plant: one station for both presses, after cooling | the hardware above, USD 17k to 33k, plus the first-station work (about USD 32k to 73k in all, 1.0M to 2.4M THB) |
|
||||
|
||||
All three figures are estimates; the bill of materials names a source for each priced line. They fit inside the existing metrology
|
||||
launch-tier line, USD 170k to 460k for XRF, inline vision and the audio
|
||||
station ([total investment](../finance/total-investment.md)). The plan
|
||||
prices therefore do not change. That line has no published split, so the
|
||||
vision share is not yet confirmed.
|
||||
|
||||
## Where to buy in Thailand
|
||||
|
||||
| Brand | Channel | Status |
|
||||
|---|---|---|
|
||||
| Keyence | Keyence (Thailand), direct sales | free demos and test reports, as Keyence offers in other markets ([Keyence](https://www.keyence.eu/landing/lpc/surface-defect-detection.jsp)); confirm locally |
|
||||
| Basler | LINX KK (Thailand), Basler's only official distributor in Thailand ([LINX](https://linx.co.th/en)) | |
|
||||
| Cognex | local distributor | still to name |
|
||||
| Hikrobot | local distributor or the Chinese route | still to name |
|
||||
| Micro-Epsilon, LMI, Optris | local distributor | still to name |
|
||||
|
||||
## Next steps
|
||||
|
||||
1. **Lighting trials.** Get a dozen records with known defects from a
|
||||
partner plant: non-fill, stitching, bubbles, an off-centre one, and a
|
||||
splatter colour. Test them with a borrowed line-scan camera and two
|
||||
lights.
|
||||
2. **Keyence test.** Ask Keyence Thailand for a test report on the same
|
||||
records.
|
||||
3. **Newbilt.** Ask how the Classic hands over its spindle stacks and
|
||||
cooling plates (records per stack, records per plate), and for the
|
||||
drawing of its plate (diameter, thickness, alloy, centre hole) so the
|
||||
locally cut plates fit its magazine. Also ask for the cycle counter over
|
||||
OPC UA, so every stack label carries the record key (stamper, press,
|
||||
cycle, side; see [digital factory](../digital-factory.md)).
|
||||
4. **Warp sensors.** Choose between two point lasers and a line profiler
|
||||
once the trials show whether a thickness map is worth the extra cost.
|
||||
5. **Plate and settling trial.** Cut two sheets of plates (56), half of
|
||||
them anodised. Press one job with a plate every 5, 10 and 25 records,
|
||||
and read edge run-out and dish on the station after 1 hour and after
|
||||
24 hours, plus the scratch counts on plate faces against record faces.
|
||||
That confirms 5 records per plate or shows that 10 is enough (black,
|
||||
colour and specials apart), and shows whether a 1-hour reading
|
||||
predicts the settled one.
|
||||
6. **EtherCAT bench.** Before the frame is built, run one A6-EC kit, the
|
||||
EK1101 with its terminals and the spindle encoder from the mini PC
|
||||
with qitech_lib on EtherCrab: eight tests and pass marks are in the
|
||||
[control plan](inline-qc-control-plan.md#7-bench-test-before-the-frame-is-built)
|
||||
(about THB 56,000 of parts, all reused in the station). If the
|
||||
EtherCrab stack falls short on the drive, repeat the test with the
|
||||
IgH master.
|
||||
7. **Acceptance test.** Write it before ordering. It should cover the
|
||||
detection rate per defect class on the trial set, the false-reject
|
||||
rate on good records (black and specials apart), and every result
|
||||
matched to its record key.
|
||||
@@ -0,0 +1,349 @@
|
||||
# Optical QC station: EtherCAT control plan
|
||||
|
||||
How the [inline optical QC station](inline-optical-qc.md) is controlled,
|
||||
wired, priced, built and tested. Decided in October 2026: EtherCAT, no
|
||||
PLC, and the 100 W StepperOnline servo kit on both axes. Prices for the
|
||||
EtherCAT parts were checked on [geizhals.de](https://geizhals.de/) and in
|
||||
the [QiTech shop](https://shop.qitech.de/collections/ethercat) on
|
||||
19 October 2026; the station software builds on QiTech's open-source
|
||||
EtherCAT library (section 5). The station hardware itself (frame, cameras, lights,
|
||||
lasers) is in the station doc and its
|
||||
[bill of materials](inline-qc-station/inline-qc-station-bom.csv).
|
||||
|
||||
## 1. What is decided
|
||||
|
||||
| Part | Choice | Why |
|
||||
|---|---|---|
|
||||
| Fieldbus | EtherCAT, 1 ms cycle, distributed clocks | one cable for drives and I/O; the laser samples and the spindle position come from the same cycle |
|
||||
| Spindle drive | StepperOnline A6-EC100L2A1-M17 (100 W, A6-200EC drive), cyclic synchronous position, 1:6 timing belt | torque need about 0.02 N·m at the motor against 0.32 N·m rated; the belt brings the load inertia to about 28 times the rotor (station doc) |
|
||||
| Conveyor drive | the same kit, cyclic synchronous velocity | one spare covers both axes |
|
||||
| Controller | fanless Intel N100 mini PC with Intel i226-V ports, NixOS with a real-time kernel | open source stack, declared in the plant's clan like every other machine |
|
||||
| Master software | QiTech's EtherCAT library (qitech_lib, LGPL-3.0) on EtherCrab; IgH EtherCAT Master as the fallback | Rust like the factory application, already running QiTech's own production machines, with distributed clocks and a servo driver to copy; IgH is older and proven |
|
||||
| Camera clock | separate RS-422 encoder on the spindle shaft | the A6-EC drive has no divided encoder output |
|
||||
| Safety | hardwired: safety relay, two contactors in the drive supply | the 100 W kit has no STO; the 400 W STO kit's manual names no safety rating (station doc) |
|
||||
|
||||
## 2. Bus layout
|
||||
|
||||
```
|
||||
Station controller (N100, NixOS, real-time kernel)
|
||||
|
|
||||
|-- port 1 (i226-V) == EtherCAT ==> EK1101 coupler
|
||||
| |-- EL1809 16 digital inputs
|
||||
| |-- EL2809 16 digital outputs
|
||||
| |-- EL3152 2 analog inputs (warp lasers, 4 to 20 mA)
|
||||
| |-- EL5101 spindle encoder (A, B, index)
|
||||
| |-- EL9011 end cap
|
||||
| |
|
||||
| X2 out ==> A6-200EC spindle (CSP)
|
||||
| ==> A6-200EC conveyor (CSV)
|
||||
|
|
||||
|-- port 2 (i226-V) -- plain Ethernet --> edge PC, plant OT network
|
||||
|
||||
Spindle encoder (RS-422, 5 V from the EL5101)
|
||||
A, B ---> racer 2 line-scan 1 ---> racer 2 line-scan 2 ---> EL5101 (A, B, index)
|
||||
```
|
||||
|
||||
- **The drives sit at the end of the line.** On the small A6-200EC the
|
||||
control electronics share the main supply; there are no separate
|
||||
control-power terminals ([A6-EC manual](https://www.omc-stepperonline.com/download/A6-EC_series_servo_drive_manual.pdf),
|
||||
specification table). So when the safety contactors open, both drives
|
||||
leave the bus. At the end of the line that cuts nothing else off: the
|
||||
coupler, the I/O and the encoder count stay up, and the master can read
|
||||
the e-stop and door status and bring the drives back after the reset.
|
||||
The distributed-clock reference also sits on the I/O side for the same
|
||||
reason.
|
||||
- **One RS-422 line, three receivers.** The encoder's line driver feeds
|
||||
both cameras and the EL5101 in a chain (RS-422 allows up to ten
|
||||
receivers). The racer 2 inputs take RS-422 with a switchable 120 Ω
|
||||
terminator ([Basler](https://docs.baslerweb.com/io-control-racer-2-l-xl)).
|
||||
Only the last receiver on the line is terminated; check on the bench
|
||||
whether the EL5101 input already is.
|
||||
- **Port 2 is ordinary Ethernet** to the edge PC and the plant's OT
|
||||
network (VLAN as in [digital factory](../digital-factory.md)). The
|
||||
EtherCAT port is a point-to-point cable to the EK1101, never a switch.
|
||||
|
||||
## 3. Signals
|
||||
|
||||
**EL1809, 16 inputs (24 V):**
|
||||
|
||||
| Ch | Signal | Device |
|
||||
|---|---|---|
|
||||
| 1 | record at the infeed | diffuse photoelectric sensor |
|
||||
| 2 | label trigger (also wired straight to the two colour cameras' trigger inputs) | diffuse photoelectric sensor |
|
||||
| 3 | record at the inspection position (also to the conveyor drive's touch probe 1, CN1 DI5) | through-beam pair |
|
||||
| 4 | outfeed full | diffuse photoelectric sensor |
|
||||
| 5, 6 | lift up, lift down | cylinder switches |
|
||||
| 7, 8 | mandrel open, mandrel clamped | cylinder switches |
|
||||
| 9, 10 | pusher home, pusher out | cylinder switches |
|
||||
| 11 | safety relay status | PNOZ s3 semiconductor output |
|
||||
| 12 | door closed (status contact) | safety door switch |
|
||||
| 13 | contactors closed | contactor auxiliary contact |
|
||||
| 14 | reset pressed | second contact on the reset button |
|
||||
| 15 | air pressure ok | pressure switch on the FRL |
|
||||
| 16 | spare | |
|
||||
|
||||
**EL2809, 16 outputs (24 V, 0.5 A):** lift up, lift down, mandrel clamp,
|
||||
pusher out, pusher back, stack light green, amber and red, buzzer, light
|
||||
controllers on (lights only during the turn), reset-button lamp; five
|
||||
spare (an ionising bar at the infeed is one candidate).
|
||||
|
||||
**EL3152, 2 analog inputs:** the two optoNCDT 1420 lasers at 90 and 130 mm
|
||||
radius. Their analog output is 4 to 20 mA; voltage only comes through a
|
||||
load resistor in the cable
|
||||
([Micro-Epsilon manual](https://micro-epsilon.com/download/manuals/man--optoNCDT-1420--en.pdf)),
|
||||
so the current-input EL3152 replaces the ±10 V EL3102 of the first draft.
|
||||
|
||||
**EL5101:** spindle encoder A, B and index. It counts the spindle angle
|
||||
directly (not the motor behind the belt) and latches the count at the
|
||||
index once a turn.
|
||||
|
||||
**Drive inputs:** only the conveyor drive's touch probe 1 is used: the
|
||||
through-beam latches the conveyor position at the record's leading edge,
|
||||
so the stop over the chuck does not depend on the 1 ms cycle or the
|
||||
input filter.
|
||||
|
||||
**Process data per drive.** The A6-EC has one freely mapped RPDO and
|
||||
TPDO plus fixed sets; the fixed 1702h set carries control word, target
|
||||
position, target velocity and mode together (manual, PDO section), so
|
||||
both drives can share one mapping and differ only in the mode (8 for
|
||||
CSP, 9 for CSV). The drive runs only in DC sync mode; its SYNC0 period
|
||||
range depends on the mode, so the 1 ms cycle is the first bench check.
|
||||
|
||||
## 4. Prices from geizhals.de and the QiTech shop
|
||||
|
||||
Lowest price on 19 October 2026, in EUR including 19% German VAT; THB at
|
||||
38.115 per EUR. Four terminals come from the QiTech shop (section 5),
|
||||
the rest from the lowest geizhals.de offer.
|
||||
|
||||
| Part | Qty | Example | EUR | THB | Source |
|
||||
|---|---|---|---|---|---|
|
||||
| Station controller | 1 | ANDAQI RS55 (6 × i226-V) / MNBOXCONET P2-N100 (2 × i226-V, fanless) | 393.99 to 455.99 | 15,017 to 17,380 | [geizhals](https://geizhals.de/mini-pc-barebone-netzwerk-pc-intel-n100-a2926989.html) |
|
||||
| EtherCAT coupler | 1 | Beckhoff EK1101 (EK1100 with an ID switch) | 85.13 | 3,245 | [QiTech shop](https://shop.qitech.de/products/beckhoff-ek1101), 148 in stock |
|
||||
| 16 digital inputs | 1 | Beckhoff EL1809 | 16.53 | 630 | [QiTech shop](https://shop.qitech.de/products/beckhoff-el1809), 157 in stock |
|
||||
| 16 digital outputs | 1 | Beckhoff EL2809 | 41.03 | 1,564 | [QiTech shop](https://shop.qitech.de/products/beckhoff-el2809), 104 in stock |
|
||||
| 2 analog inputs, 4 to 20 mA | 1 | Beckhoff EL3152 | 208.90 | 7,962 | [geizhals](https://geizhals.de/185886294) |
|
||||
| Encoder interface, RS-422 | 1 | Beckhoff EL5101 | 291.04 | 11,093 | [geizhals](https://geizhals.de/2974477757) |
|
||||
| End cap | 1 | Beckhoff EL9011 | 1.76 | 67 | [QiTech shop](https://shop.qitech.de/products/beckhoff-el9011), 131 in stock |
|
||||
| Spindle encoder | 1 | E6B2-CWZ1X 2000 P/R (marketplace) / GHH60 2500 P/R line driver | 45.52 to 187.83 | 1,735 to 7,159 | [geizhals](https://geizhals.de/6925000400) |
|
||||
| Safety relay | 1 | Pilz PNOZ s3 750103 | 148.38 | 5,656 | [geizhals](https://geizhals.de/pilz-pnoz-s3-24vdc-2-n-o-750103-a3204143.html) |
|
||||
| Contactor, 24 V DC coil | 2 | Siemens 3RT2015 | 27.95 each | 2,131 | [geizhals](https://geizhals.de/siemens-leistungsschuetz-3rt2015-1bb41-a3269085.html) |
|
||||
| E-stop button | 1 | Schneider Harmony, 40 mm head | 45.08 | 1,718 | [geizhals](https://geizhals.de/208045150) |
|
||||
| HMI touch monitor 10.1 inch | 1 | iiyama ProLite TF1015MC-B3 | 311.90 | 11,888 | [geizhals](https://geizhals.de/iiyama-prolite-tf1015mc-b3-a3228748.html) |
|
||||
| 24 V supply, 120 W | 1 | Mean Well SDR-120-24 | 38.87 to 47.35 | 1,482 to 1,805 | [geizhals](https://geizhals.de/980542712) |
|
||||
| Servo kit 100 W, EtherCAT | 2 | StepperOnline A6-EC100L2A1-M17 | USD 123.29 each | 8,137 | not on geizhals; [StepperOnline](https://www.omc-stepperonline.com/a6-series-100w-ethercat-ac-servo-motor-kit-3000rpm-0-32nm-17-bit-absolute-encoder-ip67-a6-ec100l2a1-m17), China warehouse |
|
||||
| **Total** | | | **1,684.03 to 1,896.82 + USD 246.58** | **72,324 to 80,434** | |
|
||||
|
||||
Notes on the prices:
|
||||
|
||||
- **German VAT comes off, Thai duty and VAT go on.** For an order
|
||||
shipped to Thailand the 19% German VAT is not charged; Thai import VAT
|
||||
(7%) and duty are added. The listed gross price is therefore used as
|
||||
the landed low end; the bill of materials adds 30% for shipping and a
|
||||
Thai distributor as the high end (estimate).
|
||||
- **QiTech shop:** Beckhoff terminals new in the original box, bought
|
||||
out of an insolvency, at a fraction of the usual price: EL1809
|
||||
EUR 16.53 against EUR 93.97 on geizhals, EL2809 EUR 41.03 against
|
||||
EUR 102.97, EK1101 EUR 85.13 against EUR 150.75 for an EK1100 (no
|
||||
current geizhals offer). Together EUR 207.57 (THB 7,912) less. The shop
|
||||
ships worldwide by DHL from Darmstadt in 7 to 14 working days; the
|
||||
postage to Thailand only shows at checkout (not checked). It has no
|
||||
EL3152 or EL5101, so those two stay with geizhals.
|
||||
- **Mini PCs** on geizhals are marketplace brands (ANDAQI, MNBOXCONET,
|
||||
AIOPCWA). Before ordering, check that the ports are i226-V (not the
|
||||
older i225) and that the BIOS lets C-states be switched off.
|
||||
- **Encoder:** the EUR 45.52 E6B2-CWZ1X listings come from marketplace
|
||||
sellers and may be copies; the bench test decides whether one is good
|
||||
enough. A genuine Omron or a 2,500-pulse line-driver encoder (GHH60,
|
||||
EUR 187.83) is the fallback.
|
||||
- **Contactors:** the price is for 3RT2015-1BB41 (one NO auxiliary
|
||||
contact). The feedback loop needs the NC version, 3RT2015-1BB42
|
||||
(price not checked; same class).
|
||||
- **Not on geizhals:** the servo kits (StepperOnline direct), the optoNCDT
|
||||
lasers and the Basler cameras (both in the station bill of materials).
|
||||
|
||||
Bill of materials effect: the control group comes to USD 4.2k to 7.7k
|
||||
(edge PC with GPU and the cabinet lot included) and the station to
|
||||
**USD 16.7k to 32.7k (THB 0.55M to 1.08M)**.
|
||||
|
||||
## 5. Software on the station controller
|
||||
|
||||
**QiTech Control, checked 19 October 2026.** QiTech, a machine builder in
|
||||
Darmstadt (filament extrusion and winding), publishes the control
|
||||
software of its own machines:
|
||||
[QiTech Control](https://github.com/qitechgmbh/control), LGPL-3.0, 359
|
||||
stars, 2,855 commits since January 2025, last push 16 October 2026,
|
||||
running more than ten of their production machines (their README). It is
|
||||
a Rust server on EtherCrab (their fork `ethercrab-dc`) with axum and
|
||||
Socket.IO, an Electron and React front end, and a NixOS image with a
|
||||
tuned kernel. The EtherCAT layer is a separate library,
|
||||
[qitech_lib](https://github.com/qitechgmbh/qitech_lib), also LGPL-3.0.
|
||||
|
||||
What fits:
|
||||
|
||||
- The same choices as this plan: Rust, EtherCrab, NixOS, Beckhoff
|
||||
terminals, no PLC.
|
||||
- Distributed clocks are built in (SYNC0 at 1 ms with a 500 µs shift by
|
||||
default), with SDO access, PDO mapping and the EtherCAT state changes.
|
||||
- Drivers exist for the EK1100 and the EL2809 of our list, and for 4 to
|
||||
20 mA inputs (EL3021, EL3024).
|
||||
- A CiA402 servo driver for the Panasonic MINAS A6 over CoE (169 lines)
|
||||
is the template for the A6-EC: the same profile and the same PDO and
|
||||
SDO steps.
|
||||
- Their NixOS settings run in production: `isolcpus=2,3` (core 2 for the
|
||||
EtherCAT thread, core 3 for the control loop), `nohz_full`,
|
||||
`rcu_nocbs`, `pcie_aspm=off`, `preempt=full` on kernel 6.18, and a
|
||||
realtime group with rtprio and memlock.
|
||||
|
||||
What is missing:
|
||||
|
||||
- Drivers for the EK1101, the EL1809 (the 16-channel twin of the
|
||||
supported EL1008), the EL3152, the EL5101 and the A6-EC drive. A
|
||||
Beckhoff driver is a short file (their EL2809: 138 lines). We write
|
||||
them and send them upstream.
|
||||
- The library's README warns that its API "may change drastically"
|
||||
before a stable release, so we pin one commit.
|
||||
- The full QiTech Control app (Electron front end, a GNOME desktop on the
|
||||
machine PC, their machine catalogue) is built around their machines.
|
||||
|
||||
**Decision:** qitech_lib, pinned, is the EtherCAT layer; the station
|
||||
service on top of it is ours; the full app is not used. The HMI stays a
|
||||
web page from the station service, which keeps the controller image
|
||||
small and the station inside the factory application's stack. Adding the
|
||||
station as a machine in a fork of their app stays open if their front
|
||||
end proves worth it. LGPL-3.0 leaves our own code under our own licence;
|
||||
changes to the library are shared under the LGPL, which we want anyway
|
||||
for the drivers. The obligations only apply if we hand the software to
|
||||
someone else.
|
||||
|
||||
**Also in their shop, not taken:** TwinSAFE terminals (EL1918
|
||||
EUR 140.89, EL2904 EUR 105.85, EL6910 EUR 106.12) need Beckhoff's
|
||||
TwinCAT tools to set up the safety logic and a master that passes the
|
||||
safety frames between terminals, which qitech_lib does not offer; the
|
||||
PNOZ relay is simpler. Beckhoff servo terminals with STO (EL7211-9014
|
||||
EUR 215.99 with an AM8122 motor at EUR 285.33) cost about EUR 500 an
|
||||
axis and need a 48 V supply; the 100 W kit stays.
|
||||
|
||||
**Operating system (NixOS module in the plant's clan):**
|
||||
|
||||
- Start from QiTech's tested kernel settings above. If the bench jitter
|
||||
test fails, move to 6.12 LTS with PREEMPT_RT (in the mainline kernel
|
||||
since 6.12), which the IgH fallback needs anyway: its native i226 (igc)
|
||||
driver is listed for 6.12
|
||||
([IgH device drivers](https://docs.etherlab.org/ethercat/1.6/doxygen/devicedrivers.html)).
|
||||
- The EtherCAT port's interrupts pinned to the EtherCAT core, deep
|
||||
C-states and Energy Efficient Ethernet off on that port.
|
||||
- The station service runs under systemd with real-time priority,
|
||||
locked memory and raw-socket rights, and restarts on failure; logs go
|
||||
to the plant's log store.
|
||||
|
||||
**Station service (Rust, one program, written by us):**
|
||||
|
||||
1. **Bus loop:** the qitech_lib EtherCAT thread every 1 ms with
|
||||
distributed clocks; brings all slaves to OP, maps the drive PDOs,
|
||||
runs the CiA402 state machine of both drives, and re-adds a drive
|
||||
that left the bus after an e-stop.
|
||||
2. **Sequence:** one state machine per record: wait at the infeed,
|
||||
convey, stop on the latched leading edge, lift, clamp, one turn,
|
||||
unclamp, lower, convey out, push if rejected. Every step has a
|
||||
timeout and a fault text (for example "lift up not reached in 0.8 s").
|
||||
3. **Measurement:** during the turn, each cycle stores the EL5101 count
|
||||
and both laser values, about 1,000 points a turn at one turn a
|
||||
second. The laser output lags 750 µs at 4 kHz (Micro-Epsilon), a fixed
|
||||
offset of about 0.3° at that speed, corrected in software. Edge
|
||||
run-out and dish are computed at the end of the turn.
|
||||
4. **Edge PC link** over port 2: record in place, turn started, turn
|
||||
done with the warp values; the edge PC answers with the verdict and
|
||||
the reason. No answer in time means reject and an alarm.
|
||||
5. **HMI:** a web page served by the same program and shown on the touch
|
||||
monitor in a kiosk browser: state, last results, alarms, counters, and
|
||||
a setup mode (jog, single steps) that works only with the door shut.
|
||||
|
||||
The cameras keep their clock in hardware: the encoder pulses go straight
|
||||
into the racer 2 encoder input, and the camera's frequency converter
|
||||
scales them to the line count the optics need
|
||||
([Basler](https://docs.baslerweb.com/frequency-converter)). No software
|
||||
sits between the spindle and the line timing.
|
||||
|
||||
## 6. Safety
|
||||
|
||||
- **Circuit:** e-stop (two channels) and the tunnel door switch (two
|
||||
channels) on a Pilz PNOZ s3 with a monitored manual reset. Its two
|
||||
safety contacts switch two contactors in series in the 230 V supply of
|
||||
both drives; the contactors' NC mirror contacts sit in the relay's
|
||||
feedback loop. A dump valve on the FRL, wired with the contactor
|
||||
coils, vents the cylinders at the same time.
|
||||
- **Stop category 0:** power off at once. Both axes carry a few
|
||||
kg·cm², so they coast to a stop in well under a second (estimate). If
|
||||
the risk assessment asks for a controlled stop first (category 1), a
|
||||
relay with delayed outputs (Pilz PNOZ s5 class) lets the master brake
|
||||
the axes before the power goes.
|
||||
- **Target:** PL d (estimate). A risk assessment to ISO 12100 and
|
||||
ISO 13849-1 by the machine builder decides; it is part of the
|
||||
acceptance test.
|
||||
- **After a stop:** reset, the drives power up and rejoin the bus, the
|
||||
master takes them back to OP, and the spindle angle comes from the
|
||||
EL5101 count, which never lost power.
|
||||
|
||||
## 7. Bench test, before the frame is built
|
||||
|
||||
**Parts:** one servo kit, the mini PC, the EK1101 with the four I/O
|
||||
terminals and the end cap, the spindle encoder, the PNOZ s3, two
|
||||
contactors, the e-stop and the 24 V supply: EUR 1,372.13 (geizhals.de
|
||||
and the QiTech shop) plus USD 123.29, about **THB 56,000 (USD 1,710)**. Every part goes into
|
||||
the station afterwards. One laser and one line-scan camera, ordered
|
||||
early from the station list, make the test complete. A reject record on
|
||||
a test mandrel is the load.
|
||||
|
||||
| # | Test | Pass (our targets) |
|
||||
|---|---|---|
|
||||
| 1 | qitech_lib (EtherCrab) brings coupler, terminals and drive to OP with distributed clocks at 1 ms | all slaves in OP, no lost frames over 24 h |
|
||||
| 2 | Cycle timing under load: images streaming on port 2, HMI open, CPU stress on the other cores | worst-case jitter under 50 µs over 24 h |
|
||||
| 3 | Spindle in CSP: one turn a second, 0.15 s run-up | stop repeatable within ±0.1° at the spindle |
|
||||
| 4 | EL5101 count against the servo position | exactly 6 motor turns per spindle turn over 1,000 turns, index latched every turn |
|
||||
| 5 | Laser through the EL3152 on the reject record | the warp trace repeats turn to turn within 0.05 mm, a tenth of the smallest edge run-out limit (0.5 mm, Mobineko) |
|
||||
| 6 | Camera clock: racer 2 on the encoder chain | the set number of lines every turn, none missed over 100 turns |
|
||||
| 7 | Conveyor (same drive in CSV): through-beam on touch probe 1 | position latched on every pass |
|
||||
| 8 | E-stop and door | contactors open, drive leaves the bus, I/O stays in OP; drive back in OP within 10 s of the reset |
|
||||
|
||||
If the EtherCrab stack fails tests 1, 2, 3 or 8 and a week of work does
|
||||
not fix it, repeat them with the IgH master on the 6.12 real-time
|
||||
kernel. The station
|
||||
service keeps the bus loop behind one interface, so only that part
|
||||
changes.
|
||||
|
||||
## 8. Build order and timing (estimates)
|
||||
|
||||
| Weeks | Step | Who |
|
||||
|---|---|---|
|
||||
| 1 to 3 | order the bench parts; servo kits from StepperOnline's China warehouse, Beckhoff and the rest from Germany or a Thai distributor | us |
|
||||
| 3 to 6 | drivers for EK1101, EL1809, EL3152, EL5101 and the A6-EC in qitech_lib, sent upstream; bench test (section 7) | us |
|
||||
| 5 to 9 | cabinet schematic (QElectroTech, open source) and cabinet build; station service and HMI | us, with a panel builder in Chiang Mai if needed |
|
||||
| 7 to 11 | frame, conveyor, spindle head and pneumatics | machine builder |
|
||||
| 10 to 12 | cabinet on the frame, wiring, drive tuning on the real spindle, first records | us and the machine builder |
|
||||
| 12 to 14 | risk assessment, acceptance test, then into production behind the cooling racks | us and the machine builder |
|
||||
|
||||
So the control work should start about four months before the first
|
||||
records need checking (estimate).
|
||||
|
||||
## 9. Spares
|
||||
|
||||
One servo kit (covers both axes), one spindle encoder and one contactor:
|
||||
about USD 210 at the prices above. At the QiTech shop's prices a spare
|
||||
coupler, EL1809 and EL2809 add only EUR 142.69 (USD 165), so they are
|
||||
stocked too. The EL3152 and EL5101 are not; a failed one is a few days by
|
||||
courier from Europe (estimate).
|
||||
|
||||
## 10. Open points
|
||||
|
||||
1. **The A6-EC drive on qitech_lib** is untested; the driver is ours to
|
||||
write from their MINAS A6 one. The bench answers it, with IgH as the
|
||||
fallback. Pin the qitech_lib commit; its API is not stable yet.
|
||||
2. **SYNC0 range of the A6-EC** at 1 ms in CSP and CSV: not in the
|
||||
material read so far; the bench checks it.
|
||||
3. **EL5101 termination** and the RS-422 chain with three receivers.
|
||||
4. **Shipping:** the QiTech shop's postage to Thailand (shown at
|
||||
checkout) and a Thai Beckhoff quote for the EL3152 and EL5101.
|
||||
5. **Risk assessment** by the machine builder: confirms PL d and stop
|
||||
category 0, or asks for the delayed relay.
|
||||
6. Still open from the station doc: 7"/10" quick change, anti-static at
|
||||
the infeed, belt tension against the motor's 78 N radial load.
|
||||
@@ -0,0 +1,5 @@
|
||||
# intermediate files of render_annotated.py / annotate_render.py
|
||||
_*.png
|
||||
_anchors.json
|
||||
*-annotated-base.png
|
||||
*.FCBak
|
||||
@@ -0,0 +1,111 @@
|
||||
# Draw the part labels onto the investor render of the inline QC station.
|
||||
# uv run --with pillow python docs/equipment/inline-qc-station/annotate_render.py
|
||||
# Reads inline-qc-station-annotated-base.png and _anchors.json from render_annotated.py
|
||||
# (FreeCAD) and writes inline-qc-station-annotated.png.
|
||||
import json
|
||||
import os
|
||||
from PIL import Image, ImageChops, ImageDraw, ImageFont
|
||||
|
||||
D = os.path.dirname(os.path.abspath(__file__))
|
||||
FONTS = "C:/Windows/Fonts/"
|
||||
SCALE = 0.75 # 4000 px render, drawn at 3/4 size (anti-aliased)
|
||||
|
||||
TITLE = "Inline optical QC station"
|
||||
SUBTITLE = ("Every record checked on both faces in one turn: surface, label, warp and centring. "
|
||||
"Failed records leave the line automatically.")
|
||||
FOOTER = ("CNX Vinyl, concept model (FreeCAD); bought parts drawn as outlines. 1.9 × 0.65 × 1.5 m, "
|
||||
"front panels and lid removed for the view. Hardware about USD 17k to 33k per station (estimate).")
|
||||
NAVY, GREY, LINE = (18, 53, 91), (85, 95, 105), (60, 74, 90)
|
||||
|
||||
|
||||
def font(name, size):
|
||||
return ImageFont.truetype(FONTS + name, size)
|
||||
|
||||
|
||||
F_TITLE, F_SUB = font("seguisb.ttf", 76), font("segoeui.ttf", 36)
|
||||
F_LAB, F_DESC, F_FOOT = font("seguisb.ttf", 40), font("segoeui.ttf", 31), font("segoeui.ttf", 27)
|
||||
|
||||
meta = json.load(open(os.path.join(D, "_anchors.json"), encoding="utf-8"))
|
||||
img = Image.open(os.path.join(D, "inline-qc-station-annotated-base.png")).convert("RGB")
|
||||
img = img.resize((round(img.width * SCALE), round(img.height * SCALE)), Image.LANCZOS)
|
||||
bb = ImageChops.difference(img, Image.new("RGB", img.size, (255, 255, 255))).getbbox()
|
||||
pad = 30
|
||||
crop = (max(0, bb[0] - pad), max(0, bb[1] - pad), min(img.width, bb[2] + pad), min(img.height, bb[3] + pad))
|
||||
img = img.crop(crop)
|
||||
anchors = [dict(a, xy=(a["xy"][0] * SCALE - crop[0], a["xy"][1] * SCALE - crop[1])) for a in meta["anchors"]]
|
||||
|
||||
COL_W, GAP, TOP, BOTTOM, MX = 760, 90, 280, 140, 90
|
||||
W = img.width + 2 * (MX + COL_W + GAP)
|
||||
H = img.height + TOP + BOTTOM
|
||||
canvas = Image.new("RGB", (W, H), (255, 255, 255))
|
||||
ox, oy = MX + COL_W + GAP, TOP
|
||||
canvas.paste(img, (ox, oy))
|
||||
d = ImageDraw.Draw(canvas)
|
||||
|
||||
d.text((MX, 60), TITLE, font=F_TITLE, fill=NAVY)
|
||||
d.text((MX + 4, 165), SUBTITLE, font=F_SUB, fill=GREY)
|
||||
d.line([(MX, 238), (W - MX, 238)], fill=(215, 220, 226), width=2)
|
||||
d.text((MX, H - 90), FOOTER, font=F_FOOT, fill=GREY)
|
||||
|
||||
# split: the left-most half of the anchors on the left, the rest on the right
|
||||
order = sorted(anchors, key=lambda a: a["xy"][0])
|
||||
half = (len(order) + 1) // 2
|
||||
cols = {"L": order[:half], "R": order[half:]}
|
||||
BLOCK = 108 # label height incl. spacing
|
||||
|
||||
|
||||
def _cross(p1, p2, p3, p4):
|
||||
def o(a, b, c):
|
||||
return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0])
|
||||
return (o(p1, p2, p3) > 0) != (o(p1, p2, p4) > 0) and (o(p3, p4, p1) > 0) != (o(p3, p4, p2) > 0)
|
||||
|
||||
|
||||
def place(items, edge_x):
|
||||
"""Label slots kept near each anchor's height without overlapping, then the anchor-to-slot
|
||||
assignment that makes no two leader lines cross (fewest crossings, then least drift)."""
|
||||
import itertools
|
||||
items = sorted(items, key=lambda a: a["xy"][1])
|
||||
lo, hi = oy - 20, oy + img.height - BLOCK + 20
|
||||
ys = [min(max(a["xy"][1] + oy - 26, lo), hi) for a in items]
|
||||
for i in range(1, len(ys)):
|
||||
ys[i] = max(ys[i], ys[i - 1] + BLOCK)
|
||||
over = ys[-1] - hi
|
||||
if over > 0:
|
||||
ys = [y - over for y in ys]
|
||||
for i in range(len(ys) - 2, -1, -1):
|
||||
ys[i] = min(ys[i], ys[i + 1] - BLOCK)
|
||||
best = None
|
||||
for perm in itertools.permutations(range(len(items))):
|
||||
segs = [((edge_x, ys[k] + 26), (items[i]["xy"][0] + ox, items[i]["xy"][1] + oy)) for k, i in enumerate(perm)]
|
||||
n = sum(_cross(*segs[a], *segs[b]) for a in range(len(segs)) for b in range(a + 1, len(segs)))
|
||||
drift = sum(abs(ys[k] + 26 - items[i]["xy"][1] - oy) for k, i in enumerate(perm))
|
||||
score = n * 1e6 + drift
|
||||
if best is None or score < best[0]:
|
||||
best = (score, perm)
|
||||
print("crossings", int(best[0] // 1e6))
|
||||
return [(items[i], ys[k]) for k, i in enumerate(best[1])]
|
||||
|
||||
|
||||
for side, items in cols.items():
|
||||
edge = MX + COL_W + GAP - 20 if side == "L" else ox + img.width + 20
|
||||
for a, y in place(items, edge):
|
||||
ax, ay = a["xy"][0] + ox, a["xy"][1] + oy
|
||||
# text in a fixed column, left-aligned; the leader leaves from the end of the title line,
|
||||
# runs level to the column edge, then straight to the part
|
||||
tl = d.textlength(a["title"], font=F_LAB)
|
||||
ly = y + 26
|
||||
if side == "L":
|
||||
tx = MX
|
||||
pts = [(tx + tl + 16, ly), (MX + COL_W + GAP - 20, ly), (ax, ay)]
|
||||
else:
|
||||
tx = ox + img.width + GAP
|
||||
pts = [(tx - 16, ly), (ox + img.width + 20, ly), (ax, ay)]
|
||||
d.line(pts, fill=LINE, width=3, joint="curve")
|
||||
d.ellipse([ax - 10, ay - 10, ax + 10, ay + 10], fill=(255, 255, 255))
|
||||
d.ellipse([ax - 7, ay - 7, ax + 7, ay + 7], fill=NAVY)
|
||||
d.text((tx, y), a["title"], font=F_LAB, fill=NAVY)
|
||||
d.text((tx, y + 52), a["desc"], font=F_DESC, fill=GREY)
|
||||
|
||||
out = os.path.join(D, "inline-qc-station-annotated.png")
|
||||
canvas.save(out, optimize=True)
|
||||
print("saved", out, canvas.size)
|
||||
@@ -0,0 +1,480 @@
|
||||
# Build the CNX Vinyl inline optical QC station (concept) in FreeCAD.
|
||||
#
|
||||
# Run inside the FreeCAD GUI (26.3):
|
||||
# exec(open(r"C:/dev/cnx_vinyl/docs/equipment/inline-qc-station/build_station.py", encoding="utf-8").read())
|
||||
# It creates the document "InlineQCStation", saves inline-qc-station.FCStd next
|
||||
# to this script and leaves the view open for rendering (render_station.py).
|
||||
#
|
||||
# Concept, not a fabrication drawing: the frame uses the real 8-slot 40 series
|
||||
# section (profile_shape), bought parts are drawn as their envelope boxes. Sizes
|
||||
# follow ../inline-optical-qc.md. At the end the script lists any part that does
|
||||
# not reach the floor through parts it touches (panels not counted).
|
||||
#
|
||||
# Axes: x = record flow (infeed at x = 0, outfeed at x = L), y = across
|
||||
# (operator front at -y), z = up from the floor. All values in mm.
|
||||
|
||||
import os
|
||||
import FreeCAD as App
|
||||
import Part
|
||||
|
||||
try:
|
||||
import FreeCADGui as Gui
|
||||
HAVE_GUI = App.GuiUp
|
||||
except Exception:
|
||||
HAVE_GUI = False
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__)) if "__file__" in dir() else r"C:/dev/cnx_vinyl/docs/equipment/inline-qc-station"
|
||||
OUT = os.path.join(HERE, "inline-qc-station.FCStd")
|
||||
V = App.Vector
|
||||
|
||||
# ---------------------------------------------------------------- parameters
|
||||
L = 1900 # frame length along the flow
|
||||
YF = 300 # centre of the outer frame profiles, +/- y
|
||||
P = 40 # profile size (40 x 40 slot profile; 40 x 80 for the base)
|
||||
ZB = 900 # top of the rim belts = record underside while conveyed
|
||||
R_REC = 150.8 # 12" record radius (IEC 98: 301.6 mm diameter)
|
||||
T_REC = 2.0 # record thickness (approx.)
|
||||
R_LABEL = 50.0 # label radius
|
||||
R_HOLE = 3.62 # centre hole 7.24 mm
|
||||
R_REC_AREA = 146.3 # recorded outer radius (292.6 mm max): the rim outside it carries no grooves
|
||||
Y_BELT = 148.5 # round belts run under the unrecorded rim
|
||||
ZL = 960 # record underside when the chuck has lifted it
|
||||
LIFT = 75 # chuck stroke: pad top 885 (below the belts) -> 960
|
||||
|
||||
X_IN = 200 # infeed: operator or Classic unloader puts the record here
|
||||
X_LB = 520 # label gate: both label cameras, on the fly with strobe
|
||||
X_IS = 880 # inspection: lift, clamp, one turn under the line-scans
|
||||
X_RJ = 1320 # reject pusher
|
||||
X_OUT = L - 30 - R_REC - 4 # outfeed end stop: good records wait here
|
||||
XT0, XT1 = 320, 1100 # light-tight tunnel uprights (inner faces 360 / 1100)
|
||||
|
||||
TOP_LINE = (X_IS + 50, X_IS + 155) # top line-scan sees the +x radius, r 50..155
|
||||
BOT_LINE = (X_IS - 155, X_IS - 50) # bottom line-scan sees the -x radius
|
||||
WD_LINE = 330 # 4k x 7 um sensor, 160 mm field, f = 50 mm -> ~330 mm working distance
|
||||
WD_LABEL = 303 # 2840 px x 2.74 um sensor, 140 mm field, f = 16 mm
|
||||
|
||||
# ---------------------------------------------------------------- colours
|
||||
ALU = (0.78, 0.80, 0.83)
|
||||
DARK = (0.18, 0.19, 0.21)
|
||||
BLACK = (0.04, 0.04, 0.05)
|
||||
CAM = (0.36, 0.52, 0.70) # camera bodies
|
||||
LENS = (0.08, 0.08, 0.09)
|
||||
LIGHT = (0.97, 0.95, 0.80) # emitting faces
|
||||
LIGHTBODY = (0.25, 0.25, 0.27)
|
||||
BELT = (0.20, 0.62, 0.34) # green PU round belt
|
||||
UHMW = (0.95, 0.95, 0.93)
|
||||
PNEU = (0.70, 0.72, 0.75)
|
||||
SERVO = (0.12, 0.12, 0.14)
|
||||
RED = (0.85, 0.10, 0.10)
|
||||
YELLOW = (0.95, 0.80, 0.10)
|
||||
GREEN = (0.15, 0.70, 0.25)
|
||||
AMBER = (0.98, 0.60, 0.10)
|
||||
PANEL = (0.06, 0.06, 0.07)
|
||||
CLEAR = (0.75, 0.85, 0.95)
|
||||
CABINET = (0.72, 0.73, 0.70)
|
||||
LASER = (1.0, 0.05, 0.05)
|
||||
|
||||
for _d in list(App.listDocuments().values()):
|
||||
if _d.Name.startswith("InlineQCStation") or _d.FileName.replace("\\", "/").endswith("inline-qc-station.FCStd"):
|
||||
App.closeDocument(_d.Name)
|
||||
doc = App.newDocument("InlineQCStation")
|
||||
doc.Label = "CNX inline optical QC station (concept)"
|
||||
groups = {}
|
||||
|
||||
|
||||
def grp(name):
|
||||
if name not in groups:
|
||||
g = doc.addObject("App::DocumentObjectGroup", name)
|
||||
groups[name] = g
|
||||
return groups[name]
|
||||
|
||||
|
||||
def add(group, name, shape, color=ALU, transp=0):
|
||||
o = doc.addObject("Part::Feature", name)
|
||||
o.Shape = shape
|
||||
grp(group).addObject(o)
|
||||
if HAVE_GUI:
|
||||
vo = o.ViewObject
|
||||
vo.ShapeColor = color
|
||||
vo.Transparency = transp
|
||||
vo.LineColor = (0.25, 0.25, 0.25)
|
||||
return o
|
||||
|
||||
|
||||
def box(x0, y0, z0, x1, y1, z1):
|
||||
return Part.makeBox(x1 - x0, y1 - y0, z1 - z0, V(x0, y0, z0))
|
||||
|
||||
|
||||
def cyl(r, h, base, d=V(0, 0, 1)):
|
||||
return Part.makeCylinder(r, h, base, d)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- real slot profiles
|
||||
# 8-slot 40 series (item / Misumi HFS8 class): 8.2 mm slot opening, 4.3 mm lip,
|
||||
# undercut chamber 16 mm wide, slot depth 12 mm, centre bore 6.8 mm (M8 tap),
|
||||
# corner cavities, 0.8 mm corner chamfer. 40 x 80 adds a centre cavity.
|
||||
ALU_BRACKET = (0.60, 0.62, 0.65)
|
||||
_FACES = {}
|
||||
|
||||
|
||||
def _slot(cx, cy, nx, ny):
|
||||
td = [(-4.1, -1), (-4.1, 4.3), (-8.0, 4.3), (-8.0, 7.5), (-4.1, 12.0),
|
||||
(4.1, 12.0), (8.0, 7.5), (8.0, 4.3), (4.1, 4.3), (4.1, -1)]
|
||||
tx, ty = -ny, nx
|
||||
pts = [V(cx + t * tx + d * nx, cy + t * ty + d * ny, 0) for t, d in td]
|
||||
return Part.Face(Part.makePolygon(pts + [pts[0]]))
|
||||
|
||||
|
||||
def profile_face(a, b):
|
||||
"""Cross-section a (local X) by b (local Y), both multiples of 40, corner at the origin."""
|
||||
if (a, b) in _FACES:
|
||||
return _FACES[(a, b)]
|
||||
c = 0.8
|
||||
o = [V(c, 0, 0), V(a - c, 0, 0), V(a, c, 0), V(a, b - c, 0), V(a - c, b, 0), V(c, b, 0), V(0, b - c, 0), V(0, c, 0)]
|
||||
f = Part.Face(Part.makePolygon(o + [o[0]]))
|
||||
cuts = []
|
||||
for i in range(int(a // 40)):
|
||||
cuts += [_slot(20 + 40 * i, 0, 0, 1), _slot(20 + 40 * i, b, 0, -1)]
|
||||
for j in range(int(b // 40)):
|
||||
cuts += [_slot(0, 20 + 40 * j, 1, 0), _slot(a, 20 + 40 * j, -1, 0)]
|
||||
for i in range(int(a // 40)):
|
||||
for j in range(int(b // 40)):
|
||||
cuts.append(Part.Face(Part.Wire(Part.makeCircle(3.4, V(20 + 40 * i, 20 + 40 * j, 0)))))
|
||||
for cx, cy in [(5.4, 5.4), (a - 5.4, 5.4), (a - 5.4, b - 5.4), (5.4, b - 5.4)]:
|
||||
cuts.append(Part.Face(Part.Wire(Part.makeCircle(2.2, V(cx, cy, 0)))))
|
||||
if a == 40 and b == 80:
|
||||
cuts.append(Part.Face(Part.makePolygon([V(14, 33, 0), V(26, 33, 0), V(26, 47, 0), V(14, 47, 0), V(14, 33, 0)])))
|
||||
if a == 80 and b == 40:
|
||||
cuts.append(Part.Face(Part.makePolygon([V(33, 14, 0), V(47, 14, 0), V(47, 26, 0), V(33, 26, 0), V(33, 14, 0)])))
|
||||
for k in cuts:
|
||||
f = f.cut(k)
|
||||
_FACES[(a, b)] = f
|
||||
return f
|
||||
|
||||
|
||||
def profile_shape(x0, y0, z0, x1, y1, z1):
|
||||
"""A real slot profile filling the axis-aligned bar x0..x1, y0..y1, z0..z1."""
|
||||
dx, dy, dz = x1 - x0, y1 - y0, z1 - z0
|
||||
long_axis = max((dx, "x"), (dy, "y"), (dz, "z"))[1]
|
||||
if long_axis == "x": # local X -> Y, local Y -> Z, extrusion -> X
|
||||
a, b, n = dy, dz, dx
|
||||
m = App.Matrix(0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1)
|
||||
elif long_axis == "y": # local X -> Z, local Y -> X, extrusion -> Y
|
||||
a, b, n = dz, dx, dy
|
||||
m = App.Matrix(0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1)
|
||||
else:
|
||||
a, b, n = dx, dy, dz
|
||||
m = App.Matrix()
|
||||
a, b = round(a), round(b)
|
||||
if a % 40 or b % 40:
|
||||
return box(x0, y0, z0, x1, y1, z1)
|
||||
sol = profile_face(a, b).extrude(V(0, 0, n))
|
||||
if long_axis != "z":
|
||||
sol.transformShape(m)
|
||||
sol.translate(V(x0, y0, z0))
|
||||
return sol
|
||||
|
||||
|
||||
def prof(group, name, x0, y0, z0, x1, y1, z1):
|
||||
return add(group, name, profile_shape(x0, y0, z0, x1, y1, z1), ALU)
|
||||
|
||||
|
||||
def gusset(group, name, corner, d1, d2, w):
|
||||
"""Cast angle bracket in the inside corner: legs 32 mm along d1 and d2, 34 mm wide along w."""
|
||||
p0 = corner - w * 17
|
||||
pts = [p0, p0 + d1 * 32, p0 + d2 * 32, p0]
|
||||
tri = Part.Face(Part.makePolygon(pts))
|
||||
return add(group, name, tri.extrude(w * 34), ALU_BRACKET)
|
||||
|
||||
|
||||
def rot(shape, center, axis, deg):
|
||||
s = shape.copy()
|
||||
s.rotate(center, axis, deg)
|
||||
return s
|
||||
|
||||
|
||||
def ring(r_out, r_in, h, base):
|
||||
return cyl(r_out, h, base).cut(cyl(r_in, h + 2, base - V(0, 0, 1)))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- frame
|
||||
G = "Frame"
|
||||
for i, (x, y) in enumerate([(20, -YF), (20, YF), (XT0 + 20, -YF), (XT0 + 20, YF),
|
||||
(XT1 + 20, -YF), (XT1 + 20, YF), (L - 20, -YF), (L - 20, YF)]):
|
||||
add(G, f"Foot{i}", cyl(30, 12, V(x, y, 0)).fuse(cyl(8, 50, V(x, y, 12))), DARK)
|
||||
for s in (-1, 1):
|
||||
prof(G, f"BaseBeam{'F' if s < 0 else 'B'}", 0, s * YF - 20, 60, L, s * YF + 20, 140) # 40 x 80
|
||||
for x0, z1, nm in [(0, 870, "End0"), (XT0, 1500, "Tunnel0"), (XT1, 1500, "Tunnel1"),
|
||||
(L - P, 1340 if s < 0 else 1080, "End1")]: # front end upright carries the touch screen
|
||||
prof(G, f"Upright{nm}{'F' if s < 0 else 'B'}", x0, s * YF - 20, 140, x0 + P, s * YF + 20, z1)
|
||||
prof(G, f"TopBeam{'F' if s < 0 else 'B'}", XT0 + P, s * YF - 20, 1460, XT1, s * YF + 20, 1500)
|
||||
prof(G, f"LowBeam{'F' if s < 0 else 'B'}", XT0 + P, s * YF - 20, 420, XT1, s * YF + 20, 460)
|
||||
prof(G, f"RejectBeam{'F' if s < 0 else 'B'}", XT1 + P, s * YF - 20, 1040, L - P, s * YF + 20, 1080)
|
||||
for x0, nm in [(0, "End0"), (XT0, "Tunnel0"), (XT1, "Tunnel1"), (L - P, "End1")]:
|
||||
prof(G, f"BaseCross{nm}", x0, -YF + 20, 100, x0 + P, YF - 20, 140)
|
||||
prof(G, f"ConvCross{nm}", x0, -YF + 20, 790, x0 + P, YF - 20, 830)
|
||||
# top bridge: label camera and top line-scan
|
||||
prof(G, "TopCrossLabel", X_LB + 70, -YF + 20, 1460, X_LB + 110, YF - 20, 1500)
|
||||
xt = sum(TOP_LINE) / 2
|
||||
prof(G, "TopCrossLineScan", xt + 48, -YF + 20, 1460, xt + 88, YF - 20, 1500)
|
||||
prof(G, "TopCrossThermal", XT0 + P, -YF + 20, 1460, XT0 + P + 40, YF - 20, 1500)
|
||||
prof(G, "TopCrossBacklight", sum(BOT_LINE) / 2 - 38, -YF + 20, 1460, sum(BOT_LINE) / 2 + 2, YF - 20, 1500)
|
||||
# lower bridge: bottom label camera, bottom line-scan, chuck lift
|
||||
xb = sum(BOT_LINE) / 2
|
||||
prof(G, "LowCrossLabel", X_LB + 70, -YF + 20, 420, X_LB + 110, YF - 20, 460)
|
||||
prof(G, "LowCrossLineScan", xb - 20, -YF + 20, 420, xb + 20, YF - 20, 460)
|
||||
prof(G, "LowCrossChuck", X_IS - 20, -YF + 20, 420, X_IS + 20, YF - 20, 460)
|
||||
prof(G, "LowCrossBacklight", xt - 20, -YF + 20, 420, xt + 20, YF - 20, 460)
|
||||
prof(G, "BaseCrossCabinet0", 1200, -YF + 20, 100, 1240, YF - 20, 140)
|
||||
prof(G, "BaseCrossCabinet1", 1580, -YF + 20, 100, 1620, YF - 20, 140)
|
||||
prof(G, "RejectBridgeCross", X_RJ - 20, -YF + 20, 1040, X_RJ + 20, YF - 20, 1080)
|
||||
|
||||
# cast angle brackets in the visible frame corners
|
||||
EX, EZ, EY = V(1, 0, 0), V(0, 0, 1), V(0, 1, 0)
|
||||
_k = 0
|
||||
for s in (-1, 1):
|
||||
y = s * YF
|
||||
for x, dirs in [(P, (1,)), (XT0, (-1,)), (XT0 + P, (1,)), (XT1, (-1,)), (XT1 + P, (1,)), (L - P, (-1,))]:
|
||||
for d in dirs:
|
||||
gusset(G, f"Bracket{_k}", V(x, y, 140), EX * d, EZ, EY); _k += 1
|
||||
for x, d, z in [(XT0 + P, 1, 1460), (XT1, -1, 1460), (XT0 + P, 1, 420), (XT1, -1, 420),
|
||||
(XT1 + P, 1, 1040), (L - P, -1, 1040)]:
|
||||
gusset(G, f"Bracket{_k}", V(x, y, z), EX * d, EZ * -1, EY); _k += 1
|
||||
|
||||
# ---------------------------------------------------------------- conveyor
|
||||
G = "Conveyor"
|
||||
for s in (-1, 1):
|
||||
side = "F" if s < 0 else "B"
|
||||
prof(G, f"Rail{side}", 0, s * 180 - 20, 830, L, s * 180 + 20, 870)
|
||||
add(G, f"BeltSlideCarrier{side}", box(45, min(s * 140, s * 200), 870, L - 45, max(s * 140, s * 200), 880), DARK)
|
||||
add(G, f"BeltSlide{side}", box(45, s * Y_BELT - 5, 880, L - 45, s * Y_BELT + 5, 894), UHMW)
|
||||
add(G, f"BeltTop{side}", cyl(3, L - 40, V(20, s * Y_BELT, ZB - 3), V(1, 0, 0)), BELT)
|
||||
add(G, f"BeltReturn{side}", cyl(3, L - 40, V(20, s * Y_BELT, ZB - 49), V(1, 0, 0)), BELT)
|
||||
for x, nm in [(20, "Idler"), (L - 20, "Drive")]:
|
||||
add(G, f"Pulley{nm}{side}", cyl(23, 14, V(x, s * Y_BELT - 7, ZB - 26), V(0, 1, 0)), DARK)
|
||||
add(G, f"PulleyAxle{nm}{side}", cyl(6, 6, V(x, min(s * (Y_BELT + 6), s * 160), ZB - 26), V(0, 1, 0)), PNEU)
|
||||
# infeed side guides with a flared mouth, PU strip on the rim height
|
||||
add(G, f"SideGuide{side}", box(110, s * 157 - 3, ZB + 2, XT0 - 10, s * 157 + 3, ZB + 14), UHMW)
|
||||
add(G, f"SideGuideFlare{side}", rot(box(40, s * 157 - 3, ZB + 2, 112, s * 157 + 3, ZB + 14),
|
||||
V(110, s * 157, ZB), V(0, 0, 1), s * 25), UHMW)
|
||||
add(G, f"GuidePost{side}", box(150, min(s * 160, s * 172), 870, 170, max(s * 160, s * 172), ZB + 14), DARK)
|
||||
add(G, "DriveShaft", cyl(6, 2 * Y_BELT + 60, V(L - 20, -Y_BELT - 30, ZB - 26), V(0, 1, 0)), DARK)
|
||||
add(G, "DriveGearmotor", cyl(35, 150, V(L - 20, 210, ZB - 26), V(0, 1, 0))
|
||||
.fuse(box(L - 60, 200, ZB - 70, L + 15, 230, ZB + 15)), SERVO)
|
||||
add(G, "EndStopBar", box(L - 30, -200, ZB + 30, L - 12, 200, ZB + 48), DARK)
|
||||
for s in (-1, 1):
|
||||
add(G, f"EndStopPost{'F' if s < 0 else 'B'}", box(L - 30, min(s * 170, s * 190), 870, L - 12, max(s * 170, s * 190), ZB + 30), DARK)
|
||||
add(G, "EndStopBumper", box(L - 32, -40, ZB + 4, L - 26, 40, ZB + 30), (0.9, 0.5, 0.1))
|
||||
|
||||
# presence sensors (diffuse, looking up through the open centre) and the stop beam
|
||||
G = "Sensors"
|
||||
for x, nm in [(X_IN, "Infeed"), (X_LB - 120, "LabelTrigger"), (L - 120, "Outfeed")]:
|
||||
add(G, f"Presence{nm}", box(x - 15, -120, 850, x + 15, -100, 885), (0.15, 0.35, 0.75))
|
||||
add(G, f"PresenceBracket{nm}", box(x - 10, -160, 840, x + 10, -100, 850), DARK)
|
||||
xs = X_IS + R_REC
|
||||
for s in (-1, 1):
|
||||
add(G, f"StopBeam{'Tx' if s < 0 else 'Rx'}", box(xs - 10, min(s * 200, s * 222), 870, xs + 10, max(s * 200, s * 222), ZB + 25),
|
||||
(0.15, 0.35, 0.75))
|
||||
add(G, "StopBeamRay", cyl(0.8, 400, V(xs, -200, ZB + 8), V(0, 1, 0)), LASER, 40)
|
||||
|
||||
# ---------------------------------------------------------------- label gate
|
||||
G = "LabelGate"
|
||||
add(G, "LabelCamTop", box(X_LB - 15, -15, ZB + WD_LABEL + 50, X_LB + 15, 15, ZB + WD_LABEL + 92), CAM)
|
||||
add(G, "LabelLensTop", cyl(17, 50, V(X_LB, 0, ZB + WD_LABEL)), LENS)
|
||||
add(G, "LabelRingTop", ring(70, 42, 22, V(X_LB, 0, ZB + 170)), LIGHTBODY)
|
||||
add(G, "LabelRingTopFace", ring(62, 48, 1, V(X_LB, 0, ZB + 169)), LIGHT)
|
||||
prof(G, "LabelCamTopPost", X_LB + 70, -20, ZB + 160, X_LB + 110, 20, 1460)
|
||||
add(G, "LabelCamTopPlate", box(X_LB + 15, -12, ZB + WD_LABEL + 55, X_LB + 70, 12, ZB + WD_LABEL + 87), DARK)
|
||||
add(G, "LabelRingTopClamp", box(X_LB + 58, -14, ZB + 166, X_LB + 70, 14, ZB + 196), DARK)
|
||||
zl = ZB - WD_LABEL
|
||||
add(G, "LabelCamBottom", box(X_LB - 15, -15, zl - 92, X_LB + 15, 15, zl - 50), CAM)
|
||||
add(G, "LabelLensBottom", cyl(17, 50, V(X_LB, 0, zl - 50)), LENS)
|
||||
add(G, "LabelRingBottom", ring(70, 42, 22, V(X_LB, 0, ZB - 80)), LIGHTBODY)
|
||||
add(G, "LabelRingBottomFace", ring(62, 48, 1, V(X_LB, 0, ZB - 58)), LIGHT)
|
||||
prof(G, "LabelCamBottomPost", X_LB + 70, -20, 460, X_LB + 110, 20, ZB - 48)
|
||||
add(G, "LabelCamBottomPlate", box(X_LB + 15, -12, zl - 87, X_LB + 70, 12, zl - 55), DARK)
|
||||
add(G, "LabelRingBottomClamp", box(X_LB + 58, -14, ZB - 84, X_LB + 70, 14, ZB - 54), DARK)
|
||||
|
||||
# ---------------------------------------------------------------- inspection: lift, clamp, one turn
|
||||
G = "Chuck"
|
||||
zp = ZL # pad top, lifted (shown lifted)
|
||||
add(G, "ChuckPad", cyl(40, 10, V(X_IS, 0, zp - 10)), (0.85, 0.45, 0.10))
|
||||
add(G, "ChuckMandrel", cyl(3.5, 9, V(X_IS, 0, zp)).fuse(Part.makeCone(3.5, 1.2, 4, V(X_IS, 0, zp + 9))), DARK)
|
||||
add(G, "SpindleHousing", cyl(25, 110, V(X_IS, 0, zp - 120)), PNEU)
|
||||
add(G, "LiftPlate", box(X_IS - 40, -40, zp - 132, X_IS + 40, 150, zp - 120), DARK)
|
||||
add(G, "SpindleServo", cyl(30, 110, V(X_IS, 110, zp - 242)), SERVO)
|
||||
add(G, "SpindleBeltCover", box(X_IS - 32, -32, zp - 120, X_IS + 32, 142, zp - 100), (0.3, 0.3, 0.32))
|
||||
add(G, "LiftCylinderRods", cyl(6, 100, V(X_IS - 30, 0, zp - 232)).fuse(cyl(6, 100, V(X_IS + 30, 0, zp - 232))), PNEU)
|
||||
add(G, "LiftCylinder", box(X_IS - 50, -25, zp - 322, X_IS + 50, 25, zp - 232), PNEU)
|
||||
prof(G, "LiftPost", X_IS - 20, -20, 460, X_IS + 20, 20, zp - 322)
|
||||
|
||||
G = "LineScanTop"
|
||||
zr = ZL + T_REC # top face of the lifted record
|
||||
add(G, "LineCamTop", box(xt - 31, -31, zr + WD_LINE + 60, xt + 31, 31, zr + WD_LINE + 105), CAM)
|
||||
add(G, "LineLensTop", cyl(25, 60, V(xt, 0, zr + WD_LINE)), LENS)
|
||||
prof(G, "LineCamTopPost", xt + 48, -20, zr + 150, xt + 88, 20, 1460)
|
||||
add(G, "LightHangerTop", box(xt + 58, -112, zr + 130, xt + 78, 112, zr + 150), DARK)
|
||||
add(G, "CoaxHangerTop", box(xt + 58, -10, zr + 80, xt + 78, 10, zr + 130), DARK)
|
||||
add(G, "LineCamTopPlate", box(xt + 31, -20, zr + WD_LINE + 62, xt + 48, 20, zr + WD_LINE + 103), DARK)
|
||||
x0, x1 = TOP_LINE[0] - 5, TOP_LINE[1] + 5
|
||||
add(G, "CoaxLightTop", box(x0, -30, zr + 50, x1, 30, zr + 110), LIGHTBODY)
|
||||
add(G, "CoaxLightTopFace", box(x0 + 3, -26, zr + 49, x1 - 3, 26, zr + 50), LIGHT)
|
||||
for s in (-1, 1):
|
||||
b = box(x0, -15, 0, x1, 15, 30)
|
||||
b.translate(V(0, s * 100, zr + 15))
|
||||
add(G, f"DarkFieldTop{'F' if s < 0 else 'B'}", rot(b, V(0, s * 100, zr + 30), V(1, 0, 0), s * 20), LIGHTBODY)
|
||||
add(G, f"DarkFieldTopBracket{'F' if s < 0 else 'B'}", box(xt + 58, s * 100 - 5, zr + 48, xt + 78, s * 100 + 5, zr + 130), DARK)
|
||||
bx0, bx1 = BOT_LINE[0] - 5, BOT_LINE[1] + 5
|
||||
add(G, "BacklightForBottomCam", box(bx0, -20, zr + 30, bx1, 20, zr + 52), LIGHTBODY)
|
||||
add(G, "BacklightForBottomCamFace", box(bx0 + 3, -17, zr + 29, bx1 - 3, 17, zr + 30), LIGHT)
|
||||
add(G, "BacklightBracketTop", box(xb - 30, -5, zr + 52, xb - 10, 5, 1460), DARK)
|
||||
add(G, "ScanLineTop", box(TOP_LINE[0], -0.6, zr + 0.05, TOP_LINE[1], 0.6, zr + 0.5), LASER)
|
||||
add(G, "ThermalPost", box(XT0 + 60, -240, 1400, XT0 + 80, -220, 1460), DARK)
|
||||
add(G, "ThermalCam", rot(box(XT0 + 70, -260, 1380, XT0 + 130, -200, 1440), V(XT0 + 100, -230, 1410), V(1, 0, 0), -30), (0.95, 0.45, 0.10))
|
||||
|
||||
G = "LineScanBottom"
|
||||
zu = ZL # underside of the lifted record
|
||||
add(G, "LineCamBottom", box(xb - 31, -31, zu - WD_LINE - 105, xb + 31, 31, zu - WD_LINE - 60), CAM)
|
||||
add(G, "LineLensBottom", cyl(25, 60, V(xb, 0, zu - WD_LINE - 60)), LENS)
|
||||
prof(G, "LineCamBottomPost", xb - 20, 40, 460, xb + 20, 80, ZB - 20)
|
||||
add(G, "CoaxHangerBottom", box(xb - 10, 30, ZB - 70, xb + 10, 40, ZB - 30), DARK)
|
||||
add(G, "LineCamBottomPlate", box(xb - 20, 31, zu - WD_LINE - 105, xb + 20, 40, zu - WD_LINE - 60), DARK)
|
||||
add(G, "CoaxLightBottom", box(bx0, -30, ZB - 80, bx1, 30, ZB - 20), LIGHTBODY)
|
||||
add(G, "CoaxLightBottomFace", box(bx0 + 3, -26, ZB - 20, bx1 - 3, 26, ZB - 19), LIGHT)
|
||||
for s in (-1, 1):
|
||||
b = box(bx0, -15, 0, bx1, 15, 30)
|
||||
b.translate(V(0, s * 175, zu - 40))
|
||||
add(G, f"DarkFieldBottom{'F' if s < 0 else 'B'}", rot(b, V(0, s * 175, zu - 25), V(1, 0, 0), -s * 8), LIGHTBODY)
|
||||
add(G, f"DarkFieldBottomBracket{'F' if s < 0 else 'B'}", box(bx0 + 40, s * 192 - 5, 870, bx0 + 60, s * 192 + 5, zu - 35), DARK)
|
||||
add(G, "BacklightForTopCam", box(x0, -20, ZB - 40, x1, 20, ZB - 15), LIGHTBODY)
|
||||
prof(G, "BacklightPost", xt - 20, -20, 460, xt + 20, 20, ZB - 40)
|
||||
add(G, "BacklightForTopCamFace", box(x0 + 3, -17, ZB - 15, x1 - 3, 17, ZB - 14), LIGHT)
|
||||
add(G, "ScanLineBottom", box(BOT_LINE[0], -0.6, zu - 0.5, BOT_LINE[1], 0.6, zu - 0.05), LASER)
|
||||
|
||||
G = "WarpLasers"
|
||||
for r in (90, 130):
|
||||
add(G, f"Laser_r{r}", box(X_IS - 23, -r - 10, ZB - 55, X_IS + 23, -r + 10, ZB - 15), (0.15, 0.35, 0.75))
|
||||
add(G, f"LaserBeam_r{r}", cyl(0.8, zu - (ZB - 15), V(X_IS, -r, ZB - 15)), LASER, 30)
|
||||
add(G, f"LaserBracket_r{r}", box(X_IS - 10, -r - 10, 830, X_IS + 10, -r + 10, ZB - 55), DARK)
|
||||
prof(G, "LaserRail", X_IS - 20, -200, 790, X_IS + 20, -70, 830)
|
||||
|
||||
# ---------------------------------------------------------------- reject
|
||||
G = "Reject"
|
||||
add(G, "RodlessCylinder", box(X_RJ - 30, -300, 1000, X_RJ + 30, 300, 1040), PNEU)
|
||||
yc = -205 # carriage retracted at the front
|
||||
add(G, "PusherCarriage", box(X_RJ - 35, yc - 30, 960, X_RJ + 35, yc + 30, 1000), DARK)
|
||||
add(G, "PusherArm", box(X_RJ - 10, yc - 10, ZB + 26, X_RJ + 10, yc + 10, 960), DARK)
|
||||
add(G, "PusherPaddle", box(X_RJ - 100, yc + 10, ZB + 4, X_RJ + 100, yc + 22, ZB + 26), (0.9, 0.5, 0.1))
|
||||
CX0, CX1 = X_RJ - 170, X_RJ + 170
|
||||
Y_CH, Z_CH = 205, ZB - 7 # chute top edge: just outside the back rail, below the belt plane
|
||||
chute = box(CX0, 0, 0, CX1, 360, 6)
|
||||
chute = rot(chute, V(0, 0, 0), V(1, 0, 0), -42)
|
||||
chute.translate(V(0, Y_CH, Z_CH))
|
||||
add(G, "RejectChute", chute, (0.55, 0.57, 0.60))
|
||||
for xw in (CX0 - 6, CX1):
|
||||
w = box(xw, 0, 0, xw + 6, 360, 80)
|
||||
w = rot(w, V(0, 0, 0), V(1, 0, 0), -42)
|
||||
w.translate(V(0, Y_CH, Z_CH))
|
||||
add(G, f"ChuteWall{xw}", w, (0.55, 0.57, 0.60))
|
||||
import math
|
||||
_zc = Z_CH - math.tan(math.radians(42)) * (YF + 20 - Y_CH) # chute underside above the back frame line
|
||||
for i, xs_ in enumerate((CX0 + 10, CX1 - 50)):
|
||||
prof(G, f"ChuteSupport{i}", xs_, YF - 20, 140, xs_ + 40, YF + 20, math.floor(_zc))
|
||||
binb = box(CX0 - 20, 380, 0, CX1 + 20, 720, 560).cut(box(CX0 - 8, 392, 12, CX1 + 8, 708, 600))
|
||||
add(G, "RejectBin", binb, (0.85, 0.20, 0.15), 20)
|
||||
|
||||
# ---------------------------------------------------------------- enclosure (black, light-tight tunnel)
|
||||
G = "Enclosure"
|
||||
slot = box(XT0 - 10, -205, 860, XT1 + P + 10, 205, ZB + 30)
|
||||
for x, nm in [(XT0 - 3, "Infeed"), (XT1 + P, "Outfeed")]:
|
||||
up = box(x, -YF - 22, 870, x + 3, YF + 22, 1500).cut(slot)
|
||||
add(G, f"EndWallUpper{nm}", up, PANEL, 55)
|
||||
lo = box(x, -YF - 22, 140, x + 3, YF + 22, 870).cut(box(x - 1, -205, 815, x + 4, 205, 880))
|
||||
add(G, f"EndWallLower{nm}", lo, PANEL, 55)
|
||||
for s in (-1, 1):
|
||||
side = "Front" if s < 0 else "Back"
|
||||
y0 = s * (YF + 20) if s > 0 else -YF - 23
|
||||
add(G, f"Panel{side}Upper", box(XT0, y0, 870, XT1 + P, y0 + 3, 1500), PANEL, 55)
|
||||
add(G, f"Panel{side}Lower", box(XT0, y0, 140, XT1 + P, y0 + 3, 870), PANEL, 55)
|
||||
add(G, "PanelTop", box(XT0, -YF - 23, 1500, XT1 + P, YF + 23, 1503), PANEL, 55)
|
||||
add(G, "PanelBottom", box(XT0, -YF - 20, 140, XT1 + P, YF + 20, 143), PANEL, 55)
|
||||
add(G, "DoorHandle", box(700, -YF - 45, 1150, 860, -YF - 23, 1175), DARK)
|
||||
add(G, "GuardRejectFront", box(XT1 + P, -YF - 23, 870, L, -YF - 20, 1100), CLEAR, 75)
|
||||
add(G, "GuardRejectTop", box(XT1 + P, -YF - 23, 1100, L, YF + 23, 1103), CLEAR, 75)
|
||||
|
||||
# ---------------------------------------------------------------- electrical and operator
|
||||
G = "Electrical"
|
||||
add(G, "Cabinet", box(1180, -200, 140, 1640, 170, 750), CABINET)
|
||||
add(G, "CabinetHandle", box(1600, -215, 400, 1615, -200, 520), DARK)
|
||||
add(G, "StackLightPole", cyl(10, 123, V(XT1 + 20, YF, 1500)), DARK)
|
||||
for i, c in enumerate([GREEN, AMBER, RED]):
|
||||
add(G, f"StackLight{i}", cyl(25, 57, V(XT1 + 20, YF, 1623 + i * 57)), c)
|
||||
add(G, "HMIArm", box(L - 40, -YF - 80, 1225, L, -YF - 20, 1245), DARK)
|
||||
add(G, "HMI", rot(box(L - 260, -YF - 100, 1150, L, -YF - 80, 1320), V(L - 130, -YF - 90, 1235), V(1, 0, 0), -15), (0.10, 0.10, 0.12))
|
||||
add(G, "EStopBox", box(XT1, -YF - 60, 930, XT1 + 80, -YF - 20, 1010), YELLOW)
|
||||
add(G, "EStop", cyl(22, 25, V(XT1 + 40, -YF - 60, 970), V(0, -1, 0)), RED)
|
||||
add(G, "ValveTerminal", box(XT0 + 80, YF + 20, 300, XT0 + 330, YF + 70, 380), PNEU)
|
||||
add(G, "FRL", box(XT0 + 360, YF + 20, 280, XT0 + 440, YF + 80, 420), (0.2, 0.4, 0.8))
|
||||
prof(G, "PneumaticsRail", XT0 + P, YF - 20, 260, XT1, YF + 20, 300)
|
||||
|
||||
# ---------------------------------------------------------------- records
|
||||
G = "Records"
|
||||
|
||||
|
||||
def record(name, x, y, z, label_color, body=BLACK, transp=0, tilt=None):
|
||||
disc = cyl(R_REC, T_REC, V(x, y, z)).cut(cyl(R_HOLE, T_REC + 2, V(x, y, z - 1)))
|
||||
lab = cyl(R_LABEL, 0.3, V(x, y, z + T_REC)).cut(cyl(R_HOLE, 2, V(x, y, z + T_REC - 0.5)))
|
||||
labb = cyl(R_LABEL, 0.3, V(x, y, z - 0.3)).cut(cyl(R_HOLE, 2, V(x, y, z - 1)))
|
||||
if tilt:
|
||||
c, ax, deg = tilt
|
||||
disc, lab, labb = rot(disc, c, ax, deg), rot(lab, c, ax, deg), rot(labb, c, ax, deg)
|
||||
add(G, name, disc, body, transp)
|
||||
add(G, name + "LabelA", lab, label_color)
|
||||
add(G, name + "LabelB", labb, label_color)
|
||||
|
||||
|
||||
record("RecordInfeed", X_IN, 0, ZB, (0.95, 0.85, 0.75), body=(0.80, 0.12, 0.16), transp=25) # translucent red special
|
||||
record("RecordInspection", X_IS, 0, ZL, (0.20, 0.45, 0.80))
|
||||
record("RecordOutfeed", X_OUT, 0, ZB, (0.95, 0.60, 0.15))
|
||||
import math
|
||||
sc, a = 200, math.radians(42)
|
||||
yr = Y_CH + math.cos(a) * sc + 6 * math.sin(a)
|
||||
zr2 = Z_CH - math.sin(a) * sc + 6 * math.cos(a)
|
||||
record("RecordReject", X_RJ, yr, zr2, (0.6, 0.6, 0.6), tilt=(V(X_RJ, yr, zr2), V(1, 0, 0), -42))
|
||||
|
||||
doc.recompute()
|
||||
doc.saveAs(OUT)
|
||||
n = len([o for o in doc.Objects if o.TypeId == "Part::Feature"])
|
||||
bb = None
|
||||
for o in doc.Objects:
|
||||
if o.TypeId == "Part::Feature":
|
||||
bb = o.Shape.BoundBox if bb is None else bb.united(o.Shape.BoundBox)
|
||||
print("objects", n, "bbox", round(bb.XMin), round(bb.XMax), round(bb.YMin), round(bb.YMax), round(bb.ZMin), round(bb.ZMax))
|
||||
print("saved", OUT)
|
||||
|
||||
# every part should touch another one, without counting the panels (hidden in the open views);
|
||||
# list the ones that do not (gap > 1 mm)
|
||||
_panels = set(o.Name for o in groups["Enclosure"].Group)
|
||||
_parts = [o for o in doc.Objects if o.TypeId == "Part::Feature" and o.Name not in _panels]
|
||||
# connectivity: every part must reach the floor through touching parts (gap <= 1 mm)
|
||||
_adj = {o.Name: set() for o in _parts}
|
||||
for ia, oa in enumerate(_parts):
|
||||
ba = oa.Shape.BoundBox
|
||||
for ob in _parts[ia + 1:]:
|
||||
bq = ob.Shape.BoundBox
|
||||
if (bq.XMin > ba.XMax + 2 or bq.XMax < ba.XMin - 2 or bq.YMin > ba.YMax + 2 or bq.YMax < ba.YMin - 2
|
||||
or bq.ZMin > ba.ZMax + 2 or bq.ZMax < ba.ZMin - 2):
|
||||
continue
|
||||
if oa.Shape.distToShape(ob.Shape)[0] <= 1.0:
|
||||
_adj[oa.Name].add(ob.Name)
|
||||
_adj[ob.Name].add(oa.Name)
|
||||
_seen = [o.Name for o in _parts if o.Shape.BoundBox.ZMin < 1]
|
||||
_todo = list(_seen)
|
||||
_seen = set(_seen)
|
||||
while _todo:
|
||||
for nb in _adj[_todo.pop()]:
|
||||
if nb not in _seen:
|
||||
_seen.add(nb)
|
||||
_todo.append(nb)
|
||||
_floating = sorted(n for n in _adj if n not in _seen)
|
||||
print("parts not connected to the floor:", _floating if _floating else "none")
|
||||
|
After Width: | Height: | Size: 1.5 MiB |
@@ -0,0 +1,42 @@
|
||||
group,item,qty,example,unit_usd_low,unit_usd_high,line_usd_low,line_usd_high,source
|
||||
Frame,"40x40 slot profile, cut to length",32 m (45 pieces),"8-slot 4040 (Misumi HFS8-4040 class, or Thai/Chinese generic)",11,21,354,676,per m; Shopee Thailand listing from THB 356; aluxprofile EUR 19 to 24 per m
|
||||
Frame,"40x80 slot profile, base beams",3.8 m (2 pieces),8-slot 4080,22,42,84,160,"per m; estimate, about twice the 4040 price"
|
||||
Frame,"Cast angle brackets (24 drawn), T-nuts, screws, end caps",1 lot,,250,600,250,600,estimate
|
||||
Frame,Levelling feet M16,8,,8,25,64,200,each; estimate
|
||||
Enclosure,"Black panels, 4 mm ACM or PP, light-tight tunnel",4.3 m2,,25,60,108,258,per m2; estimate
|
||||
Enclosure,"Clear polycarbonate guard, reject zone",1.4 m2,,30,70,42,98,per m2; estimate
|
||||
Enclosure,"Door hinges, handle, safety door switch",1 lot,,120,350,120,350,estimate
|
||||
Conveyor,"PU round belt 6 mm, welded endless",2 x 3.8 m,,15,40,30,80,"each; PU round belt listings (RS, Amazon) plus welding"
|
||||
Conveyor,"Round-belt pulleys, shaft, bearings, UHMW slide strips, side guides",1 lot,,250,700,250,700,"pulleys USD 5 to 11 each (ServoCity, REV); rest estimate"
|
||||
Conveyor,"Conveyor drive: 100 W EtherCAT servo kit (same as the spindle), cyclic synchronous velocity",1,StepperOnline A6-EC100L2A1-M17,123,300,123,300,"USD 123.29 kit, China warehouse (StepperOnline, Oct 2026); high end allows for shipping, duty and a small belt reduction (estimate)"
|
||||
Handling,"Guided lift cylinder, 20 mm bore, 75 mm stroke",1,SMC MGPM20-75,330,450,330,450,SMC MGPM20-30 USD 322 (Misumi US) to 390 (Motion); 75 mm stroke a little more
|
||||
Handling,"Spindle servo kit 100 W, EtherCAT (A6-200EC drive), cyclic synchronous position; 1:6 timing belt to the spindle",1,StepperOnline A6-EC100L2A1-M17,123,300,123,300,"USD 123.29 kit, China warehouse (StepperOnline, Oct 2026); high end allows for shipping and duty (estimate)"
|
||||
Handling,"Spindle head: bearing housing, timing belt, label pad, pneumatic expanding mandrel",1,machined parts,600,1800,600,1800,estimate
|
||||
Handling,"Rodless cylinder 25 mm, 350 mm stroke, with paddle",1,SMC MY1B / CY3B class,400,900,400,900,estimate
|
||||
Handling,"Valve terminal, FRL with a dump valve switched by the safety relay, pressure switch, tubing, fittings",1 lot,,400,1000,400,1000,estimate
|
||||
Vision,"4k monochrome line-scan camera, GigE",2,Basler racer 2 r2L4096 / Hikrobot MV-CL042-91GM,857,1088,1714,2176,Basler web shop via price listing
|
||||
Vision,"Line-scan lens, 50 mm",2,,300,800,600,1600,estimate
|
||||
Vision,Coaxial line light,2,,295,446,590,892,made-in-china listing USD 295 to 349; Vision Datum USD 420; light186 from USD 446
|
||||
Vision,"Dark-field line light, about 150 mm",4,Vision Datum LiN+ class,250,400,1000,1600,Vision Datum LiN+ USD 380
|
||||
Vision,Diffuse line backlight,2,,200,400,400,800,estimate
|
||||
Vision,"Colour area camera, 8 MP, GigE",2,Basler ace 2 a2A2840-14gcPRO,1119,1119,2238,2238,Basler web shop via price listing
|
||||
Vision,Lens 16 mm,2,,150,400,300,800,estimate
|
||||
Vision,Ring light,2,,150,400,300,800,estimate
|
||||
Vision,Strobe and light controllers,2,,300,800,600,1600,estimate
|
||||
Sensors,"Laser distance sensor, 50 mm range",2,Micro-Epsilon optoNCDT 1420,520,1600,1040,3200,"list from EUR 470 (Micro-Epsilon); ILD1420-25 about USD 1,600 (Radwell)"
|
||||
Sensors,Photoelectric presence sensors and one through-beam (the through-beam also to the conveyor drive's touch probe),5,,50,150,250,750,each; estimate
|
||||
Sensors,"Cylinder position switches (lift up/down, pusher home/out, mandrel open/clamped)",6,SMC D-M9 class,25,60,150,360,each; estimate
|
||||
Sensors,"Spindle incremental encoder, RS-422 line driver, 5 V, 2,000 to 2,500 pulses a turn: A/B clock both line-scans, A/B/Z to the EL5101",1,Omron E6B2-CWZ1X 2000 P/R class,53,282,53,282,"E6B2-CWZ1X 2000 P/R listing EUR 45.52 to GHH60 2500 P/R line driver EUR 187.83 (geizhals.de, 19 Oct 2026, lowest listed price incl. 19% German VAT; marketplace sellers, test on the bench); high end +30% for shipping, Thai duty and VAT or a Thai distributor (estimate)"
|
||||
Sensors,"Thermal camera (option, not in the total)",0 (1 optional),Optris Xi 400,2100,3000,0,0,"from EUR 1,950 (Optris); USD 2,995 (moviTHERM)"
|
||||
Control,"EtherCAT station controller: fanless mini PC, Intel N100, 2 or more Intel i226-V ports, NixOS real-time tuned, station service on QiTech's open-source EtherCAT library (EtherCrab based; IgH fallback)",1,ANDAQI RS55 / MNBOXCONET P2-N100 / AIOPCWA AI201-TF,455,685,455,685,"EUR 393.99 to 455.99 (geizhals.de, 19 Oct 2026, lowest listed price incl. 19% German VAT: geizhals.de/mini-pc-barebone-netzwerk-pc-intel-n100-a2926989.html); high end +30% for shipping, Thai duty and VAT or a Thai distributor (estimate)"
|
||||
Control,EtherCAT coupler (the EK1101 adds an ID switch),1,Beckhoff EK1101,98,128,98,128,"EUR 85.13, 148 in stock (QiTech community shop (shop.qitech.de, new in original box from an insolvency, 19 Oct 2026, incl. 19% German VAT: shop.qitech.de/products/beckhoff-ek1101); high end +30% for shipping from Darmstadt and Thai duty and VAT (estimate)"
|
||||
Control,"16 digital inputs, 24 V: photoelectric sensors, cylinder switches, safety status",1,Beckhoff EL1809,19,25,19,25,"EUR 16.53, 157 in stock (QiTech community shop (shop.qitech.de, new in original box from an insolvency, 19 Oct 2026, incl. 19% German VAT: shop.qitech.de/products/beckhoff-el1809); high end +30% for shipping from Darmstadt and Thai duty and VAT (estimate)"
|
||||
Control,"16 digital outputs, 24 V, 0.5 A: valves, stack light, light enable",1,Beckhoff EL2809,47,62,47,62,"EUR 41.03, 104 in stock (QiTech community shop (shop.qitech.de, new in original box from an insolvency, 19 Oct 2026, incl. 19% German VAT: shop.qitech.de/products/beckhoff-el2809); high end +30% for shipping from Darmstadt and Thai duty and VAT (estimate)"
|
||||
Control,"2 analog inputs, 4 to 20 mA: the two warp lasers",1,Beckhoff EL3152,241,314,241,314,"EUR 208.90 (geizhals.de, 19 Oct 2026, lowest listed price incl. 19% German VAT: geizhals.de/185886294); high end +30% for shipping, Thai duty and VAT or a Thai distributor (estimate)"
|
||||
Control,"Incremental encoder interface, RS-422, 5 V encoder supply: spindle encoder count and index latch",1,Beckhoff EL5101,336,437,336,437,"EUR 291.04 (geizhals.de, 19 Oct 2026, lowest listed price incl. 19% German VAT: geizhals.de/2974477757); high end +30% for shipping, Thai duty and VAT or a Thai distributor (estimate)"
|
||||
Control,End cap,1,Beckhoff EL9011,2,3,2,3,"EUR 1.76, 131 in stock (QiTech community shop (shop.qitech.de, new in original box from an insolvency, 19 Oct 2026, incl. 19% German VAT: shop.qitech.de/products/beckhoff-el9011); high end +30% for shipping from Darmstadt and Thai duty and VAT (estimate)"
|
||||
Control,"Edge PC with GPU, 4 GigE PoE ports, NixOS",1,,1500,3200,1500,3200,"qscompute buying guides 2026: USD 1,490 to 3,200"
|
||||
Control,"HMI: 10.1 inch PCAP touch monitor, 7H glass, showing the station's browser page",1,iiyama ProLite TF1015MC-B3,360,468,360,468,"EUR 311.90 (geizhals.de, 19 Oct 2026, lowest listed price incl. 19% German VAT: geizhals.de/iiyama-prolite-tf1015mc-b3-a3228748.html); high end +30% for shipping, Thai duty and VAT or a Thai distributor (estimate)"
|
||||
Control,"Safety: relay for e-stop and door switch, 2 contactors in series in the drive supply (the 100 W kit has no STO), e-stop button, reset button",1 lot,"Pilz PNOZ s3 750103, Siemens 3RT2015 24 V DC coil, Schneider Harmony e-stop",300,389,300,389,"PNOZ s3 EUR 148.38, 3RT2015-1BB41 EUR 27.95 each, e-stop EUR 45.08 (geizhals.de, 19 Oct 2026, lowest listed price incl. 19% German VAT); reset button EUR 10 (estimate); high end +30% for shipping, Thai duty and VAT or a Thai distributor (estimate)"
|
||||
Control,"Cabinet, 24 V 120 W supply, breakers, terminals, wiring, shielded EtherCAT patch cables, stack light",1 lot,Mean Well SDR-120-24 supply,800,2000,800,2000,"estimate; Mean Well SDR-120-24 from EUR 38.87 and shielded Cat5e patch cables from EUR 0.62 (geizhals.de, 19 Oct 2026)"
|
||||
Total,"Hardware per station, thermal camera excluded",,,,,16671,32681,sum of the lines above
|
||||
|
|
After Width: | Height: | Size: 443 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 322 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 528 KiB |
|
After Width: | Height: | Size: 91 KiB |
@@ -0,0 +1,160 @@
|
||||
# Render the investor view of the inline QC station and the screen positions of
|
||||
# the parts to call out (run in the FreeCAD GUI after build_station.py):
|
||||
# exec(open(r"C:/dev/cnx_vinyl/docs/equipment/inline-qc-station/render_annotated.py", encoding="utf-8").read())
|
||||
# Writes inline-qc-station-annotated-base.png, a check image with magenta markers,
|
||||
# and anchors.json; annotate_render.py (Pillow) then draws the labels.
|
||||
import json
|
||||
import os
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
import Part
|
||||
from pivy import coin
|
||||
|
||||
OUTDIR = r"C:/dev/cnx_vinyl/docs/equipment/inline-qc-station"
|
||||
W, H = 4000, 3000
|
||||
V = App.Vector
|
||||
|
||||
# (key, 3D point on a face turned to the camera, title, one-line description)
|
||||
ANCHORS = [
|
||||
("frame", V(340, -320, 1150), "Aluminium profile frame", "40 × 40 mm slot profile, 1.9 × 0.65 × 1.5 m"),
|
||||
("belts", V(70, -151.5, 897), "Rim-belt conveyor", "touches only the record's edge, never a groove"),
|
||||
("infeed", V(200, -80, 902.5), "Infeed", "the operator sets each cooled record down"),
|
||||
("label", V(520, -15, 1275), "Label cameras, top and bottom", "right label, right side, centred"),
|
||||
("tunnel", V(820, 319, 1100), "Light-tight tunnel", "black panels keep factory light out"),
|
||||
("lscan_top", V(975, -31, 1385), "Line-scan camera, top", "images a full radius while the record turns once"),
|
||||
("lights", V(935, -30, 1042), "Inspection lights", "coaxial, low-angle dark-field and backlight"),
|
||||
("chuck", V(880, -25, 690), "Lift-and-turn chuck", "lifts the record 75 mm, one turn in about 1 s"),
|
||||
("lscan_bot", V(778, -31, 547), "Line-scan camera, bottom", "the underside, in the same turn"),
|
||||
("lasers", V(880, -130, 925), "Laser warp sensors", "edge run-out and dish, to 0.1 mm"),
|
||||
("pusher", V(1320, -300, 1020), "Reject pusher", "pushes a failed record down a chute into the bin behind"),
|
||||
("outfeed", V(1715, -140, 902), "Outfeed", "good records wait for sleeving"),
|
||||
("cabinet", V(1420, -200, 450), "Control cabinet", "EtherCAT controller, drives and the NixOS edge PC"),
|
||||
("hmi", V(1770, -404, 1235), "Touch screen", "every verdict with its reason"),
|
||||
("estop", V(1140, -386, 970), "Emergency stop", "and a safety switch on the tunnel door"),
|
||||
("stack", V(1120, 274, 1720), "Stack light", "green: pass, red: reject"),
|
||||
]
|
||||
AZ, EL = 12.0, 28.0 # camera from the front, 12 deg to the right, 28 deg above
|
||||
|
||||
doc = App.getDocument("InlineQCStation")
|
||||
Gui.setActiveDocument(doc.Name)
|
||||
view = Gui.getDocument(doc.Name).ActiveView
|
||||
try:
|
||||
view.setCameraType("Orthographic")
|
||||
except Exception:
|
||||
pass
|
||||
_vp = App.ParamGet("User parameter:BaseApp/Preferences/View")
|
||||
_navi_before = _vp.GetBool("ShowNaviCube", True)
|
||||
_vp.SetBool("ShowNaviCube", False)
|
||||
_anim_before = _vp.GetBool("UseNavigationAnimations", True)
|
||||
_vp.SetBool("UseNavigationAnimations", False)
|
||||
_presel_before = _vp.GetBool("EnablePreselection", True)
|
||||
_vp.SetBool("EnablePreselection", False) # no hover highlight in the pictures
|
||||
Gui.Selection.clearPreselection()
|
||||
Gui.Selection.clearSelection()
|
||||
|
||||
|
||||
def back_off(v, dist=8000):
|
||||
"""Move the orthographic camera back along its axis so nothing sits behind the near plane."""
|
||||
c = v.getCameraNode()
|
||||
d = c.orientation.getValue().multVec(coin.SbVec3f(0, 0, -1))
|
||||
c.position.setValue(c.position.getValue() - d * dist)
|
||||
c.nearDistance.setValue(100)
|
||||
c.farDistance.setValue(dist * 4)
|
||||
Gui.updateGui()
|
||||
|
||||
open_view_hidden = ["PanelTop", "PanelFrontUpper", "PanelFrontLower", "GuardRejectFront", "GuardRejectTop",
|
||||
"DoorHandle", "ThermalCam", "ThermalPost"]
|
||||
for o in doc.Objects:
|
||||
if o.TypeId == "Part::Feature":
|
||||
o.ViewObject.Visibility = o.Name not in open_view_hidden
|
||||
for o in doc.getObject("Enclosure").Group:
|
||||
o.ViewObject.Transparency = 45
|
||||
|
||||
import math
|
||||
|
||||
|
||||
def set_camera(az, el, margin=1.04):
|
||||
"""Orthographic camera looking at the whole model from the front, az to the right, el above."""
|
||||
a, e = math.radians(az), math.radians(el)
|
||||
tv = V(math.sin(a) * math.cos(e), -math.cos(a) * math.cos(e), math.sin(e)) # towards the viewer
|
||||
d = tv * -1
|
||||
right = d.cross(V(0, 0, 1)).normalize()
|
||||
up = right.cross(d).normalize()
|
||||
m = App.Matrix(right.x, up.x, -d.x, 0, right.y, up.y, -d.y, 0, right.z, up.z, -d.z, 0, 0, 0, 0, 1)
|
||||
rot = App.Rotation(m)
|
||||
bb = None
|
||||
for o in doc.Objects:
|
||||
if o.TypeId == "Part::Feature" and o.ViewObject.Visibility:
|
||||
bb = o.Shape.BoundBox if bb is None else bb.united(o.Shape.BoundBox)
|
||||
corners = [V(x, y, z) for x in (bb.XMin, bb.XMax) for y in (bb.YMin, bb.YMax) for z in (bb.ZMin, bb.ZMax)]
|
||||
us = [c.dot(right) for c in corners]
|
||||
vs = [c.dot(up) for c in corners]
|
||||
cu, cv = (min(us) + max(us)) / 2, (min(vs) + max(vs)) / 2
|
||||
centre = right * cu + up * cv + d * (bb.Center.dot(d))
|
||||
hgt = max(max(vs) - min(vs), (max(us) - min(us)) * H / W) * margin
|
||||
cam = view.getCameraNode()
|
||||
cam.orientation.setValue(*rot.Q)
|
||||
pos = centre + tv * 8000
|
||||
cam.position.setValue(pos.x, pos.y, pos.z)
|
||||
cam.height.setValue(hgt)
|
||||
cam.focalDistance.setValue(8000)
|
||||
cam.nearDistance.setValue(100)
|
||||
cam.farDistance.setValue(32000)
|
||||
Gui.updateGui()
|
||||
|
||||
|
||||
set_camera(AZ, EL)
|
||||
base = os.path.join(OUTDIR, "inline-qc-station-annotated-base.png")
|
||||
view.saveImage(base, W, H, "White")
|
||||
|
||||
cam = view.getCameraNode()
|
||||
pos = cam.position.getValue()
|
||||
inv = cam.orientation.getValue().inverse()
|
||||
hgt = cam.height.getValue()
|
||||
|
||||
|
||||
def project(p):
|
||||
c = inv.multVec(coin.SbVec3f(p.x - pos[0], p.y - pos[1], p.z - pos[2]))
|
||||
s = H / hgt if W >= H else W / hgt
|
||||
return [W / 2 + c[0] * s, H / 2 - c[1] * s]
|
||||
|
||||
|
||||
out = {"size": [W, H], "anchors": []}
|
||||
for key, p, title, desc in ANCHORS:
|
||||
out["anchors"].append({"key": key, "xy": project(p), "title": title, "desc": desc})
|
||||
|
||||
# check image: the same view with a magenta ball on every anchor (shows position and occlusion)
|
||||
balls = []
|
||||
for key, p, *_ in ANCHORS:
|
||||
b = doc.addObject("Part::Feature", "Marker_" + key)
|
||||
b.Shape = Part.makeSphere(9, p)
|
||||
b.ViewObject.ShapeColor = (1.0, 0.0, 1.0)
|
||||
b.ViewObject.LineColor = (1.0, 0.0, 1.0)
|
||||
balls.append(b)
|
||||
Gui.updateGui()
|
||||
view.saveImage(os.path.join(OUTDIR, "_markers-check.png"), W, H, "White")
|
||||
# markers alone, nothing in front of them: exact screen positions (camera unchanged)
|
||||
_vis = {o.Name: o.ViewObject.Visibility for o in doc.Objects if o.TypeId == "Part::Feature"}
|
||||
for o in doc.Objects:
|
||||
if o.TypeId == "Part::Feature" and not o.Name.startswith("Marker_"):
|
||||
o.ViewObject.Visibility = False
|
||||
for b in balls:
|
||||
b.ViewObject.Visibility = True
|
||||
Gui.updateGui()
|
||||
view.saveImage(os.path.join(OUTDIR, "_markers-only.png"), W, H, "White")
|
||||
for n, v in _vis.items():
|
||||
if not n.startswith("Marker_"):
|
||||
doc.getObject(n).ViewObject.Visibility = v
|
||||
for b in balls:
|
||||
doc.removeObject(b.Name)
|
||||
|
||||
for o in doc.getObject("Enclosure").Group:
|
||||
o.ViewObject.Transparency = 55 if o.Name not in ("GuardRejectFront", "GuardRejectTop") else 75
|
||||
for o in doc.Objects:
|
||||
if o.TypeId == "Part::Feature":
|
||||
o.ViewObject.Visibility = True
|
||||
_vp.SetBool("ShowNaviCube", _navi_before)
|
||||
_vp.SetBool("UseNavigationAnimations", _anim_before)
|
||||
_vp.SetBool("EnablePreselection", _presel_before)
|
||||
json.dump(out, open(os.path.join(OUTDIR, "_anchors.json"), "w", encoding="utf-8"), ensure_ascii=False, indent=1)
|
||||
print("saved", base)
|
||||
@@ -0,0 +1,152 @@
|
||||
# Render the inline QC station views (run in the FreeCAD GUI after build_station.py).
|
||||
# exec(open(r"C:/dev/cnx_vinyl/docs/equipment/inline-qc-station/render_station.py", encoding="utf-8").read())
|
||||
# Detail views are rendered from a temporary document holding the model clipped
|
||||
# to a box (Part common), because coin clip planes did not reach the render here.
|
||||
import os
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
import Part
|
||||
|
||||
OUTDIR = r"C:/dev/cnx_vinyl/docs/equipment/inline-qc-station"
|
||||
doc = App.getDocument("InlineQCStation")
|
||||
|
||||
_vp = App.ParamGet("User parameter:BaseApp/Preferences/View")
|
||||
_navi_before = _vp.GetBool("ShowNaviCube", True)
|
||||
_vp.SetBool("ShowNaviCube", False)
|
||||
_anim_before = _vp.GetBool("UseNavigationAnimations", True)
|
||||
_vp.SetBool("UseNavigationAnimations", False)
|
||||
_presel_before = _vp.GetBool("EnablePreselection", True)
|
||||
_vp.SetBool("EnablePreselection", False)
|
||||
Gui.Selection.clearPreselection()
|
||||
Gui.Selection.clearSelection()
|
||||
from pivy import coin
|
||||
|
||||
|
||||
def prep(d):
|
||||
Gui.setActiveDocument(d.Name)
|
||||
v = Gui.getDocument(d.Name).ActiveView
|
||||
try:
|
||||
v.setCameraType("Orthographic")
|
||||
except Exception:
|
||||
pass
|
||||
for m in ("setNavigationCubeVisible", "setCornerCrossVisible"):
|
||||
if hasattr(v, m):
|
||||
getattr(v, m)(False)
|
||||
return v
|
||||
|
||||
|
||||
def members(group):
|
||||
g = doc.getObject(group)
|
||||
return list(g.Group) if g else []
|
||||
|
||||
|
||||
def show_all():
|
||||
for o in doc.Objects:
|
||||
if o.TypeId == "Part::Feature":
|
||||
o.ViewObject.Visibility = True
|
||||
|
||||
|
||||
def hide(groups=(), names=()):
|
||||
for gname in groups:
|
||||
for o in members(gname):
|
||||
o.ViewObject.Visibility = False
|
||||
for n in names:
|
||||
o = doc.getObject(n)
|
||||
if o:
|
||||
o.ViewObject.Visibility = False
|
||||
|
||||
|
||||
def shoot(v, fname, orient, w=3200, h=2400):
|
||||
getattr(v, orient)()
|
||||
Gui.updateGui()
|
||||
v.fitAll()
|
||||
Gui.updateGui()
|
||||
# move the orthographic camera well back so no part sits behind the near plane
|
||||
c = v.getCameraNode()
|
||||
d = c.orientation.getValue().multVec(coin.SbVec3f(0, 0, -1))
|
||||
c.position.setValue(c.position.getValue() - d * 8000)
|
||||
c.nearDistance.setValue(100)
|
||||
c.farDistance.setValue(32000)
|
||||
Gui.updateGui()
|
||||
path = os.path.join(OUTDIR, fname)
|
||||
v.saveImage(path, w, h, "White")
|
||||
print("saved", path)
|
||||
|
||||
|
||||
def clipped_doc(name, clipbox, skip_groups=()):
|
||||
skip = set()
|
||||
for gname in skip_groups:
|
||||
skip.update(o.Name for o in members(gname))
|
||||
d = App.newDocument(name)
|
||||
for o in doc.Objects:
|
||||
if o.TypeId != "Part::Feature" or o.Name in skip:
|
||||
continue
|
||||
s = o.Shape.common(clipbox)
|
||||
if s.isNull() or s.Volume < 1e-3:
|
||||
continue
|
||||
n = d.addObject("Part::Feature", o.Name)
|
||||
n.Shape = s
|
||||
n.ViewObject.ShapeColor = o.ViewObject.ShapeColor
|
||||
n.ViewObject.Transparency = o.ViewObject.Transparency
|
||||
n.ViewObject.LineColor = o.ViewObject.LineColor
|
||||
d.recompute()
|
||||
return d
|
||||
|
||||
|
||||
view = prep(doc)
|
||||
enclosure_tops = ["PanelTop", "PanelFrontUpper", "PanelFrontLower", "GuardRejectFront", "GuardRejectTop", "DoorHandle"]
|
||||
|
||||
# 1 open iso: front panels and lid off, the rest of the enclosure translucent
|
||||
show_all()
|
||||
hide(names=enclosure_tops)
|
||||
shoot(view, "inline-qc-station-iso.png", "viewIsometric")
|
||||
|
||||
# 2 closed iso: as it stands in the hall
|
||||
show_all()
|
||||
for o in members("Enclosure"):
|
||||
o.ViewObject.Transparency = 15 if o.Name not in ("GuardRejectFront", "GuardRejectTop") else 70
|
||||
shoot(view, "inline-qc-station-closed.png", "viewIsometric")
|
||||
for o in members("Enclosure"):
|
||||
o.ViewObject.Transparency = 55 if o.Name not in ("GuardRejectFront", "GuardRejectTop") else 75
|
||||
|
||||
# 3 front elevation without the front panels
|
||||
show_all()
|
||||
hide(names=enclosure_tops)
|
||||
shoot(view, "inline-qc-station-front.png", "viewFront")
|
||||
|
||||
# 4 plan view without the lid and the top bridge
|
||||
show_all()
|
||||
hide(names=enclosure_tops + ["TopBeamF", "TopBeamB", "TopCrossLabel", "TopCrossLineScan", "TopCrossThermal",
|
||||
"TopCrossBacklight", "RejectBridgeCross", "RodlessCylinder", "PusherCarriage",
|
||||
"LabelCamTop", "LabelCamTopPost", "LabelCamTopPlate", "LineCamTop", "LineCamTopPost",
|
||||
"LineCamTopPlate", "LightHangerTop", "CoaxHangerTop", "CoaxLightTop", "CoaxLightTopFace",
|
||||
"BacklightForBottomCam", "BacklightForBottomCamFace", "BacklightBracketTop",
|
||||
"LabelRingTop", "LabelRingTopFace", "ThermalCam", "ThermalPost",
|
||||
"DarkFieldTopF", "DarkFieldTopB", "DarkFieldTopBracketF", "DarkFieldTopBracketB",
|
||||
"StackLight0", "StackLight1", "StackLight2", "StackLightPole", "HMI", "HMIArm"])
|
||||
shoot(view, "inline-qc-station-top.png", "viewTop")
|
||||
show_all()
|
||||
hide(names=enclosure_tops)
|
||||
view.viewIsometric()
|
||||
view.fitAll()
|
||||
doc.save()
|
||||
|
||||
# 5 inspection elevation: x 600..1120, everything in front of y = -150 cut away
|
||||
d5 = clipped_doc("QCDetailFront", Part.makeBox(520, 500, 1100, App.Vector(600, -150, 400)),
|
||||
skip_groups=("Enclosure", "Electrical", "Reject"))
|
||||
v5 = prep(d5)
|
||||
shoot(v5, "inline-qc-station-detail-front.png", "viewFront", w=2400, h=2400)
|
||||
App.closeDocument(d5.Name)
|
||||
|
||||
# 6 inspection zone, 3/4 view: x 600..1120, z 400..1500
|
||||
d6 = clipped_doc("QCDetailIso", Part.makeBox(520, 700, 1100, App.Vector(600, -350, 400)),
|
||||
skip_groups=("Enclosure", "Electrical", "Reject"))
|
||||
v6 = prep(d6)
|
||||
shoot(v6, "inline-qc-station-detail.png", "viewIsometric", w=2400, h=2400)
|
||||
App.closeDocument(d6.Name)
|
||||
|
||||
Gui.setActiveDocument(doc.Name)
|
||||
_vp.SetBool("ShowNaviCube", _navi_before)
|
||||
_vp.SetBool("UseNavigationAnimations", _anim_before)
|
||||
_vp.SetBool("EnablePreselection", _presel_before)
|
||||
print("done")
|
||||
@@ -1,13 +1,169 @@
|
||||
# Pressing Line: Equipment Plan
|
||||
|
||||
The target press fleet is a **50/50 split between fully automated and
|
||||
semi-automatic presses**: automated presses for standard production volume,
|
||||
and semi-automatic presses for splatter and other color effects, special
|
||||
editions, and small runs, where an operator working the mold directly is an
|
||||
advantage rather than a cost. The semi-automatic side is covered by the
|
||||
Newbilt evaluation below; a fully automated press line is an open
|
||||
procurement item (see the [vendor landscape](../suppliers/vendor-landscape.md)
|
||||
for the Pheenix Alpha candidate).
|
||||
## Launch plant: one Duplex system and one Classic (October 2026)
|
||||
|
||||
Decided (user, October 2026): the plant launches with **one Newbilt Duplex
|
||||
system** (two HRP 12 presses, EX 50 main and EX 35 colour extruder) and
|
||||
**one Newbilt Classic**, bought in one capital round with the galvanics,
|
||||
stamper-prep and cutting room and commissioned in sequence
|
||||
([total investment](../finance/total-investment.md#launch-plant-october-2026)).
|
||||
That is ~0.71 to 0.97 million records a year on two shifts
|
||||
([scale](../scale.md#production-capacity)). The second Duplex system below
|
||||
is a growth option with its room, utility modules and ring-main tees
|
||||
reserved, not part of the investment. The five-press fleet stays the
|
||||
layout the hall and the utility backbone are built for.
|
||||
|
||||
## Layout fleet: an all-Newbilt fleet of five presses (October 2026)
|
||||
|
||||
Two **Newbilt Duplex** systems, each with two HRP 12 presses fed by an
|
||||
**EX 50** main extruder with an **EX 35** auxiliary extruder beside it for
|
||||
a second colour, plus one **Newbilt Classic** fully automatic press. The
|
||||
whole fleet runs from **one shared hydraulic supply and one shared
|
||||
compressed-air supply** (October 2026):
|
||||
|
||||
| | Presses | Extruders | Hydraulics and air |
|
||||
|---|---|---|---|
|
||||
| Duplex system 1 | 2 semi-automatic | EX 50 main + EX 35 colour | shared central supply |
|
||||
| Duplex system 2 | 2 semi-automatic | EX 50 main + EX 35 colour | shared central supply |
|
||||
| Classic | 1 fully automatic | built in | shared central supply (to confirm with Newbilt) |
|
||||
| **Fleet** | **5: 4 semi-automatic, 1 automatic** | **2 EX 50, 2 EX 35, 1 built in** | **one hydraulic plant, one air plant** |
|
||||
|
||||
This replaces the earlier target of a 50/50 split between automated and
|
||||
semi-automatic presses (two of each, with the Pheenix AD12 as the
|
||||
automated candidate). What it means:
|
||||
|
||||
- **The semi-automatic side carries most of the volume.** Splatter and
|
||||
other colour effects, special editions and small runs are where an
|
||||
operator working the mould is an advantage rather than a cost, and
|
||||
Newbilt itself recommends the Duplex for splatter, and the EX 35 on
|
||||
each system adds the second colour strand for splatter, marble and
|
||||
half-and-half work, which is what the flyer offers it for. The Classic
|
||||
takes the long standard runs.
|
||||
- **One vendor, one mould family.** Classic and Duplex share insert sets
|
||||
(below), so the whole fleet runs one family of moulds and spares and one
|
||||
service relationship. The single-vendor risk is the same one the Pheenix
|
||||
path would have carried.
|
||||
- **Phasing.** The Newbilt Single 2.1 system of the 2024 quote (one press,
|
||||
one extruder) is the first half of Duplex system 1: its hydraulic
|
||||
aggregate is already sized for the second press. Since October 2026 the
|
||||
launch plant buys the whole of system 1 (second press and EX 35) and the
|
||||
Classic at once; system 2 is the growth step ([scale](../scale.md) capacity table,
|
||||
[roadmap](../roadmap.md) item 24). The
|
||||
[press fleet calculator](../fleet-calculator.html) works out the mix of
|
||||
Duplex systems and Classics for a target output and specials share,
|
||||
with the utilities from Newbilt's site requirements; the Classic counts
|
||||
there as one HRP 12 press plus one extruder until Newbilt states its
|
||||
figures.
|
||||
- **One shared hydraulic and air supply.** A central hydraulic plant
|
||||
(pumps, tank, accumulators) and one compressed-air plant feed every
|
||||
press through ring mains, instead of a hydraulic unit per system. It
|
||||
means one plant room to maintain and one place for noise and heat, and
|
||||
it makes adding presses a matter of tapping the ring main. In the
|
||||
[Payap scenario model](../site-candidates.md#payap-scenario-model-october-2026)
|
||||
it is a plant room at the west end of the press hall, with a service
|
||||
trench along the press rows. Open for the re-quote (below): whether the
|
||||
Single 2.1's own aggregate becomes part of the central plant or a
|
||||
standby, and whether the Classic can run from it.
|
||||
|
||||
Built to grow from one press (October 2026): the plant room is built at
|
||||
full size, and the hydraulic and air ring mains are sized for the whole
|
||||
fleet from the start, with a valved, capped tee at every press position,
|
||||
the empty ones included, so a new press is connected without stopping
|
||||
the others. The proposal for the Single 2.1's own aggregate, already
|
||||
sized for the second press, is to set it in the plant room as the first
|
||||
pump set on the ring main instead of beside the press; system 2 and the
|
||||
Classic add pump sets in parallel on one manifold with the accumulators,
|
||||
and a standby set follows. Each branch gets its own isolation valves and
|
||||
filter: with one shared oil system, a contamination event otherwise
|
||||
reaches every press. Chinese pump sets and accumulators for the
|
||||
standby set were checked in October 2026; the press aggregates stay
|
||||
Newbilt's ([Chinese suppliers](../suppliers/china-utilities.md#hydraulics)).
|
||||
Steam and cooling follow the same pattern; the phased list for all
|
||||
three is in
|
||||
[scale](../scale.md#utility-phasing-backbone-once-modules-with-the-presses).
|
||||
- **Cell layout (October 2026).** Each Duplex system is one operator's
|
||||
cell, as sketched in [duplex-cell-layout-sketch.png](duplex-cell-layout-sketch.png)
|
||||
(arrangement only, not to scale):
|
||||
- the operator stands in the middle, with the two presses either side
|
||||
turned 45° towards him;
|
||||
- the EX 50 and the EX 35 stand side by side behind him, between the
|
||||
presses;
|
||||
- one trimmer per cell stands in front of him on the left.
|
||||
|
||||
At Newbilt's sizes (site requirements p. 10: press footprint about
|
||||
0.9 m², extruder about 0.5 m², room to walk around every machine, at
|
||||
least 60 cm to walls) the cell is about 5 × 3 m, with 0.6 to 0.8 m
|
||||
between machines. The EX 35 and trimmer footprints are not published,
|
||||
so those are estimates. The [Payap scenario model](../site-candidates.md#payap-scenario-model-october-2026) draws
|
||||
both systems this way.
|
||||
- **Room to grow: a hall laid out for Duplex systems (October 2026).**
|
||||
The plant will mainly press special editions (splatter, marble, colour
|
||||
effects), not mono colours: the specials share is planned at 60 % and
|
||||
more ([revenue model](../finance/revenue-model.md)), and specials run
|
||||
only on the Duplex systems. The press hall therefore keeps five Duplex
|
||||
bays (the launch system and four more) and four Classic positions (the
|
||||
launch Classic and three more). At the calculator's floor figures (110
|
||||
m² per Duplex bay, 50 m² per Classic) that is 550 + 200 = ~750 m² of the
|
||||
~870 m² hall, ~73/27 by floor and 10 to 4 by presses; the rest stays
|
||||
open for mould carts and staging. Growth adds Duplex systems first.
|
||||
This split balances the hall by output at 60 % specials: ten
|
||||
semi-automatic presses (600 to 800 records an hour, estimate) carry the
|
||||
specials and the four Classics (~512 an hour) the standard records. A
|
||||
60/40 floor split (four Duplex bays, six Classics), planned first the
|
||||
same month, left the Classics about half loaded at that share. This is
|
||||
an option, not part of the plan or the investment: the layout keeps the
|
||||
floor, and the central hydraulic and air plant should be sized or
|
||||
extendable for it. At Newbilt's per-press figures, the fourteen presses
|
||||
would draw ~2.1 to 2.5 t/h of steam and up to ~1.8 MW of cooling, so
|
||||
boiler, chiller and grid connection would be a phase of their own
|
||||
([scale](../scale.md#production-capacity)). The Payap scenario model in
|
||||
FreeCAD still draws the earlier layout (two Duplex bays and eleven
|
||||
Classic positions).
|
||||
- **Capacity** at maturity stays at ~1.0 to 1.5 million records a year on
|
||||
two shifts, the range the [revenue model](../finance/revenue-model.md)
|
||||
uses: four semi-automatic presses at 60 to 80 records an hour (estimate)
|
||||
and the Classic at ~128 an hour (28 s cycle, vendor figure).
|
||||
- **Utilities, re-based for this fleet (October 2026).** At Newbilt's
|
||||
per-machine figures (steam 150 to 180 kg/h, cooling up to 125 kW per
|
||||
press) the five presses draw ~750 to 900 kg/h of steam and up to ~650 kW
|
||||
of cooling with extruders and hydraulics, against the ~400 kg/h steam
|
||||
generator and ~250 kW cooling system that the 2024 quote's exclusions
|
||||
describe for one Duplex. The proposal is a bank of two 500 kg/h boilers
|
||||
and three 250 kW chillers, one module per press stage, in a boiler hall
|
||||
and a chiller compound built for four modules each
|
||||
([scale](../scale.md#detached-utility-yard-parking-and-what-that-moves));
|
||||
the layout, the
|
||||
operating cases and the open RFQ questions are in
|
||||
[steam and cooling](../steam-cooling.html), the electrical consequences in
|
||||
[scale](../scale.md) and the costs in the
|
||||
[utilities CSV](../finance/utilities-investment.csv).
|
||||
- **Investment**: the fleet change is carried in the added-scope table of
|
||||
[total investment](../finance/total-investment.md) until the next
|
||||
re-base.
|
||||
- **For the re-quote** ([roadmap](../roadmap.md) item 4): the Duplex with
|
||||
an EX 50 and an EX 35 as an upgrade of the Single 2.1 and as a second
|
||||
complete system, and whether the EX 50 is the VEX 50 of the 2024 quote;
|
||||
whether one EX 50 keeps both presses of a system at full rate (the
|
||||
flyer's Duplex main configuration runs two presses on one extruder); the
|
||||
Classic's price, weight, power, steam and cooling figures; and the
|
||||
central hydraulic supply (an option the flyer offers) for the whole
|
||||
fleet, extendable to the full hall (five Duplex systems, four Classics),
|
||||
including whether the Classic
|
||||
can run from it, whether the presses hold their pressure from it over
|
||||
the ring-main lengths of the hall, the filtration and isolation each
|
||||
branch needs, and whether the Single 2.1's aggregate can be its first
|
||||
pump set.
|
||||
|
||||
The Pheenix AD12 leaves the plan; it stays in the
|
||||
[vendor landscape](../suppliers/vendor-landscape.md) as the comparison if
|
||||
the Classic re-quote disappoints, and Pheenix stays a galvanics candidate
|
||||
([galvanics and stamper prep](galvanics.md)). ResurRec, which the August
|
||||
2026 tour found running a Newbilt Classic in Bangkok (a directory listing
|
||||
names an M-Tech Allegro II instead), appears to have
|
||||
equipped its new Japan plant with AD12s (Alexander's identification
|
||||
from photos, October 2026, [revenue model](../finance/revenue-model.md#resurrec-japan-october-2026)).
|
||||
Why they chose the AD12 there is a question for the Classic re-quote, the
|
||||
Pheenix call and the ResurRec talks.
|
||||
|
||||
## Semi-automatic line: Newbilt
|
||||
|
||||
@@ -25,20 +181,91 @@ The core semi-automatic machinery under evaluation comes from
|
||||
(scrap feeds back as the ~20% recycled share of the feedstock), 7" center
|
||||
label punch, buffer spindles and separator plates.
|
||||
|
||||
The June 2024 Newbilt quotation totals **≈ €200,500** including freight from
|
||||
The June 2024 Newbilt quotation totals **EUR 200,500** (about **USD 232k
|
||||
/ 7.7M THB** at August 2026 rates), including freight from
|
||||
Alsdorf to Thailand and seaworthy packaging. Two major utility systems are
|
||||
deliberately excluded and will be **sourced and installed locally in
|
||||
Thailand**: a ~400 kg/h steam generator (with water treatment) and a ~250 kW
|
||||
cooling water system. The quotation has passed its validity date and will need
|
||||
re-confirmation before ordering.
|
||||
|
||||
## Newbilt range: Making Vinyl Europe 2026 flyers
|
||||
|
||||
Collected at the Newbilt booth in Haarlem (30 September to 2 October 2026);
|
||||
the PDFs are in [`newbilt/flyers-2026/`](newbilt/flyers-2026/). Figures are
|
||||
vendor-published, not quoted.
|
||||
|
||||
| Machine | What it is | Flyer figures |
|
||||
|---|---|---|
|
||||
| **Classic** | Fully automatic press: hydraulic 3-column frame based on the Toolex Alpha, built-in extruder, automatic cake loading, label feed, record loading and unloading, cooling-plate handling and spindle stacking | 12" at 110, 140, 160 and 180 g, 7" in development; 28 s cycle at 180 g, claimed ≥95 % yield and ≥95 % uptime (2024 flyer); steam temperature, cooling-water temperature and flow monitored; cooling by time or by delivered water volume, adjusted automatically as the cooling water warms up; Siemens safety PLC, cycle and trend recording, SCADA interface with OPC UA (2024 flyer) |
|
||||
| **Duplex** | Semi-automatic system in three configurations: Single (1 press, 1 extruder), Duplex main (2 presses, 1 extruder), Duplex with two extruders (2 presses, 2 extruders run as one system with shared control and one hydraulic unit) | 12", 10" and 7"; solid colours, splatter, marble, half and half, picture discs; hydraulic unit normally supplied, or an external central supply shared by several systems |
|
||||
| **EX 35** | Auxiliary extruder beside the main one, for a second or third colour | 35 mm PVC screw, 3 heating zones, 2 fans, frequency-controlled screw speed, PVC strand output, touchscreen HMI, prepared for Newbilt online support |
|
||||
| **Edge Trimmer** | Trims the pressed record to its final diameter | Hardened heated blade with adjustable temperature; 7", 10" and 12" with one trimming plate per size (sold separately); standalone, or wired and piped to the Newbilt extruder and then part of the Duplex/Single emergency-stop circuit |
|
||||
| **Granulator 400** | Grinds edge trim and label-free records into regrind | 200 to 250 kg/h, 7.5 kW, crushing chamber 410 × 270 mm, 12 rotor knives, 8 mm screen, 800 kg; cyclone collection with stainless contact surfaces, dust bags and outlet magnet, about 100 kg storage |
|
||||
| **Label Punch** | Removes the label area so rejected records can be granulated | 106 mm punch for 7", 10" and 12"; manual loading, then automatic transport, punching and collection; optional dinker for 7" |
|
||||
|
||||
What this changes in the plan:
|
||||
|
||||
- **Classic and Duplex share inserts.** Insert sets move between the two
|
||||
machines, so the current all-Newbilt fleet (Duplex systems for the
|
||||
semi-automatic side, the Classic for the automated press) runs one mould
|
||||
family. Newbilt itself recommends the Duplex for splatter, which is why
|
||||
the semi-automatic side carries most of the fleet. The Pheenix AD12
|
||||
stays the comparison for the Classic.
|
||||
- **Regrind loop.** The granulator flyer puts edge trim at about 20 to 40 g
|
||||
per 12" 180 g record, 11 to 22 % of the record's mass, which brackets the
|
||||
~20 % recycled share in the process schematic. Rejected records go
|
||||
through the Label Punch first; trim goes into the granulator directly. A
|
||||
Classic at 28 s makes about 128 records/h, so roughly 2.5 to 5 kg/h of
|
||||
trim per press (estimate): one Granulator 400 at 200 to 250 kg/h runs in
|
||||
short batches, not continuously.
|
||||
- **Compound storage (October 2026).** Special designs will run in tens
|
||||
of colours, so the compound store is sized for them:
|
||||
- a colour store with pallet racking next to the regrind and conveying
|
||||
room: about 100 pallet positions on four levels in the
|
||||
[Payap scenario model](../site-candidates.md#payap-scenario-model-october-2026) (estimate);
|
||||
- a few outdoor silos (proposed) for black and the standard colours,
|
||||
filled from big bags or by bulk truck and conveyed to the extruders.
|
||||
|
||||
Compound is the heaviest material in the plant (~160 to 270 t a year at
|
||||
the mature fleet: 1.0 to 1.5 million records at roughly 160 to 180 g
|
||||
each with trim), so it
|
||||
stays on the ground floor. The compound suppliers' answer on 25 kg sacks
|
||||
versus big bags
|
||||
([Making Vinyl briefing](../suppliers/making-vinyl-europe-2026-exhibitors.md))
|
||||
decides how the silos are filled.
|
||||
- **Hydraulics.** One central hydraulic supply for several systems is an
|
||||
option on the flyer and is now the plan, together with one shared
|
||||
compressed-air supply (see "Current plan" above); it changes the
|
||||
machine-floor layout and the utility list in [scale.md](../scale.md).
|
||||
- **Colour effects.** The EX 35 is the add-on for multi-colour work on the
|
||||
semi-automatic side. It is not in the 2024 quote; the current plan has
|
||||
one per Duplex system.
|
||||
- **For the re-quote**, where sources disagree: the Classic's operator panel
|
||||
(two 21" touchscreens in the 2024 flyer, one 10" on the Newbilt website);
|
||||
its built-in extruder power (7.5 kW, 400 V drive motor in the 2024 flyer,
|
||||
15 kW in this repo's earlier notes, source not recorded); 10" on the
|
||||
Classic (in the 2024 flyer and on the website, not in the 2026 flyer);
|
||||
and whether the Edge Trimmer is the Vario trimmer of the 2024 quote.
|
||||
- **Stamper fit.** Ask both press vendors which stamper centre hole and
|
||||
edge form their moulds expect: the Sibert VSP punches Ø25.4 mm as
|
||||
standard and the VSC coiner needs tooling per mould type (see
|
||||
[galvanics and stamper prep](galvanics.md)).
|
||||
|
||||
## Site requirements
|
||||
|
||||
Site planning for the semi-automatic line works from Newbilt's Duplex
|
||||
requirements: roughly 200 m² of production floor, 32 kVA connected
|
||||
electrical load, saturated steam at 10 bar, and compressed air and cooling
|
||||
water circuits, plus side rooms for materials, compressor, chiller, and
|
||||
finished goods.
|
||||
finished goods. These are per Duplex system: the current fleet needs two,
|
||||
plus floor for the Classic (~400 m², plus ~50 to 75 m² for the Classic,
|
||||
estimate). The machines themselves are small: a press is about 0.9 m², an
|
||||
extruder about 0.5 m², and the hydraulic aggregate about 1.0 m², which
|
||||
Newbilt prefers outside the pressing room; the minimum room height is
|
||||
2.5 m. Most of the 200 m² is walking, handling and side-room space. The
|
||||
layout drawing that page 11 of the site requirements refers to is not in
|
||||
our copy; ask for it with the re-quote.
|
||||
|
||||
**Floor loading is a building-selection criterion**: the slab must carry
|
||||
multiple tons per m² in the machine areas. A Newbilt press weighs 1,350 kg
|
||||
@@ -50,4 +277,5 @@ from press cycles come on top of the static figures, so the structural
|
||||
engineer gets the vendor data sheets, not just the totals.
|
||||
|
||||
Source documents live in [`newbilt/`](newbilt/): the budgetary offer, the
|
||||
Duplex site requirements, the process schematic, and the service rate card.
|
||||
Duplex site requirements, the process schematic, the service rate card, and
|
||||
the 2026 product flyers in [`newbilt/flyers-2026/`](newbilt/flyers-2026/).
|
||||
@@ -28,7 +28,8 @@ option per room.
|
||||
sensors logging in every zone, with alarms on excursions, tied into the
|
||||
plant monitoring below.
|
||||
- **Energy design**: conditioning a whole factory in a tropical climate is
|
||||
a major electrical load on top of the 250 kW process cooling, and it must
|
||||
a major electrical load on top of the process cooling (up to ~650 kW for
|
||||
the five presses), and it must
|
||||
be included in the solar PV and battery sizing from the start. Heat
|
||||
recovery from the press hall (steam, hydraulics, and hot PVC all reject
|
||||
heat) and from compressors should feed the design rather than fight it.
|
||||
@@ -38,15 +39,20 @@ option per room.
|
||||
- **Access control**: zoned, not just at the gate. Minimum zones: general
|
||||
production, galvanics clean room (controlled access is already a safety
|
||||
requirement), chemical storage, master/stamper archive, server/IT room,
|
||||
finished goods and shipping. Badge or biometric, with logs.
|
||||
finished goods and shipping, and the visitor corridor. Badge or
|
||||
biometric, with logs.
|
||||
- **CCTV**: entrances, perimeter, loading dock, production floor, chemical
|
||||
storage, archive. Retention policy to be defined; Thai PDPA (personal data
|
||||
protection) applies to camera footage of staff and visitors.
|
||||
- **Intrusion alarm** with monitoring, covering off-hours.
|
||||
- **Perimeter and lighting**: fencing appropriate to the site, lit
|
||||
approaches and parking.
|
||||
- **Visitor management**: sign-in, escort rules, PPE issue at entry, no
|
||||
unaccompanied access to production or galvanics.
|
||||
- **Visitor management**: sign-in, escort rules, no unaccompanied access to
|
||||
production or galvanics. Tours run through the glazed visitor corridor
|
||||
([crane, workshop and tours](crane-workshop-tours.md)), which keeps
|
||||
visitors out of noise, dust and plating air and so needs no PPE; anyone
|
||||
who goes onto the floor itself is escorted and issued PPE at entry as
|
||||
before.
|
||||
|
||||
## Protecting the irreplaceable
|
||||
|
||||
@@ -62,6 +68,81 @@ option per room.
|
||||
salts are hazardous. Locked storage, inventory tracking, and controlled
|
||||
issue to the galvanics team.
|
||||
|
||||
### Archive room: mobile shelving
|
||||
|
||||
Planned (October 2026): the archive in the office is fitted with **mobile
|
||||
archive shelving**, carriages on floor rails that close up into one block
|
||||
and open a single aisle where it is needed. The reference is A-Z
|
||||
Solutions' archive shelving (Vienna; fahrbare Archivregale,
|
||||
https://www.a-z-solutions.eu/buero-archiv/archivregale, checked October
|
||||
2026): hand wheel or electric push-button drive, optional front panels,
|
||||
lockable, and the vendor asks to be involved early because the rails set
|
||||
requirements on the floor and the room layout. Prices are not published.
|
||||
|
||||
**What it holds.** The father and the mother of every side (decided
|
||||
October 2026, [galvanics](equipment/galvanics.md)): 4 parts per title,
|
||||
about 1,200 to 2,400 a year at full capacity, in protective sleeves,
|
||||
standing in labelled boxes. Also paper records that have to be kept as
|
||||
originals. A reference pressing of every title could go here too; that is
|
||||
a proposal, not decided.
|
||||
|
||||
**Size, estimates.** A 12" father or mother grows on a 14" lacquer: about
|
||||
35 cm across, 0.25 mm thick, ~9.6 dm² ([plant
|
||||
operation](plant-operation.html) and galvanics figures), so about 0.2 kg of
|
||||
nickel. In a sleeve with a separator, assume ~3 mm of shelf per part:
|
||||
~330 parts and ~75 kg per shelf metre, on 400 mm deep shelves with ~400 mm
|
||||
clear height, five levels to ~2.2 m. In the Payap scenario's office the
|
||||
archive is a ground-floor room of about 4 × 5.75 m
|
||||
([site candidates](site-candidates.md)). With the rails along the long
|
||||
side it takes two fixed single-sided runs, four double-sided carriages
|
||||
about 3 m long and one ~0.9 m working aisle: ~150 shelf metres, roughly
|
||||
50,000 parts, which is 20 years or more of fathers and mothers at full
|
||||
capacity. Static shelving with an aisle between every pair of runs
|
||||
would hold about 60 % of that.
|
||||
|
||||
**What it asks of the building.**
|
||||
|
||||
- **Floor load.** Fully loaded, a double carriage carries about a tonne
|
||||
per metre of length: ~11 kN/m² under the shelving block and ~6 kN/m²
|
||||
averaged over the room (estimates), above an office floor. The archive stays on the ground slab, and
|
||||
that slab keeps the full rating if the slab is zoned lighter under
|
||||
offices ([phase 1 RFQ](finance/phase1-construction-rfq.md)).
|
||||
- **Rails.** Set into the floor screed during fit-out, or on a raised
|
||||
floor ramped at the door, so the shelving layout and the rail positions
|
||||
are fixed before the floor finish. Rail type, depth and floor flatness
|
||||
tolerance come from the shelving supplier.
|
||||
- **Drive.** A geared hand wheel with an aisle lock is enough for a room
|
||||
one or two people use and has nothing to fail; electric drive is an
|
||||
option, not a need.
|
||||
- **The room around it** stays as above: clean-agent gas suppression
|
||||
(the suppression designer confirms the agent reaches into the closed
|
||||
carriage block), climate control with the archive in the tightest
|
||||
monitoring tier ([digital factory](digital-factory.md)), a water-leak
|
||||
sensor along the rails, lockable carriages behind the room's access
|
||||
control.
|
||||
- **Locations.** Every box carries a barcode and every position an
|
||||
address (carriage, face, level, slot); each part's serial number in
|
||||
ERPNext carries its archive location, so a repress order says which box
|
||||
to pull.
|
||||
|
||||
**Open points.**
|
||||
|
||||
- **Quotes:** A-Z Solutions and LPI Rack Range (Thailand), a Bangkok
|
||||
manufacturer of office mobile shelving and industrial racking
|
||||
([supplier map](suppliers/equipment-suppliers.md)), against the same spec (carriages ~3 m, five levels, 400 mm
|
||||
shelves, at least ~100 kg per shelf level per metre, geared hand wheel
|
||||
with aisle lock, central lock, rail embedding detail, delivery and
|
||||
installation in Chiang Mai). Steel shelving shipped from Austria is
|
||||
heavy, so the A-Z system is the reference spec rather than the default
|
||||
buy.
|
||||
- **Storage format:** sleeves, boxes, passivation and humidity for
|
||||
archived nickel parts, from the galvanics vendors
|
||||
([open questions](equipment/galvanics.md#open-questions-for-the-quotes)).
|
||||
- **Two compartments:** with fathers and mothers in one room, one event
|
||||
can take both. Keeping the fathers (rarely pulled) in a second fire
|
||||
compartment or off site, and the mothers (pulled for every repress) in
|
||||
this room, would meet the off-site point above.
|
||||
|
||||
## Fire and life safety
|
||||
|
||||
- **Fire detection and alarm** throughout; suppression matched to each zone
|
||||
@@ -131,7 +212,12 @@ sprinkler demand, so the site carries its own reserve and pumps.
|
||||
**Warehouse racking height drives the real number.** If finished-goods
|
||||
storage goes above roughly 3.7 m, the commodity classification and sprinkler
|
||||
design change, and the stored volume grows with them. Fix the racking height
|
||||
before the fire design is frozen, not after.
|
||||
before the fire design is frozen, not after. The
|
||||
[Payap scenario model](site-candidates.md#payap-scenario-model-october-2026)
|
||||
draws the 9 m × 4 m tank with its pump house at the front. It also draws
|
||||
6 m warehouse racking and about twice the floor area this figure was
|
||||
based on, a paper store among it, so treat ~200 m³ as a floor there,
|
||||
not as the answer.
|
||||
|
||||
The property insurer will drive much of the final specification, so involve
|
||||
them before the design is fixed. The archive gas system and the BESS
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
# Phase 1 Construction: Rough Pricing Request
|
||||
|
||||
Spec sheet for asking a contractor for a budget-level price on the phase 1
|
||||
buildings and site works. Quantities come from the parametric model
|
||||
(`docs/cnx_vinyl_parametric.FCStd`) sited on the candidate Mueang Chi
|
||||
parcel; everything here is planning-stage, not construction documents. In
|
||||
Thailand this scope is typically quoted as a PEB (pre-engineered steel
|
||||
building) per m² plus civil works, and the sheet is structured that way.
|
||||
|
||||
Context to give the contractor up front: the land is not yet purchased and
|
||||
zoning is unverified, so this is a budget number, not a bid.
|
||||
|
||||
## 1. Main production building
|
||||
|
||||
| Item | Spec |
|
||||
|---|---|
|
||||
| Type | Single-storey steel portal frame (PEB), no mezzanine, **crane-ready: one 5 t EOT crane runway over the production compartment** (see §1c) |
|
||||
| Footprint | **60 × 25 m = 1,500 m²** |
|
||||
| Roof | Monopitch, **10° pitch**, roof plane **1,523 m²**, low eave **7.0 m**, high side **~11.4 m** (both above finished floor) |
|
||||
| Roof load | Carries a rooftop PV array (~425 modules, ~247 kWp): add **~20 kg/m²** dead load plus wind uplift on racking; PV mounts on the purlins |
|
||||
| Envelope | **Insulated sandwich panels, walls and roof, PIR core — EPS core excluded** (fire and insurability), fire-rated class stated (FM-approved or B-s1,d0). **Roof 100 mm PIR** with light-colored top skin, **walls 75 mm PIR**. Taped/gasketed joints throughout — the building is air-conditioned (20–26 °C, 35–60 % RH) and must be airtight against smoke-season PM2.5. No skylights. Not bare metal sheet with blanket insulation. **See §1a for where mineral-wool core is required instead** |
|
||||
| Wall quantities | Masonry/precast dado **170 m perimeter × 2.5 m = 425 m²** (impact, security, washdown), internally insulated so the envelope stays continuous; **sandwich panel above dado ~1,140 m²** |
|
||||
| Floor | **200 mm** ground-bearing slab rated **30 kN/m² UDL**, provision for machine plinths, power-floated finish |
|
||||
| Finished floor level | **+1.2 m above surrounding ground** — see §1b |
|
||||
| Doors | 2 loading doors (insulated sectional) as **sealed dock positions**: dock shelters/seals plus dock levelers, so the docked trailer acts as the airlock and doors never open to outside air. **1 machine door** (~4.5 × 5.0 m insulated sectional, fully sealed) at the ramp end, see §1c. Personnel entrances with vestibule; fire exits per code |
|
||||
| Interior | **Shell only — no internal fit-out** in this price (clean room, offices etc. priced later) |
|
||||
|
||||
On the slab spec: 30 kN/m² (3 t/m²) is the standard industrial warehouse
|
||||
class, not a premium — it is what the presses and pallet racking need, and
|
||||
stepping up from a light-duty slab adds only on the order of 100–200 THB/m².
|
||||
The real cost variable is the ground underneath (see soil, below). A later
|
||||
value-engineering option is to zone the slab — 30 kN/m² under press hall and
|
||||
warehouse only, lighter under offices, but for rough pricing the whole
|
||||
floor is specified at 30 so the number is conservative. If it is zoned,
|
||||
the archive room keeps the full rating: it gets mobile shelving loaded
|
||||
with nickel parts, about 11 kN/m² under the shelving when full (estimate), and
|
||||
its rails go into the floor screed at fit-out
|
||||
([facility security](../facility-security.md#archive-room-mobile-shelving)).
|
||||
|
||||
### 1a. Panel core: where PIR is not enough
|
||||
|
||||
PIR is specified for the general envelope because it gives the best thermal
|
||||
performance per millimetre (λ ≈ 0.022 W/mK, so roughly U 0.28 W/m²K walls
|
||||
and 0.21 W/m²K roof), which is what the conditioned interior needs. Two
|
||||
places it should **not** be used, and the contractor should price
|
||||
**mineral-wool core** panels instead:
|
||||
|
||||
- **Fire compartmentation.** A panel's reaction-to-fire class is not a fire
|
||||
resistance rating. Any wall required to compartment — production hall to
|
||||
warehouse, and anything separating the boiler hall — needs rated
|
||||
construction achieving **EI 60 or EI 120**, which in panel form means
|
||||
mineral wool, not PIR.
|
||||
- **Acoustics.** PIR performs poorly for sound, typically **Rw 25–30 dB**;
|
||||
it is a stiff closed-cell foam and behaves as a mass-spring-mass system
|
||||
with coincidence dips. Presses, compressors, chillers and the boiler are
|
||||
all significant sources and the site is agricultural land, so a neighbour
|
||||
complaint is a permitting risk. Mineral-wool core reaches roughly
|
||||
**Rw 32–40 dB**.
|
||||
|
||||
Ask the contractor to price the general envelope in PIR and to quote
|
||||
mineral-wool core as a **separate rate per m²** for nominated compartment
|
||||
and acoustic walls, stating the panel thickness needed to hold the same
|
||||
U-value (mineral wool at λ ≈ 0.038 needs roughly 130 mm walls / 180 mm roof
|
||||
to match, and is heavier — it may affect purlin and frame sizing).
|
||||
|
||||
**Open decision:** which elevations are acoustically governed. That depends
|
||||
on the neighbour to be identified at the land survey. Until then, price the
|
||||
mineral-wool rate but leave the area provisional.
|
||||
|
||||
### 1b. Raised floor and site fill
|
||||
|
||||
The dock-height question is now **decided**: the whole building floor is
|
||||
raised rather than forming a recessed dock pit. This is a civil works item
|
||||
and must be included.
|
||||
|
||||
| Item | Quantity |
|
||||
|---|---|
|
||||
| Compacted structural fill under the building platform | **1,711 m³** |
|
||||
| Fill build-up | 1.0 m compacted fill + 200 mm slab = **FFL +1.2 m** |
|
||||
| Reinforced concrete edge beam to retained faces | **56.1 m³**, ~85 m of retained edge |
|
||||
| Battered faces | Two faces battered at **1V:2H** rather than retained (no edge beam) |
|
||||
|
||||
The loading face and the car-park elevation are retained by the edge beam;
|
||||
the other two faces are battered. The dispatch room behind the docks runs as
|
||||
a buffer climate zone, separated from the conditioned warehouse by
|
||||
interlocked high-speed roll doors.
|
||||
|
||||
**Access at grade.** With FFL at +1.2 m the building needs its own access,
|
||||
now modelled and to be included:
|
||||
|
||||
| Item | Spec |
|
||||
|---|---|
|
||||
| Vehicle ramp | **10.5 m run × 4.5 m wide at 1:10**, rising 1,050 mm from yard level to FFL, sited at the far end of the building — opposite the docks, so it does not conflict with dock operations. **~22.9 m³** concrete |
|
||||
| Personnel steps | **3 flights**: main entrance on the car-park elevation, plus two fire exits — one at the opposite end of the same elevation, one at the dock end. Each **1.5 m wide, 6 risers at 175 mm, 5 treads at 280 mm, 1.2 m top landing**. **~2.3 m³** each |
|
||||
|
||||
Two things deliberately not in the model, to be priced anyway: **handrails**
|
||||
to both sides of every flight and to the ramp, and **door thresholds**.
|
||||
|
||||
The ramp is 1:10, which suits forklifts and vans but is **not** an
|
||||
accessible gradient. **A step-free visitor entrance is now required**: the
|
||||
plant will run public tours through a glazed visitor corridor (see
|
||||
[crane, workshop and tours](../crane-workshop-tours.md)). Price a **1:12
|
||||
ramp at the main entrance**, about 14.4 m of run for the 1.2 m rise plus
|
||||
intermediate landings, with handrails both sides.
|
||||
|
||||
Exit positions are provisional: they are placed for reasonable escape
|
||||
distances on a 60 × 25 m footprint, but final numbers and locations follow
|
||||
the fire strategy and the racking layout, neither of which is fixed.
|
||||
|
||||
### 1c. Overhead crane and machine door
|
||||
|
||||
The building must carry an overhead crane for moving machines in, out and
|
||||
to the maintenance workshop. Background and the reasoning behind each
|
||||
figure: [crane, workshop and tours](../crane-workshop-tours.md).
|
||||
|
||||
| Item | Spec |
|
||||
|---|---|
|
||||
| Crane | Single-girder EOT, **5 t SWL** (3.2 t as an alternative price), span the full building width (~24 m between rail centres), electric wire-rope hoist with inverter drives, radio remote, light duty class |
|
||||
| Runway | Both long walls, over the **production compartment only**: from the ramp-end wall to the production/warehouse fire wall, **~40 to 48 m** (estimate, set by the warehouse depth). Brackets or stepped columns, runway beams, rails, end stops, enclosed conductor rail |
|
||||
| Frame | Designed for crane wheel loads and braking forces from day one |
|
||||
| Hook height | **State the achievable hook height under the 7.0 m low eave.** Price **+1.0 m on the low eave** as an option |
|
||||
| Machine door | ~**4.5 m wide × 5.0 m high** insulated sectional, fully sealed, at the ramp end; the runway reaches its inside face |
|
||||
| Machine bay slab | The bay inside the machine door rated for a rigid truck reversing in: **wheel point loads**, not only the 30 kN/m² distributed rating |
|
||||
| Ramp | Confirm the 10.5 m × 4.5 m 1:10 ramp and its transitions take a rigid truck reversing up to the machine door |
|
||||
|
||||
The crane itself may be quoted by a specialist sub; the runway, frame
|
||||
premium and machine door belong in the shell price. Inside the crane zone
|
||||
no wall may run full height across the building; internal partitions are
|
||||
fit-out and are not in this price.
|
||||
|
||||
## 2. Detached utility yard
|
||||
|
||||
Simple industrial enclosures beside the main building.
|
||||
|
||||
| Building | Area | Height |
|
||||
|---|---|---|
|
||||
| Boiler hall, laid out for four 500 kg/h boiler modules | ~162 m² (18 × 9 m) | 6.0 m |
|
||||
| Biomass fuel store | 42 m² | 5.0 m |
|
||||
| Chiller compound: open to the sky, screened, four chiller pads (~4.0 × 2.6 m each) | ~135 m² (12.5 × 10.8 m) | screen ~2.5 m |
|
||||
| Cooling pump and heat-exchanger room | ~40 m² (8 × 5 m) | 4.0 m |
|
||||
|
||||
The boiler hall and the chiller compound are built once for four modules
|
||||
each, and the plant goes in one module at a time as presses arrive
|
||||
([scale](../scale.md#detached-utility-yard-parking-and-what-that-moves)):
|
||||
price the floor, pads, plinths and wall openings for all four now. The
|
||||
sizes are estimates until the boiler and chiller vendors send footprints.
|
||||
Air-cooled chillers need open air, so the earlier "chiller room" is an open
|
||||
compound; the cooling tower pad of the water-cooled concept is deleted (a
|
||||
dry cooler, if bought, gets a pad sized with its quote).
|
||||
|
||||
The 14 m flue stack comes with the boiler — excluded here. The boiler hall
|
||||
envelope should be non-combustible (mineral-wool panels or masonry), not
|
||||
PIR.
|
||||
|
||||
## 3. Site works
|
||||
|
||||
| Item | Quantity |
|
||||
|---|---|
|
||||
| Perimeter wall | **~444 m** boundary, **2.0 m** high block/precast on strip footing (~174 m³) |
|
||||
| Main gate | **One** gate only: piers plus **bi-parting sliding leaves, 10.0 m clear opening** (2 × 5 m). The previously mooted second gate is deleted |
|
||||
| Paving — heavy duty | **1,608 m²** rigid reinforced concrete for laden trucks: truck apron, dock face, internal circulation road, Phase 2 link |
|
||||
| Paving — general | **2,779 m²** lighter hardstanding: car park, yard and margins |
|
||||
| **Paving total** | **4,387 m²** — see note below |
|
||||
| Car/scooter parking | Roofed canopies: **27.7 × 7.0 m (195 m², 10 cars)** + **13.7 × 5.5 m (76 m², 30 scooters)**, steel canopy built **PV-ready** for ~40 kWp (structure for the panels' dead load and uplift, conduit to the main board); panels later, not in this contract |
|
||||
| Guard house | **12 m² (4 × 3 m)**, insulated/AC'd, with toilet; sited at the gate, north-west side |
|
||||
| Tank foundations | Ring foundation for a **9 m dia × 4 m** fire water tank (**~250 m³, ~250 t full** — the geometry gives 254 m³ gross; if 200 m³ usable with freeboard is intended, the foundation still carries the full 250 t) sited in the **north-west corner of the plot**, with the **fire pump house adjacent to it**; plus a **5 m dia × 3 m** raw water tank. Tanks themselves are vendor-supplied bolted panels — foundations only |
|
||||
| Fire main | Ring main runs from the north-west corner to the buildings — quote the **length**, not just "a ring main" |
|
||||
| Drainage & sanitation | Site stormwater drainage, domestic septic/treatment for ~25 staff — **see note below** |
|
||||
|
||||
**On the paving quantity.** This is a deliberate increase: the site is now
|
||||
paved continuously from the road frontage through to the Phase 2 building.
|
||||
At 4,387 m² it is roughly 2.5× the 1,500–2,000 m² this sheet previously
|
||||
carried, and it becomes one of the larger civil numbers in the package. Two
|
||||
things follow:
|
||||
|
||||
- The two paving classes are quoted separately on purpose. Do **not** price
|
||||
the whole 4,387 m² at truck spec.
|
||||
- Roughly the last third of the general paving is the Phase 2 approach,
|
||||
which will be dug up again for Phase 2 piling and foundations. **Option to
|
||||
price:** compacted sub-base only now, surfaced after Phase 2 completes.
|
||||
|
||||
**On drainage.** 4,387 m² of pavement is about 46 % of the 9,567 m² plot,
|
||||
but the figure that matters for attenuation is the **total sealed area**:
|
||||
adding the main building (1,500 m²), utility yard (~379 m²), guard house
|
||||
(12 m²) and parking canopies (271 m²) gives **~6,549 m², or 68 % of the
|
||||
plot**. Quote the contractor that number, not the paving one.
|
||||
Runoff increases materially over the agricultural baseline, and
|
||||
stormwater attenuation — quite possibly a detention pond — may be required
|
||||
for the factory permit. Ask the contractor to state what they have assumed.
|
||||
|
||||
## 4. Exclusions
|
||||
|
||||
State these so the number is clean: process machinery, PV system, HVAC
|
||||
plant, chiller/boiler/tanks themselves, sprinkler system, internal fit-out,
|
||||
transformer (PEA), and land works beyond normal grading.
|
||||
|
||||
## 5. Questions the contractor will ask
|
||||
|
||||
- **Soil conditions**: unknown — the plot is agricultural land in Mueang
|
||||
Chi, Lamphun, likely soft former paddy. A soil boring test (~30–50k THB)
|
||||
comes before any real number. For rough pricing, ask them to assume
|
||||
soft-to-medium Lamphun valley soil and to **state the foundation
|
||||
assumption they price** (footings vs driven piles; a piled slab can add
|
||||
several hundred to 1,000+ THB/m²). The soil, not the slab spec, is the
|
||||
main price risk in the whole package, and it now applies to 4,387 m² of
|
||||
pavement and a 1,711 m³ fill platform as well as the building.
|
||||
- **Tank proximity to the building**: the fire water tank sits about 4.5 m
|
||||
from the main building. Full, it is ~250 t on a 9 m ring foundation. On
|
||||
soft ground, ask whether they price a deeper tank foundation, ground
|
||||
improvement, or want the tank moved further off.
|
||||
- **Panel core**: PIR general with mineral wool at compartment and acoustic
|
||||
walls (§1a) — separate rate per m², and any frame implications.
|
||||
- **Sprinklers**: OH2 sprinkler system, ring main, and hydrants are planned
|
||||
but not designed (see [facility security](../facility-security.md)). Ask
|
||||
whether they price it or use a specialist sub — quoted separately either
|
||||
way.
|
||||
- **Racking height** in the warehouse zone: undecided; drives the fire
|
||||
design, not the shell, but they may ask.
|
||||
- **Crane**: achievable hook height at the 7.0 m eave, the frame premium
|
||||
for crane loads, and whether they supply the crane or price a
|
||||
specialist sub (§1c).
|
||||
- **Permits**: ask whether the price includes permit drawings by a licensed
|
||||
engineer for the building permit and Ror.Ngor. 4 factory license — rough
|
||||
shell prices usually don't.
|
||||
|
||||
## 6. What to ask for back
|
||||
|
||||
- **THB/m² rough range for the PEB shell** at the insulated-panel spec
|
||||
above — not the bare-shed spec
|
||||
- Separate rates for **heavy-duty** and **general** paving
|
||||
- A separate rate for **mineral-wool core** panel
|
||||
- The **crane package** separately: runway and frame premium, machine
|
||||
door, the crane itself, and the hook height they achieve
|
||||
- A lump figure for the rest of the site works
|
||||
- The foundation/geotech assumption behind all of it
|
||||
|
||||
That is enough to sanity-check against the ~24–42M THB Thai-sourced
|
||||
utilities baseline in the [utilities CSV](utilities-investment.csv);
|
||||
building construction is currently an unpriced line in
|
||||
[scale](../scale.md).
|
||||
|
After Width: | Height: | Size: 186 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 174 KiB |
@@ -0,0 +1,458 @@
|
||||
# Share price for the 40 % on offer: market-based ranges (October 2026)
|
||||
|
||||
What a share in the plant company could cost the co-investors who take up
|
||||
the 40 % beside the lead investor, and what it could be worth once the
|
||||
plant runs, worked from public market data (dated and linked below) and
|
||||
the plan's own figures. The basis is the funding decision of 20 October
|
||||
2026: **the shareholders fund the whole plant as share capital, with no
|
||||
bank loan**. **This page is not a valuation opinion and not an offer
|
||||
price.** Every result is an estimate or an illustration, given as a range
|
||||
or as scenarios; the share price itself is for the shareholders'
|
||||
agreement (business plan B, section 12.2). Computed 20 October 2026.
|
||||
|
||||
Owning documents: [total investment](total-investment.md#two-plans-a-at-180m-thb-and-b-at-215m-thb-october-2026)
|
||||
(plans, shareholding and the Funding paragraph), [revenue model](revenue-model.md#operating-pictures-of-plan-a-and-plan-b-october-2026)
|
||||
(operating pictures), [BOI](../boi.md) (debt-to-equity and incentives), the
|
||||
[plant and business plan calculator](../fleet-calculator.html) (ten-year
|
||||
cash view) and the [business plan, Plan B](../business-plan/CNX-Vinyl-Business-Plan-B.pdf)
|
||||
(sections 8.3, tranches, and 12.2, ownership and structure).
|
||||
|
||||
## What is decided
|
||||
|
||||
- **Funding** (user, 20 October 2026): **the shareholders fund the whole
|
||||
plant and get shares for it; no bank loan is planned.** Plan B's ~217M
|
||||
THB is paid in as share capital, registered in full and called in
|
||||
instalments against the tranches of business plan section 8.3
|
||||
([total investment, Funding paragraph](total-investment.md#two-plans-a-at-180m-thb-and-b-at-215m-thb-october-2026)).
|
||||
The share price, any founders' or in-kind shares and the call schedule
|
||||
are not agreed.
|
||||
- **Shareholding** (user, 20 October 2026): the lead investor holds **at
|
||||
least 60 %** of the company that holds the plant and the BOI promotion,
|
||||
so **at most 40 % is for sale**. Ploy Printing (intended strategic
|
||||
co-investor, in cash, in kind or both), any founders' shares and any
|
||||
further co-investor all come out of that 40 %
|
||||
([total investment](total-investment.md#two-plans-a-at-180m-thb-and-b-at-215m-thb-october-2026)).
|
||||
On ~217M of share capital at one price that is at least ~130M THB for
|
||||
the lead investor and at most ~87M for the 40 %.
|
||||
- **Plan B is the proposal**: ~217M THB at the midpoint (201.6M before
|
||||
the 10M to 20M ramp-up reserve), labelled ~215M; ~156M to 277M from the
|
||||
low to the high end of every block; no contingency (~30M at 15 % is not
|
||||
in the price). Plan A (~182M) is the comparison only.
|
||||
- **BOI**: debt-to-equity no higher than 3:1 for the life of the
|
||||
privileges. With no debt the ceiling is met with room to spare and no
|
||||
longer sets an equity floor; a loan added later would have to stay
|
||||
within it. Vinyl pressing is expected in incentive **Group B: no
|
||||
corporate income tax holiday on the core activity**; upgrade measures
|
||||
(automation, R&D) may add limited exemptions, to be structured by a BOI
|
||||
consultant ([BOI](../boi.md)). This page uses the 20 % Thai corporate
|
||||
tax rate.
|
||||
- **Operating picture, Plan B, mature year at 60 % specials**
|
||||
([revenue model](revenue-model.md#operating-pictures-of-plan-a-and-plan-b-october-2026)):
|
||||
revenue 2.28 / 3.65 / 5.41M USD, EBITDA 0.23 / 1.73 / 3.79M USD,
|
||||
operating profit -0.55 / 1.24 / 3.50M USD (adverse / central /
|
||||
favourable). The central EBITDA margin (~47 %) is far above the 15 to
|
||||
25 % pressing plants earn, so **the adverse column is the honest one**;
|
||||
the central column is used here only with that caveat.
|
||||
- **Calculator, preset planB** ([fleet-calculator.html](../fleet-calculator.html),
|
||||
read 20 October 2026): ten-year cumulative cash -6.56M to +12.92M USD,
|
||||
cash payback in year ~4.2, IRR ~22 % (22.2 %), NPV ~4.7M USD (4.68M).
|
||||
Its basis, from the page source: discount rate **10 %** (input
|
||||
`discRate`, marked estimate), **pre-tax and pre-financing**, no terminal
|
||||
value, "Corporate income tax and BOI's CIT exemptions ... are not
|
||||
modelled", ramp 35 / 70 / 90 % in years 1 to 3, depreciation over 12.5
|
||||
years. With no loan, pre-financing is the shareholders' own position.
|
||||
- **FX**: 33 THB/USD (planning rate, total investment).
|
||||
- **No loan terms are on file, and no loan is planned.** No interest
|
||||
rate, repayment schedule or debt-service figure appears on this page.
|
||||
The one levered table below ("if a loan were added later") uses the
|
||||
most debt the 3:1 rule would allow, nothing repaid, only to show what
|
||||
leverage would do to the figures; it is not the plan.
|
||||
|
||||
## Thai company law basics
|
||||
|
||||
From the Civil and Commercial Code (Thai text from the Office of the
|
||||
Council of State with English translation on
|
||||
[ThaiLawOnline](https://www.thailawonline.com/thai-civil-code/section-1105/),
|
||||
cross-checked against the Siam Legal library, sections
|
||||
[1096 to 1116](https://library.siam-legal.com/thai-law/civil-and-commercial-code-limited-companies-section-1096-1116/)
|
||||
and [1117 to 1143](https://library.siam-legal.com/thai-law/civil-and-commercial-code-limited-companies-section-1117-1143/);
|
||||
checked 20 October 2026; to be confirmed by Thai counsel in phase 0):
|
||||
|
||||
- **Section 1096**: the shareholders' liability is limited to the amount,
|
||||
if any, unpaid on their shares. Capital registered but not yet called
|
||||
is owed to the company.
|
||||
- **Section 1117**: a share may not be less than **5 THB**. The par value
|
||||
is otherwise free; 100 THB a share is a common choice and is used below
|
||||
as the worked example (not decided).
|
||||
- **Section 1105**: shares **may not be issued below par**. Issuing above
|
||||
par (a share premium) is permitted **only if the memorandum of
|
||||
association sanctions it**, and the premium is paid with the first
|
||||
payment. The **first payment must be at least 25 %** of par.
|
||||
- **Calls on the rest (sections 1120 to 1125)**: unless a general meeting
|
||||
decides otherwise, the directors call the unpaid money (1120), with at
|
||||
least **21 days' notice by registered letter** (1121). A shareholder who
|
||||
misses a call owes interest from the due date (1122); the directors may
|
||||
send a second registered notice with a reasonable deadline that can
|
||||
warn of forfeiture (1123), then declare the shares forfeited (1124);
|
||||
forfeited shares are sold without delay **by public auction**, the
|
||||
proceeds pay the call and interest and any surplus goes back to the
|
||||
shareholder (1125). This is the frame for calling the share capital in
|
||||
instalments against the tranches.
|
||||
- **Section 1108** (amended by Act No. 23 B.E. 2565, in force 7 February
|
||||
2023): the statutory meeting ratifies the promoters' contracts and
|
||||
expenses, fixes any payment to promoters, and fixes the shares to be
|
||||
allotted as paid up **otherwise than in money**; the service or property
|
||||
given for them must be described expressly to the meeting. **Section
|
||||
1119**: otherwise every share is paid in money, and no set-off against
|
||||
the company is allowed. After formation, new shares paid in kind need a
|
||||
special resolution (**section 1221**). This is the route for founders'
|
||||
work, the lead investor's pre-round costs and Ploy Printing's in-kind
|
||||
contribution.
|
||||
- **Section 1220**: capital is increased by special resolution;
|
||||
**section 1222**: all new shares must first be offered to existing
|
||||
shareholders in proportion to their holdings (statutory pre-emption).
|
||||
- **Section 1194** (amended 2008): a special resolution needs **three
|
||||
quarters of the votes of the shareholders present and entitled to
|
||||
vote**. A 60 % holder alone therefore cannot pass one when the 40 %
|
||||
attends: capital increases, in-kind allotments after formation and
|
||||
changes to the memorandum or articles need part of the 40 %.
|
||||
|
||||
## Market data
|
||||
|
||||
Checked 20 October 2026. Damodaran files are the January 2026 release
|
||||
(dated 5 January 2026) under
|
||||
`https://pages.stern.nyu.edu/~adamodar/pc/datasets/`, read with pandas.
|
||||
|
||||
| Item | Value | Source | Data date |
|
||||
|---|---|---|---|
|
||||
| EV/EBITDA, Emerging Markets, firms with positive EBITDA | Packaging & Container **13.3x** (341 firms); Entertainment 14.9x; Machinery 25.0x; Chemical (Specialty) 16.0x; Total Market 12.3x | Damodaran, [vebitdaemerg.xls](https://pages.stern.nyu.edu/~adamodar/pc/datasets/vebitdaemerg.xls) | 5 Jan 2026 |
|
||||
| EV/EBITDA, Global (cross-check) | 9.6x; 18.7x; 16.9x; 13.1x; 14.7x (same order) | [vebitdaGlobal.xls](https://pages.stern.nyu.edu/~adamodar/pc/datasets/vebitdaGlobal.xls) | 5 Jan 2026 |
|
||||
| P/E, aggregate market cap / net income of money-making firms, EM (cross-check) | 18.9x; 18.8x; 35.7x; 24.8x; 16.6x | [peemerg.xls](https://pages.stern.nyu.edu/~adamodar/pc/datasets/peemerg.xls) | 5 Jan 2026 |
|
||||
| P/E, same basis, Global | 16.2x; 27.8x; 27.9x; 21.9x; 20.3x | [peGlobal.xls](https://pages.stern.nyu.edu/~adamodar/pc/datasets/peGlobal.xls) | 5 Jan 2026 |
|
||||
| Unlevered beta corrected for cash, EM | **0.61**; 1.22; 1.50; 1.11; **0.85** | [betaemerg.xls](https://pages.stern.nyu.edu/~adamodar/pc/datasets/betaemerg.xls) | 5 Jan 2026 |
|
||||
| Unlevered beta corrected for cash, Global | 0.58; 0.98; 1.33; 1.04; 0.83 | [betaGlobal.xls](https://pages.stern.nyu.edu/~adamodar/pc/datasets/betaGlobal.xls) | 5 Jan 2026 |
|
||||
| Thailand equity risk premium | **6.18 %** = mature market 4.20 % + country risk premium 1.98 % (Moody's Baa1, rating-based default spread 1.27 %); January 2026 file: 6.30 %; CDS-based alternative 5.04 % | Damodaran, [ctrypremJuly26.xlsx](https://pages.stern.nyu.edu/~adamodar/pc/datasets/ctrypremJuly26.xlsx) | 1 Jul 2026 (spreads corrected 9 Jul) |
|
||||
| Thai corporate income tax | 20 % | same file, "Country Tax Rates" | 2025 |
|
||||
| Thai government bond yield, 10 years | **2.30 %** | ThaiBMA, [government bond yield curve](https://www.thaibma.or.th/compositerpt/GovYieldCurve.aspx) | 19 Oct 2026 |
|
||||
| Illiquidity discount (DLOM) | Restricted-stock studies **25 to 35 %** (Maher 35.4 % mean, 1969 to 1973; Silber 33.75 % median, 1981 to 1988; Johnson 20 %); after controlling for issuer differences Bajaj et al. ~7 %; pre-IPO transactions ~45 % (Emory), 32 to 75 % (Willamette); conventional practice 20 to 30 %; McCord v. Commissioner (2003): court accepted 20 % | Damodaran, [Marketability and Value: Measuring the Illiquidity Discount](https://pages.stern.nyu.edu/~adamodar/pdfiles/papers/liquidity.pdf), pp. 17, 28 to 30, 35 to 36 | July 2005 |
|
||||
| Target returns of venture investors by stage | Start-up 50 to 70 %; **first stage 40 to 60 %**; second stage 35 to 50 %; bridge / IPO 25 to 35 %. Actual returns far lower (20-year early-stage VC 21.4 %, all VC 16.9 %, to 2007), the gap being failure risk | Damodaran, [Valuing Young, Start-up and Growth Companies](https://pages.stern.nyu.edu/~adamodar/pdfiles/papers/younggrowth.pdf), Tables 2 and 3, p. 15 (the paper gives no source line for Table 2) | May 2009 |
|
||||
| SET-listed Thai peers, EV/EBITDA and P/E (secondary market-data site) | SCGP (SCG Packaging) 10.1x, 21.0x, EBITDA margin 14.8 %; TPAC (Thai Plaspac) **4.7x**, 5.5x, margin 18.0 %; SITHAI (Srithai Superware) 3.2x, 7.3x; GRAMMY (GMM Grammy, music and media) 8.6x, 51.9x | stockanalysis.com statistics pages, e.g. [SCGP](https://stockanalysis.com/quote/bkk/SCGP/statistics/), [TPAC](https://stockanalysis.com/quote/bkk/TPAC/statistics/), [SITHAI](https://stockanalysis.com/quote/bkk/SITHAI/statistics/), [GRAMMY](https://stockanalysis.com/quote/bkk/GRAMMY/statistics/) | 19 to 20 Oct 2026 |
|
||||
|
||||
Not used: a bank lending rate. No loan is planned, the methods below need
|
||||
none, and none is on file for this project.
|
||||
|
||||
## Method
|
||||
|
||||
All amounts in M THB unless stated; EBITDA converted at 33 THB/USD.
|
||||
Multiples are used unrounded (4.69x, 13.33x, 14.92x), so a hand check with
|
||||
the rounded figures can differ by 1 or 2 THB a share.
|
||||
|
||||
- **A. Founding round at par, pari passu, all equity.** Everyone pays the
|
||||
same price, par, in money (or in kind at the same value). Share capital
|
||||
= the plan price; shares = capital / 100 THB; the lead investor's 60 %
|
||||
and the 40 % in shares and THB. Plan B at ~217M, Plan B before the
|
||||
reserve (201.6M) and Plan A (~182M) as the comparison. The capital is
|
||||
registered in full and called in instalments: at least 25 % on
|
||||
subscription (section 1105), the rest by the directors (section 1120)
|
||||
against the tranche gates of business plan section 8.3.
|
||||
- **B. Development premium.** Work and money spent before the round
|
||||
(phase 0 at 1.3M to 2.6M THB; design, vendor work, the platform
|
||||
software) credited as a pre-money value P of 0, 1.3, 2.6, 5, 10 or 20M.
|
||||
The new cash C is Plan B's 217M. Post-money = P + C. With the share
|
||||
count held at the par case (2,170,000), the cash pays (P + C) /
|
||||
2,170,000 a share, the developers receive P / that price in shares paid
|
||||
otherwise than in money, and the 40 % costs 0.4 x (P + C). A pre-money
|
||||
credit and shares at par for the same amount give the same ownership;
|
||||
the table shows it as a price because that is how a co-investor sees it.
|
||||
- **C. Value once the plant runs** (mature year, ~year 4 to 5).
|
||||
Enterprise value = mature-year EBITDA x EV/EBITDA; **net debt 0**, so
|
||||
equity value = enterprise value; minority stake in a private company:
|
||||
less a 20 to 35 % illiquidity discount (the restricted-stock range and
|
||||
the court's 20 %); per share on the 2,170,000 shares. No cash is netted
|
||||
either: cash the plant earns by then is assumed paid out or spent on
|
||||
growth (the second Duplex is funded from revenue); cash kept in the
|
||||
company would add to every value. Three multiples: **4.7x**, the median
|
||||
of the three SET-listed plastics and packaging peers (TPAC, SITHAI,
|
||||
SCGP); **13.3x**, Emerging Markets Packaging & Container, the closest
|
||||
industry; **14.9x**, the median of the five EM industries (Machinery's
|
||||
25.0x reflects machine builders and is not used on its own). EBITDA:
|
||||
adverse, central, favourable, plus a cross-check at an industry-norm
|
||||
margin: 20 % (the middle of the 15 to 25 % in the revenue model; the SET
|
||||
peers earn 15 to 18 %) of central revenue, 0.73M USD. One sensitivity
|
||||
table shows the same cases if a loan were added later at the 3:1
|
||||
ceiling (equity 54.25M, 542,500 shares, debt 162.75M, nothing repaid).
|
||||
- **D. Price a financial co-investor would pay today (venture-capital
|
||||
method).** Post-money value today = equity value in year 5 from C
|
||||
(net debt 0), before the illiquidity discount (the target returns
|
||||
already price illiquidity and failure), divided by (1 + r) to the
|
||||
fifth. Pre-money = post-money minus the 217M paid in; the justified
|
||||
price per share = 100 THB x post-money / 217M. **Stage: first stage, 40
|
||||
to 60 %.** The technology is proven (vendor presses, galvanics and
|
||||
cutting lines in use elsewhere) and the product is known, so this is
|
||||
not a start-up inventing a product; but there is no plant, no customer
|
||||
and no validated price (roadmap item 1 is open), so it is not second
|
||||
stage. Start-up rates (50 to 70 %) apply if market validation fails to
|
||||
produce buyer prices; second-stage rates once the plant runs and sells.
|
||||
Cross-check: a CAPM cost of equity, 2.30 % + beta x 6.18 %, with the EM
|
||||
**unlevered** beta as it stands (no debt, so no relevering): Packaging
|
||||
& Container 0.61, cost of equity **6.1 %**; Total Market 0.85, **7.5 %**.
|
||||
CAPM prices market risk only: nothing for size, illiquidity or a plant
|
||||
not yet built, which is what the gap to the venture targets measures.
|
||||
The 10-year yield contains Thailand's default spread; netting it out,
|
||||
as Damodaran does, would lower both by about 1.3 points, so the gross
|
||||
yield is the cautious choice.
|
||||
- **E.** The calculator's project return, which with no loan is also the
|
||||
shareholders' return, against these rates.
|
||||
|
||||
## Results
|
||||
|
||||
### A. Founding round at par, pari passu, all equity (estimate)
|
||||
|
||||
| Case | Share capital | Shares at 100 THB | Lead investor, 60 % | Co-investors, 40 % | 25 % first payment (40 %'s part) |
|
||||
|---|---|---|---|---|---|
|
||||
| **Plan B, all equity** (~217M) | **217.0M** | **2,170,000** | 1,302,000 shares, **130.2M** | 868,000 shares, **86.8M** | 54.25M (21.7M) |
|
||||
| Plan B before the reserve | 201.6M | 2,016,000 | 1,209,600 shares, 121.0M | 806,400 shares, 80.6M | 50.4M (20.2M) |
|
||||
| Plan A, all equity (comparison) | 182.0M | 1,820,000 | 1,092,000 shares, 109.2M | 728,000 shares, 72.8M | 45.5M (18.2M) |
|
||||
|
||||
The price is **100 THB a share in every row**; a larger plan means more
|
||||
shares, not a different price. At the legal minimum par of 5 THB Plan B
|
||||
would be 43,400,000 shares at 5 THB: the same money for the same 40 %. In
|
||||
practice the registered capital is set to a round figure. The 40 % at
|
||||
par, ~86.8M THB, matches the plan's "at most ~87M" (total investment,
|
||||
Funding paragraph; business plan 12.2).
|
||||
|
||||
**Which calls fall when** (illustrative; the calls follow the actual
|
||||
tranche releases). The tranche shares of business plan section 8.3 are
|
||||
ranges of the 201.6M before the reserve; the reserve is drawn from
|
||||
tranche 4 on. Phase 0 (tranche 0) is spent before the company exists: in
|
||||
the project calendar the company is incorporated after the BOI
|
||||
certificate, so the promoters pay phase 0 and the statutory meeting
|
||||
ratifies it (section 1108), reimbursed from the first call or credited as
|
||||
shares at par (B).
|
||||
|
||||
| Call | When | Tranche need, M THB (share of 217M) | Call, share of 217M | Call, M THB | Lead investor, 60 % | The 40 % |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 1 | On subscription, at incorporation: tranche 1 (BOI certificate, lease, zoning, soil, pricing validated) with phase 0 | 41.6 to 63.1 (19 to 29 %) | **25 %**, the legal minimum | 54.25 | 32.55 | 21.70 |
|
||||
| 2 | Tranche 2: building permit, vendor build dates in writing | 70.6 to 90.7 (33 to 42 %) | 40 % | 86.80 | 52.08 | 34.72 |
|
||||
| 3 | Tranche 3: building watertight, first machinery shipped | 30.2 to 40.3 (14 to 19 %) | 20 % | 43.40 | 26.04 | 17.36 |
|
||||
| 4 | Tranche 4: metal path commissioned, first stampers; the reserve | 26.1 to 44.2 (12 to 20 %) | 15 % | 32.55 | 19.53 | 13.02 |
|
||||
| | **Total** | | **100 %** | **217.00** | **130.20** | **86.80** |
|
||||
|
||||
The 25 / 40 / 20 / 15 split is one fit to the tranche ranges, rounded to
|
||||
add up to 100 %; it is arithmetic, not a schedule. If tranche 1 lands at
|
||||
its high end, the first payment is set above the 25 % minimum (~29 %) or
|
||||
the second call comes forward. Each call needs at least 21 days' notice
|
||||
(section 1121), so a call goes out three weeks before the money is due
|
||||
to a vendor.
|
||||
|
||||
### B. Development premium (illustrative)
|
||||
|
||||
New cash 217M (all equity); share count held at 2,170,000.
|
||||
|
||||
| Pre-money credited | Post-money | Price the cash pays | Premium over par | Shares to the developers (share of company) | The 40 % costs |
|
||||
|---|---|---|---|---|---|
|
||||
| 0 (par) | 217.0M | 100 THB | 0 % | 0 | 86.8M |
|
||||
| 1.3M (phase 0, low end) | 218.3M | 100.6 THB | 0.6 % | 12,923 (0.6 %) | 87.3M |
|
||||
| 2.6M (phase 0, high end) | 219.6M | 101.2 THB | 1.2 % | 25,692 (1.2 %) | 87.8M |
|
||||
| 5M | 222.0M | 102 THB | 2.3 % | 48,874 (2.3 %) | 88.8M |
|
||||
| 10M | 227.0M | 105 THB | 4.6 % | 95,595 (4.4 %) | 90.8M |
|
||||
| 20M | 237.0M | 109 THB | 9.2 % | 183,122 (8.4 %) | 94.8M |
|
||||
|
||||
On a 217M round the pre-round work is a small share of the company: the
|
||||
phase 0 rows come to 0.6 to 1.2 %. A premium must still rest on
|
||||
documented costs or assets: invoices for the phase 0 work, time records at
|
||||
an agreed rate, the platform code and designs handed to the company.
|
||||
Money already spent on the company's behalf is most simply counted as
|
||||
capital at par or reimbursed as a promoter's expense ratified at the
|
||||
statutory meeting (section 1108); either way it gives the same 0.6 to
|
||||
1.2 %. Credit beyond documented spending is a valuation of work and needs
|
||||
a basis the other shareholders accept. Whose credit it is matters for the
|
||||
60/40: founders' in-kind shares come out of the 40 % (at 10M they would be
|
||||
4.4 % of the company, leaving 35.6 % for Ploy Printing and others), the
|
||||
lead investor's out of the 60 %. **For a company without a plant or
|
||||
revenue, the defensible default is par.**
|
||||
|
||||
### C. What a share could be worth once the plant runs (estimate)
|
||||
|
||||
Mature year, **net debt 0** (all equity), 2,170,000 shares paid at 100
|
||||
THB. Each cell: enterprise value, which is also the equity value; value
|
||||
per share after a 35 % to 20 % illiquidity discount; in brackets, the
|
||||
multiple on the 100 THB paid.
|
||||
|
||||
| Mature-year EBITDA | Thai listed peers, 4.7x | EM packaging, 13.3x | EM industry median, 14.9x |
|
||||
|---|---|---|---|
|
||||
| **Adverse**, 0.23M USD (7.6M THB) | 35.6M: **11 to 13 THB** (0.1x) | 101.2M: **30 to 37 THB** (0.3 to 0.4x) | 113.2M: **34 to 42 THB** (0.3 to 0.4x) |
|
||||
| Industry-norm margin, 20 % of central revenue, 0.73M USD (24.1M THB) | 113.0M: 34 to 42 THB (0.3 to 0.4x) | 321.1M: 96 to 118 THB (1.0 to 1.2x) | 359.4M: 108 to 133 THB (1.1 to 1.3x) |
|
||||
| Central, 1.73M USD (57.1M THB) | 267.8M: **80 to 99 THB** (0.8 to 1.0x) | 761.0M: 228 to 281 THB (2.3 to 2.8x) | 851.8M: 255 to 314 THB (2.6 to 3.1x) |
|
||||
| Favourable, 3.79M USD (125.1M THB) | 586.6M: 176 to 216 THB (1.8 to 2.2x) | 1,667.2M: 499 to 615 THB (5.0 to 6.1x) | 1,866.0M: 559 to 688 THB (5.6 to 6.9x) |
|
||||
|
||||
What this means, plainly:
|
||||
|
||||
- **Without a loan the shares keep some value in the adverse case, but
|
||||
lose most of it**: 11 to 42 THB for every 100 THB paid, a loss of 58 to
|
||||
89 %. Nothing is owed ahead of the shareholders, so the plant's value
|
||||
is theirs; at the adverse EBITDA that value is small.
|
||||
- **At Thai listed multiples even the central case is below par** (80 to
|
||||
99 THB), and so is an industry-norm margin at that multiple (34 to 42);
|
||||
at the EM multiples the industry-norm margin is about par (96 to 133
|
||||
THB). Only the central case at an EM-industry multiple (2.3 to 3.1x)
|
||||
and the favourable case (1.8 to 6.9x) put a share clearly above what
|
||||
was paid.
|
||||
- **The large multiples of the earlier version of this page (7 to 25x
|
||||
par) came from leverage**, not from the plant: with three quarters
|
||||
borrowed, the same enterprise value, less the debt, was spread over a
|
||||
quarter of the shares. The table below shows that case.
|
||||
- The choice of multiple moves the result more than anything else: Thai
|
||||
listed plastics and packaging companies trade at 3 to 10x EBITDA, the
|
||||
EM industries at 12 to 25x.
|
||||
|
||||
**If a loan were added later (sensitivity, not the plan).** Equity at the
|
||||
3:1 ceiling, 54.25M (542,500 shares at 100 THB), debt 162.75M, nothing
|
||||
repaid, no loan terms assumed; value per share after the discount:
|
||||
|
||||
| Mature-year EBITDA | 4.7x | 13.3x | 14.9x |
|
||||
|---|---|---|---|
|
||||
| Adverse | ~0 (equity -127.2M) | ~0 (equity -61.6M) | ~0 (equity -49.5M) |
|
||||
| Industry-norm margin | ~0 (equity -49.8M) | 190 to 234 THB (1.9 to 2.3x) | 236 to 290 THB (2.4 to 2.9x) |
|
||||
| Central | 126 to 155 THB (1.3 to 1.5x) | 717 to 882 THB (7.2 to 8.8x) | 826 to 1,016 THB (8.3 to 10.2x) |
|
||||
| Favourable | 508 to 625 THB (5.1 to 6.3x) | 1,803 to 2,219 THB (18 to 22x) | 2,041 to 2,512 THB (20 to 25x) |
|
||||
|
||||
Leverage multiplies the good cases and wipes the shares out in the bad
|
||||
ones: the adverse case and an industry-norm margin at Thai listed
|
||||
multiples leave nothing for the shareholders once the debt is repaid,
|
||||
where all equity leaves 11 to 42 THB. Any interest and repayment would
|
||||
change these values either way; none is assumed.
|
||||
|
||||
### D. What a financial co-investor would pay today (estimate)
|
||||
|
||||
Year-5 equity value from C (net debt 0, before the illiquidity discount),
|
||||
discounted over five years. Price per share justified against par (100
|
||||
THB); a price above 100 means the round could carry a premium at that
|
||||
return, below 100 means par is already rich.
|
||||
|
||||
| Year-5 equity, central case | First stage 40 % | First stage 60 % | CAPM 6.1 % | CAPM 7.5 % |
|
||||
|---|---|---|---|---|
|
||||
| 4.7x, 267.8M | post-money 49.8M, **23 THB** | 25.5M, **12 THB** | 199.3M, 92 THB | 186.2M, 86 THB |
|
||||
| 13.3x, 761.0M | 141.5M, **65 THB** | 72.6M, **33 THB** | 566.5M, 261 THB | 529.1M, 244 THB |
|
||||
| 14.9x, 851.8M | 158.4M, **73 THB** | 81.2M, **37 THB** | 634.0M, 292 THB | 592.2M, 273 THB |
|
||||
|
||||
Other cases at the first-stage rates (40 % / 60 %): **adverse 3 / 2 THB
|
||||
at 4.7x, 9 / 4 at 13.3x, 10 / 5 at 14.9x**; industry-norm margin 10 / 5,
|
||||
28 / 14 and 31 / 16 THB; favourable 50 / 26 THB at 4.7x, 143 / 73 at
|
||||
13.3x, 160 / 82 at 14.9x. So a purely financial investor at first-stage
|
||||
target returns would pay **below par in every case but one**: the
|
||||
favourable case at an EM multiple and the lower 40 % rate (143 to 160
|
||||
THB). In the central case it would pay 12 to 73 THB, in the adverse case
|
||||
2 to 10. Pre-money values are negative wherever the price is below 100
|
||||
(for example -75.5M at 13.3x and 40 % in the central case). At the CAPM
|
||||
cost of equity, which prices market risk only, the central case is
|
||||
worth 86 to 292 THB today and the adverse case 11 to 39 THB. Ploy
|
||||
Printing as a supplier and the founders as operators have reasons to
|
||||
hold at par that a purely financial investor does not.
|
||||
|
||||
### E. Cross-check with the calculator
|
||||
|
||||
With no loan, **the shareholders' return is the project return**: the
|
||||
calculator's ~22 % IRR (pre-tax, no terminal value) and ~4.7M USD NPV at
|
||||
its 10 % discount rate are what the 217M of share capital (6.56M USD in
|
||||
year 0) earns before tax on the calculator's picture. That clears the
|
||||
CAPM cost of equity (6.1 to 7.5 %) and the calculator's 10 %, is close to
|
||||
the returns venture funds actually earned (16.9 to 21.4 %, Damodaran
|
||||
Table 3), and sits well below the 40 to 60 % first-stage targets, so the
|
||||
calculator alone would not support a premium to a financial investor.
|
||||
The 20 % corporate income tax (Group B, no CIT holiday on the core
|
||||
activity) lowers it: a rough check, tax on the calculator's yearly cash
|
||||
less straight-line depreciation over its 12.5 years (0.49M USD a year),
|
||||
gives **~18 % after tax** (estimate). The calculator's cash view is
|
||||
itself well above the revenue model's central EBITDA (2.23M against
|
||||
1.73M USD), so this return is not the honest case either; in the adverse
|
||||
case EBITDA pays the price back in ~37 years (revenue model).
|
||||
|
||||
## What it means
|
||||
|
||||
- **A founding round pari passu at par is the defensible default.** Until
|
||||
the plant exists, a share is worth the cash behind it. At par (100 THB)
|
||||
the 40 % is 868,000 shares for ~86.8M THB of Plan B's ~217M share
|
||||
capital, and the lead investor's 60 % is 1,302,000 shares for ~130.2M,
|
||||
the same price for everyone. The memorandum needs no premium clause for
|
||||
this.
|
||||
- **A development premium only for documented costs or assets.** Phase 0
|
||||
money (1.3M to 2.6M THB) is 0.6 to 1.2 % of a 217M round and is most
|
||||
simply counted as capital at par. Anything above documented spending
|
||||
is a valuation of work; in-kind shares need their description before
|
||||
the statutory meeting (section 1108) or a special resolution later
|
||||
(section 1221), and a premium needs the memorandum's sanction (section
|
||||
1105).
|
||||
- **Later entrants pay a market-based price.** Once the plant runs and
|
||||
its accounts show the real EBITDA, the market multiples put a share
|
||||
anywhere from a tenth of par to several times par, so shares issued
|
||||
after the founding round should be priced from results (C and D with
|
||||
actual figures), not at par. Statutory pre-emption (section 1222) lets
|
||||
the founding shareholders keep their share of such a round.
|
||||
- **The 40 % now carries four times the money, and needs protection to
|
||||
match.** All-equity funding puts ~86.8M THB into the 40 % instead of
|
||||
~21.7M at the old 3:1 floor, with no lender ahead of it; the adverse
|
||||
case still loses most of it, while the lead investor controls 60 % of
|
||||
the votes. Items for the shareholders' agreement: keep statutory
|
||||
pre-emption and do not waive it in the articles; information rights
|
||||
(monthly management accounts, the BOI progress and annual reports, the
|
||||
evidence for each tranche gate before its call); a board seat or
|
||||
observer for the 40 %; reserved matters; and keep the three-quarters
|
||||
threshold for special resolutions (section 1194), which already gives
|
||||
the 40 % a say on capital increases, in-kind allotments and changes to
|
||||
the memorandum.
|
||||
- **The call schedule belongs in the agreement.** The directors make the
|
||||
calls (section 1120) and the 60 % appoints most of them, so the
|
||||
agreement should tie each call to its tranche gate (business plan 8.3),
|
||||
make every call pro rata to all shareholders on the same date, and say
|
||||
what happens when a shareholder misses one. The Code's route is
|
||||
interest from the due date (section 1122), a second notice that can
|
||||
warn of forfeiture (1123), forfeiture (1124) and a public auction of
|
||||
the forfeited shares, the surplus returned (1125). The agreement can
|
||||
add who may take up a missed call or the forfeited shares first, so a
|
||||
stake does not pass to an outside bidder, and evidence that each
|
||||
shareholder can meet its calls: the lead investor carries 60 % of each
|
||||
one (~52M THB at the second call), so a missed call there would stall
|
||||
the build.
|
||||
|
||||
## Caveats
|
||||
|
||||
- **Not a valuation opinion, not an offer price.** Ranges and scenarios
|
||||
from public data and the plan's estimates, for discussion. No share
|
||||
price is agreed; it goes into the shareholders' agreement.
|
||||
- **No loan is planned and no loan terms are on file.** The levered table
|
||||
in C is a sensitivity at the most the 3:1 rule allows; no interest
|
||||
rate, schedule or debt-service figure is assumed.
|
||||
- **The extra cost of specials is not modelled** in the revenue model's
|
||||
direct cost, so every EBITDA here is an upper bound until compound
|
||||
quotes exist.
|
||||
- **Central is optimistic, adverse is honest.** The central EBITDA margin
|
||||
(~47 %) is far above the 15 to 25 % pressing plants earn and the 15 to
|
||||
18 % of the SET peers; the industry-norm row shows the difference.
|
||||
- **Contingency is not in the price.** At 15 % (~30M THB), an overrun
|
||||
funded by the shareholders at par adds ~300,000 shares at 100 THB
|
||||
(pro rata, the 60/40 holds) and lowers every per-share value in C and D
|
||||
by about an eighth; funded by a loan, it would add net debt instead.
|
||||
- **Cash is not counted.** Net debt 0 nets no cash: cash the plant earns
|
||||
before year 5 is assumed paid out (a return of its own, not in C) or
|
||||
spent on growth; cash kept in the company adds to the values.
|
||||
- **Market multiples are for listed companies**, most of them far larger
|
||||
than this plant; a small private company would usually be priced below
|
||||
them (estimate). The illiquidity discount covers part of that, not all.
|
||||
Damodaran's Emerging Markets set (27,360 firms) spans many countries and
|
||||
is not a Thai benchmark; the Thai listed peers are only three plastics
|
||||
and packaging companies, read from a secondary market-data site.
|
||||
- **Taxes and BOI**: EV/EBITDA is a pre-tax measure; the calculator is
|
||||
pre-tax. The after-tax return in E assumes no CIT holiday on the core
|
||||
activity (Group B, [BOI](../boi.md)); any upgrade-measure exemption
|
||||
would raise it somewhat.
|
||||
- **Timing**: year 5 after the round is the plant's third or fourth year
|
||||
of sales (the build takes ~1.5 to 2 years), so a mature-year EBITDA by
|
||||
then is itself optimistic; each extra year of delay divides D's values
|
||||
by a further 1.4 to 1.6 at the first-stage rates. The calculator puts
|
||||
all 6.56M USD in year 0; calling the capital over the build changes the
|
||||
IRR a little either way.
|
||||
- **Law**: the Code summaries are from English translations checked
|
||||
against the Thai text online; Thai counsel confirms them in phase 0,
|
||||
along with the call and forfeiture mechanics in the articles and how
|
||||
BOI counts in-kind capital.
|
||||
@@ -4,40 +4,324 @@ Everything priced or estimated so far, rolled into one view. Blocks marked
|
||||
"estimate" have no vendor confirmation; the rest trace to quotes or the
|
||||
researched ranges in this repo. Treat all figures as budgetary with a wide
|
||||
margin (plus or minus 30 to 50% on the estimates) until RFQs replace them.
|
||||
FX: ~38 THB/EUR. Compiled July 2026.
|
||||
|
||||
## Full vision, all blocks
|
||||
**Currency: USD and THB.** FX at 5 August 2026: **1 USD = 33 THB**.
|
||||
Vendor quotes issued in another currency are kept in that currency
|
||||
wherever they appear next to their source document, and converted here at
|
||||
**1 EUR = 1.155 USD** and **1 GBP = 1.35 USD**. Original figures compiled
|
||||
July 2026; the underlying THB estimates are unchanged, because EUR/THB at
|
||||
~38 is where it was when they were made.
|
||||
|
||||
| Block | Low (EUR) | High (EUR) | Basis |
|
||||
## Launch plant (October 2026)
|
||||
|
||||
Decided (user, October 2026): the plant launches **with everything in one
|
||||
capital round**, commissioned in sequence, with no bridge stampers and no
|
||||
outsourced cutting:
|
||||
|
||||
- one **Newbilt Duplex** system: two HRP 12 semi-automatic presses, an
|
||||
EX 50 main and an EX 35 colour extruder
|
||||
([pressing line](../equipment/pressing-line.md));
|
||||
- one **Newbilt Classic** fully automatic press;
|
||||
- one **Pheenix Alpha** galvanics line (PASU, PPPU, one PDPU, PMPB) with
|
||||
zero-discharge water treatment
|
||||
([galvanics and stamper prep](../equipment/galvanics.md));
|
||||
- the **Sibert** stamper-prep line (VSF, VSP, VSC);
|
||||
- a **Sillitoe SDMS** cutting room
|
||||
([vendor landscape](../suppliers/vendor-landscape.md#mastering-and-cutting-sillitoe-audio-technology-australia));
|
||||
- the **modular steam and cooling plant**: two 500 kg/h boiler modules and
|
||||
two 250 kW chiller modules, in a boiler hall and a chiller compound
|
||||
built for four each ([scale](../scale.md#utility-phasing-backbone-once-modules-with-the-presses)).
|
||||
|
||||
Cassette and CD-R duplication stay in. The second Duplex system and the
|
||||
further Classics are growth options with room reserved, not in this
|
||||
investment. Three presses make roughly 0.7 to 0.95 million records a year
|
||||
on two shifts (estimate: the [scale](../scale.md) basis gives ~0.71 to
|
||||
0.97 million, the planning rates of the
|
||||
[fleet calculator](../fleet-calculator.html) ~0.94 million).
|
||||
|
||||
| Block | USD | THB | Basis |
|
||||
|---|---|---|---|
|
||||
| Newbilt semi-auto line, full Duplex | 300,000 | 320,000 | 2024 quote 200,500 + quoted 2nd press/extruder ~100,000; expired, needs re-quote |
|
||||
| 2 automated presses (Pheenix AD12) | 500,000 | 800,000 | unverified ~$340k/press indicative + delivery and commissioning |
|
||||
| Galvanics line (Digital Matrix) | 280,000 | 560,000 | six-figure-USD turnkey inference from vendor research |
|
||||
| Zero-discharge water treatment (ZLD) | 80,000 | 210,000 | utilities CSV option row, 3-8M THB |
|
||||
| Stamper prep (Sibert VSP, VSF, VSC) | 50,000 | 150,000 | estimate, pricing unpublished |
|
||||
| Mastering and cutting room (Agnew lathe and head, cutter amps, console, room treatment) | 250,000 | 500,000 | estimate, bespoke market |
|
||||
| Metrology and QC stack (confocal, profiler, XRF, inline vision, audio station) | 300,000 | 700,000 | estimate, phaseable |
|
||||
| Utilities, solar, HVAC, racking baseline | 630,000 | 1,100,000 | reviewed utilities CSV, 23.98-41.63M THB |
|
||||
| Building ~1,500 m² plus civil works | 560,000 | 950,000 | estimate at 12,000-20,000 THB/m² Thai industrial construction plus ~20% site works |
|
||||
| Land 6-8 rai, if purchased | 315,000 | 840,000 | estimate at 2-4M THB/rai industrial; leasing cuts this to near zero upfront |
|
||||
| Traceability and factory software | 50,000 | 150,000 | estimate |
|
||||
| Freight, installation, training (non-Newbilt equipment) | 100,000 | 200,000 | estimate |
|
||||
| Working capital, PVC stock, spares | 100,000 | 200,000 | estimate |
|
||||
| Subtotal | ~3,500,000 | ~6,700,000 | |
|
||||
| Contingency 15% | ~500,000 | ~1,000,000 | |
|
||||
| **Total, full vision** | **~4,000,000** | **~7,700,000** | **~150M to 290M THB** |
|
||||
| Phase 0: BOI consultant, legal and lease work, soil test, re-quotes | 40k – 80k | 1.3M – 2.6M | estimate |
|
||||
| Newbilt Duplex system (two HRP 12, EX 50 + EX 35, trimmer, label oven, shrink wrapper, grinder, label punch) | 350k – 370k | 11.6M – 12.2M | 2024 quote EUR 200,500 for the Single 2.1 plus the quoted second press and extruder ~USD 115k; expired, re-quote |
|
||||
| Newbilt Classic | 290k – 460k | 9.6M – 15.2M | placeholder (the old AD12 band per press); **no Newbilt price on file** |
|
||||
| Pheenix galvanics line (PASU, PPPU, PDPU, PMPB) | 324k – 445k | 10.7M – 14.7M | **OMS's reference plus 20 %** (user, October 2026): OMS's 4-cell wet room with the know-how transfer, EUR 234k to 321k (~USD 270k to 371k, [galvanics](../equipment/galvanics.md#oms-introduction-letter-9-october-2026)), as the price basis for the Pheenix line; **no Pheenix price on file** (was 320k to 650k, estimate) |
|
||||
| Galvanics water: ZLD evaporator and DI water | 97k – 258k | 3.2M – 8.5M | [utilities CSV](utilities-investment.csv) rows, now launch scope |
|
||||
| Water-treatment building next to galvanics (~12 × 10 m, proposed) | 52k – 87k | 1.7M – 2.9M | estimate at the building rate below |
|
||||
| Sibert VSF, VSP, VSC | 250k | 8.3M | Sibert's budget confirmation, 5 October 2026; its time, spares, shipping and travel in the freight and working-capital lines |
|
||||
| Cutting room: Sillitoe SDMS, spare cutterhead and support, mastering console and chain, monitoring, room build-out | 200k – 350k | 6.6M – 11.6M | SDMS list price USD 125k (ex tax and shipping); the rest estimate |
|
||||
| Metrology and QC stack (XRF, laser confocal, wide-area profiler, inline vision on three presses, audio station) | 350k – 810k | 11.6M – 26.7M | estimate, phaseable ([quality automation](../quality-automation.md)) |
|
||||
| PVC lab, day-one tier | 55k – 150k | 1.8M – 5.0M | estimate, [quality automation](../quality-automation.md) |
|
||||
| Utilities, steam, solar, battery, HVAC, clean zones, racking | 1,045k – 1,764k | 34.5M – 58.2M | [utilities CSV](utilities-investment.csv) baseline re-sized for three presses: chiller bank two modules instead of three; **biomass steam** (two 500 kg/h modules, 6M to 10M THB, plus the fuel store and handling, 1M to 2M) and **PV on the factory roof** (~520 kWp at 20 to 26 THB/W installed; office roof and parking canopies PV-ready), both user decisions of 17 October 2026; the battery installed (Thai market prices checked October 2026, sources in the CSV) |
|
||||
| Building ~1,500 m² plus civil and site works | 650k – 1,100k | 21.4M – 36.3M | estimate at 12,000 – 20,000 THB/m² plus ~20 % site works; soil is the main variable |
|
||||
| Overhead crane, runway, frame premium, machine door | 97k – 227k | 3.2M – 7.5M | estimate, [crane, workshop and tours](../crane-workshop-tours.md) |
|
||||
| Maintenance workshop and machine bay fit-out | 30k – 76k | 1.0M – 2.5M | estimate, same |
|
||||
| Visitor corridor and accessible entrance | 67k – 148k | 2.2M – 4.9M | estimate, same |
|
||||
| Utility yard built for four boiler and four chiller modules | 73k – 122k | 2.4M – 4.0M | estimate, [scale](../scale.md#detached-utility-yard-parking-and-what-that-moves) |
|
||||
| Factory software, ERPNext, artist platform public side | 115k – 310k | 3.8M – 10.2M | estimate: factory software 60k – 170k, ERPNext implementation 15k – 50k ([digital factory](../digital-factory.md#erpnext-the-plants-erp)), artist platform 40k – 90k ([artist platform](../artist-platform.md)) |
|
||||
| Cassette duplication and CD-R duplication | 55k – 190k | 1.8M – 6.3M | estimate, business plan sections 4.8 and 4.9 |
|
||||
| Freight, installation, commissioning, training (Pheenix, Sibert, Sillitoe, Newbilt beyond its quoted 5 days) | 150k – 300k | 5.0M – 9.9M | estimate |
|
||||
| Working capital, PVC stock, spares, lease deposit, first-year rent | 135k – 290k | 4.5M – 9.6M | estimate; land is leased, so no land purchase |
|
||||
| Subtotal | ~4.42M – 7.79M | ~146M – 257M | midpoint ~6.11M USD, ~202M THB |
|
||||
| Contingency 15 % | ~0.66M – 1.17M | ~22M – 39M | |
|
||||
| **Total, launch plant** | **~5.1M – 9.0M USD** | **~168M – 296M THB** | midpoint ~7.02M USD, ~232M THB |
|
||||
|
||||
## Phased entry
|
||||
Not in the total: a **reserve for the ramp-up** (staff hired before first
|
||||
revenue, overheads until volume covers them; ~10M to 20M THB, estimate),
|
||||
CD replication, financing costs, currency moves, the archive's mobile
|
||||
shelving (to quote), and the central hydraulic plant around the Newbilt
|
||||
aggregates: standby pump set, accumulator station and ring main (not
|
||||
costed yet; a Thai HPU builder quotes it,
|
||||
[Chinese suppliers](../suppliers/china-utilities.md#hydraulics)). The blocks are vendor prices without Thai duty or
|
||||
import VAT, so they assume BOI promotion: without it, ~5 % duty on ~2.3M
|
||||
USD of imported machinery (~0.11M USD) comes on top, plus ~0.17M USD of
|
||||
import VAT paid at the border and reclaimed later (estimates).
|
||||
|
||||
A credible launch phase is far smaller, roughly **1.5M to 2.5M EUR**:
|
||||
### The investor's question: 180M THB, maybe 20 % more (October 2026)
|
||||
|
||||
*Superseded by [Two plans](#two-plans-a-at-180m-thb-and-b-at-215m-thb-october-2026)
|
||||
below. Written against the earlier Pheenix estimate (USD 320k to 650k,
|
||||
total ~227M THB at the midpoint); its galvanics lever is now the base
|
||||
price.*
|
||||
|
||||
The project's investor asked whether the plant can be built for **180M
|
||||
THB (~5.45M USD), possibly up to 20 % more (216M THB, ~6.55M USD)**.
|
||||
|
||||
| Case | Launch plant | Against 180M | Against 216M |
|
||||
|---|---|---|---|
|
||||
| Low end of every block | ~161M THB | fits, ~19M to spare | fits |
|
||||
| Midpoint | ~227M THB | ~47M over | ~11M over |
|
||||
| High end of every block | ~292M THB | ~112M over | ~76M over |
|
||||
|
||||
**Read honestly: 216M THB is a realistic target for the full equipment
|
||||
list; 180M THB holds only if the open quotes land low.** At the midpoint
|
||||
four levers bring the plant inside 216M without dropping any of the
|
||||
machines decided above (midpoint values with their share of the
|
||||
contingency, estimates):
|
||||
|
||||
| Lever | Saves | Launch plant after it |
|
||||
|---|---|---|
|
||||
| Rooftop solar and battery through a solar PPA (the EPC owns and finances the array, the plant buys the power) instead of buying them | ~12.3M THB | ~214M THB |
|
||||
| Metrology launch tier (XRF, inline vision, audio station), the laser confocal and the wide-area profiler bought from revenue | ~10.1M THB | ~204M THB |
|
||||
| Pheenix galvanics priced near OMS's reference for a 4-cell wet room | ~6.7M THB | ~198M THB |
|
||||
| Visitor corridor built later; the plant runs without public tours at first | ~4.1M THB | ~193M THB |
|
||||
|
||||
Add the ramp-up reserve of ~10M to 20M THB and that is **~203M to 213M
|
||||
THB, inside the 216M**. Reaching 180M at the midpoint needs scope cuts on
|
||||
top: cassette and CD-R later (~4.6M THB) and renting a crane for the
|
||||
installations while the frame stays crane-ready (~3.7M THB) give ~185M
|
||||
before the reserve, still above 180M, so 180M is a low-quote outcome, not
|
||||
a plan.
|
||||
|
||||
Chinese suppliers for the boilers, compressed air and hydraulics were
|
||||
checked in October 2026
|
||||
([Chinese suppliers](../suppliers/china-utilities.md)): about 2M THB at
|
||||
the midpoint, ~2.5M with its share of the contingency, mostly on the two
|
||||
boiler modules (ASME-stamped 1.25 MPa units from makers with Thai
|
||||
references, installed by a Thai contractor) and a little on the
|
||||
compressor (a Chinese brand bought through its Thai office). That is
|
||||
about 1 % of the target and does not change the answer; the Newbilt
|
||||
hydraulic aggregates stay Newbilt's. Chinese chillers and HVAC, larger
|
||||
blocks, are not checked yet.
|
||||
|
||||
What decides it: the two largest machine lines have no price at all (the
|
||||
Classic and the Pheenix galvanics line), and the building depends on the
|
||||
soil. Four requests settle most of the band: the Newbilt re-quote for the
|
||||
Duplex and the Classic, a Pheenix quote for the galvanics line, the
|
||||
building RFQ with a soil test, and distributor quotes for the metrology
|
||||
stack. Until they are in, quote **~216M THB** to the investor as the
|
||||
target with the levers above, and 180M as the low-quote case.
|
||||
|
||||
## Two plans: A at ~180M THB and B at ~215M THB (October 2026)
|
||||
|
||||
**The main investor wants to go with Plan B** (user, 19 October 2026).
|
||||
Plan B is the proposal from here on: the investor deck leads with it,
|
||||
and Plan A stays as the comparison, the version with the lowest launch
|
||||
capital. Nothing in either plan's figures changes with that choice.
|
||||
|
||||
**Shareholding (user, 20 October 2026): the main investor holds at least
|
||||
60 % of the company** that holds the plant and the BOI promotion, so at
|
||||
most **40 % is for sale** to other shareholders. Ploy Printing's stake
|
||||
(cash, in kind or both), any founders' shares and any further
|
||||
co-investor all come out of that 40 %. BOI promotion permits up to 100 %
|
||||
foreign ownership of the promoted activity ([BOI](../boi.md)), so the
|
||||
split needs no particular nationality on either side.
|
||||
|
||||
**Funding (user, 20 October 2026): the shareholders fund the whole plant
|
||||
and get shares for it; no bank loan is planned.** Plan B's ~217M THB is
|
||||
paid in as share capital, so at one share price the main investor's 60 %
|
||||
is at least **~130M THB** and the 40 % at most **~87M THB** (~121M and
|
||||
~81M on the 201.6M before the ramp-up reserve; Plan A for comparison:
|
||||
~109M and ~73M of ~182M). Arithmetic only: the share price, any
|
||||
founders' or in-kind shares and the call schedule are not agreed. BOI's
|
||||
3:1 debt-to-equity ceiling is met with room to spare (no debt), so it no
|
||||
longer sets an equity floor; the machinery, and in Plan B the owned PV
|
||||
array and battery, stay unpledged and could secure a loan later if one
|
||||
is ever needed. Thai company law lets the capital be registered in full
|
||||
and called in instalments (at least 25 % on subscription, the rest called
|
||||
by the directors), which fits releasing the money in tranches against
|
||||
milestones. The terms go into the shareholders' agreement (business plan
|
||||
section 12.2). Possible share prices from market data:
|
||||
[share price](share-price.md).
|
||||
|
||||
Decided (user, October 2026): the business plan comes in **two
|
||||
versions** for the investor, built from the same documents:
|
||||
|
||||
- **Plan A, ~180M THB**: the launch plant with every machine decided
|
||||
above (one Duplex system, one Classic, galvanics, Sibert, the cutting
|
||||
room), brought down with six cost levers.
|
||||
- **Plan B, ~215M THB**: the same launch plant, one Duplex system and
|
||||
one Classic, with everything in: none of Plan A's six levers taken.
|
||||
First drawn as five presses at ~225M THB (Plan A plus 25 %); re-defined
|
||||
by the user on 17 October 2026 ("plan b should also only start with 1
|
||||
duplex and 1 classic, but with all levers"). In both plans the second
|
||||
Duplex system is a growth step from revenue.
|
||||
- **Both run on biomass steam, with PV on the factory roof only**
|
||||
(user, 17 October 2026: "only put solar on the factory, prepare the
|
||||
other buildings for solar, option a and b should operate on biomass").
|
||||
The office roof and the parking canopies are built PV-ready. With
|
||||
biomass the plant's running load falls to ~230 kW, so the best array
|
||||
is ~500 to 550 kWp ([sustainability](../sustainability.md#pv-size-with-biomass-steam)),
|
||||
about the ~520 kWp factory roof. Against the earlier electric steam
|
||||
and ~640 kWp, in Plan B the biomass boilers and fuel store add ~3.8M
|
||||
at the midpoint over the Thai electric bank and the smaller array saves
|
||||
~2.8M, so it rises from ~216M to **~217M**; Plan A leases the array and
|
||||
had the cheaper Chinese electric boilers, so it takes the full ~5.4M,
|
||||
from ~177M to **~182M**. Biomass saves ~4.2M THB a year of steam energy
|
||||
(calculator).
|
||||
|
||||
Both are priced **without contingency** (user decision) and **with the
|
||||
ramp-up reserve**, because the reserve is cash the investor puts in
|
||||
before volume carries the plant. Pheenix galvanics is priced at OMS's
|
||||
reference plus 20 % in both. Midpoints, estimates:
|
||||
|
||||
| Plan A: launch plant with six levers | Saves | Subtotal after it |
|
||||
|---|---|---|
|
||||
| Launch plant, every block, no contingency | | ~201.6M THB (~6.11M USD) |
|
||||
| Solar (~520 kWp on the factory roof) and battery through a solar PPA (the installer owns and finances the array, the plant buys the power) | ~14.7M | ~186.9M |
|
||||
| Metrology launch tier: XRF, inline vision and audio station at launch; laser confocal and wide-area profiler (USD 180k to 350k) bought from revenue | ~8.8M | ~178.1M |
|
||||
| Visitor corridor built later; no public tours at first | ~3.6M | ~174.5M |
|
||||
| Cassette and CD-R duplication later | ~4.0M | ~170.5M |
|
||||
| Crane rented for the installations; frame, runway and machine door stay crane-ready | ~3.2M | ~167.3M |
|
||||
| Compressor through the Chinese route ([Chinese suppliers](../suppliers/china-utilities.md)); the route priced only electric boilers, so with biomass it saves only the compressor | ~0.25M | **~167.1M (~5.06M USD)** |
|
||||
| Ramp-up reserve | | +10M to 20M |
|
||||
| **Plan A** | | **~182M THB (~5.52M USD)**, ~2M above 180M at the midpoint (177M with the reserve's low end); ~132M to 233M from the low to the high end of every block |
|
||||
|
||||
| Plan B: the launch plant, everything in | USD | THB |
|
||||
|---|---|---|
|
||||
| Launch plant, every block, no contingency (the six lever items included: owned solar (~520 kWp) and battery ~14.7M, full metrology ~8.8M, visitor corridor ~3.6M, cassette and CD-R ~4.0M, bought crane ~3.2M, Thai compressor ~0.25M, together ~34.5M THB at the midpoint) | 4.42M – 7.79M | ~146M – 257M, **~201.6M (~6.11M USD)** at the midpoint |
|
||||
| Ramp-up reserve | | +10M to 20M |
|
||||
| **Plan B** | | **~217M THB (~6.56M USD): ~215M**, ~156M to 277M from the low to the high end of every block |
|
||||
|
||||
Plan B costs ~35M THB (~19 %) more than Plan A and, at the midpoint,
|
||||
sits ~0.6M above the investor's 180M THB plus 20 % (216M) and 8.4M under
|
||||
the 225M mark (its high end, ~277M, is above both). It keeps what Plan A leases or defers:
|
||||
owned solar on the factory roof and the battery, the full
|
||||
metrology stack from the first release, the visitor corridor and tours
|
||||
from the start, cassette and CD-R, the bought crane, Thai-supplied
|
||||
utilities with local service. Both plans have the same three presses and
|
||||
make the same ~0.58 to 0.90 million records a year at the planned 60 %
|
||||
specials (Duplex-limited); the operating pictures are in the
|
||||
[revenue model](revenue-model.md#operating-pictures-of-plan-a-and-plan-b-october-2026).
|
||||
The [plant and business plan calculator](../fleet-calculator.html) has
|
||||
both as presets.
|
||||
|
||||
**Not in either plan price:**
|
||||
- **Contingency.** The blocks are budgetary (plus or minus 30 to 50 % on
|
||||
the estimates, top of this page), so the plans carry no buffer for
|
||||
quotes landing high. At this page's 15 % that would be ~25M THB on
|
||||
Plan A and ~30M on Plan B at the midpoint.
|
||||
- The central hydraulic plant (not costed yet), the archive's mobile
|
||||
shelving (to quote), CD replication, financing costs, currency moves,
|
||||
and Thai duty and import VAT (the blocks assume BOI promotion).
|
||||
|
||||
**What decides between them:** not demand, since both make the same
|
||||
records, but whether the investor funds ~35M THB more at launch for what
|
||||
Plan A leases or buys from revenue. On the modelled numbers Plan B's
|
||||
extra earns little: the same EBITDA in the revenue model (the calculator
|
||||
puts Plan B ~0.06M USD a year ahead, the PPA power bill its owned array
|
||||
avoids), more depreciation and a longer payback;
|
||||
its case rests on that bill and on what the operating table leaves out:
|
||||
full stamper metrology for the traceability pitch from the first release,
|
||||
tours and the Payap programmes from day one, cassette and CD-R sales, and
|
||||
utilities with local service. The BOI no longer promotes solar
|
||||
installations (Announcement 3/2568, in force 1 July 2025; only the
|
||||
battery may still qualify, see [BOI](../boi.md)), so owning the array
|
||||
earns no tax benefit, only the bill. Most of Plan B's items can be added
|
||||
to Plan A later from revenue; the corridor is cheaper to have from the
|
||||
start. **Plan A over 180M:** the way back is a quote for a Chinese
|
||||
biomass boiler (ZOZEN, Sitong, Taiguo and Yongxing build them; none
|
||||
priced yet): ~2M or more below the Getabec-class package brings Plan A
|
||||
to 180M at the midpoint. Both plans keep the second Duplex as a growth step, with its
|
||||
floor, utility positions and ring-main tees reserved: ~15.4M THB at the
|
||||
midpoint for the system (~8.7M), a third chiller module CH-3 (~2.1M),
|
||||
their freight and installation (~1.2M) and the working capital for the
|
||||
extra records (~3.4M), estimates on the calculator's basis, as first
|
||||
priced for the five-press Plan B.
|
||||
|
||||
## Full vision, all blocks (July 2026, superseded)
|
||||
|
||||
The five-press full vision below is superseded by the launch plant above.
|
||||
Scale, pressing line, roadmap, revenue model (which now has a launch-plant
|
||||
operating picture) and the fleet calculator are re-based on the launch
|
||||
plant; the business plan is next. It stays for the record of how the
|
||||
blocks were built.
|
||||
|
||||
| Block | USD | THB | Basis |
|
||||
|---|---|---|---|
|
||||
| Newbilt semi-auto line, full Duplex | 350k – 370k | 11.5M – 12.2M | 2024 quote EUR 200,500 (~USD 232k) + quoted 2nd press/extruder ~USD 115k; expired, needs re-quote. The fleet has since changed, see the added-scope table |
|
||||
| 2 automated presses (Pheenix AD12) | 580k – 920k | 19.1M – 30.5M | unverified ~USD 340k/press indicative + delivery and commissioning. Replaced by the Newbilt Classic in the current fleet, see the added-scope table |
|
||||
| Galvanics line (Digital Matrix or Pheenix Alpha) | 320k – 650k | 10.7M – 21.4M | six-figure-USD turnkey inference from vendor research; the Pheenix range (2024 flyers, [galvanics and stamper prep](../equipment/galvanics.md)) is unpriced too; OMS's reference prices (letter, 9 October 2026) put a complete 4-cell wet room at EUR 224k basic to 311k advanced (~USD 259k to 359k; ~270k to 371k with know-how transfer), installation and water treatment extra: at or below this block's low end, kept until quotes exist |
|
||||
| Zero-discharge water treatment (ZLD) | 90k – 240k | 3.0M – 8.0M | utilities CSV option row |
|
||||
| Stamper prep (Sibert VSP, VSF, VSC) | 60k – 170k | 1.9M – 5.7M | estimate kept until the re-base; Sibert has since confirmed USD 250k for the three (its time, spares, shipping and travel extra), the difference is in the table below |
|
||||
| Mastering and cutting room (Agnew or Sillitoe lathe system, cutter amps, console, room treatment) | 290k – 580k | 9.6M – 19.1M | estimate, bespoke market; the Sillitoe SDMS lists at USD 125k for lathe, head, amplifier and automation (ex tax, shipping), which makes the low end reachable; band kept until both quotes exist |
|
||||
| Metrology and QC stack (confocal, profiler, XRF, inline vision, audio station) | 350k – 810k | 11.5M – 26.7M | estimate, phaseable |
|
||||
| Utilities, solar, HVAC, racking baseline | 730k – 1,270k | 24.0M – 41.6M | reviewed [utilities CSV](utilities-investment.csv), THB-native; sized for one Duplex, the five-press re-size is in the table below |
|
||||
| Building ~1,500 m² plus civil works | 650k – 1,100k | 21.4M – 36.2M | estimate at 12,000–20,000 THB/m² Thai industrial construction plus ~20% site works |
|
||||
| Land 6–8 rai, if purchased | 360k – 970k | 12.0M – 32.0M | estimate at 2–4M THB/rai industrial; leasing cuts this to near zero upfront |
|
||||
| Traceability and factory software | 60k – 170k | 1.9M – 5.7M | estimate |
|
||||
| Freight, installation, training (non-Newbilt equipment) | 120k – 230k | 3.8M – 7.6M | estimate |
|
||||
| Working capital, PVC stock, spares | 120k – 230k | 3.8M – 7.6M | estimate |
|
||||
| Subtotal | ~4.1M – 7.7M | ~135M – 254M | |
|
||||
| Contingency 15% | ~0.6M – 1.2M | ~20M – 38M | |
|
||||
| **Total, full vision** | **~4.7M – 8.9M USD** | **~155M – 294M THB** | |
|
||||
|
||||
### Added scope, not yet in the roll-up
|
||||
|
||||
Decided, or re-priced by a vendor, after the roll-up above was compiled;
|
||||
carried here until the next re-base folds them into the blocks (the
|
||||
building, software and stamper prep lines, and the contingency on top).
|
||||
|
||||
| Block | USD | THB | Basis |
|
||||
|---|---|---|---|
|
||||
| Overhead crane, runway, frame premium, machine door | 97k – 227k | 3.2M – 7.5M | estimate, [crane, workshop and tours](../crane-workshop-tours.md) |
|
||||
| Maintenance workshop and machine bay fit-out | 30k – 76k | 1.0M – 2.5M | estimate, same |
|
||||
| Visitor corridor and accessible entrance | 67k – 148k | 2.2M – 4.9M | estimate, same |
|
||||
| Artist platform, public side (calculator, campaigns, payments) | 40k – 90k | 1.3M – 3.0M | estimate, [artist platform](../artist-platform.md) |
|
||||
| PVC material lab, day-one tier (incl. plaque press and sample conditioning) | 55k – 150k | 1.8M – 5.0M | estimate, [quality automation](../quality-automation.md); not costed in the metrology block above. The mature tier (torque rheometer, DSC, FTIR, ~120k – 240k) is deferred, with partner labs in between |
|
||||
| Stamper prep re-priced: USD 250k for VSP, VSF and VSC against the 60k – 170k block above | +190k (low case) / +80k (high case) | +6.3M / +2.6M | Sibert's budget confirmation, email of 5 October 2026 ([galvanics and stamper prep](../equipment/galvanics.md)); itemised quotation to follow. Its time, spare parts, shipping and travel are extra and fall into the freight/installation and spares blocks above |
|
||||
| Press fleet changed (October 2026) to two Newbilt Duplex systems (two presses each, EX 50 main extruder and EX 35 colour extruder) plus one Newbilt Classic, replacing the two blocks above (930k – 1,290k): Duplex system 1 as the first block (350k – 370k; the quote's second-extruder option becomes the EX 35), system 2 ~230k – 300k (two presses at the quoted ~115k per press and extruder set as the yardstick, plus hydraulic unit and EX 35, estimate; no EX 35 price on file), the Classic ~290k – 460k (the AD12 band per press as a placeholder; no Newbilt price on file) | −60k (low case) / −160k (high case) | −2.0M / −5.3M | estimate, [pressing line](../equipment/pressing-line.md); the Newbilt re-quote replaces it. The utilities for five presses are re-sized in the row below |
|
||||
| Utilities re-sized for the five-press fleet (October 2026): boiler bank 2 × 500 kg/h, chiller bank 3 × 250 kW with plate heat exchanger and tanks, larger softener and loop treatment ([steam and cooling](../steam-cooling.html)) | +185k (low case) / +294k (high case) | +6.1M / +9.7M | estimate, [utilities CSV](utilities-investment.csv) re-based from 24.0M – 41.6M to 30.1M – 51.3M THB |
|
||||
| Utility yard built for four boiler and four chiller modules (October 2026): yard ~379 m² against 178 m² ([scale](../scale.md#detached-utility-yard-parking-and-what-that-moves)) | 73k – 122k | 2.4M – 4.0M | estimate: the building rate above on the ~200 m² the yard grows by; the open chiller compound costs less than a building, so this is the cautious end. The valved branches and feeders for the empty positions are not priced yet |
|
||||
| ERPNext for the whole plant (October 2026): configuration with Thai tax, integration with every tool, Nix packaging; `vinyl-erp` server | to quote | to quote | not in the sum: 3.5 to 6 person-months in-house or a partner quote (Ecosoft), plus 2k to 4k USD hardware ([digital factory](../digital-factory.md#erpnext-the-plants-erp)); no licence fee |
|
||||
| Archive mobile shelving for the father and mother archive (October 2026) | to quote | to quote | not in the sum: A-Z Solutions publishes no prices; quote it and a Thai supplier ([facility security](../facility-security.md#archive-room-mobile-shelving)) |
|
||||
| **Added so far** | **~678k – 1,027k** | **~22.3M – 33.9M** | about 13 to 17% on the full-vision subtotal |
|
||||
|
||||
## Phased entry (superseded October 2026)
|
||||
|
||||
Superseded by the launch plant above, which launches with galvanics, the
|
||||
cutting room and three presses. The earlier phased entry, kept for
|
||||
reference: a launch phase of roughly **1.7M to 2.9M USD (~57M to 95M
|
||||
THB)**:
|
||||
|
||||
- Newbilt Single system (not Duplex yet)
|
||||
- Bridge stampers from Stamper Discs, so no galvanics line at launch
|
||||
- Basic QC (microscope, benchtop PVC lab, sampled listening), full
|
||||
metrology deferred
|
||||
metrology deferred; the PVC lab's day-one tier is the added-scope row
|
||||
above
|
||||
- Leased building instead of purchase, modest first solar array
|
||||
- Galvanics, automated presses, full metrology, and the biomass boiler
|
||||
follow as revenue-funded or second-round expansions
|
||||
- Galvanics, the second Duplex system and the Classic, full metrology,
|
||||
and the biomass boiler follow as revenue-funded or second-round
|
||||
expansions
|
||||
|
||||
The planning already supports this: the Duplex-ready hydraulics, the
|
||||
bridge-supplier role for Stamper Discs, the staged electric-to-biomass
|
||||
@@ -49,12 +333,24 @@ exactly this reason.
|
||||
- **BOI**: machinery duty exemption applies across most of the equipment
|
||||
blocks, and the solar and automation spend converts into CIT-exemption
|
||||
headroom; the application precedes every purchase order (see
|
||||
[boi.md](../boi.md))
|
||||
- **Buy vs lease** on land and building swings roughly 0.9M to 1.8M EUR of
|
||||
upfront capital
|
||||
[boi.md](../boi.md)). The blocks are vendor prices without Thai duty or
|
||||
import VAT, so the headline assumes promotion: without it, ~0.14M USD of
|
||||
duty and ~0.2M USD of import VAT (reclaimable later) come on top at the
|
||||
start fleet (estimate)
|
||||
- **Buy vs lease** on land and building swings roughly **1.0M to 2.1M
|
||||
USD (~34M to 69M THB)** of upfront capital, and also moves the launch
|
||||
date by about three quarters; see
|
||||
[project-timeline.md](../project-timeline.md)
|
||||
- **Biggest uncertainty bands**: metrology (partly a choice of ambition),
|
||||
the mastering/cutting room (bespoke vendor, no public pricing), the
|
||||
automated presses (single unverified price point), and land
|
||||
Newbilt Classic (no price on file), and land
|
||||
- **Currency exposure is real and is not modelled here.** Revenue is
|
||||
mostly USD/EUR from export customers, the cost base is mostly THB, and
|
||||
the largest single equipment block is EUR-denominated and unhedged
|
||||
against an order that will not be placed for roughly a year (see
|
||||
[project-timeline.md](../project-timeline.md)). A 10% move in EUR/THB
|
||||
between now and the Newbilt order is worth ~USD 25–35k on that line
|
||||
alone. Ask for the re-quote to state its currency and validity period.
|
||||
- Every band narrows only with RFQs; the supplier map in
|
||||
[equipment-suppliers.md](../suppliers/equipment-suppliers.md) lists who
|
||||
to ask
|
||||
@@ -1,18 +1,19 @@
|
||||
category,item,spec_summary,candidate_thai_suppliers,cost_low_thb,cost_high_thb,cost_basis,notes
|
||||
steam,Electric/gas once-through boiler package,"~400-500 kg/h at 10 bar / 180 C incl. softener, feed tank, economizer, installed","Miura Thailand (Chachoengsao); Bangkok Industrial Boilers; STE Thailand",2500000,4000000,engineering estimate,"Miura-class modular once-through; BIB budget option ~2.0-3.5M; service is Bangkok-centric, confirm northern dispatch SLA"
|
||||
steam,Biomass/wood-fired boiler package (option),"~0.5 t/h solid fuel (wood chips/pellets/rice husk) incl. fuel feed, grate, dust control, softener, installed",Getabec PCL (Thai fabrication and service),4000000,7000000,engineering estimate,"Sustainability path matching Deepgrooves NL precedent; Viessmann has no strong Thai channel; higher capex, lower fuel opex in the North; NOT included in baseline total"
|
||||
steam,Steam balance of plant,"Traps, accumulator, condensate return",Forbes Marshall Thailand,0,0,included,"Largely included in boiler package rows; line kept for RFQ completeness"
|
||||
compressed_air,Screw compressor skid (oil-injected),"~7.5 kW VSD screw + refrigerated dryer (3 C PDP) + coalescing filters + ~500 L receiver, installed","Atlas Copco Thailand; Kaeser Thailand (SM-T/Aircenter); Ingersoll Rand Thailand",350000,600000,engineering estimate,"14-30 m3/h demand is small (5-10 hp class); oil-injected + filter train meets 5 micron / 3 C spec"
|
||||
compressed_air,True oil-free class-0 (option),Same duty in oil-free class-0,"Atlas Copco (ZR/ZT); Kaeser",1200000,1800000,engineering estimate,"Only if air contacts product stream; NOT included in baseline total"
|
||||
cooling,Process chiller package 250 kW,"~71 RT air-cooled screw/scroll chiller + pumps + buffer tank + controls, installed, closed loop","Trane Thailand; Carrier Thailand; Daikin Applied Thailand; Hitachi Thailand",2500000,4000000,engineering estimate,"Newbilt spec: 220 l/min peak, 20-25 C supply; chiller is the safe choice for hot-season wet-bulb"
|
||||
cooling,Cooling tower + HX loop (alternative),"FRP tower ~250-300 kW reject + plate HX + pumps + tanks + water treatment","Liang Chi Thailand (tower, large service org); Process Cooling Solutions; Tasaki (integrators)",1000000,2000000,engineering estimate,"Cheaper capex but wet-bulb-limited; hybrid tower + trim chiller is the efficiency-optimal design; NOT included in baseline total"
|
||||
water,Boiler feedwater duplex softener,~0.5-0.8 m3/h feedwater duty,"Veolia Water Technologies Thailand; Hydrotek; local RO/softener integrators",80000,200000,market estimate,May suffice alone for a small fire-tube boiler
|
||||
water,RO skid (option),0.5-1 m3/h low-TDS feed,"Veolia; Hydrotek; local integrators",200000,500000,market estimate,"Only if low-TDS feed needed; NOT included in baseline total"
|
||||
water,Closed-loop cooling water treatment,"Side-stream filtration + dosing + conductivity blowdown control",Veolia; Hydrotek; local integrators,150000,400000,engineering estimate,Chemicals are ongoing opex on top
|
||||
water,Galvanics ZLD evaporator (future),"Small MVR or low-temp vacuum evaporator for plating rinse, installed","Core unit imported (WTEYA, Greenlan, Fred); Thai integration via Veolia or Hydrotek",3000000,8000000,market estimate,"For the future galvanics line, zero-discharge requirement; NOT included in baseline total"
|
||||
storage,Pallet racking and shelving,"100-200 pallet positions selective/heavy-duty (beams sized 1000-1500 kg/pallet, records are dense) + archive and finished-goods shelving, installed","Jenbunjerd; local fabricators (Sahawatthanakit, UPR, SD Shelf); SSI Schaefer (premium)",800000,1500000,published list prices + engineering estimate,"SSI Schaefer premium tier ~1.5-3M for same scope; ~1000-2000 THB per pallet position at local tier"
|
||||
steam,Electric/gas once-through boiler bank (alternative),"2 x 500 kg/h modules at 10.5 bar / 180 C, lead/lag, shared feed tank, feed pumps, economizer, installed","Miura Thailand (Chachoengsao); Bangkok Industrial Boilers; STE Thailand; Chinese route (October 2026): ZOZEN, Sitong, Fangkuai, Taiguo (ASME claimed, Thai references, no Thai service partner), see suppliers/china-utilities.md",4500000,7000000,engineering estimate,"NOT included in baseline total since 17 Oct 2026 (user: both plans run on biomass); kept as the alternative. Launch plant (October 2026): one Duplex system and one Classic, 450-540 kg/h at Newbilt's 150-180 kg/h per press, so B-1 and B-2 both at launch; the boiler hall is built for four modules (scale.md utility phasing); a third module for N+1 is an RFQ option; Miura-class modular once-through; service is Bangkok-centric, confirm northern dispatch SLA; Chinese route estimate 2.8M-5.5M THB installed (two ASME-stamped 1.25 MPa bodies USD 15k-35k each, inspection and certification, freight, Thai contractor balance of plant), about 1.6M THB less at the midpoint; imported boilers need DIW certification-body verification either way"
|
||||
steam,"Biomass/wood-fired boiler package, 2 x 500 kg/h or one ~1 t/h","~1 t/h solid fuel (wood chips/pellets/rice husk) incl. fuel feed, grate, dust control, softener, installed",Getabec PCL (Thai fabrication and service),6000000,10000000,engineering estimate,"Baseline since 17 Oct 2026 (user: ""option a and b should operate on biomass""); the launch plant draws 450-540 kg/h, so the two 500 kg/h modules of the boiler hall (B-1, B-2) or one ~1 t/h package; Chinese makers build biomass boilers too (ZOZEN DZL, Sitong DZL/SZL, Taiguo, Yongxing; china-utilities.md), not priced yet; fuel ~300 t air-dry wood or ~460 t fresh chips a year at ~850k records, ~0.67M THB at 0.7 THB/kWh of heat (biomass.md); sustainability path matching Deepgrooves NL precedent"
|
||||
steam,Biomass fuel store and handling,"Covered fuel store (42 m2 in the site model, ~6-7 weeks of fresh chips; ~80 m2 for a 3-month monsoon stock), chip bay, ash bins, compact loader",Local steel-shed contractors; loader dealers (used compact loaders),1000000,2000000,engineering estimate,"biomass.md: fuel handling and storage come on top of the boiler package; shed at roughly half the main building's 12,000-20,000 THB/m2 plus a used loader (estimate)"
|
||||
steam,Steam balance of plant,"Traps, accumulator, condensate return",Forbes Marshall Thailand,0,0,included,Largely included in boiler package rows; line kept for RFQ completeness
|
||||
compressed_air,Screw compressor skid (oil-injected),"~7.5 kW VSD screw + refrigerated dryer (3 C PDP) + coalescing filters + ~500 L receiver, installed","Atlas Copco Thailand; Kaeser Thailand (SM-T/Aircenter); Ingersoll Rand Thailand; Chinese brands with Thai offices (October 2026): Kaishan Compressor (Thailand), Denair Thailand, see suppliers/china-utilities.md",350000,600000,engineering estimate,"14-30 m3/h demand is small (5-10 hp class); oil-injected + filter train meets 5 micron / 3 C spec; Chinese route estimate 0.15M-0.3M THB installed (PM VSD 11 kW class USD 2k-5k, dryer, receiver, filters, installation)"
|
||||
compressed_air,True oil-free class-0 (option),Same duty in oil-free class-0,Atlas Copco (ZR/ZT); Kaeser,1200000,1800000,engineering estimate,Only if air contacts product stream; NOT included in baseline total
|
||||
cooling,Process chiller bank 2 x 250 kW,"2 x ~71 RT air-cooled screw/scroll chillers rated at 40 C ambient (CH-1, CH-2) + primary pumps + plate HX + warm and cold tanks + VFD supply pumps + controls, backbone (HX frame, tanks, pumps, mains) sized for four modules, installed",Trane Thailand; Carrier Thailand; Daikin Applied Thailand; Hitachi Thailand,4900000,7900000,engineering estimate,"Launch plant (October 2026): Duplex system ~261 kW hot-afternoon peak (scale.md) plus the Classic up to ~125 kW (Newbilt per press), ~390 kW against 500 kW installed; was 3 x 250 kW at 6.5-10.5M for five presses, less one module at ~1.6-2.6M THB (estimate); CH-3 and CH-4 come with the growth options; 3 x 350 kW frame pads stay the alternative (steam-cooling.html)"
|
||||
cooling,Cooling tower + HX loop (alternative),Dry cooler or FRP tower ~650-750 kW reject + plate HX + pumps + tanks + water treatment,"Liang Chi Thailand (tower, large service org); Process Cooling Solutions; Tasaki (integrators)",2000000,3500000,engineering estimate,Cheaper capex but wet-bulb-limited; hybrid tower + trim chiller is the efficiency-optimal design; NOT included in baseline total
|
||||
water,Boiler feedwater duplex softener,~1.0-1.2 m3/h feedwater duty (five-press boiler bank),Veolia Water Technologies Thailand; Hydrotek; local RO/softener integrators,120000,300000,market estimate,May suffice alone for a small fire-tube boiler
|
||||
water,RO skid (option),0.5-1 m3/h low-TDS feed,Veolia; Hydrotek; local integrators,200000,500000,market estimate,"Launch scope since October 2026 as the DI water supply for the galvanics PMPB (with polishing); carried in the galvanics water block of total-investment.md, so NOT included in this baseline total"
|
||||
water,Closed-loop cooling water treatment,Side-stream filtration + dosing + conductivity blowdown control,Veolia; Hydrotek; local integrators,200000,500000,engineering estimate,"Sized for the five-press loop with its open return tank (Newbilt press outlets are open, max. 2 bar); chemicals are ongoing opex on top"
|
||||
water,Galvanics ZLD evaporator,"Small MVR or low-temp vacuum evaporator for plating rinse, installed","Core unit imported (WTEYA, Greenlan, Fred); Thai integration via Veolia or Hydrotek",3000000,8000000,market estimate,"Launch scope since October 2026 (galvanics in-house from the start); carried as its own block in total-investment.md, so NOT included in this baseline total"
|
||||
storage,Pallet racking and shelving,"100-200 pallet positions selective/heavy-duty (beams sized 1000-1500 kg/pallet, records are dense) + archive and finished-goods shelving, installed","Jenbunjerd; LPI Rack Range (Thailand), Bangkok/Samut Prakan, racking and office mobile shelving; local fabricators (Sahawatthanakit, UPR, SD Shelf); SSI Schaefer (premium)",800000,1500000,published list prices + engineering estimate,SSI Schaefer premium tier ~1.5-3M for same scope; ~1000-2000 THB per pallet position at local tier
|
||||
hvac,Whole-factory HVAC,"~1500 m2 at 20-26 C, 35-60% RH, ePM1/F7-F9 filtration sized for burning-season PM2.5, ducting and controls","Daikin Thailand; Trane; Mitsubishi Electric; Carrier; filtration: Camfil Thailand, AAF",7500000,15000000,engineering estimate at 5000-10000 THB/m2,"RH low end of 35% is aggressive for tropics and drives desiccant cost; if 45-60% RH acceptable, cost drops materially"
|
||||
hvac,Clean-room-grade zone adder,"Cutting room + galvanics clean room, ~2 x 60 m2, ISO 7/8 with HEPA terminals, positive pressure, airlocks","Same HVAC vendors + clean-room contractors; Camfil HEPA",1200000,3400000,engineering estimate at 10000-28000 THB/m2 adder,Applied only to the two tight zones
|
||||
solar,PV rooftop EPC (illustrative 300 kWp),"Turnkey C&I rooftop EPC incl. Deye hybrid inverters, at 25000-35000 THB/kWp","Solar Nicolo (Deye tier-1 distributor); Banpu NEXT; SCG Cleanergy; Sermsang; local Chiang Mai installers",7500000,10500000,market rate per kWp; size illustrative,"Final kWp open until site selection; grid tariff ~3.88 THB/kWh implies ~4-6 yr C&I payback"
|
||||
solar,Battery stack 271 kWh (Gobel),"GP-SRA-HV314 HV LiFePO4 rack, 15 x 18 kWh packs, direct from Shenzhen, 50-60 day lead",Gobel Power (no Thai distributor; integration by solar EPC),1400000,2030000,vendor listed price USD 39900-58000 at ~35 THB/USD,"Confirm Deye BMS protocol compatibility and that the EPC warrants a mixed-vendor DC bus; certs (UN38.3/IEC 62619/CE) to be requested"
|
||||
total,BASELINE TOTAL,"Electric steam + oil-injected air + chiller + softener + loop treatment + local racking + HVAC + clean zones + 300 kWp solar + 271 kWh BESS",,23980000,41630000,sum of baseline rows,"~630k-1100k EUR at 38 THB/EUR; excludes options rows (biomass premium, oil-free, tower alternative, RO, ZLD evaporator, SSI premium tier); all figures budgetary +/- 30%, get RFQs before BOI/finance filings"
|
||||
hvac,Clean-room-grade zone adder,"Cutting room + galvanics clean room, ~2 x 60 m2, ISO 7/8 with HEPA terminals, positive pressure, airlocks",Same HVAC vendors + clean-room contractors; Camfil HEPA,1200000,3400000,engineering estimate at 10000-28000 THB/m2 adder,Applied only to the two tight zones
|
||||
solar,"PV EPC, factory roof (~520 kWp on the Payap scenario plot)","Turnkey C&I EPC on the factory roof (~523 kWp in the parts model), incl. inverters (Deye hybrids where the battery connects), at 20000-26000 THB/kWp; office roof (~65 kWp) and car and scooter canopies (~54 kWp) PV-ready, panels later",Solar Nicolo (Deye tier-1 distributor); Banpu NEXT; SCG Cleanergy; Sermsang; CapSolar; local Chiang Mai installers,10400000,13520000,"market rate per kWp (October 2026 check): DEDE Thailand PV Status (Mahidol survey) 22-25 THB/W for 10 kW-1 MW C&I systems in 2023; CapSolar 2026 20-25 THB/W under 1 MWp (20-23 at 500 kWp); Saimai Solar 2026 list 5.4M THB for 300 kW (18 THB/W); top of range covers Deye SUN-50K-SG01HP3 hybrid inverters (160,500 THB each at Supsaringkan, about nine 50 kW units for ~430 kVA); size: the factory roof, user decision 17 Oct 2026 (was every roof and canopy, ~640 kWp, and before that an illustrative 300 kWp)","Size: with biomass steam the best array is ~500-550 kWp (hourly sketch, sustainability.md), so the factory roof's ~520 kWp; on the Mueang Chi hall the factory roof takes ~247 kWp (scale.md); PV-ready means structure for the panels, conduit and a spare way at the main board (in the building and site works); ~87% of the yield used on site under PEA zero export (estimate); self-consumed PV worth ~3.7 THB/kWh, ~4.1-5.8 yr payback (sustainability.md, grid tariff)"
|
||||
solar,Battery stack 271 kWh (Gobel) installed,"GP-SRA-HV314 HV LiFePO4 rack, 15 x 18 kWh packs, direct from Shenzhen, 50-60 day lead; plus enclosure, fire detection and suppression, controls and installation",Gobel Power (no Thai distributor; integration by solar EPC),2000000,3500000,"battery: vendor listed price USD 39900-58000 at ~35 THB/USD = 1.40-2.03M THB, in line with DEDE's 5000-7000 THB/kWh for LiFePO4 (Mahidol survey); installed: estimate below CapSolar's 12000-15000 THB/kWh for a fully installed factory BESS (2026), because the Deye hybrid inverters in the PV row do the power conversion",Confirm Deye BMS protocol compatibility and that the EPC warrants a mixed-vendor DC bus; certs (UN38.3/IEC 62619/CE) to be requested
|
||||
total,BASELINE TOTAL,Biomass boiler package (2 modules) + fuel store + oil-injected air + chiller bank (2 modules) + softener + loop treatment + local racking + HVAC + clean zones + ~520 kWp factory-roof solar + 271 kWh BESS,,34470000,58220000,sum of baseline rows,"Launch plant, one Duplex system and one Classic (October 2026; biomass steam and PV on the factory roof only 17 Oct 2026, was 34.37M-56.34M with electric steam and ~640 kWp; solar and battery re-priced from Thai market data and the array sized to every roof and canopy 17 Oct 2026, was 27.57M-47.50M at 300 kWp and 28.47M-48.73M before the re-price; was 30.07M-51.33M THB for five presses, 23.98M-41.63M for one Duplex); ~750k-1280k EUR at 38 THB/EUR; excludes options rows and the galvanics water rows (ZLD, DI), which total-investment.md carries with galvanics; all figures budgetary +/- 30%, get RFQs before BOI"
|
||||
|