Skip to the content
2 layers140 × 100 mmPlts monitoring controller, the printed circuit board in 3D

Integrated to PLTSMonitoring_PWA

Size
140 × 100 mm
Copper layers
2
Thickness
1.6 mm
Parts
152
Nets
120
Pads
490
Tracks, vias
2,023, 367
Pours
17
Routed
Yes
KiCad
KiCad 9.0 (file 20241229)
Created
2 Sep 2026
Updated
22 Sep 2026

Overview

Plts monitoring controller is an open-source printed circuit board by desvandi, from the desvandi/PLTSMonitoring_Firmware-Backend repository on GitHub. It is a 2-layer board of 140 × 100 mm with 152 parts on 120 nets, routed with 2,023 tracks and 367 vias.

It is built around the ESP32-WROOM-32E, MAX3485CSA+T and ACS712ELCTR-30A-T, with the CP2102N-A02-GQFN24, AP2112K-3.3 and DS3231SN# among its other parts. Its parts include 34 resistors, 27 capacitors, 8 ICs, 6 diodes and 6 transistors. It belongs with the ESP32 boards of this library.

Main components

12

README

README.md

PLTS Monitoring — Firmware, Backend GAS, & Toolkit

Firmware Version: v1.9.3 · Backend GAS: WAVE-7+ · License: MIT Status: Development (v1.9.x INA219 dynamic gain switching — hardware acceptance pending; v1.9.3 menutup REL-03/REL-04: build kini reproducible) Repositori kembar (PWA frontend): desvandi/PLTSMonitoring_PWA


Daftar Isi

  1. Gambaran Proyek
  2. Arsitektur Sistem
  3. Struktur Repositori
  4. Hardware Requirements
  5. Firmware v1.9.x — INA219 Dynamic Gain Switching
  6. Panduan Deployment Lengkap
  7. Konfigurasi Firmware
  8. Backend Google Apps Script
  9. CI/CD Pipeline
  10. Release Engineering
  11. Hardware Acceptance
  12. Testing
  13. Troubleshooting
  14. Changelog

1. Gambaran Proyek

Proyek ini adalah sistem monitoring PLTS (Pembangkit Listrik Tenaga Surya) berbasis ESP32 untuk baterai 48V LiFePO4. Sistem mencakup telemetri lengkap (tegangan, arus, daya, SOC, suhu, BMS), alarm real-time, kontrol relay 8-channel, OTA update dengan signature verification, dan push notification.

Dua Subsistem

SubsistemFungsiKomponen
PLTS Monitor (dasbor)Telemetri → Google Apps Script → PWA Next.js; realtime MQTT opsionalfirmware/, firmware-generic/, code.gs/, scripts/
Push-Alarm MonitorIoTAlarm sensor via Web Push terenkripsi (VAPID + aes128gcm)push-alarm/

Prinsip Inti

  • Never fabricate certainty — setiap pengukuran membawa value/unit/quality/source/timestamp; sensor gagal → null (bukan 0)
  • Fail-closed — production build menolak konfigurasi tanpa signature/CA/allowlist
  • Immutable releases — setiap release ditandatangani GPG + Ed25519, provenance binding machine-verifiable

2. Arsitektur Sistem

text
┌─────────────────────────────────────────────────────────────┐
│                     ESP32-WROOM-32                          │
│                                                             │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
│  │ INA219   │  │ ADC GPIO │  │ SHT31    │  │ PCF8574  │   │
│  │ (Arus)   │  │ (Tegang) │  │ (Suhu)   │  │ (Relay)  │   │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘   │
│       │ I²C         │ ADC         │ I²C         │ I²C      │
│  ┌────┴─────────────┴─────────────┴─────────────┴────┐    │
│  │              Firmware v1.9.3                      │    │
│  │  • Dynamic PGA Switching (±80mV / ±160mV)        │    │
│  │  • Voltage Divider 190kΩ/10kΩ (20:1)             │    │
│  │  • 8-Channel Relay Controller (E-WAVE)           │    │
│  │  • Reproducible Build (deterministic identity)   │    │
│  │  • OTA Manager (Ed25519 + SHA-256)               │    │
│  │  • MQTT TLS / HTTPS telemetry                    │    │
│  └───────────────────┬──────────────────────────────┘    │
│                      │                                    │
└──────────────────────┼────────────────────────────────────┘
                       │
              ┌────────┴────────┐
              │   WiFi / MQTT   │
              └────────┬────────┘
                       │

Topologi Operasi

TopologiTransportBackendUse Case
A (Dasbor)HTTPS POSTGoogle Apps Script + Google SheetsStandby/standalone tanpa internet real-time
B (Realtime)MQTT TLSBroker MQTT + PWA subscribeReal-time dashboard dengan live updates

