Clean up RFP ESP32-S3 target and tooling
Some checks failed
WLED CI / wled_build (push) Has been cancelled
Deploy Nightly / wled_build (push) Has been cancelled
Deploy Nightly / Deploy nightly (push) Has been cancelled

This commit is contained in:
2026-04-17 01:00:37 +02:00
parent 3a01c00635
commit 95137a6d65
7 changed files with 278 additions and 43 deletions

3
.gitignore vendored
View File

@@ -5,8 +5,11 @@
.gitignore .gitignore
.idea .idea
.pio .pio
.piohome
.pioenvs .pioenvs
.piolibdeps .piolibdeps
.tools
.venv
.vscode .vscode
.vscode/extensions.json .vscode/extensions.json

View File

@@ -0,0 +1,64 @@
# RFP ESP32-S3 WROOM-1 N16R8 (3 x 106)
This repository includes a tracked PlatformIO target for the RFP ESP32-S3 WROOM-1 N16R8 nodes with three LED outputs and 106 pixels per output.
Build target:
- `rfp_esp32s3_wroom1_n16r8_3x106`
Default output pins:
- Output 1: `GPIO4`
- Output 2: `GPIO5`
- Output 3: `GPIO6`
Pins intentionally avoided:
- `GPIO0`, `GPIO3`, `GPIO45`, `GPIO46` for boot / strapping
- `GPIO19`, `GPIO20` for USB
- `GPIO33` to `GPIO37` because they are reserved by octal PSRAM / flash on `N16R8`
- `GPIO48` because it is used as the onboard status pixel
Build:
```powershell
python -m platformio run -e rfp_esp32s3_wroom1_n16r8_3x106
```
Build and upload:
```powershell
.\tools\flash_rfp_s3.ps1 -ComPort COM7
```
Build only with the helper script:
```powershell
.\tools\flash_rfp_s3.ps1 -BuildOnly
```
Local Wi-Fi defaults:
- Keep SSID and password in the ignored file `wled00/my_config.h`.
- If the file does not exist yet, create it with your local values:
```cpp
#pragma once
#define CLIENT_SSID "your-ssid"
#define CLIENT_PASS "your-password"
```
Important:
- The `3 x 106` bus layout is used as the default when the device has no saved `cfg.json`.
- If a board already has a saved WLED config, do a factory reset or erase settings once so the default bus layout is recreated.
Onboard status pixel on `GPIO48`:
- `green blinking`: DDP realtime active
- `green solid`: network connected
- `blue blinking`: AP / setup mode active
- `red fast blinking`: Wi-Fi configured but currently disconnected
- `amber fast blinking`: network connected, MQTT configured, but MQTT not connected
- `off`: idle / no status to show

View File

