
ReflowOven controller
TilenTinta/ReflowOven_controller
An open source controller for converting kitchen toaster oven to reflow oven

PowerControlHub is a flexible automation controller for 12V systems. It combines relay switching, sensor monitoring, and smart‑home connectivity (MQTT, Home Assistant, REST, BLE) into one device. Ideal for boats, campers, off‑grid cabins, basements, and DIY smart‑home projects, it works as a standalone sensor hub or a full power‑control system.
SmartFuseBox is an open-source printed circuit board by k3ldar, from the k3ldar/PowerControlHub repository on GitHub, published under the GPL-3.0 licence. It is a 4-layer board of 144.2 × 82.8 mm with 93 parts on 91 nets, routed with 490 tracks and 33 vias.
It is built around the SN65HVD230D, DS18B20 and MP2303ADN, with the ULN2803A, SS54 and SRD-12VDC-SL-C among its other parts. Its parts include 33 capacitors, 15 connectors, 12 resistors, 11 diodes and 8 switches. It belongs with the home automation and IoT and radio and wireless boards and the ESP32 boards of this library.
PowerControlHub is an Arduino-based 12V power distribution and control system for marine and off-grid applications. It provides configurable fused relay switching, multi-protocol sensor telemetry, WiFi/BLE/MQTT connectivity, and a companion touchscreen control panel — all managed through a unified serial command protocol and EEPROM-persisted configuration.
Current firmware version: 1.0.0.0 — see
FirmwareVersion.h.
PowerControlHub is a single-unit firmware target running on an Arduino Uno R4 WiFi or ESP32 NodeMCU-32. The Nextion touchscreen display is driven directly by the PCH controller over a dedicated hardware serial port (Serial2 for GPS; display connected via NextionControl).
The firmware entry point is PowerControlHubApp, which owns all subsystem instances and wires them together at startup. Host and debug communication uses a text-based framed serial protocol:
<CMD>:<key>=<value>;<key>=<value>\nCommands are grouped by prefix (F, C, R, H, W, S, M, N, E, T) and are available over serial, USB, and — where applicable — the HTTP REST API. See Docs/Commands.md for the full reference.
Prototype PCBs for PowerControlHub were supported by PCBWay, enabling rapid iteration from design to real-world testing.
See the PCB Sponsorship & Manufacturing page for photos, build details, and ongoing testing.
Default, Horn (COLREGS sound signal output), or NightRelay (automatic day/night switching driven by the LDR sensor).MessageBus on every state change.All sensors inherit from BaseSensor and are registered with SensorController. The RemoteSensor class provides an extensibility point for sensors on external devices that push readings via serial.
| Sensor | Class | Poll Interval | Notes |
|---|---|---|---|
| DHT11 | Dht11SensorHandler | 2 500 ms | Temperature (°C) and relative humidity (%). Raises TemperatureSensorFailure warning on read error; clears automatically on recovery. |
| Light (LDR) | LightSensorHandler | 30 000 ms | Rolling average over 10 readings. 3-reading debounce before day/night state change. Configurable ADC threshold (default 512). Drives a NightRelay automatically. |
| Water Level | WaterSensorHandler | Configurable | 15-reading rolling average. Active-pin corrosion-reduction control (power applied only during measurement). |
| GPS | GpsSensorHandler | Continuous | GY-GPS6MV2 (NMEA). Reports latitude, longitude, altitude, speed (km/h), course, cumulative distance. Provides UTC time for automatic RTC synchronisation. Raises GpsFailure warning if no valid fix for 30 seconds. |
| System Diagnostics | SystemSensorHandler | Configurable | Free heap memory, CPU usage percentage, WiFi/BT enabled state, SD log file size (bytes), system uptime (d HH:MM:SS), active warning count. |
Sensors expose data over Serial, WiFi REST, BLE, and MQTT. Custom local or remote sensors can be added with minimal boilerplate; see Docs/Sensors.md.
C12.MaxConcurrentClients).WeakWifiSignal warning when signal falls below −70 dBm.| Route | Handler | Purpose |
|---|---|---|
/api/relay | RelayNetworkHandler | Relay state read/write |
/api/sensor | SensorNetworkHandler | Sensor telemetry |
/api/sound | SoundNetworkHandler | COLREGS horn signals |
/api/system | SystemNetworkHandler | System status, heartbeat, OTA |
/api/config | ConfigNetworkHandler | Configuration read/write |
/api/warning | WarningNetworkHandler | Warning bitmask access |
/api/timer | SchedulerNetworkHandler | Scheduled event read |
/api/externalsensor | ExternalSensorNetworkHandler | Remote sensor config |
/ | WebIndexNetworkHandler | Index page |
Uses a platform-abstraction interface (IWifiRadio) to isolate board-specific WiFi drivers from application logic.
BLUETOOTH_SUPPORT defined.BluetoothManager:
BluetoothSystemService — system diagnostics characteristics.BluetoothSensorService — sensor telemetry characteristics with notifications.BluetoothRelayService — relay state read and write characteristics.IBluetoothRadio interface — higher-level code operates exclusively through the interface pointer, with runtime null-checks replacing compile-time guards.BLUETOOTH_SUPPORT and WIFI_SUPPORT are mutually exclusive on this board. Enforced by a compile-time #error. On ESP32, both can operate simultaneously.MQTTClient) — no third-party MQTT library dependency.WIFI_SUPPORT. Guarded by #if defined(WIFI_SUPPORT) in BoardConfig.h.A 32-bit bitmask tracks up to 32 independent typed conditions within WarningManager.
SensorFailure (bit 20). SensorFailure clears only when all sensor warnings are cleared.MessageBus via WarningChanged.Event-driven relay automation engine with EEPROM-persisted configuration.
SchedulerSettings.| Dimension | Supported Values |
|---|---|
| Triggers | TimeOfDay, Sunrise, Sunset, Interval, DayOfWeek, Date |
| Conditions | TimeWindow, DayOfWeek, IsDark, IsDaylight, RelayIsOn, RelayIsOff |
| Actions | RelayOn, RelayOff, RelayToggle, RelayPulse, AllRelaysOn, AllRelaysOff, SetPinHigh, SetPinLow |
Sunrise and sunset triggers are computed in real time from GPS coordinates by SunCalculator. The IsDark / IsDaylight conditions fall back to the LDR sensor when GPS is unavailable.
MessageBus provides a lightweight publish/subscribe event system for internal component decoupling. No dynamic allocation occurs at publish time — subscriber lists use function-local statics.
Key events: WarningChanged, RelayStatusChanged, TemperatureUpdated, HumidityUpdated, LightSensorUpdated, WaterLevelUpdated, GpsLocationUpdated, GpsAltitudeUpdated, GpsSpeedUpdated, WifiConnectionStateChanged, WifiSignalStrengthChanged, SystemMetricsUpdated. Full reference: Docs/MessageBus.md.
WIFI_SUPPORT + OTA_AUTO_UPDATE only.k3ldar/PowerControlHub) every 24 hours.PowerControlHub-esp32-v{major}.{minor}.{patch}.{build}.bin with SHA-256 checksum verification.api.github.com; ISRG Root X1 for assets.githubusercontent.com).F12:apply=1 or the OtaFlagAutoApply bit in SystemHeader::reserved[0].idle, checking, available, downloading, rebooting, failed, uptodate) is queryable at any time via F13.SdCardLogger / MicroSdDriver. Configurable SPI pins (C4). Raises SpiPinConfigError, SdCardMissing, SdCardError, or SdCardLowSpace warnings as appropriate.CARD_CONFIG_LOADER) — reads config.txt at boot to override EEPROM settings without reflashing.RtcDS1302Driver) with configurable pins (C18). Automatically synchronised from GPS UTC time on each valid GPS fix.SystemCpuMonitor. Available over serial, WiFi, and MQTT.SystemHeader with magic number validation (0x53464201).C8).ACK:<cmd>=Invalid pin before the value reaches EEPROM. Board-specific tables are selected automatically from the IDF toolchain macros — no manual configuration required. See Docs/PinGuard.md.crashCounter in SystemHeader is incremented at the start of every boot and only reset after full initialisation succeeds. If the counter reaches CrashCounterThreshold (default 3), the firmware resets the config to safe defaults before any hardware initialisation runs, breaking a watchdog reset loop caused by invalid pin configuration.NavigationController manages an ordered list of active pages, rebuilt dynamically when the location type changes — no reboot required.LocationType is Power, Sail, Fishing, or Yacht.Config struct for future HTTP authentication.PowerControlHub/ Firmware source (relays, sensors, WiFi, BLE, MQTT, OTA, SD, Nextion display)
Docs/ Reference documentation
TestData/ Serial command test scriptsPowerControlHubApp
├── MessageBus Pub/sub event bus (no dynamic allocation)
├── RelayController Relay switching, linking, pulse, action types
├── SoundController COLREGS signal sequencer -> horn relay
├── SensorController Sensor pipeline (local + remote)
│ ├── Dht11SensorHandler
│ ├── LightSensorHandler
│ ├── WaterSensorHandler
│ ├── GpsSensorHandler
│ ├── SystemSensorHandler
│ └── RemoteSensor (xN)
├── ConfigController EEPROM config lifecycle
├── WarningManager 32-bit bitmask, sensor failure aggregation
├── ScheduleController Event engine: trigger -> condition -> action
├── WifiController WiFi lifecycle, HTTP REST API
│ └── WifiServer Connection state machine, request routing
├── BluetoothController BLE lifecycle (BLUETOOTH_SUPPORT)
│ └── BluetoothManager
│ ├── BluetoothSystemService
│ ├── BluetoothSensorService
│ └── BluetoothRelayService
├── MQTTController MQTT 3.1.1 client, HA auto-discovery (MQTT_SUPPORT)
├── SdCardLogger SD card log writer (SD_CARD_SUPPORT)
├── RtcDS1302Driver DS1302 real-time clockWiFi and Bluetooth subsystems are each accessed through a platform-agnostic interface (IWifiRadio, IBluetoothRadio). Board-specific drivers (R4WifiRadio, Esp32WifiRadio, BluetoothController) are constructed only inside PowerControlHubApp under the appropriate #if defined(...) guard. All higher-level code operates through interface pointers with runtime null-checks, minimising preprocessor usage and enabling straightforward test doubles.
The Config struct is a versioned, packed POD serialised to EEPROM. The current layout version is 6 (ConfigVersion6). The SystemHeader (32 bytes) precedes the config payload and contains a magic number (0x53464201), boot count, crash counter, reset reason, OTA flags, and a 16-bit checksum. A config version mismatch triggers migration logic in ConfigManager and raises DefaultConfigurationFuseBox.
| Board | WiFi | BLE | MQTT | OTA | Notes |
|---|---|---|---|---|---|
| Arduino Uno R4 WiFi | Yes | Yes | Yes | No | WiFi and BLE are mutually exclusive (shared RF path) |
| Arduino Uno R4 Minima | No | No | No | No | Serial and sensor support only |
| ESP32 NodeMCU-32 | Yes | Yes | Yes | Yes | Full feature support; WiFi and BLE simultaneous |
Board selection is controlled by a single #define in Local.h using the trailing-underscore convention. BoardConfig.h derives all capability flags, EEPROM limits, and enforces incompatible feature combinations at compile time.
| Requirement | Details |
|---|---|
| Arduino IDE | 1.8.19 or Arduino IDE 2.x |
| Git for Windows | Standard installation |
| Windows 10 / 11 | No special configuration required |
| Library | Source |
|---|---|
SerialCommandManager | Si Carter |
DHT sensor library | Adafruit |
QMC5883LCompass | Arduino Library Manager |
NextionControl | Custom — copy NextionControl/ folder to Arduino libraries/ directory |
Clone the repository:
git clone https://github.com/k3ldar/PowerControlHubInstall all required libraries via the Arduino IDE Library Manager, and copy NextionControl manually.
Open k3ldar/PowerControlHub.ino in the Arduino IDE.
Edit Local.h to activate the correct board and feature flags (see Configuration).
Select the target board and COM port, then upload.
Full setup walkthrough: Docs/SETUP.md.
All hardware-specific configuration is isolated in a single file: PowerControlHub/Local.h. No other file requires modification for a standard hardware setup.
Exactly one board define must be active. Remove the trailing underscore to activate:
#define ARDUINO_UNO_R4 // Arduino Uno R4 WiFi
#define ARDUINO_R4_MINIMA_ // Arduino Uno R4 Minima (inactive)
#define ESP32_NODE_32_ // ESP32 NodeMCU-32 (inactive)| Define | Default | Approx. Flash | Description |
|---|---|---|---|
FUSE_BOX_CONTROLLER | Active | — | Enables the full SFB subsystem stack |
WIFI_SUPPORT | Active | — | WiFi controller and HTTP REST API |
MQTT_SUPPORT | Active | ~40 KB | MQTT client and HA auto-discovery (requires WIFI_SUPPORT) |
BLUETOOTH_SUPPORT | Inactive | ~144 KB | BLE services (mutually exclusive with WiFi on Uno R4) |
SD_CARD_SUPPORT | Active | ~32 KB | SD card logger and SPI driver |
NEXTION_DISPLAY_DEVICE | Active | ~52 KB | Nextion display page system |
OTA_AUTO_UPDATE | Active | ~165 KB | GitHub OTA (ESP32 + WiFi only) |
LED_MANAGER | Inactive | — | Arduino R4 WiFi LED matrix (experimental) |
CARD_CONFIG_LOADER | Inactive | — | Load config overrides from SD config.txt at boot |
constexpr uint8_t ConfigRelayCount = 8; // number of relay channelsPins are assigned at runtime via the R11 serial command and persisted to EEPROM. 0xFF marks a pin as unassigned.
Full configuration reference: Docs/Local.md.
Commands follow the frame format: <CMD>:<key>=<value>;<key>=<value>\n
# Save config to EEPROM
C0
# Enable WiFi in client mode, set SSID and password
C11:v=1
C12:v=1
C13:YourSSID
C14:YourPassword
C0
# Switch relay 0 on / off
R3:i=0;v=1
R3:i=0;v=0
# Query all relay states
R2
# Read temperature and humidity
S0
S1
# Enable MQTT and set broker
M0:v=1
M1:192.168.1.100Full command reference (all groups, all parameters): Docs/Commands.md.
# Relay control
POST /api/relay/R3?i=0&v=1
# Sensor data
GET /api/sensor/S0
# System status
GET /api/system/F2
# OTA status
GET /api/system/F13| Document | Contents |
|---|---|
| Docs/Commands.md | Full serial and REST command reference (all groups F, C, R, H, W, S, M, N, E, T) |
| Docs/Local.md | Local.h configuration reference: board selection, feature flags, pin layout |
| Docs/PinGuard.md | GPIO validation: board pin tables, blocked pin tiers, crash loop guard |
| Docs/Sensors.md | Sensor classes, poll intervals, MQTT channels, warning behaviour, extensibility guide |
| Docs/Warnings.md | 32-bit warning type reference, WarningManager API, propagation model |
| Docs/Wifi.md | WiFi architecture: connection state machine, persistent connection model, handler pattern |
| Docs/BluetoothBle.md | BLE service/characteristic reference, connection model, adding new services |
| Docs/ScheduleEvents.md | Scheduler data structures, trigger/condition/action types, EEPROM layout |
| Docs/MessageBus.md | Event reference, publish/subscribe API |
| Docs/SETUP.md | Prerequisites, library installation, build instructions |
| Docs/BOM.md | Bill of materials: hardware, fasteners, connectors, 3D-printed parts |
OTA_AUTO_UPDATE defined. Not available on Arduino Uno R4.LED_MANAGER): Experimental on Arduino R4 WiFi; not recommended for production use.Local.h. SPI pin configuration must be correct or SpiPinConfigError is raised.PowerControlHub is released under the GNU General Public License v3.0.
See LICENSE for the full licence text.
Copyright © 2025 Simon Carter (s1cart3r@gmail.com)
| Qty | Value | Footprint | References |
|---|---|---|---|
| 14 | 0.1uf | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C1, C5, C7, C9, C11, C12, C14, C16, C19, C21, C23, C25, C27, C30 |
| 13 | 10uf | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C2, C6, C8, C10, C13, C15, C17, C18, C20, C22, C24, C26, C28 |
| 10 | SS54 | Diode_SMD:D_SMA | D1, D2, D3, D4, D5, D6, D7, D8, D9, D10 |
| 8 | Conn_01x03_Socket | TerminalBlock:TerminalBlock_MaiXu_MX126-5.0-03P_1x03_P5.00mm | J2, J4, J5, J6, J7, J8, J9, J10 |
| 8 | SRD-12VDC-SL-C | Relay_THT:Relay_SPDT_SANYOU_SRD_Series_Form_C | K1, K2, K3, K4, K5, K6, K7, K8 |
| 4 | Conn_01x04_Socket | Connector_JST:JST_PH_S4B-PH-K_1x04_P2.00mm_Horizontal | J11, J12, J13, J14 |
| 4 | MountingHole | MountingHole:MountingHole_3.2mm_M3 | H1, H2, H3, H4 |
| 3 | 1k | Passives:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R1, R5, R8 |
| 3 | 4.7k | Passives:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R12, R13, R19 |
| 2 | 12uf | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C31, C33 |
| 2 | Conn_01x02_Socket | TerminalBlock:TerminalBlock_MaiXu_MX126-5.0-02P_1x02_P5.00mm | J1, J3 |
| 1 | 100k | Passives:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R14 |
| 1 | 10k | Passives:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R16 |
| 1 | 10nf | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C29 |
| 1 | 10uH, 4A | Inductor_SMD:L_SOREDE_SNR.1050_10x10x5mm | L2 |
| 1 | 120R | Passives:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R11 |
| 1 | 2k | Passives:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R18 |
| 1 | 4.8nf | Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder | C32 |
| 1 | 44.2k | Passives:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R17 |
| 1 | 470uf | Capacitor_SMD:CP_Elec_10x10.5 | C4 |
| 1 | 680uf | Capacitor_SMD:CP_Elec_6.3x7.7 | C3 |
| 1 | 8.2k | Passives:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder | R15 |
| 1 | BC817 | PCM_4ms_Package_SOT:SOT-23 | Q1 |
| 1 | BK-6013 | Semiconductors:FUSE_BK-6013 | XF1 |
| 1 | Buzzer | Buzzer_Beeper:Buzzer_12x9.5RM7.6 | BZ1 |
| 1 | Conn_01x02_Socket | Connector_JST:JST_XH_S2B-XH-A-1_1x02_P2.50mm_Horizontal | J15 |
| 1 | DS18B20 | Package_TO_SOT_THT:TO-92_Inline | U2 |
| 1 | ESP32-S3-DEVKITC-1-N16R8V | Modules_Sensors:XCVR_ESP32-S3-DEVKITC-1-N16R8V | U6 |
| 1 | LED | LED_SMD:LED_0805_2012Metric_Pad1.15x1.40mm_HandSolder | D12 |
| 1 | MP2303ADN | Package_SO:SOIC-8-1EP_3.9x4.9mm_P1.27mm_EP2.62x3.51mm | U3 |
| 1 | NPN | PCM_4ms_Package_SOT:SOT23-3_PO123 | Q2 |
| 1 | SN65HVD230 | Package_SO:SOIC-8_3.9x4.9mm_P1.27mm | U5 |
| 1 | ULN2803A | Package_SO:SOIC-18W_7.5x11.6mm_P1.27mm | U1 |
It measures 144.2 × 82.8 mm and has 4 copper layers, 1.6 mm thick.
93 parts, built around the SN65HVD230D, DS18B20, MP2303ADN and ULN2803A. 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.
From the k3ldar/PowerControlHub repository on GitHub, at the commit this page was made from: the board is KiCad/8Relays/SmartFuseBox.kicad_pcb and its schematic KiCad/8Relays/SmartFuseBox.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the GPL-3.0 licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