3. Struktur Repositori

text
PLTSMonitoring_Firmware-Backend/
├── firmware/                    # Modular production firmware (v1.9.3)
│   ├── Core/                    #   Config.h, Types.h, Globals.h, Common.h
│   ├── Drivers/                 #   INA219, ADC, SHT31, ACS712, PCF8574, RTC
│   ├── Services/                #   OtaManager, RelayController, AlarmRegistry, dll
│   ├── Network/                 #   MQTT transport, telemetry publisher, OTA handler
│   ├── Web/                     #   HTTP server, REST handlers (status, OTA, config, dll)
│   ├── Storage/                 #   NVS config store, filesystem
│   ├── Utils/                   #   Crypto (Ed25519), CRC, I2C recovery, JSON
│   ├── AI/                      #   GasAdvisor (HMAC-signed AI insights)
│   ├── Comm/                    #   BMS protocols (CAN, Modbus RTU/TCP)
│   ├── firmware_v1.ino          #   Main entry point
│   ├── platformio.ini           #   Build configs: development, staging, production
│   └── partitions_ota_1mb5.csv  #   OTA partition table
│
├── firmware-generic/            # Generic firmware (ESP Web Tools flashing)
│   ├── src/
│   │   └── plts_firmware_v1.ino #   Single-file firmware (same features, simpler build)
│   ├── manifest.json            #   ESP Web Tools manifest (v1.9.3)
│   ├── platformio.ini
│   └── bin/                     #   CI-built binaries (gitignored)
│
├── code.gs/                     # Google Apps Script backend
│   └── Code.gs                  #   doPost handler, telemetry ingest, HMAC, OTA dispatch

4. Hardware Requirements

Komponen Utama

KomponenSpesifikasiFungsi
ESP32-WROOM-32Dual-core 240MHz, 4MB Flash, WiFi+BTMikrokontroler utama
INA219I²C 0x40, shunt 100A/75mV (R=0.75mΩ)Pengukuran arus baterai (1A–150A)
Shunt Resistor100A/75mV (0.75mΩ)Low-side current sensing
Voltage DividerR1=190kΩ, R2=10kΩ (ratio 20:1) + 0.1µF capPembacaan tegangan baterai 42–57.5V via ADC
SHT31I²C, ±0.3°C, ±2%RHSuhu + kelembaban ambient
PCF8574I²C expander 8-bit8-channel relay control
Relay Module8-channel, active-LOW optocouplerKontrol beban PLTS
Emergency RelayActive-LOW, normally-closed E-stopSafety cutoff (hardware-level)
ACS712-30A (opsional)ADC GPIO35Arus AC inverter
PZEM-004T (opsional)Modbus RTUMeter AC presisi

Wiring INA219 (Low-Side Sensing)

text
Baterai (+) ──────────────────────────────────────── Beban (+)
                                              │
                                         [Divider]
                                         R1=190kΩ
                                              │
Baterai (−) ──────┬──────────────────────┬───── ADC GPIO34
                  │                      │
              [Shunt 100A]              R2=10kΩ
              75mV, 0.75mΩ               │
                  │                   [0.1µF]
                  ├──── INA219 Vin+      │
                  │                      │
                  └──── INA219 Vin−      │
                  │                      │
                 GND ────────────────────┘

Penting: R100 (0.1Ω) bawaan modul INA219 wajib dicopot. Gunakan shunt eksternal 100A/75mV. INA219 dipasang low-side (jalur GND) karena Vbus bisa 57.5V > 26V max INA219.

Pin Assignment

GPIOFungsiModul
21I²C SDAINA219, SHT31, PCF8574
22I²C SCLINA219, SHT31, PCF8574
34ADC1 CH6Voltage divider (input-only, WiFi-safe)
35ADC1 CH7ACS712 AC current (opsional)
0BOOT buttonFactory reset trigger
2Built-in LEDStatus indicator

5. Firmware v1.9.x — INA219 Dynamic Gain Switching

Masalah

Rentang arus PLTS sangat lebar: 1A (standby) hingga 150A (beban puncak). Single PGA range INA219 tidak bisa cover keduanya:

  • ±80mV: saturasi di ~106A (150A × 0.75mΩ = 112.5mV > 80mV)
  • ±160mV: resolusi buruk di arus standby 1–2A

Solusi: Dynamic PGA Switching

Firmware v1.9.2+ (termasuk v1.9.3) secara otomatis beralih PGA berdasarkan besaran arus:

ModeRegisterPGA RangeMax CurrentResolusi
Standby0x0FFF±80mV (gain /2)106A10µV/bit (0.013A)
Peak0x17FF±160mV (gain /4)213A10µV/bit