@@ -107,6 +107,7 @@ default_envs =
;; === esp32-S3 === with 16MB flash ;; === esp32-S3 === with 16MB flash
esp32S3_16MB_PSRAM_M_HUB75 ;; for S3 with 16MB flash, HUB75 supported (MOONHUB HUB75 adapter board) esp32S3_16MB_PSRAM_M_HUB75 ;; for S3 with 16MB flash, HUB75 supported (MOONHUB HUB75 adapter board)
esp32S3_WROOM-2_M ;; for S3 WROOM-2; HUB75 supported esp32S3_WROOM-2_M ;; for S3 WROOM-2; HUB75 supported
; rfp_esp32s3_wroom1_n16r8_3x106 ;; RFP ESP32-S3 WROOM-1 N16R8, 3x106 pixels on GPIO 4/5/6
;; ;;
;; === esp32-S2 boards === ;; === esp32-S2 boards ===
esp32s2_PSRAM_S ;; OTA-compatible with upstream esp32s2_PSRAM_S ;; OTA-compatible with upstream
@@ -2438,6 +2439,32 @@ build_flags = ${env:esp32S3_8MB_PSRAM_M_opi.build_flags}
[env:esp32S3_8MB_PSRAM_M] ;; legacy alias [env:esp32S3_8MB_PSRAM_M] ;; legacy alias
extends = env:esp32S3_8MB_PSRAM_M_opi extends = env:esp32S3_8MB_PSRAM_M_opi
[env:rfp_esp32s3_wroom1_n16r8_3x106]
;; RFP ESP32-S3 WROOM-1 N16R8, 16MB flash / 8MB OPI PSRAM, 3 outputs x 106 pixels
extends = env:esp32S3_8MB_PSRAM_M_opi
board_upload.flash_size = 16MB
board_upload.maximum_size = 16777216
board_build.partitions = tools/WLED_ESP32_16MB.csv
build_unflags = ${env:esp32S3_8MB_PSRAM_M_opi.build_unflags}
-D WLED_RELEASE_NAME=esp32S3_8MB_PSRAM_M_opi
-D LEDPIN=21
-D BTNPIN=0
-D RLYPIN=1
-D IRPIN=-1
-D AUDIOPIN=-1
build_flags = ${env:esp32S3_8MB_PSRAM_M_opi.build_flags}
-D WLED_RELEASE_NAME=RFP_ESP32S3_N16R8_3x106
-D LEDPIN=4
-D DATA_PINS=4,5,6
-D PIXEL_COUNTS=106,106,106
-D DEFAULT_LED_COUNT=106
-D STATUSPIXELPIN=48
-D STATUSPIXELCOLORORDER=COL_ORDER_GRB
-D BTNPIN=-1
-D RLYPIN=-1
-D IRPIN=-1
-D AUDIOPIN=-1
[env:esp32S3_8MB_S] [env:esp32S3_8MB_S]
;; MM for ESP32-S3 boards - FASTPATH + optimize for speed; ; HUB75 support included (may still have pin conflicts) ;; MM for ESP32-S3 boards - FASTPATH + optimize for speed; ; HUB75 support included (may still have pin conflicts)
extends = esp32_4MB_V4_M_base extends = esp32_4MB_V4_M_base

44
tools/flash_rfp_s3.ps1 Normal file
View File

@@ -0,0 +1,44 @@
param(
[string]$ComPort,
[switch]$BuildOnly
)
$ErrorActionPreference = "Stop"
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$repoRoot = Split-Path -Parent $scriptDir
$envName = "rfp_esp32s3_wroom1_n16r8_3x106"
$venvPython = Join-Path $repoRoot ".venv\Scripts\python.exe"
if (-not $BuildOnly -and [string]::IsNullOrWhiteSpace($ComPort)) {
throw "ComPort is required unless -BuildOnly is used."
}
if (Test-Path $venvPython) {
$pythonCommand = $venvPython
$pythonArgs = @()
} elseif (Get-Command py -ErrorAction SilentlyContinue) {
$pythonCommand = "py"
$pythonArgs = @("-3")
} elseif (Get-Command python -ErrorAction SilentlyContinue) {
$pythonCommand = "python"
$pythonArgs = @()
} else {
throw "No Python runtime found. Install Python or create .venv first."
}
$pioHome = Join-Path $repoRoot ".piohome"
$env:PLATFORMIO_CORE_DIR = $pioHome
$env:PLATFORMIO_PACKAGES_DIR = Join-Path $pioHome "packages"
$env:PLATFORMIO_PLATFORMS_DIR = Join-Path $pioHome "platforms"
$env:PLATFORMIO_CACHE_DIR = Join-Path $pioHome ".cache"
$env:PLATFORMIO_BUILD_CACHE_DIR = Join-Path $pioHome "buildcache"
$args = @("-m", "platformio", "run", "-e", $envName)
if (-not $BuildOnly) {
$args += @("-t", "upload", "--upload-port", $ComPort)
}
& $pythonCommand @pythonArgs @args
exit $LASTEXITCODE

View File

