Skip to content

Commit 40743fd

Browse files
committed
Board Presets and Art-Net-In updates and readPin checks and doc updates
Docs ==== - Add ESPConnect in installation - Add board presets in IO - Add Art-Net In in drivers Back-end ======== - IO: add maxPower for DigOcta and Dig2Go - readPins, only assign if valid(gpio) - Art-Net In: add universe Min/Max
1 parent 966b2b5 commit 40743fd

File tree

9 files changed

+97
-44
lines changed

9 files changed

+97
-44
lines changed

docs/develop/development.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,11 @@ Firmware binaries come in 2 flavours: including boot and partition (merged) and
110110
!!! tip "flash firmware using esptool"
111111
* [>_] in the statusbar of vscode
112112
```
113-
esptool --port /dev/cu.usbmodem11201 write-flash 0x0 ./build/merged/MoonLight_esp32-s3-devkitc-1-n16r8v_0-6-0_webflash.bin
113+
esptool --port /dev/cu.usbserial-1130 write-flash -b 2000000 0x0 ./build/merged/MoonLight_esp32-s3-devkitc-1-n16r8v_0-6-1_webflash.bin
114114
```
115+
* replace port and file to match your setup
115116
* optionally add erase-flash before write-flash
117+
* -b 2000000: Baud rate: lower if too high for your device
116118
* use ./build/release/MoonLight_esp32-s3-devkitc-1-n16r8v_0-6-0.bin and address 0x10000 to flash only the MoonLight partition
117119

118120
### Adding an ESP32 device Definition

docs/gettingstarted/installation.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,18 @@ Keep this page visible until installation complete.
165165