Hysteresis

text
|I| < 90A   → ±80mV  (high-resolution standby)
|I| ≥ 100A  → ±160mV (peak load, no saturation)

Gap 10A mencegah chattering saat beban hover di sekitar threshold.

INA219 Config Register (TI Datasheet SBOS448G)

text
Bit 15    : RST (1 = reset)
Bit 14    : RESERVED (must be 0)
Bit 13    : BRNG (0 = 16V FSR, 1 = 32V FSR)
Bits 12:11: PG (00=±40mV, 01=±80mV, 10=±160mV, 11=±320mV)
Bits 10:7 : BADC (4-bit, 1111 = 12-bit/128-sample/68ms)
Bits 6:3  : SADC (4-bit, 1111 = 12-bit/128-sample/68ms)
Bits 2:0  : MODE (111 = shunt+bus continuous)

Safety Features

  1. Register readback verification — setiap PGA switch diverifikasi via I²C readback
  2. Sample discard — sample pertama setelah PGA switch dibuang (settling time 68ms)
  3. Saturation detection — di ±80mV mode, jika shunt > 78mV → emergency switch ke ±160mV
  4. pga_mode telemetry — field bat.pgaMode ("80mV"/"160mV") dikirim ke backend + PWA

Verifikasi Register

bash
python3 scripts/decode_ina219_config.py 0x0FFF 0x17FF
python3 scripts/test_ina219_config_registers.py

6. Panduan Deployment Lengkap

Prasyarat

  • PlatformIO Core 6.1.18+ (pip install platformio)
  • Python 3.11+ (untuk scripts)
  • Git dengan GPG signing configured
  • Google Account (untuk Apps Script + Sheets)
  • Vercel Account (untuk PWA deployment — lihat repo PWA)

Langkah 1: Clone Repositori

bash
git clone https://github.com/desvandi/PLTSMonitoring_Firmware-Backend.git
cd PLTSMonitoring_Firmware-Backend

Langkah 2: Build Firmware

Opsi A: Modular Production (Recommended)
bash
cd firmware

# Set production secrets (WAJIB sebelum build production)
export MQTT_BROKER_HOST="your-broker.example.com"
export MQTT_BROKER_PORT="8883"
export MQTT_USERNAME="plts-device"
export MQTT_PASSWORD="your-password"
export MQTT_ROOT_CA="$(cat roots.pem)"
export OTA_ED25519_PUBLIC_KEY_HEX="your-64-hex-char-public-key"
export OTA_HTTPS_ROOT_CA="$(cat ota-ca.pem)"

# Build
pio run -e production

# Output: .pio/build/production/firmware.bin
Opsi B: Development (tanpa secrets)
bash
cd firmware
pio run -e development
Opsi C: Generic (ESP Web Tools browser flashing)
bash
cd firmware-generic
pio run -e esp32dev
# Output: bin/plts_firmware_v1.9.3.bin

Langkah 3: Sign Firmware (Ed25519)

bash
# Generate keypair (sekali saja)
python3 scripts/sign_firmware.py --gen-keys
# Output: firmware_signing_private.pem + firmware_signing_public.pem

# Sign binary
python3 scripts/sign_firmware.py --sign .pio/build/production/firmware.bin
# Output: firmware.bin.sig (128 hex chars = 64 bytes Ed25519)

# Verify
python3 scripts/sign_firmware.py --verify firmware.bin.sig firmware.bin

Langkah 4: Flash ke ESP32

Via USB (PlatformIO)
bash
cd firmware
pio run -e production -t upload
# Monitor:
pio device monitor -b 115200
Via ESP Web Tools (Browser)
  1. Host firmware-generic/bin/ di web server (GitHub Pages, Vercel, dll)
  2. Buka PWA → Setup → "Install Firmware" button
  3. Browser akan flash via Web Serial API

Langkah 5: Deploy Backend Google Apps Script

  1. Buka script.google.com → New Project
  2. Copy seluruh isi code.gs/Code.gs ke editor
  3. Buat Google Sheet baru, copy ID dari URL
  4. Di Apps Script, jalankan setupMasterTemplate() (Run → function)
  5. Set AUTH_TOKEN di Config sheet (minimal 16 karakter, tidak boleh "CHANGE_ME")
  6. Deploy → New Deployment → Web App
    • Execute as: Me
    • Who has access: Anyone
  7. Copy Web App URL → simpan untuk konfigurasi PWA

Langkah 6: Generate OTA Signing Keys

bash
# Generate Ed25519 keypair untuk OTA
python3 scripts/sign_firmware.py --gen-keys

