SmartHome P4
Autonomous controller · ESP32-P4 firmware

SmartHome P4

A local smart-home controller on a 1024×600 touch panel. Up to 15 rooms and 64 devices, relays and discrete inputs over RS-485/Modbus, scenes, schedules and automation rules, MQTT / Home Assistant / IR transports — everything is configured on-screen, stored in NVS and runs without the cloud.

Work in progress. An experimental engineering project by the NARMOVION lab, not a finished product — expect bugs, changes and incomplete functionality; use at your own risk.
SoC: ESP32-P4 rev 1.3 Board radio: ESP32-C6 · Wi-Fi 6 UI: LVGL v9 IDF: v6.0.2 Firmware: smarthome p4 0.22
Download full firmware · BIN 1.7 MB
Single ESP32-P4 merged image · flash at 0x0 · DIO 40 MHz · 16 MB · ESP-IDF v6.0.2
Rooms
15 renamable
Devices
64 in catalogue
Relays
16 2×8 RS-485
Scenes / rules
16/16
Display
1024×600 touch
What it is

A local hub for the home

The firmware is independent from the weather station and GreenHouse P4. On boot app_main turns the backlight off (so no blue MIPI-DSI frame flashes after a reboot or OTA), then brings up storage, time, networking and the automation core in sequence, and only then draws the interface.

All logic runs locally

Relays, inputs, scenes, schedules and rules run on the controller itself. Wi-Fi and MQTT are optional — the home keeps working without the internet.

Configuration in NVS

Rooms, devices, scenes and rules are stored as a single blob (magic 0x53485034, version 4). Wi-Fi and MQTT settings live in their own NVS namespaces.

Safe state

Output state is deliberately never written to flash: after a reboot the configured “safe” position is always restored, never an accidentally latched output.

Manual timeout

A device switched on by hand can turn itself off after a set interval — handy for lights, ventilation and gates.

Platform

Compute, memory and display

A JC1060P470C / JC-ESP32P4-M3 class board: ESP32-P4 as the main SoC and ESP32-C6 as the Wi-Fi 6 radio, connected over ESP-Hosted (SDIO 40 MHz, the single-port Wi-Fi Remote path).

UnitValueNote
SoCESP32-P4 rev 1.32×RISC-V @ 360 MHz, 256 KB L2 cache
RadioESP32-C6Wi-Fi 6 / BLE, ESP-Hosted SDIO 40 MHz
PSRAM32 MBHEX mode, 200 MHz
Flash16 MB (Boya)DIO, 40 MHz
Display1024×600MIPI-DSI, JD9165 panel
TouchCapacitiveon the I²C bus (GPIO7/8)
ConsoleUSB Serial/JTAGlog and flashing, port COM10
Wiring

Interfaces and buses

Peripherals are split across three buses: a shared I²C (touch + climate sensors), an isolated RS-485 for the power side, and the board’s service interfaces (audio, microSD).

I²C GPIO7 / GPIO8

  • Touchscreen of the display
  • SHT45 — temperature, humidity
  • SCD41 — CO₂
  • BH1750 — illuminance
  • 100 kHz, internal pull-ups

RS-485 UART3 · GPIO26/27

  • Isolated connector
  • Modbus-RTU, 9600 8N1
  • 2×8-channel relays (addresses 1/2)
  • Reads discrete inputs

Audio I²S ES8311 / ES7210

  • MCLK 13, SCLK 12
  • WS 10, DOUT 9, DIN 48
  • Power-amp EN GPIO11

microSD SDIO 4-bit

  • CLK 43, CMD 44
  • D0–D3 39–42
  • FatFS
Pins

Full GPIO map

Every pin used by the firmware and the board BSP.

UnitSignalGPIOTypeNote
DisplayMIPI-DSI data/clockDSIMIPI-DSIJD9165 panel, 1024×600
DisplayBacklight (BL)23LEDC/GPIOTurned off first in app_main
DisplayReset (RST)0GPIOPanel reset
I²CSDA7I²C0Touch + sensors, 100 kHz
I²CSCL8I²C0SHT45 / SCD41 / BH1750
RS-485UART3 TX26RS-485Isolated, 9600 8N1
RS-485UART3 RX27RS-485Modbus-RTU relays and inputs
AudioI²S MCLK / SCLK13/12I²SES8311 / ES7210 codec
AudioWS / DOUT / DIN10/9/48I²S—
AudioPower-amp EN11GPIOAmplifier enable
microSDCLK / CMD43/44SDIOFatFS
microSDD0–D339-42SDIO4-bit mode
ServiceGPS UART1 (reserved)37/38UARTReserved, unused in SmartHome
Relay power is separate. The board only provides the RS-485 logic signal. Relay modules and leak/reed sensors are powered from their own supply; RS-485 grounds are tied together and the A/B line runs as a twisted pair.
Relays and inputs

