Bus-powered KNX TP device with Wi-Fi. No USB — firmware is installed from the device itself.
There is nothing to flash on this page. The TULX has no USB port; it carries a recovery system that installs firmware over your network. This page publishes the images and explains how to build your own.
TULX32-Recovery-xxxx — without a key as delivered — with its page at
http://192.168.4.1/. Scan for your network there and join it; the page then
shows the device's new address. Until an application is installed that starts, the access point
stays open, so you can go on with the next step on the same page..bin below and upload it under Install from a file.The recovery's access point is open as delivered, so the device stays reachable when it has no network. Give it a key under Recovery access point on the recovery page if you want to close it.
Factory reset: while the recovery is running, hold S1 for 10 s until the LED stays on, then release it. This erases the installed application with all its settings (the KNX configuration included), the Wi-Fi settings and the access-point key. The recovery itself stays: the device comes back as delivered, with its access point open, and an application can be installed again.
| File | Application | Version | Size | MD5 |
|---|
These are application images, not full flash images. The recovery checks the MD5 from the manifest before it starts what it wrote.
Any ESP32-C6 application can run on the TULX. It is installed like the images above (Install from a file); an image without the busware marker is installed after you confirm it. Checked with ESP-IDF 5.5 and Arduino-ESP32 3.x.
.bin your build
produces for the app. A merged image (bootloader + partition table + app) is accepted
too; only its application part is installed. A bootloader alone is refused.0x278000 bytes), the size of
ota_0.The partition table is fixed on the device. Build against it:
partitions_tulx.csv
| Name | Offset | Size | Use |
|---|---|---|---|
nvs | 0x9000 | 20 KiB | NVS — yours, and where the Wi-Fi driver keeps the network |
otadata | 0xE000 | 8 KiB | start selection |
ota_0 | 0x10000 | 2 528 KiB | your application |
storage | 0x288000 | 128 KiB | LittleFS — yours |
actor_db | 0x2A8000 | 32 KiB | NVS used by busware applications |
factory | 0x2B0000 | 1 280 KiB | the recovery — do not touch |
prov | 0x3F0000 | 4 KiB | start pass — do not touch |
rcfg | 0x3F1000 | 4 KiB | access-point key of the recovery — do not touch |
coredump | 0x3F2000 | 56 KiB | core dump |
ota_0 at 0x10000. An ESP32
application is not linked to a flash address — the bootloader maps it through the
MMU — so a normal build fits as long as it uses this table and stays within
2 528 KiB.0x8000: the application reads
the table from there at run time.ota_0 is written. Anything else your build produces
— a LittleFS or SPIFFS image, a data partition — never reaches the device.
Embed initial content in the application and create the file system in
storage on the first start.PlatformIO (Arduino):
[env:tulx]
platform = <an Arduino-ESP32 3.x platform, e.g. pioarduino>
board = esp32-c6-devkitc-1
framework = arduino
board_build.flash_size = 4MB
board_build.partitions = partitions_tulx.csv
; do not add -DARDUINO_USB_CDC_ON_BOOT=1 -- Serial has to stay on UART0
ESP-IDF (sdkconfig.defaults):
CONFIG_IDF_TARGET="esp32c6"
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_tulx.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
CONFIG_ESP_CONSOLE_UART_NUM=0
Upload the application image: .pio/build/tulx/firmware.bin (PlatformIO) or
build/<project>.bin (ESP-IDF).
| Part | Connection |
|---|---|
| MCU | ESP32-C6FH4, 4 MB flash in the package |
| KNX transceiver | NCN5130 in TP-UART mode: GPIO4 = ESP TX → NCN RXD, GPIO5 = ESP RX ← NCN TXD, 38 400 baud 8E1 (set by the hardware) |
| LED | GPIO8, active low |
| Button S1 | GPIO14, active low with an external pull-up. At start-up it is the recovery button (5 s). |
| Console | UART0, on the service connector only — there is no USB |
esp_wifi_start() (in Arduino too:
after WiFi.begin()):
esp_wifi_set_max_tx_power(72); /* quarter-dBm units: 72 = 18 dBm */
At the default 20 dBm the supply collapses under load and the board resets.esp_ota_begin() refuses the partition it runs from. Updates go through the
recovery.factory is the only
partition a running application can select:
#include "esp_ota_ops.h"
const esp_partition_t *f = esp_partition_find_first(
ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
if (f && esp_ota_set_boot_partition(f) == ESP_OK) esp_restart();
The recovery makes your application the start image again when it comes up, so a
restart without installing anything returns to it.WiFi.begin() without
arguments; an ESP-IDF application reads it with esp_wifi_get_config() after
esp_wifi_init().Machine-readable index: manifest.json ·
partition table: partitions_tulx.csv