# Public key hex (untuk firmware Config.h / OTA_ED25519_PUBLIC_KEY_HEX)
xxd -p -c 64 firmware_signing_public.pem | head -1
# Atau:
python3 -c "
from cryptography.hazmat.primitives import serialization
key = open('firmware_signing_public.pem','rb').read()
pub = serialization.load_pem_public_key(key)
raw = pub.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw)
print(raw.hex())
"

Langkah 7: Konfigurasi ESP32 (via PWA)

  1. Buka PWA di browser (deploy dari repo PWA)
  2. Hubungkan ke WiFi AP ESP32 ("PLTS-Setup-XXXX")
  3. PWA akan redirect ke setup page
  4. Isi: WiFi SSID+password, GAS URL, AUTH_TOKEN, MQTT broker (opsional)
  5. Submit → ESP32 reboot → connect ke WiFi

Langkah 8: Verifikasi

  1. Buka Serial Monitor: pio device monitor -b 115200
  2. Verifikasi log INA219:
    text
    [INA219 0x40] config readback OK: 0x0FFF (BRNG=0 16V, PGA=1 ±80mV, BADC=15, SADC=15, MODE=7)
    [INA219 0x40] init: shunt=0.7500 mΩ, cal=0x..., sign=-1.0, pga=80mV
  3. Buka PWA → verifikasi telemetri muncul
  4. Cek Google Sheet → data telemetri masuk

7. Konfigurasi Firmware

Environment Variables (Production Build)

VariableWajibDescription
MQTT_BROKER_HOSTYaMQTT broker hostname
MQTT_BROKER_PORTYaMQTT port (8883 untuk TLS)
MQTT_USERNAMEYaMQTT username
MQTT_PASSWORDYaMQTT password
MQTT_ROOT_CAYaPEM-encoded Root CA untuk TLS
OTA_ED25519_PUBLIC_KEY_HEXYa64 hex char Ed25519 public key
OTA_HTTPS_ROOT_CAYaPEM Root CA untuk HTTPS OTA download

Runtime Config (via PWA / NVS)

ConfigDefaultDescription
deviceName"PLTS-XXXX"Nama device
siteName"Site"Nama lokasi
idleCurrentThreshold0.5ADeadband arus idle
cfgBmsProtocol"auto"Protokol BMS (auto/CAN/Modbus)

INA219 Constants (firmware/Core/Config.h)

cpp
static constexpr float    INA219_SHUNT_OHM          = 0.00075f;   // 0.75 mΩ
static constexpr float    INA219_PGA_SWITCH_UP_A    = 100.0f;     // switch to 160mV
static constexpr float    INA219_PGA_SWITCH_DOWN_A  = 90.0f;      // switch back to 80mV
static constexpr uint16_t INA219_CONFIG_PGA_80MV   = 0x0FFF;     // ±80mV, 12b/128s, cont
static constexpr uint16_t INA219_CONFIG_PGA_160MV  = 0x17FF;     // ±160mV, 12b/128s, cont

Voltage Divider Constants

cpp
static constexpr float DIVIDER_R1       = 190000.0f;  // 190 kΩ
static constexpr float DIVIDER_R2       = 10000.0f;   // 10 kΩ
static constexpr float DIVIDER_RATIO    = 20.0f;      // (R1+R2)/R2
static constexpr float ADC_FINE_TUNE    = 1.000000f;  // kalibrasi multimeter

8. Backend Google Apps Script

Struktur code.gs/Code.gs

FunctionFungsi
doPost(e)Entry point — parse JSON, HMAC auth, route action
recordTelemetry_(body, deviceKey)Simpan telemetri ke Google Sheets
latestTelemetry_(deviceKey)Baca telemetri terbaru
otaGetManifest_(deviceKey)Serve OTA manifest ke device
otaPublish_(body, deviceKey)Publish OTA command ke device
emergencyCommand_(body, deviceKey)Dispatch emergency command
setupMasterTemplate()Inisialisasi sheets + config (run sekali)

Google Sheets Schema

ColumnFieldType
0timestampDateTime (server)
1device_keyString
2sequenceInteger
3event_timeDateTime (device)
5v_batFloat
6i_bat_dcFloat
7p_bat_dcFloat
8socFloat
.........
39ina219_pga_modeString ("80mV"/"160mV"/"")

HMAC Authentication

text
Authorization: HMAC <deviceKey>:<base64(HMAC-SHA256(authToken, canonicalString))>

9. CI/CD Pipeline

Workflow: .github/workflows/build-firmware.yml

text
push/PR to main → [test] → [build-staging] → [build-generic-tree] → [build-production]
                                                                          ↓
                                                              [release-gate]
                                                                          ↓
                                                          [verify-tag-signature] (tag push only)
                                                                          ↓
                                                      [verify-hardware-acceptance] (tag push only)
                                                                          ↓
                                                          [release-publish] (tag push only)