Power peripherals over Modbus-RTU

On the isolated UART3 bus (9600 8N1) the firmware drives up to two 8-channel Waveshare relay modules at addresses 1 and 2 — 16 relays total — and reads their discrete inputs.

Relay control · function 0x05

Single-coil write: channels 0–7 → module 1, 8–15 → module 2, coil number = channel % 8. The command is confirmed by the module’s echo reply. Bus access is serialised with a mutex.

Input read · function 0x02

Every second the 8 discrete inputs of each module are polled. Devices with the “RS485 Input” transport mirror the input state — float switch, leak, reed contact.

TransportPurposeAddressing
RS485 RelayRelay outputchannel 0–15
RS485 InputDiscrete inputchannel 0–15
ModbusGeneric Modbus deviceaddress
I²C / 1-WireLocal sensorsaddress / channel
MQTTPublishes ON/OFF to a command topictopic
Home AssistantMQTT + subscribes to a state topictopic
IRIR remotechannel
Sensors

Built-in I²C bus

A dedicated task polls three sensors on the shared GPIO7/8 bus every 5 seconds with CRC checking. Each sensor’s presence is detected automatically.

SHT45 0x44

  • Temperature −45…+130 °C
  • Humidity relative
  • High-precision command 0xFD

SCD41 0x62

  • CO₂, ppm
  • Periodic measurement
  • Read on data-ready

BH1750 0x23

  • Illuminance, lux
  • Continuous high-resolution mode
  • Divide by 1.2
Status. Readings are gathered in the background and ready for automation. There is no dedicated sensor screen yet — in 0.22 the “Settings” screen is already functional (Wi-Fi and MQTT); sensor readouts will come later.
Automation

Data model and execution rules

Each device is described by a type, transport and address; it also carries a safe state, manual timeout, automation flag, schedule and MQTT topics. Twelve device types: relay, switch, light, thermostat, curtain, ventilation, garage door, intercom, IR remote, sensor, external.

Schedule
The device switches by a start–end window (in minutes, wrapping past midnight). Inert until time is synced over SNTP.
Manual timeout
A device switched on by hand turns itself off after manual_timeout_ms.
Rules
“If the trigger is in state X → set the target to Y.” Up to 16 rules.
Scenes
A 64-bit device mask + target ON/OFF, applied with one button. Up to 16 scenes.
External state
Parsed from MQTT as ON/OFF/OPEN/CLOSED/1/0 on a device’s state topic.
Time
SNTP: pool.ntp.org and time.cloudflare.com, refreshed hourly.
Screens

Interface — 6 pages

Dark theme, #71C9FF accent, instant RU/EN switching (via the button in the top-right corner; since 0.22 the language choice is saved to NVS and restored after a reboot), an SNTP clock and an on-screen keyboard for renaming. The panel below reproduces the real layout and colours of the firmware — tap the tabs at the bottom.

SMARTHOME P4 · SMART HOME
RU
The NAME button on the rooms, devices and scenes screens opens a shared rename dialog: a single-line lv_textarea field and a full lv_keyboard on-screen keyboard.
Firmware

Flash, OTA and flashing

The 16 MB flash is laid out for OTA A/B: two ~6.1 MB app slots, a SPIFFS storage area and a coredump partition for diagnostics.

PartitionTypeOffsetSize
nvsdata / nvs0x00C00024 KB
otadatadata / ota0x0120008 KB
phy_initdata / phy0x0140004 KB
ota_0app0x0200006.1 MB
ota_1app0x6400006.1 MB
storagedata / spiffs0xC600003 MB
coredumpdata / coredump0xF60000640 KB
Flashing the merged image. The downloaded SmartHome_P4_MERGED_v0.22_20260731.bin is written to offset 0x0:
python -m esptool --chip esp32p4 -b 460800 --before default_reset --after hard_reset write_flash 0x0 SmartHome_P4_MERGED_v0.22_20260731.bin
← Back to the Lab