Open-core field hardware, firmware and edge software for instrumented, profile-driven crop cultivation. One architecture, from a cabinet to a several-hundred-square-metre facility. The companion platform IndustryFlow stores history, runs analytics and distributes profiles.
Scope and rationale: MOTIVATION.md, ADR-0001.
| Constraint | Record |
|---|---|
| Scaling multiplies node instances across zones. It adds no node classes. | ADR-0014 d2 |
| A signed, versioned JSON cultivation profile is the only channel that changes deployment behaviour. There is no remote-command API and no real-time tuning channel. | ADR-0015 d1, ADR-0025 |
| The gateway runs control loops locally against a cached profile. The cloud supplies profiles and observes; it does not command in real time. | ADR-0015 d8, ADR-0004 rev 1 |
| The over-temperature trip is analog, MCU- and bus-independent, and sits at the heating actuator. Profiles set operating parameters; hardware sets survival parameters. | ADR-0018 d10 |
| Sensor density is a deployment phase, not a fixture: dense during the empirical survey, reduced for the operating phase. The profile carries the identified model with the setpoints. | ADR-0016 |
| Layer | Choice |
|---|---|
| Field bus | Cyphal over classic CAN @ 500 kbit/s, linear topology |
| Smart-node MCU | WeAct STM32F4 64-pin core board (STM32F405RGT6; F412/F446 drop-in) |
| Node carrier PCB | Custom integration board: CAN transceiver, ATECC608 secure element, two-header sensor-module interface |
| Node firmware | Embedded C with libcanard. One application holds every module personality; the module-ID strap selects at boot |
| Node flash layout | Bootloader at the reset vector plus the application in one of two slots; build output is igrowboot.hex, igrow-a.hex, igrow-b.hex |
| Firmware update | Signed image served over the bus, uavcan.file.Read to the slot that is not running, trial boot with fallback |
| Gateway | Raspberry Pi (3B+ minimum, 4/5 for higher traffic) + isolated 2-channel CAN HAT |
| Gateway software | Python / asyncio, SocketCAN + Pycyphal + Nunavut-generated DSDL bindings |
| Cloud link | mTLS to IndustryFlow; stateless edge in steady state, with a bounded local store for buffering and survey |
| Identity | Module class from the ID strap, unique_id from the ATECC608, Node-ID from a carrier-resident store; 127 = unprovisioned |
| Security | Operator CA, signed firmware, signed profiles |
Governing records: ADR-0002 rev 3 (bus, carrier, gateway), ADR-0005 (DSDL), ADR-0020 (persistence), ADR-0027 (identity), ADR-0029 (update and bootloader), ADR-0024 / ADR-0025 (CA, profile signing).
PCBs are authored in KiCad 10 and will not open in earlier versions; cabinet distribution schematics (
E0007) use QElectroTech. Design files live instore/under the ADR-0017 scheme, packaged per document layer asExxxx-VVVVVV-S-src.zip/-D-src.zip(d19).CONTRIBUTING.mdhas the unpack/repack procedure.
Seven sensor-module classes (M01–M07), one functional subsystem each, on the universal carrier
E0001, in the cabinet distribution case E0007. Instances of one design are specialized by
populated BOM, never by new designs; a functional group fitted or omitted at build is a populate
variant with its own assembly E-number (ADR-0017 rev 2 d4).
E-numbers, sensor complement, module-ID straps, variant rules and per-design state:
REGISTRY.md.
Phase 1 is data collection only, no actuators; it ends at stage 4, full cabinet telemetry from
M01–M05. Stage sequencing, dependencies, the Phase 1 → Phase 2 boundary and the v1.0 exit
criteria: project/ROADMAP.md, 14 dependency-ordered stages.
| Path | Contents | Records |
|---|---|---|
ADR/ |
Architecture decision records — the source of truth — plus GLOSSARY.md |
ADR-0000 |
REGISTRY.md |
E-number / SP-number identifier map, machine-readable | ADR-0017, ADR-0019, ADR-0023 |
store/ |
Hardware design sources, fab packages and firmware release artifacts, flat, keyed by identifier | ADR-0017 |
spec/ |
Module specifications — M01, M02, M05, M06, M07. M03 and M04 not yet written | ADR-0014 |
firmware/ |
Node firmware (C, libcanard) and the industryflow.greenhouse DSDL vocabulary |
ADR-0005, ADR-0029 |
gateway/ |
Gateway provisioning, hardening, identity and profile-pull client | ADR-0004, ADR-0015 |
erp/ |
Instance-and-integration ERP — the pre-cloud system of record | ADR-0021, ADR-0022 |
pki/ |
Operator CA bootstrap and root-key ceremony | ADR-0024 |
signing/ |
Profile signing tool and runbook | ADR-0025 |
profiles/ |
Cultivation profile instances | ADR-0003 |
project/ |
ROADMAP.md stage plan, RESEARCH.md open directions L1–L7 |
— |
MOTIVATION.md |
The gap this project closes | — |
CONTRIBUTING.md |
Contribution licensing, DCO sign-off, working with the store | — |
Firmware — three images, ARM cross-toolchain and Ninja required:
firmware/tools/bootstrap.sh # pin submodules; needs nnvg (Nunavut)
cmake -S firmware -B firmware/build -G Ninja \
-DCMAKE_MAKE_PROGRAM="$(command -v ninja)" \
-DCMAKE_TOOLCHAIN_FILE="$PWD/firmware/cmake/arm-none-eabi.cmake"
cmake --build firmware/buildERP — application plus operator console:
cd erp && docker compose up --build # app on 127.0.0.1:8021Gateway — runs on the Pi, post-first-boot, idempotent:
sudo ./provision.sh # from the staged gateway/ bundlePer-component detail, flashing procedure and signing keys are in each directory's README.md.
Open-core, licensed per part of the repository. LICENSE.md is the authoritative
mapping — hardware designs, documentation, application code and the DSDL protocol layer carry four
different licences, and directory-level assumptions do not hold. Full texts are in
LICENSES/.
Third-party content keeps its own terms, annotated in REUSE.toml: the WeAct
core-board snapshot is published with no licence stated, so it is not covered by this project's
licences. Compliance is CI-enforced — run reuse lint before opening a pull request.