Jobs

JobTriggerFungsi
Python testsAll pushes30+ unit/property/contract tests
Build stagingAll pushesPlatformIO staging env
Build genericAll pushesPlatformIO generic tree
Build productionAll pushesPlatformIO production env (signed)
Reproducible build 2xAll pushesREL-04: build A vs clean build B — SHA harus byte-identical (modular + generic)
Release gateAll pushesStrict invariant check
Verify tag signatureTag push (v*)GPG tag + authorized signer verification
Verify HW acceptanceTag push (v*)Hardware acceptance JSON gate
Release publishTag push (v*)Create GitHub Release with 20+ assets (requires reproducible-build PASS)

Branch Protection

  • main: PR required, 0 approvals, 4 required status checks
  • Tags v*: deletion + non-fast-forward + creation blocked

10. Release Engineering

Release Chain

text
source → build → sign (Ed25519) → gate → tag-verify (GPG) → hw-verify → release

GPG Tag Signing

bash
# Generate GPG key (RSA 4096)
gpg --full-generate-key

# Configure git
git config --global user.signingkey <KEY_ID>
git config --global tag.gpgsign true

# Sign release tag
git tag -s -a v1.9.2 -m "Release v1.9.2 — INA219 dynamic gain (canonical fix)"

Provenance Binding

Setiap release menyertakan provenance-binding.json yang mengikat:

text
tag → signed tag object → release commit → source commit
→ hardware-tested binary SHA → released binary SHA
→ GitHub Release → PWA canonical release identity

Release Assets (20 files)

AssetDescription
modular-firmware.binModular production firmware (signed)
modular-firmware.bin.sigEd25519 signature
modular-firmware.bin.sha256SHA-256 hash
modular-release.jsonRelease metadata
modular-provenance.jsonBuild provenance
modular-manifest-canonical.jsonSchema 2.0 OTA manifest
generic-*.binGeneric tree binaries
hardware-acceptance.jsonPhysical test evidence
provenance-binding.jsonExplicit provenance chain

11. Hardware Acceptance

General Hardware Acceptance (v1.8.0+)

Protocol 11-criteria: boot, sensors, alarms, OTA REST, OTA MQTT, rollback, emergency relay, config persistence, security, 24h soak, factory reset.

bash
python3 scripts/verify_hardware_acceptance.py \
  --version 1.8.0 \
  --source-commit <SHA> \
  --release-json modular-release.json \
  --hw-dir docs/hardware-acceptance

INA219 Hardware Acceptance (v1.9.2/v1.9.3)

Protocol 12-criteria khusus INA219: config readback, low/mid/peak current accuracy, PGA transitions, hysteresis, current sign, voltage divider, power calculation, telemetry pga_mode. Gunakan v1.9.3.md untuk release line v1.9.3 (measurement chain identik dengan v1.9.2; bukti SHA kini byte-exact karena build reproducible).

bash
python3 scripts/verify_ina219_hardware_acceptance.py \
  --version 1.9.3 \
  --source-commit <SHA> \
  --release-json modular-release.json \
  --hw-dir docs/hardware-acceptance

OTA Physical Test (v1.8.0+)

Protocol 16-criteria: PWA → GitHub Release → download → SHA verify → upload → device flash → reboot → version check → relay safe state → rollback.

bash
python3 scripts/verify_ota_evidence.py \
  --version 1.8.0 \
  --canonical-release-json modular-release.json \
  --ota-dir docs/ota-physical-test

12. Testing

Run All Tests

bash
# Python unit + property tests
python3 scripts/test_ina219_config_registers.py
python3 scripts/test_version_identity.py
python3 scripts/test_voltage_calibration.py
python3 scripts/test_soc_calculation.py
python3 scripts/test_emergency_firmware_logic.py
# ... 30+ test scripts

# JavaScript tests
node scripts/test_wave1_integration.js
node scripts/test_wave2_data_honesty.js
node scripts/test_gas_contract.js

Key Test Scripts

ScriptFungsi
test_ina219_config_registers.pyVerifikasi PGA register constants per datasheet
test_version_identity.pyVersion parity antara modular + generic + manifest
test_wave12_contract_regression.pyCross-layer contract regression
test_ed25519_interop.pyEd25519 signature interop (Python ↔ firmware)
release_gate.pyMaster release gate (strict mode)

13. Troubleshooting

INA219: "config MISMATCH" di Serial Monitor

Penyebab: I²C write gagal atau register constant salah.