166166
* To install the latest release, you can also use the [MoonLight Installer](https://moonmodules.org/MoonLight/gettingstarted/installer/) (no need to erase the device if updating)
167167
* Upload directly from VSCode, see [Develop / Installation](https://moonmodules.org/MoonLight/develop/installation/)
168+
169+
## Update firmware using ESPConnect
170+
171+
ESPConnect is a browser-based control center for ESP32- and ESP8266-class boards. It runs entirely inside a modern Chromium browser so you can inspect hardware details, manage SPIFFS files, back up flash, and deploy firmware without installing desktop software. It is based on [Jason2866](https://github.com/Jason2866)'s [WebSerial ESPTool](https://github.com/Jason2866/WebSerial_ESPTool/tree/development).
172+
173+
[ESPConnect on GitHub](https://github.com/thelastoutpostworkshop/ESPConnect)
174+
175+
[ESPConnect](https://thelastoutpostworkshop.github.io/microcontroller_devkit/espconnect/)
176+
177+
* Click Connect and choose your device when the browser asks for permission.
178+
* Select Flash Tools, go to Flash Firmware
179+
* Open a firmware.bin file.
180+
* Files ending with _webflash.bin (e.g. MoonLight_esp32-d0_0-6-1_webflash.bin) also formats the partition: choose Flash offset 0x0 or recommended offsets Bootloader. webflash files can be found [here](https://github.com/MoonModules/MoonLight/tree/main/firmware/installer) and are used by the [MoonLight Installer](https://moonmodules.org/MoonLight/gettingstarted/installer/) as well.
181+
* Files ending with .bin, without _webflash (e.g. MoonLight_esp32-d0_0-6-1.bin). Choose recommended offsets App0 (Or App1?). Only use if you previously had MoonLight installed on the device, so the partitions has already been set. These files can be found in [published releases](https://github.com/MoonModules/MoonLight/releases).
182+
* Nightly builds if shared on [discord](https://discord.gg/MTn9mVUG5n).

docs/moonbase/inputoutput.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Currently the following boards are defined. Not all are supported yet 🚧
1111
For each board the following presets are defined:
1212

1313
* Modded: if any change to the default preset is made.
14-
* Max Power: adjust the brightness to approach this max power, depending on the number of LEDs used.
14+
* Max Power in Watts: adjust the brightness to approach this max power, depending on the number of LEDs used. Default 10: 5V * 2A = 10W (so it runs fine on USB).
1515
* Jumper1: If the board contains a jumper, it can define pin behaviour. Eg. select between Infrared and Ethernet.
1616
* Pins: This module is the central place to assign functionality to gpio pins. Other modules and nodes use the pin assignments made here.
1717

@@ -36,9 +36,10 @@ For each board the following presets are defined:
3636
* Current
3737
* Infrared
3838
* Button LightsOn: sets on/off in [Light Control](https://moonmodules.org/MoonLight/moonlight/lightscontrol/)
39+
* Relay LightsOn: sets on/off in [Light Control](https://moonmodules.org/MoonLight/moonlight/lightscontrol/)
40+
* SPI_SCK, SPI_MISO, SPI_MOSI, PHY_CS, PHY_IRQ: S3 Ethernet
3941
* Planned soon
4042
* Battery
41-
* Relay brightness
4243
* DMX (in)
4344
* Planned later
4445
* I2S for microphone and line in
@@ -55,14 +56,22 @@ For each board the following presets are defined:
5556

5657
### QuinLed boards
5758

58-
* Choose the esp32-d0 (4MB) board in the [MoonLight Installer](https://moonmodules.org/MoonLight/gettingstarted/installer/)
59-
* On first install, erase flash first as MoonLight uses a partition scheme with 3MB of flash (no ota at the moment).
59+
![Dig2Go](https://shop.allnetchina.cn/cdn/shop/products/Led_4.jpg?v=1680836018&width=1600){: style="width:100px"}
60+
![Dig Uno](https://quinled.info/wp-content/uploads/2020/02/QuinLED-Dig-Uno-v3_front.png){: style="width:100px"}
61+
![Dig Quad](https://quinled.info/wp-content/uploads/2021/11/QuinLED-Dig-Quad-AB_v3r1-2048x1154.png){: style="width:100px"}
62+
![Dig Octa](https://quinled.info/wp-content/uploads/2024/10/20240924_141857-2048x1444.png){: style="width:100px"}
63+
64+
* Dig 2Go, Dig Uno, Dig Quad: Choose the esp32-d0 (4MB) board in the [MoonLight Installer](https://moonmodules.org/MoonLight/gettingstarted/installer/)
65+
* Dig Octa: Choose the esp32-d0-16mb board in the [MoonLight Installer](https://moonmodules.org/MoonLight/gettingstarted/installer/)
66+
* On first install, erase flash first (Especially when other firmware like WLED was on it) as MoonLight uses a partition scheme with 3MB of flash (no ota at the moment).
6067
* You might need to reset your router if you first run WLED on the same MCU and no new IP is assigned.
6168

62-
!!! Tip
63-
Dig Uno: Remove fuse to connect USB cable to flash the board.
69+
!!! Tip "Dig Uno USB"
70+
Remove fuse to connect USB cable to flash the board.
6471

6572
### SE16 v1
6673

74+
![SE-16p](../firmware/installer/images/esp32-s3-stephanelec-16p.jpg){: style="width:100px"}
75+
6776
* Choose the esp32-s3-devkitc-1-n8r8v board in the [MoonLight Installer](https://moonmodules.org/MoonLight/gettingstarted/installer/)
6877
* Set jumper1 the same as you set it on the board: on: Infrared, off: Ethernet

docs/moonlight/drivers.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,21 @@ Want to add a Driver to MoonLight, see [develop](https://moonmodules.org/MoonLig
3030

3131
| Name | Preview | Controls | Remarks
3232
| ---- | ----- | ---- | ---- |
33-
| Parallel LED Driver | <img width="100" src="https://github.com/user-attachments/assets/9cbe487e-f330-40a5-8b40-6663c83e5d90"/> | <img width="320" alt="Parallel" src="https://github.com/user-attachments/assets/0c6f1543-623a-45bf-98d7-f5ddd072a1c6" /> | Drive multiple LED types, all devices including ESP32-P4(-nano) supported<br>Max Power and Light preset: See below<br>DMA buffer: set higher when LEDs flicker<br>Virtual LED Driver will be part of the Parallel LED driver.|
34-
| FastLED Driver | <img width="100" src="https://avatars.githubusercontent.com/u/5899270?s=48&v=4"/> | <img width="320" alt="FastLed" src="https://github.com/user-attachments/assets/d5ea1510-9766-4687-895a-b68c82575b8f" /> | Most used LED driver. Drive most common LEDs (WS2812).<br>Max Power: See below |
35-
| Art-Net | <img width="100" src="https://github.com/user-attachments/assets/9c65921c-64e9-4558-b6ef-aed2a163fd88"> | <img width="320" alt="Art-Net" src="https://github.com/user-attachments/assets/1428e990-daf7-43ba-9e50-667d51b456eb" /> | Drive LEDS and DMX lights over the network. See below |
33+
| Parallel LED Driver | <img width="100" src="https://github.com/user-attachments/assets/9cbe487e-f330-40a5-8b40-6663c83e5d90"/> | <img width="320" alt="Parallel" src="https://github.com/user-attachments/assets/0c6f1543-623a-45bf-98d7-f5ddd072a1c6" /> | Drive multiple LED types, all devices including ESP32-P4(-nano) supported<br>Light preset: See below<br>DMA buffer: set higher when LEDs flicker<br>Virtual LED Driver will be part of the Parallel LED driver.|
34+
| FastLED Driver | <img width="100" src="https://avatars.githubusercontent.com/u/5899270?s=48&v=4"/> | <img width="320" alt="FastLed" src="https://github.com/user-attachments/assets/d5ea1510-9766-4687-895a-b68c82575b8f" /> | Most used LED driver. Drive most common LEDs (WS2812). |
35+
| Art-Net In 🆕 | <img width="100" src="https://avatars.githubusercontent.com/u/1458252?s=200&v=4"> | DDP: Yes/No<br>Port<br>Universe Min-Max<br>View: Layers | Receive Art-Net (or DDP) packages e.g. from Touch Designer. See [below](#art-net-in) |
36+
| Art-Net Out| <img width="100" src="https://github.com/user-attachments/assets/9c65921c-64e9-4558-b6ef-aed2a163fd88"> | <img width="320" alt="Art-Net" src="https://github.com/user-attachments/assets/1428e990-daf7-43ba-9e50-667d51b456eb" /> | Send Art-Net to Drive LEDS and DMX lights over the network. See [below](#art-net-out) |
3637
| Audio Sync | <img width="100" src="https://github.com/user-attachments/assets/bfedf80b-6596-41e7-a563-ba7dd58cc476"/> | No controls | Listens to audio sent over the local network by WLED-AC or WLED-MM and allows audio reactive effects (♪ & ♫) to use audio data (volume and bands (FFT)) |
3738
| HUB75 Driver | <img width="100" src="https://github.com/user-attachments/assets/620f7c41-8078-4024-b2a0-39a7424f9678"/> | <img width="100" src="https://github.com/user-attachments/assets/4d386045-9526-4a5a-aa31-638058b31f32"/> | Drive HUB75 panels<br>Not implemented yet |
38-
| IR Driver 🆕🚧 | <img width="100" src="../../media/moonlight/IRDriver.jpeg"/> | | Receive IR commands and [Lights Control](https://moonmodules.org/MoonLight/moonlight/lightscontrol/) |
39+
| IR Driver | <img width="100" src="../../media/moonlight/IRDriver.jpeg"/> | | Receive IR commands and [Lights Control](https://moonmodules.org/MoonLight/moonlight/lightscontrol/) |
3940

4041
* The Parallel LED driver uses different hardware peripherals depending on the MCU type: ESP32-D0: I2S, ESP32-S3: LCD_CAM, ESP32-P4: Parallel IO (ParLIO).
4142
* Virtual LED Driver: Driving max 120! outputs (E.g. 48 panels of 256 LEDs each run at 50-100 FPS) using shift registers. Integrated within the Parallel LED Driver architecture. Not implemented yet
4243
<img width="100" src="https://github.com/user-attachments/assets/98fb5010-7192-44db-a5c9-09602681ee15"/><img width="100" src="https://github.com/user-attachments/assets/c81d2f56-00d1-4424-a716-8e3c30e76636"/>
4344

4445
### Max Power and Light Preset
4546

46-
* **Max Power**: max amount of power in watts to send to LEDs. Default 10: 5V * 2A = 10W (so it runs fine on USB). 🆕: Moved to board presets in [Module IO](https://moonmodules.org/MoonLight/moonbase/inputoutput/).
47+
* **Max Power**: 🆕 moved to [IO Module](https://moonmodules.org/MoonLight/moonbase/inputoutput/) board presets.
4748

4849
* **Light preset**: Defines the channels per light and color order
4950

@@ -65,7 +66,21 @@ Want to add a Driver to MoonLight, see [develop](https://moonmodules.org/MoonLig
6566
!!! info "Custom setup"
6667
These are predefined presets. In a future release custom presets will be possible.
6768

68-
### Art-Net ☸️
69+
### Art-Net In ☸️
70+
71+
Receives Art-Net data from the network.
72+
73+
* DDP: If unchecked, processes data in Art-Net format, if checked, process data in DDP format
74+
* Port: The port listening to for Art-Net
75+
* Universe Min-Max: Filters Universes (Art-Net only).
76+
* View:
77+
* Select physical layer to directly store the received channels into the physical layer
78+
* Select one of the (virtual layers) to take mapping into account (using layout specification and modifiers specified , see [Modifiers](https://moonmodules.org/MoonLight/moonlight/modifiers/), part of the [Effects Module](https://moonmodules.org/MoonLight/moonlight/effects/))
79+
80+
!!! tip "Running effects and Art-Net In"
81+
Effects can run at the same time, disable or delete them if you only want to run Art-Net In.
82+
83+
### Art-Net Out ☸️
6984

7085
Sends Lights in Art-Net compatible packages to an Art-Net controller specified by the IP address provided.
7186

src/MoonBase/Modules/ModuleIO.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,12 +323,14 @@ class ModuleIO : public Module {
323323
// pinAssigner.assignPin(32, pin_Exposed;
324324
} else if (boardID == board_QuinLEDDigOctaV2) {
325325
// Dig-Octa-32-8L
326+
object["maxPower"] = 400; // 10A Fuse * 8 ... 400 W
326327
uint8_t ledPins[8] = {0, 1, 2, 3, 4, 5, 12, 13}; // LED_PINS
327328
for (int i = 0; i < sizeof(ledPins); i++) pinAssigner.assignPin(ledPins[i], pin_LED);
328329
pinAssigner.assignPin(33, pin_Relay);
329330
pinAssigner.assignPin(34, pin_ButtonPush);
330331
} else if (boardID == board_QuinLEDDig2Go) {
331332
// dig2go
333+
object["maxPower"] = 10; // USB powered: 2A / 10W
332334
pinAssigner.assignPin(0, pin_Button_LightsOn);
333335
pinAssigner.assignPin(5, pin_Infrared);
334336
pinAssigner.assignPin(16, pin_LED);

src/MoonLight/Modules/ModuleDrivers.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ class ModuleDrivers : public NodeManager {
4444
for (JsonObject pinObject : state.data["pins"].as<JsonArray>()) {
4545
uint8_t usage = pinObject["usage"];
4646
uint8_t index = pinObject["index"];
47-
if (usage == pin_LED && index >=1 && index <= 20 && GPIO_IS_VALID_OUTPUT_GPIO(pinObject["GPIO"].as<uint8_t>())) {
48-
layerP.ledPins[index-1] = pinObject["GPIO"];
47+
uint8_t gpio = pinObject["GPIO"];
48+
if (usage == pin_LED && index >=1 && index <= 20 && GPIO_IS_VALID_OUTPUT_GPIO(gpio)) {
49+
layerP.ledPins[index-1] = gpio;
4950
}
5051
}
5152

src/MoonLight/Modules/ModuleLightsControl.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,20 @@ class ModuleLightsControl : public Module {
7575
pinButtonLightsOn = UINT8_MAX;
7676
for (JsonObject pinObject : state.data["pins"].as<JsonArray>()) {
7777
uint8_t usage = pinObject["usage"];
78+
uint8_t gpio = pinObject["GPIO"];
79+
7880
if (usage == pin_Relay_LightsOn) {
79-
pinRelayLightsOn = pinObject["GPIO"];
80-
if (GPIO_IS_VALID_OUTPUT_GPIO(pinRelayLightsOn)) {
81+
if (GPIO_IS_VALID_OUTPUT_GPIO(gpio)) {
82+
pinRelayLightsOn = gpio;
8183
pinMode(pinRelayLightsOn, OUTPUT);
8284
uint8_t newBri = _state.data["lightsOn"] ? _state.data["brightness"] : 0;
8385
digitalWrite(pinRelayLightsOn, newBri > 0 ? HIGH : LOW);
8486
EXT_LOGD(ML_TAG, "pinRelayLightsOn found %d", pinRelayLightsOn);
8587
} else
8688
EXT_LOGE(MB_TAG, "gpio %d not valid", pinRelayLightsOn);
8789
} else if (usage == pin_Button_LightsOn) {
88-
pinButtonLightsOn = pinObject["GPIO"];
89-
if (GPIO_IS_VALID_GPIO(pinButtonLightsOn)) {
90+
if (GPIO_IS_VALID_GPIO(gpio)) {
91+
pinButtonLightsOn = gpio;
9092
pinMode(pinButtonLightsOn, INPUT_PULLUP);
9193
EXT_LOGD(ML_TAG, "pinButtonLightsOn found %d", pinButtonLightsOn);
9294
} else

src/MoonLight/Nodes/Drivers/D_ArtnetIn.h

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,14 @@ class ArtNetInDriver : public Node {
2828
bool ddp = false;
2929
uint8_t view = 0; // physical layer
3030
uint16_t port = 6454;
31+
uint8_t universeMin = 0;
32+
uint8_t universeMax = 255;
3133

3234
void setup() override {
3335
addControl(ddp, "DDP", "checkbox");
3436
addControl(port, "port", "number", 0, 65538);
37+
addControl(universeMin, "universeMin", "number", 0, 65538);
38+
addControl(universeMax, "universeMax", "number", 0, 65538);
3539
addControl(view, "view", "select");
3640
addControlValue("Physical layer");
3741
uint8_t i = 1; // start with one
@@ -71,18 +75,16 @@ class ArtNetInDriver : public Node {
7175

7276
while (int packetSize = artnetUdp.parsePacket()) {
7377
if (packetSize < sizeof(ArtNetHeader) || packetSize > sizeof(packetBuffer)) {
74-
artnetUdp.clear();
78+
artnetUdp.clear(); // drains all available packets
7579
continue;
7680
}
7781

78-
if (packetSize >= sizeof(ArtNetHeader)) {
79-
artnetUdp.read(packetBuffer, min(packetSize, (int)sizeof(packetBuffer)));
82+
artnetUdp.read(packetBuffer, min(packetSize, (int)sizeof(packetBuffer)));
8083

81-
if (ddp)
82-
handleDDP();
83-
else
84-
handleArtNet();
85-
}
84+
if (ddp)
85+
handleDDP();
86+
else
87+
handleArtNet();
8688
}
8789
}
8890

@@ -121,20 +123,22 @@ class ArtNetInDriver : public Node {
121123
// Check if it's a DMX packet (opcode 0x5000)
122124
if (opcode == 0x5000) {
123125
uint16_t universe = header->universe;
124-
uint16_t dataLength = (header->length >> 8) | (header->length << 8);
125-
126-
uint8_t* dmxData = packetBuffer + sizeof(ArtNetHeader);
127-
128-
int startPixel = universe * (512 / layerP.lights.header.channelsPerLight);
129-
int numPixels = min((uint16_t)(dataLength / layerP.lights.header.channelsPerLight), (uint16_t)(layerP.lights.header.nrOfLights - startPixel));
130-
131-
for (int i = 0; i < numPixels; i++) {
132-
int ledIndex = startPixel + i;
133-
if (ledIndex < layerP.lights.header.nrOfLights) {
134-
if (view == 0) {
135-
memcpy(&layerP.lights.channels[ledIndex * layerP.lights.header.channelsPerLight], &dmxData[i * layerP.lights.header.channelsPerLight], layerP.lights.header.channelsPerLight);
136-
} else {
137-
layerP.layers[view - 1]->setLight(ledIndex, &dmxData[i * layerP.lights.header.channelsPerLight], 0, layerP.lights.header.channelsPerLight);
126+
if (universe >= universeMin && universe <= universeMax) {
127+
uint16_t dataLength = (header->length >> 8) | (header->length << 8);
128+
129+
uint8_t* dmxData = packetBuffer + sizeof(ArtNetHeader);
130+
131+
int startPixel = (universe-universeMin) * (512 / layerP.lights.header.channelsPerLight);
132+
int numPixels = min((uint16_t)(dataLength / layerP.lights.header.channelsPerLight), (uint16_t)(layerP.lights.header.nrOfLights - startPixel));
133+
134+
for (int i = 0; i < numPixels; i++) {
135+
int ledIndex = startPixel + i;
136+
if (ledIndex < layerP.lights.header.nrOfLights) {
137+
if (view == 0) {
138+
memcpy(&layerP.lights.channels[ledIndex * layerP.lights.header.channelsPerLight], &dmxData[i * layerP.lights.header.channelsPerLight], layerP.lights.header.channelsPerLight);
139+
} else {
140+
layerP.layers[view - 1]->setLight(ledIndex, &dmxData[i * layerP.lights.header.channelsPerLight], 0, layerP.lights.header.channelsPerLight);
141+
}
138142
}
139143
}
140144
}

src/MoonLight/Nodes/Drivers/D_Infrared.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,17 @@ class IRDriver : public Node {
4242
pinInfrared = UINT8_MAX;
4343
for (JsonObject pinObject : state.data["pins"].as<JsonArray>()) {
4444
uint8_t usage = pinObject["usage"];
45+
uint8_t gpio = pinObject["GPIO"];
4546
if (usage == pin_Infrared) {
46-
pinInfrared = pinObject["GPIO"];
47-
if (GPIO_IS_VALID_GPIO(pinInfrared)) {
47+
if (GPIO_IS_VALID_GPIO(gpio)) {
48+
pinInfrared = gpio;
4849
EXT_LOGD(ML_TAG, "pin_Infrared found %d", pinInfrared);
49-
} else
50+
} else {
5051
EXT_LOGE(MB_TAG, "gpio %d not valid", pinInfrared);
52+
}
5153
}
5254
}
55+
5356
if (pinInfrared != UINT8_MAX) {
5457
EXT_LOGI(IR_DRIVER_TAG, "Changing to pin #%d", pinInfrared);
5558

0 commit comments

Comments
 (0)