@@ -168,6 +168,9 @@ String PinManagerClass::getPinSpecialText(int gpio) { // special purpose PIN in
#endif #endif
#if defined(STATUSPIXELPIN)
if (gpio == STATUSPIXELPIN) return(F("WLED Status Pixel"));
#endif
#if defined(STATUSLED) #if defined(STATUSLED)
if (gpio == STATUSLED) return(F("WLED Status LED")); if (gpio == STATUSLED) return(F("WLED Status LED"));
#endif #endif

View File

@@ -71,6 +71,73 @@
#endif #endif
// WLEDMM end // WLEDMM end
#if defined(STATUSLED) || defined(STATUSPIXELPIN)
static inline void writeStatusIndicator(uint32_t color) {
#if defined(STATUSPIXELPIN)
if (statusPixelBus != nullptr) {
if (statusPixelBus->canShow()) {
statusPixelBus->setPixelColor(0, color);
statusPixelBus->show();
}
return;
}
#endif
#if defined(STATUSLED)
#if STATUSLED >= 0
#ifdef STATUSLEDINVERTED
digitalWrite(STATUSLED, color ? LOW : HIGH);
#else
digitalWrite(STATUSLED, color ? HIGH : LOW);
#endif
#else
busses.setStatusPixel(color);
#endif
#endif
}
#endif
#if defined(STATUSPIXELPIN)
#ifndef STATUSPIXELCOLORORDER
#define STATUSPIXELCOLORORDER COL_ORDER_GRB
#endif
static void initStatusPixelBus() {
if (statusPixelBus != nullptr) return;
if (pinManager.isPinAllocated(STATUSPIXELPIN)) {
USER_PRINTF("Skipping status pixel on GPIO %u because the pin is already in use.\n", STATUSPIXELPIN);
return;
}
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2)
constexpr uint8_t maxStatusPixelBusses = 4;
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
constexpr uint8_t maxStatusPixelBusses = 2;
#else
constexpr uint8_t maxStatusPixelBusses = 8;
#endif
uint8_t busIndex = busses.getNumBusses();
if (busIndex >= maxStatusPixelBusses) {
USER_PRINTLN(F("Skipping status pixel because no free hardware LED channel is left."));
return;
}
uint8_t pins[] = {STATUSPIXELPIN};
BusConfig statusCfg(TYPE_WS2812_RGB, pins, 0, 1, STATUSPIXELCOLORORDER, false, 0, RGBW_MODE_MANUAL_ONLY);
statusPixelBus = new BusDigital(statusCfg, busIndex, busses.getColorOrderMap());
if (statusPixelBus == nullptr || !statusPixelBus->isOk()) {
delete statusPixelBus;
statusPixelBus = nullptr;
USER_PRINTLN(F("Failed to initialize onboard status pixel."));
return;
}
statusPixelBus->setBrightness(255, true);
writeStatusIndicator(0);
}
#endif
#if INCLUDE_xTaskGetHandle && defined(ARDUINO_ARCH_ESP32) && (defined(WLED_DEBUG) || defined(WLED_DEBUG_HEAP)) #if INCLUDE_xTaskGetHandle && defined(ARDUINO_ARCH_ESP32) && (defined(WLED_DEBUG) || defined(WLED_DEBUG_HEAP))
// WLEDMM stack debug tool - find async_tcp task, and queries it's free stack // WLEDMM stack debug tool - find async_tcp task, and queries it's free stack
@@ -883,6 +950,9 @@ void WLED::setup()
DEBUG_PRINTLN(F("Initializing strip")); DEBUG_PRINTLN(F("Initializing strip"));
beginStrip(); beginStrip();
#if defined(STATUSPIXELPIN)
initStatusPixelBus();
#endif
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(getFreeHeapSize()); DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(getFreeHeapSize());
USER_PRINTLN(F("\nUsermods setup ...")); USER_PRINTLN(F("\nUsermods setup ..."));
@@ -1568,58 +1638,79 @@ void WLED::handleConnection()
} }
// If status LED pin is allocated for other uses, does nothing // If status LED pin is allocated for other uses, does nothing
// else blink at 1Hz when WLED_CONNECTED is false (no WiFi, ?? no Ethernet ??) // green blink = DDP realtime active
// else blink at 2Hz when MQTT is enabled but not connected // blue blink = AP active
// else turn the status LED off // green solid = network connected
// amber fast blink = MQTT configured but disconnected
// red fast blink = WiFi configured but currently disconnected
// off = idle / no status to show
void WLED::handleStatusLED() void WLED::handleStatusLED()
{ {
#if defined(STATUSLED) #if defined(STATUSLED) || defined(STATUSPIXELPIN)
[[maybe_unused]] uint32_t c = 0; uint32_t c = 0;
uint8_t nextType = 0;
uint16_t blinkIntervalMs = 0;
#if STATUSLED>=0 #if defined(STATUSLED) && STATUSLED>=0
if (pinManager.isPinAllocated(STATUSLED)) { if (pinManager.isPinAllocated(STATUSLED)) {
return; //lower priority if something else uses the same pin return; //lower priority if something else uses the same pin
} }
#endif #endif
if (WLED_CONNECTED) { if (realtimeMode == REALTIME_MODE_DDP) {
c = RGBW32(0,255,0,0); c = RGBW32(0,255,0,0);
ledStatusType = 2; nextType = 2;
} else if (WLED_MQTT_CONNECTED) { blinkIntervalMs = 250;
c = RGBW32(0,128,0,0);
ledStatusType = 4;
} else if (apActive) { } else if (apActive) {
c = RGBW32(0,0,255,0); c = RGBW32(0,0,255,0);
ledStatusType = 1; nextType = 2;
blinkIntervalMs = 500;
} else if (WLED_CONNECTED) {
#ifndef WLED_DISABLE_MQTT
if (mqttEnabled && mqttServer[0] != 0 && !WLED_MQTT_CONNECTED) {
c = RGBW32(255,96,0,0);
nextType = 3;
blinkIntervalMs = 250;
} else
#endif
{
c = RGBW32(0,255,0,0);
nextType = 1;
} }
if (ledStatusType) { } else if (WLED_WIFI_CONFIGURED) {
if (millis() - ledStatusLastMillis >= (1000/ledStatusType)) { c = RGBW32(255,0,0,0);
nextType = 3;
blinkIntervalMs = 250;
}
if (nextType != ledStatusType) {
ledStatusType = nextType;
ledStatusLastMillis = millis(); ledStatusLastMillis = millis();
#if 1 ledStatusState = (nextType == 1);
// WLEDMM un-comment this to stop the blinking writeStatusIndicator(ledStatusState ? c : 0);
if ((ledStatusType != 2) && (ledStatusType != 4)) return;
ledStatusState = !ledStatusState;
else
ledStatusState = HIGH;
#else
ledStatusState = !ledStatusState;
#endif
#if STATUSLED>=0
digitalWrite(STATUSLED, ledStatusState);
#else
busses.setStatusPixel(ledStatusState ? c : 0);
#endif
} }
} else {
#if STATUSLED>=0 if (nextType == 0) {
#ifdef STATUSLEDINVERTED if (ledStatusState) {
digitalWrite(STATUSLED, HIGH); ledStatusState = false;
#else writeStatusIndicator(0);
digitalWrite(STATUSLED, LOW); }
#endif return;
#else }
busses.setStatusPixel(0);
#endif if (nextType == 1) {
if (!ledStatusState) {
ledStatusState = true;
writeStatusIndicator(c);
}
return;
}
if (millis() - ledStatusLastMillis >= blinkIntervalMs) {
ledStatusLastMillis = millis();
ledStatusState = !ledStatusState;
writeStatusIndicator(ledStatusState ? c : 0);
} }
#endif #endif
} }

View File

@@ -751,12 +751,15 @@ WLED_GLOBAL bool doSerializeConfig _INIT(false); // flag to initiate savi
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
WLED_GLOBAL bool doPublishMqtt _INIT(false); WLED_GLOBAL bool doPublishMqtt _INIT(false);
// status led // status led / status pixel
#if defined(STATUSLED) #if defined(STATUSLED) || defined(STATUSPIXELPIN)
WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0); WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0);
WLED_GLOBAL uint8_t ledStatusType _INIT(0); // current status type - corresponds to number of blinks per second WLED_GLOBAL uint8_t ledStatusType _INIT(0); // 0=off, 1=solid, 2=slow blink, 3=fast blink
WLED_GLOBAL bool ledStatusState _INIT(false); // the current LED state WLED_GLOBAL bool ledStatusState _INIT(false); // the current LED state
#endif #endif
#if defined(STATUSPIXELPIN)
WLED_GLOBAL BusDigital* statusPixelBus _INIT(nullptr);
#endif
// server library objects // server library objects
WLED_GLOBAL AsyncWebServer server _INIT_N(((80))); WLED_GLOBAL AsyncWebServer server _INIT_N(((80)));