Fix:

  1. Cek wiring I²C (SDA=GPIO21, SCL=GPIO22, pull-up 4.7kΩ)
  2. Verifikasi constant: python3 scripts/test_ina219_config_registers.py
  3. Jika constant benar tapi readback gagal → ganti modul INA219

INA219: Arus terbaca 0A / NaN

Penyebab: R100 bawaan modul belum dicopot, atau shunt belum terpasang.

Fix:

  1. Lepas R100 (0.1Ω) dari modul INA219
  2. Pasang shunt 100A/75mV di jalur GND
  3. Verifikasi: VIN+ dan VIN− terhubung ke baut shunt

Voltage Divider: Tegangan tidak akurat

Penyebab: Toleransi resistor ±5% → error hingga ±2V di 57.5V.

Fix:

  1. Ukur tegangan aktual dengan multimeter
  2. Hitung ADC_FINE_TUNE = tegangan_aktual / tegangan_PWA
  3. Update di Config.h: static constexpr float ADC_FINE_TUNE = 1.004016f;
  4. Rebuild + reflash

OTA: "signature header missing (PRODUCTION)"

Penyebab: PWA tidak mengirim header X-Signature.

Fix: Update PWA ke versi terbaru (commit 9c8510a+) yang mengirim X-Expected-SHA256, X-Signature, X-Firmware-Version.

MQTT: "TLS connection failed"

Penyebab: Root CA tidak ter-set atau broker tidak support TLS.

Fix:

  1. Set MQTT_ROOT_CA environment variable sebelum build
  2. Verifikasi broker menggunakan port 8883 (TLS) atau 8884 (TLS+auth)
  3. Test: openssl s_client -connect broker:8883 -showcerts

14. Changelog

v1.9.3 (Current)

  • Reproducible build (REL-03/REL-04 CLOSED) — FIRMWARE_BUILD_DATE tidak lagi __DATE__/__TIME__ (wall-clock); kini diturunkan dari SOURCE_DATE_EPOCH (timestamp commit HEAD git) via firmware/scripts/set_build_date.py. Dua build dari source yang sama = SHA-256 identik.
  • CI job reproducible-build — build 2× (modular production + generic) dari clean tree, compare SHA; release-publish kini mewajibkan job ini (release tak bisa dipublish tanpa bukti determinisme).
  • buildDate semantics — /api/version buildDate kini melaporkan tanggal SOURCE commit (identitas provenance), bukan wall-clock kompilasi.
  • HW acceptance v1.9.3 protocol — template docs/hardware-acceptance/v1.9.3.template.json (12 kriteria sama dengan v1.9.2; evidence firmwareSha256 kini byte-exact vs released binary).
  • Version parity — 1.9.3 di modular (Config.h) + generic (plts_firmware_v1.ino + manifest.json) + mirror PWA (public/firmware/manifest.json).
  • Tidak ada perubahan measurement chain — INA219 PGA 0x0FFF/0x17FF, hysteresis 90A/100A, voltage divider 190k/10k, pga_mode telemetry: semuanya identik dengan v1.9.2.

v1.9.2

  • INA219 dynamic gain switching — PGA ±80mV/±160mV dengan hysteresis 90A/100A
  • Canonical register fix — constants 0x0FFF/0x17FF per TI datasheet SBOS448G
  • Register readback verification — setiap PGA switch diverifikasi via I²C readback
  • Sample discard — sample pertama setelah PGA switch dibuang (settling time)
  • Voltage divider 190kΩ/10kΩ (20:1 ratio) untuk tegangan baterai 42–57.5V
  • pga_mode telemetry — field bat.pgaMode ("80mV"/"160mV") di JSON payload
  • CURRENT_SPIKE_REJECT_A raised 120A → 160A (software ceiling, NOT hardware rating)
  • Mandatory measurement evidence — 17 field observed wajib diisi di HW acceptance

v1.8.0

  • 8-channel relay integration via PCF8574 I²C expander
  • RelayController with safety supervisor (maxOnTime, minOnTime, antiChatter)
  • 5-state lockout (NORMAL→TRIPPED→ACKNOWLEDGED→CLEARED→ARMED)
  • Interlock engine (mutual exclusion + dead time)
  • E-WAVE safety cascade (trip → all relay channels OFF)
  • REST API: /api/relays, /api/relays/{id}/{on|off|pulse}, /api/relays/all_off
  • PWA relay control view with 3-tier state model

v1.7.x

  • OTA boot-health fix (esp_ota_mark_app_valid_cancel_rollback)
  • Mixed-fleet manifest target self-check
  • PZEM-004T real AC meter support
  • Emergency relay + E-stop sense
  • 2nd ACS712 channel (genset→inverter)
  • Cross-layer contract regression tests (WAVE 7-13)