TilenTinta/ReflowOven_controller
An open source controller for converting kitchen toaster oven to reflow oven

klaus-liebler/sensact
Es gibt vier Namespaces für Nachrichten "REQUEST" und "RESPONSE", "EVENT" und "ACKNOWLEDGE". Dies wird mit den beiden LSB des Versions-Namespace-Bytes erklärt (Somit bleiben 64 Versionierungsmöglichkeiten) Alle vier…

hpbock/moba-bockstelle
Ein Blockstellenmodul für analoge Modellbahnen zur Ansteuerung von Lichtsignalen, Zugbeeinflussung und Belegtmeldung für Loconet-T.


renatorgr/Boards
Hardware and firmware for the AgOpenGPS AiO v4.5 autosteer boards: Teensy 4.1 firmware with its own web page (GPS, IMU, autosteer), a XIAO ESP32 Wi-Fi status page, XIAO adapter boards, and an Arduino Nano sprayer…

paulsonnentag/button-grid
An ESP32-S3 controller board for an 8×8 button matrix with 64 individually switched 12 V LEDs. It's designed in KiCad 9 and made to be ordered from JLCPCB.

schwabix-1311/aquaPCB
Open-hardware Raspberry Pi base board for aquaPi software. 12 V supply; six 5 A MOSFET outputs for LED lamps and fans (2 with hardware PWM); 4 SSR/relay drivers; protected inputs; 1-Wire; ADS1115 with a pH amplifier on…

sillevl/spha-rel6-hardware
Open the .kicadpro file in KiCad. The design includes files originating from an older KiCad workflow; review schematic links, footprints, design rules, zones, and manufacturing outputs after any conversion or upgrade.