v1.6.x

  • External BMS/inverter comm (CAN, Modbus RTU/TCP)
  • SOC provenance (BMS_DIRECT | SHUNT_COULOMB | OCV_ESTIMATED)
  • Transaction journal for command dedup
  • I²C bus recovery (NOISE-3)

License

MIT — see LICENSE

Kontak

Parts

152
QtyValueFootprintReferences
13100nF 25V X7RC_0603_1608MetricC20, C21, C34, C35, C40, C41, C44, C65, C66, C70, C75, C81, C82
510k 1%R_0603_1608MetricR30, R31, R45, R78, R82
410kR_0603_1608MetricR80, R81, R87, R88
44.7k 1%R_0603_1608MetricR40, R41, R79, R84
4MountingHole_3.2mm_M3MountingHole_3.2mm_M3H1, H2, H3, H4
4SMAJ5.0AD_SMAD22, D23, D24, D25
310uF 16V X5RC_0805_2012MetricC60, C62, C80
315k 1%R_0603_1608MetricR32, R33, R83
3BSS138SOT-23Q21, Q22, Q23
3Fiducial_1mm_Mask2mmFiducial_1mm_Mask2mmFID1, FID2, FID3
2100k 1%R_0603_1608MetricR71, R77
2100nF 50V X7RC_0805_2012MetricC61, C63
210nF 50V X7RC_0603_1608MetricC30, C31
2120R 1%R_0603_1608MetricR48, R49
249.9k 1% 0805R_0603_1608MetricR20a, R20b
25.1kR_0603_1608MetricR85, R86
2600R@100MHzL_0805_2012MetricFB2, FB50
2680R 1%R_0603_1608MetricR51, R52
2ACS712ELCTR-30A-TSOIC-8_3.9x4.9mm_P1.27mmU4, U5
2DT-55-B01X-02TerminalBlock_Dinkle_DT-55-B01X-02_P10.00mmJ_ACS1, J_ACS2
2S8050SOT-23Q1, Q2
2TERM 120RSolderJumper-2_P1.3mm_Open_Pad1.0x1.5mmJP_CAN_TERM, JP_RS485_TERM
1+3V3TestPoint_Pad_D2.0mmTP_3V3
1+5VTestPoint_Pad_D2.0mmTP_5V
1+5V_RELAYTestPoint_Pad_D2.0mmTP_5V_RELAY
10.5A T 63VFuse_1206_3216MetricF1
10.5A holdFuse_1812_4532MetricF2
11.1A holdFuse_1812_4532MetricF4
1100R 1%R_0603_1608MetricR70
1100nF 25V C0GC_0603_1608MetricC43
110uF 16V X5RC_0603_1608MetricC42
11A T 250VAC 5x20Fuseholder_Clip-5x20mm_Littelfuse_111_Inline_P20.00x5.00mm_D1.05mm_HorizontalF3
11kR_0603_1608MetricR74
11k 1%R_0603_1608MetricR55
11uF 25V X7RC_0603_1608MetricC83
12.2k 1%R_0603_1608MetricR22
12.2uF 100V X7RC_0603_1608MetricC50
1330R 1%R_0603_1608MetricR72
14.7uF 16V X5RC_0603_1608MetricC64
147k 1%R_0603_1608MetricR75
147uF 100VCP_Elec_10x10.5C57
147uF 25V X5RC_1210_3225MetricC52
15.6k 1%R_0603_1608MetricR21
168k 1%R_0603_1608MetricR76
1ACS1_ADCTestPoint_Pad_D2.0mmTP_ACS1_ADC
1ACS2_ADCTestPoint_Pad_D2.0mmTP_ACS2_ADC
1AO3400ASOT-23Q20
1AP2112K-3.3SOT-23-5U11
1BAT+TestPoint_Pad_D2.0mmTP_BAT+
1BATT 45-54VTerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_HorizontalJ_BAT
1BAV199SOT-23D30
1BIAS ASolderJumper-2_P1.3mm_Open_Pad1.0x1.5mmJP_RS485_BIAS_A
1BIAS BSolderJumper-2_P1.3mm_Open_Pad1.0x1.5mmJP_RS485_BIAS_B
1BOOTSW_PUSH_6mmSW2
1CAN CANH/CANL/GNDTerminalBlock_Phoenix_MKDS-1,5-3-5.08_1x03_P5.08mm_HorizontalJ_CAN
1CAN_HTestPoint_Pad_D2.0mmTP_CAN_H
1CAN_LTestPoint_Pad_D2.0mmTP_CAN_L
1CDSOT23-T24CANSOT-23D20
1CP2102N-A02-GQFN24HVQFN-24-1EP_4x4mm_P0.5mm_EP2.1x2.1mmU2
1CR2032 3VBatteryHolder_Keystone_106_1x20mmBT1
1DS3231SN#SOIC-16W_7.5x10.3mm_P1.27mmU7
1E-STOP LOOP NCTerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_HorizontalJ_ESTOP
1ENTestPoint_Pad_D2.0mmTP_EN
1ESP32-WROOM-32EESP32-WROOM-32EU1
1EXPANSION 7-PIN 2,54PinHeader_1x07_P2.54mm_VerticalJ_EXP
1E_STOP_SENSETestPoint_Pad_D2.0mmTP_ESTOP
1FL-2 100A/75mVShunt_FL2_100ARSH1
1GCT USB4105-GF-AUSB_C_Receptacle_GCT_USB4105-xx-A_16P_TopMnt_HorizontalJ1
1HF115F-1/5V-HRelay_HF115F_1K1
1I2C EXP 3V3/GND/SDA/SCLPinHeader_1x04_P2.54mm_VerticalJ_I2C_EXP
1INA219AIDCNRSOT-23-8U3
1IO0TestPoint_Pad_D2.0mmTP_IO0
1LM2596HVS 5VModule_LM2596HVSM1
1MAINS L/N 250VACTerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_HorizontalJ_PZEM_AC
1MAX3485CSA+SOIC-8_3.9x4.9mm_P1.27mmU8
1MOV 275VAC DNPRV_Disc_D21.5mm_W5mm_P10mmRV3
1NET-TIE AGND-PGNDNetTie-2_SMD_Pad0.5mmNT1
1NET-TIE DGND-PGND (DIGITAL)NetTie-2_SMD_Pad2.0mmNT2
1NET-TIE PGND-BAT- (STAR)NetTie-2_SMD_Pad2.0mmNT0
1PC817DIP-4_W7.62mmOPT1

The 128 most common of 152 parts.

Similar boards

  • 2 layers77.5 × 107.9 mmPowerBoard, the printed circuit board in 3D

    PowerBoard

    AUV-IITK/electrical-systems

    64 parts4
  • 2 layers150.5 × 48 mmBattery bus, the printed circuit board in 3D

    Battery bus

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    136 parts915
  • 4 layers144 × 127 mmFrothfet, the printed circuit board in 3D

    Frothfet

    hoeken/frothfet

    Yarrboard load controller board with current sense, volt sense, fuses, and sender support.

    394 parts14GPL-3.0
  • 4 layers86 × 29.9 mmGeiger probe, the printed circuit board in 3D

    Geiger probe

    bartkepl/CanGeigerProbe

    Polowa sonda promieniowania jonizującego z miniaturową lampą Geigera-Müllera, komunikująca się cyfrowo przez CAN 2.0B.

    116 partsMIT
  • 4 layers76 × 29.9 mmGnss node, the printed circuit board in 3D

    Gnss node

    bartkepl/CanGnssNode

    Polowy węzeł pozycyjny z modułem GNSS Quectel L76-L (GPS/GLONASS/Galileo/QZSS) i czujnikiem orientacji (akcelerometr + magnetometr), komunikujący się cyfrowo przez CAN 2.0B.

    141 partsMIT
  • 2 layers60 × 47 mmAstro driver, the printed circuit board in 3D

    Astro driver

    rudnik275/astronaut-lamp

    Ночник «космонавт на луне» → нативное HomeKit-устройство на ESP32 + HAA: разбор родной платы, схема драйвера, конфиг, корпус

    51 parts
  • 2 layers63 × 58 mmOPNpool r5, the printed circuit board in 3D

    OPNpool r5

    cvonk/OPNpool

    Integrates the functionality of a Pentair pool controller into the smart home using ESP32 SoC.

    17 parts102
  • 4 layers87.6 × 46.7 mmModbus to x, the printed circuit board in 3D

    Modbus to x

    joachimda/modbus-to-x

    ESP32 based hardware and firmware stack that bridges modbus RTU devices to modern network services.

    58 parts5MIT

Questions

How big is the Plts monitoring controller PCB?

It measures 140 × 100 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Plts monitoring controller use?

152 parts, built around the ESP32-WROOM-32E, MAX3485CSA+T, ACS712ELCTR-30A-T and CP2102N-A02-GQFN24. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Plts monitoring controller KiCad files?

From the desvandi/PLTSMonitoring_Firmware-Backend repository on GitHub, at the commit this page was made from: the board is pcb/plts-monitoring-controller.kicad_pcb and its schematic pcb/01_POWER.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Plts monitoring controller design in my own project?

Its repository states no licence, so its author keeps all rights: ask desvandi before reusing the design.