diff --git a/README.md b/README.md index c854ae5..ba4bc39 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,26 @@ +### This is a fork of ESP8266_ArtNetNode_v2 by mtongnz. + +Serveral improvements and fixes have been implemented over "v2.0.0d (beta 5g)" + +- WS2812 no longer flicker +- ESP8266WebServer leaked memory(open connections) gets reclaimed. +- Reboot on low heap. +- Universe 10 now ouputs raw pwm values to pins defined in pwmports[]. +- Default dmxA/B pins changed to D1/D2 to avoid boot flicker. +- Improved heap usage. + +### Compile options: +- CPU Frequency needs to be 160mhz, SDK 2.4.1 recommeded. +- Set lwIP to "V2 Lower Memory" +- Dont forget to upload SPIFFS (click on "ESP8266 Sketch Data Upload") Requires: https://github.com/esp8266/arduino-esp8266fs-plugin +- you can get an extra 4kb of heap by moving g_cont to sys area, this may kill timer callbacks and gdb as a side effekt https://github.com/esp8266/Arduino/pull/4553/commits/17bf98c01cd6ffc0cd1a1c48ade28ed0a01ffad0 + +those options should give you about 45kB of heap. + + +## Original README: +------------------ + # ESP8266_ArtNetNode_v2 ESP8266 based WiFi ArtNet V4 to DMX, RDM and LED Pixels diff --git a/espArtnetNode_2.0.0_b5g.bin b/espArtnetNode_2.0.0_b5g.bin deleted file mode 100644 index a2c1c0e..0000000 Binary files a/espArtnetNode_2.0.0_b5g.bin and /dev/null differ diff --git a/espArtnetNode_2.0.0_b5g_ESP01.bin b/espArtnetNode_2.0.0_b5g_ESP01.bin deleted file mode 100644 index 99a73d7..0000000 Binary files a/espArtnetNode_2.0.0_b5g_ESP01.bin and /dev/null differ diff --git a/espArtnetNode_2.0.0_b5g_NO_RESET.bin b/espArtnetNode_2.0.0_b5g_NO_RESET.bin deleted file mode 100644 index 094e7ae..0000000 Binary files a/espArtnetNode_2.0.0_b5g_NO_RESET.bin and /dev/null differ diff --git a/espArtnetNode_2.0.0_b5g_WEMOS.bin b/espArtnetNode_2.0.0_b5g_WEMOS.bin deleted file mode 100644 index b5a3f51..0000000 Binary files a/espArtnetNode_2.0.0_b5g_WEMOS.bin and /dev/null differ diff --git a/libs/espArtnetRDM/espArtNetRDM.cpp b/libs/espArtnetRDM/espArtNetRDM.cpp index addc7fb..614ef93 100644 --- a/libs/espArtnetRDM/espArtNetRDM.cpp +++ b/libs/espArtnetRDM/espArtNetRDM.cpp @@ -1319,11 +1319,11 @@ char* esp8266ArtNetRDM::getLongName() { return _art->longName; } -void esp8266ArtNetRDM::setNodeReport(char* c, uint16_t code) { +void esp8266ArtNetRDM::setNodeReport(const char* c, uint16_t code) { if (_art == 0) return; - strcpy(_art->nodeReport, c); + strcpy_P(_art->nodeReport, c); _art->nodeReportCode = code; } diff --git a/libs/espArtnetRDM/espArtNetRDM.h b/libs/espArtnetRDM/espArtNetRDM.h index cfddc57..f69ac28 100644 --- a/libs/espArtnetRDM/espArtNetRDM.h +++ b/libs/espArtnetRDM/espArtNetRDM.h @@ -244,7 +244,7 @@ class esp8266ArtNetRDM { IPAddress getSubnetMask(); bool getDHCP(); - void setNodeReport(char*, uint16_t); + void setNodeReport(const char*, uint16_t); void artPollReply(); void sendDMX(uint8_t, uint8_t, IPAddress, uint8_t*, uint16_t); diff --git a/prizes.md b/prizes.md deleted file mode 100644 index c7a12c8..0000000 --- a/prizes.md +++ /dev/null @@ -1,30 +0,0 @@ -# ESP8266_ArtNetNode_v2 -## Code Fix Prizes - -I am offering some prizes for people who can fix some of the known bugs and missing features. I have just started a new job and will have limited time for this project. Rather than make you all wait on the code, I thought I'd share it as is and ask for a bit of help. - -## Details: - -I am giving away a few of my first batch of prototype PCBs. They may have a couple of minor errors (I already found one -error due to incorrect pin mapping in an Eagle part). They will be fully populated - valued at over $30 just for parts. -They feature full optical and electrical isolation, an ESP100 with 8M flash, and 3x WS2812 status LEDs. Postage is included. - -In order to receive one, please complete one of the following tasks. You can "win" multiple boards. - -1 - Fix the WDT reset issue (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/41) - -2 - Implement stored scenes function. I want it to allow for static scenes or for chases to run. - -3 - Most bug fixes, code improvements, feature additions & helpful submissions. - - eg. Fixing the flickering WS2812 (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/36) - - Adding other pixel strips (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/42) - - Creating new web UI theme (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/22) - -These prizes will be based on the first person to submit a solution that I judge to be adequate. My decision is final. - -As stated above, I am quite short on time so it might take a while for me to test any relevant fixes. - -Thanks heaps for the support. diff --git a/source/data/index.htm.gz b/source/data/index.htm.gz new file mode 100644 index 0000000..4b471bb Binary files /dev/null and b/source/data/index.htm.gz differ diff --git a/source/data/style.css.gz b/source/data/style.css.gz new file mode 100644 index 0000000..3383630 Binary files /dev/null and b/source/data/style.css.gz differ diff --git a/source/data_uncompressed/index.htm b/source/data_uncompressed/index.htm new file mode 100644 index 0000000..ce2c23d --- /dev/null +++ b/source/data_uncompressed/index.htm @@ -0,0 +1,657 @@ + + +ESP8266 ArtNetNode Config + + + + +
+
+
+
+ esp8266

ArtNet &sACN

+ to

DMX &LED Pixels

+
+ +
+ Design by + Matthew Tong +
+
+
+
+

Error

+

There was an error communicating with the device. Refresh the page and try again. +

+
+

Fetching Data

+

Fetching data from device. If this message is still here in 15 seconds, try refreshing the page or clicking the menu option again. +

+
+

Device Status

+

Device Name: +

+

MAC Address: +

+

Wifi Status: +

+

IP Address: +

+

Subnet Address: +

+

Port A: +

+

Port B: +

+

Scene Storage: +

+

Firmware: +

+

+
+ +

WiFi Settings

+

MAC Address: +

+

+

Wifi SSID: +

+ +

Password: +

+ +

+

Hotspot SSID: +

+ +

Password: +

+ +

Start Delay: +

+ + (seconds)

+

Stand Alone: +

+ +

+ In normal mode, the hotspot will start after delay + seconds if the main WiFi won't connect. If no users connect, the device will reset and attempt the main WiFi again. This feature is purely for changing settings and ArtNet data is ignored. +

Stand alone mode disables the primary WiFi connection and allows ArtNet data to be received via the hotspot connection. +

+
+ +

IP &Node Name

+

Short Name:

+

+ +

Long Name: +

+ +

+

Enable DHCP: +

+ +

IP Address: +

+ + + + +

Subnet Address: +

+ + + + +

Gateway Address: +

+ + + + +

Broadcast Address: +

+

+ These settings only affect the main WiFi connection. The hotspot will always have DHCP enabled and an IP of 2.0.0.1 +

+
+ +

Port A Settings

+

Port Type: +

+ +

Protocol: +

+ +

Merge Mode: +

+ +

Net: +

+ +

Subnet: +

+ +

Universe: +

+ + + + + + +

+

sACN Universe: +

+ + + + +

+ +

Broadcast Address: +

+ + + + +

+
+ +

Number of Pixels: +

+ 680 max - 170 per universe +

+

Mode:

+

+ +

Start Channel:

+

+ FX modes only +

+
+
+
+ +

Port B Settings

+

Port Type: +

+ +

Protocol: +

+ +

Merge Mode: +

+ +

Net: +

+ +

Subnet: +

+ +

Universe: +

+ + + + + + +

+

sACN Universe: +

+ + + + +

+ +

Number of Pixels: +

+ 680 max - 170 per universe +

+

Mode:

+

+ +

Start Channel:

+

+ FX modes only +

+
+
+
+

Stored Scenes

+

Not yet implemented +

+
+
+

Update Firmware

+

Firmware: +

+

+ + +

+

+ +

+
+ +
+
+ + diff --git a/source/data_uncompressed/style b/source/data_uncompressed/style new file mode 100644 index 0000000..29ff21f --- /dev/null +++ b/source/data_uncompressed/style @@ -0,0 +1 @@ +espArtNetNode CSS UploadSelect and upload your CSS file. This will overwrite any previous uploads but you can restore the default below.


Restore default CSS \ No newline at end of file diff --git a/source/data_uncompressed/style.css b/source/data_uncompressed/style.css new file mode 100644 index 0000000..8cb4a3c --- /dev/null +++ b/source/data_uncompressed/style.css @@ -0,0 +1 @@ +.author,.title,ul.nav a{text-align:center}.author i,.show,.title h1,ul.nav a{display:block}input,ul.nav a:hover{background-color:#DADADA}a,abbr,acronym,address,applet,b,big,blockquote,body,caption,center,cite,code,dd,del,dfn,div,dl,dt,em,fieldset,font,form,h1,h2,h3,h4,h5,h6,html,i,iframe,img,ins,kbd,label,legend,li,object,ol,p,pre,q,s,samp,small,span,strike,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,tt,u,ul,var{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:0 0}.main h2,li.last{border-bottom:1px solid #888583}body{line-height:1;background:#E4E4E4;color:#292929;color:rgba(0,0,0,.82);font:400 100% Cambria,Georgia,serif;-moz-text-shadow:0 1px 0 rgba(255,255,255,.8);}ol,ul{list-style:none}a{color:#890101;text-decoration:none;-moz-transition:.2s color linear;-webkit-transition:.2s color linear;transition:.2s color linear}a:hover{color:#DF3030}#page{padding:0}.inner{margin:0 auto;width:91%}.amp{font-family:Baskerville,Garamond,Palatino,'Palatino Linotype','Hoefler Text','Times New Roman',serif;font-style:italic;font-weight:400}.mast{float:left;width:31.875%}.title{font:semi 700 16px/1.2 Baskerville,Garamond,Palatino,'Palatino Linotype','Hoefler Text','Times New Roman',serif;padding-top:0}.title h1{font:700 20px/1.2 'Book Antiqua','Palatino Linotype',Georgia,serif;padding-top:0}.author{font:400 100% Cambria,Georgia,serif}.author i{font:400 12px Baskerville,Garamond,Palatino,'Palatino Linotype','Hoefler Text','Times New Roman',serif;letter-spacing:.05em;padding-top:.7em}.footer,.main{float:right;width:65.9375%}ul.nav{margin:1em auto 0;width:11em}ul.nav a{font:700 14px/1.2 'Book Antiqua','Palatino Linotype',Georgia,serif;letter-spacing:.1em;padding:.7em .5em;margin-bottom:0;text-transform:uppercase}input[type=button],input[type=button]:focus{background-color:#E4E4E4;color:#890101}li{border-top:1px solid #888583}.hide{display:none}.main h2{font-size:1.4em;text-align:left;margin:0 0 1em;padding:0 0 .3em}.main{position:relative}p.left{clear:left;float:left;width:20%;min-width:120px;max-width:300px;margin:0 0 .6em;padding:0;text-align:right}p.right,select{min-width:200px}p.right{overflow:auto;margin:0 0 .6em .4em;padding-left:.6em;text-align:left}p.center,p.spacer{padding:0;display:block}.footer,p.center{text-align:center}p.center{float:left;clear:both;margin:3em 0 3em 15%;width:70%}p.spacer{float:left;clear:both;margin:0;width:100%;height:20px}input{margin:0;border:0;color:#890101;outline:0;font:400 100% Cambria,Georgia,serif}input[type=text]{width:70%;min-width:200px;padding:0 5px}input[type=number]{min-width:50px;width:50px}input:focus{background-color:silver;color:#000}input[type=checkbox]{-webkit-appearance:none;background-color:#fafafa;border:1px solid #cacece;box-shadow:0 1px 2px rgba(0,0,0,.05),inset 0 -15px 10px -12px rgba(0,0,0,.05);padding:9px;border-radius:5px;display:inline-block;position:relative}input[type=checkbox]:active,input[type=checkbox]:checked:active{box-shadow:0 1px 2px rgba(0,0,0,.05),inset 0 1px 3px rgba(0,0,0,.1)}input[type=checkbox]:checked{background-color:#fafafa;border:1px solid #adb8c0;box-shadow:0 1px 2px rgba(0,0,0,.05),inset 0 -15px 10px -12px rgba(0,0,0,.05),inset 15px 10px -12px rgba(255,255,255,.1);color:#99a1a7}input[type=checkbox]:checked:after{content:'\2714';font-size:14px;position:absolute;top:0;left:3px;color:#890101}input[type=button],input[type=file]+label{font:700 16px/1.2 'Book Antiqua','Palatino Linotype',Georgia,serif;margin:17px 0 0}input[type=button]{position:absolute;right:0;display:block;border:1px solid #adb8c0;float:right;border-radius:12px;padding:5px 20px 2px 23px;-webkit-transition-duration:.3s;transition-duration:.3s}input[type=button]:hover{background-color:#909090;color:#fff;padding:5px 62px 2px 65px}input.submit{float:left;position: relative}input.showMessage,input.showMessage:focus,input.showMessage:hover{background-color:#6F0;color:#000;padding:5px 62px 2px 65px}input[type=file]{width:.1px;height:.1px;opacity:0;overflow:hidden;position:absolute;z-index:-1}input[type=file]+label{float:left;clear:both;cursor:pointer;border:1px solid #adb8c0;border-radius:12px;padding:5px 20px 2px 23px;display:inline-block;background-color:#E4E4E4;color:#890101;overflow:hidden;-webkit-transition-duration:.3s;transition-duration:.3s}input[type=file]+label:hover,input[type=file]:focus+label{background-color:#909090;color:#fff;padding:5px 40px 2px 43px}input[type=file]+label svg{width:1em;height:1em;vertical-align:middle;fill:currentColor;margin-top:-.25em;margin-right:.25em}select{margin:0;border:0;background-color:#DADADA;color:#890101;outline:0;font:400 100% Cambria,Georgia,serif;width:50%;padding:0 5px}.footer{border-top:1px solid #888583;display:block;font-size:12px;margin-top:20px;padding:.7em 0 20px}.footer p{margin-bottom:.5em}@media (min-width:600px){.inner{min-width:600px}}@media (max-width:600px){.inner,.page{min-width:300px;width:100%;overflow-x:hidden}.footer,.main,.mast{float:left;width:100%}.mast{border-top:1px solid #888583;border-bottom:1px solid #888583}.main{margin-top:4px;width:98%}ul.nav{margin:0 auto;width:100%}ul.nav li{float:left;min-width:100px;width:33%}ul.nav a{font:12px Helvetica,Arial,sans-serif;letter-spacing:0;padding:.8em}.title,.title h1{padding:0;text-align:center}ul.nav a:focus,ul.nav a:hover{background-position:0 100%}.author{display:none}.title{border-bottom:1px solid #888583;width:100%;display:block;font:400 15px Baskerville,Garamond,Palatino,'Palatino Linotype','Hoefler Text','Times New Roman',serif}.title h1{font:600 15px Baskerville,Garamond,Palatino,'Palatino Linotype','Hoefler Text','Times New Roman',serif;display:inline}p.left,p.right{clear:both;float:left;margin-right:1em}li,li.first,li.last{border:0}p.left{width:100%;text-align:left;margin-left:.4em;font-weight:600}p.right{margin-left:1em;width:100%}p.center{margin:1em 0;width:100%}p.spacer{display:none}input[type=text],select{width:85%;}@media (min-width:1300px){.page{width:1300px}} \ No newline at end of file diff --git a/source/espArtnetNode_2.0.0_b5g.ino b/source/espArtnetNode_2.0.0_b5g.ino index 75355c9..c0fb074 100644 --- a/source/espArtnetNode_2.0.0_b5g.ino +++ b/source/espArtnetNode_2.0.0_b5g.ino @@ -1,35 +1,54 @@ /* -ESP8266_ArtNetNode v2.0.0 -Copyright (c) 2016, Matthew Tong -https://github.com/mtongnz/ESP8266_ArtNetNode_v2 - -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public -License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -You should have received a copy of the GNU General Public License along with this program. -If not, see http://www.gnu.org/licenses/ - -Note: -This is a pre-release version of this software. It is not yet ready for prime time and contains bugs (known and unknown). -Please submit any bugs or code changes so they can be included into the next release. - -Prizes up for grabs: -I am giving away a few of my first batch of prototype PCBs. They will be fully populated - valued at over $30 just for parts. -In order to recieve one, please complete one of the following tasks. You can "win" multiple boards. -1 - Fix the WDT reset issue (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/41) -2 - Implement stored scenes function. I want it to allow for static scenes or for chases to run. -3 - Most bug fixes, code improvements, feature additions & helpful submissions. + ESP8266_ArtNetNode v2.0.0 + Copyright (c) 2016, Matthew Tong + https://github.com/mtongnz/ESP8266_ArtNetNode_v2 + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with this program. + If not, see http://www.gnu.org/licenses/ + + Note: + This is a pre-release version of this software. It is not yet ready for prime time and contains bugs (known and unknown). + Please submit any bugs or code changes so they can be included into the next release. + + Prizes up for grabs: + I am giving away a few of my first batch of prototype PCBs. They will be fully populated - valued at over $30 just for parts. + In order to recieve one, please complete one of the following tasks. You can "win" multiple boards. + 1 - Fix the WDT reset issue (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/41) + 2 - Implement stored scenes function. I want it to allow for static scenes or for chases to run. + 3 - Most bug fixes, code improvements, feature additions & helpful submissions. eg. Fixing the flickering WS2812 (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/36) Adding other pixel strips (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/42) Creating new web UI theme (https://github.com/mtongnz/ESP8266_ArtNetNode_v2/issues/22) - -These prizes will be based on the first person to submit a solution that I judge to be adequate. My decision is final. -This competition will open to the general public a couple of weeks after the private code release to supporters. + + These prizes will be based on the first person to submit a solution that I judge to be adequate. My decision is final. + This competition will open to the general public a couple of weeks after the private code release to supporters. +*/ + +/* + More pixels need more ram! for longer chains make sure to use sdk > 2.4.1 with lwip2 low mem + + Http interface can still cause crashes, normal operation seems solid now. + + --->>>> Make sure to RESTART the esp once AFTER serial FLASHING, esp.restart fails if you dont. + + todo: + Sometimes we get stuck in a reboot loop, seems like wifi state gets messed up. + ws2812 needs 160mhz currently, calculate timing nops count in precompiler + calculate heap usage and check if setting is possible. + There seems to be another mem leak left + */ +struct tcp_pcb; +extern struct tcp_pcb* tcp_tw_pcbs; +extern "C" void tcp_abort (struct tcp_pcb* pcb); + #include #include #include @@ -43,11 +62,11 @@ This competition will open to the general public a couple of weeks after the pri #include "wsFX.h" extern "C" { - #include "user_interface.h" +#include "user_interface.h" extern struct rst_info resetInfo; } -#define FIRMWARE_VERSION "v2.0.0 (beta 5g)" +#define FIRMWARE_VERSION "v2.0.0d (beta 5g)" #define ART_FIRM_VERSION 0x0200 // Firmware given over Artnet (2 bytes) @@ -62,41 +81,62 @@ extern "C" { #define ESTA_DEV 0xEE000000 // RDM Device ID (used with Man Code to make 48bit UID) +/* + + //W works for strip on esp12, R works as pwm out + SD2 (GPIO 10) //can be used on esp-12F in DIO mode, otherwise used for flash. + D0 (GPIO 16) R + D1 (GPIO 5) RW -- Default OUT A + D2 (GPIO 4) RW -- Default OUT B + D3 (GPIO 0) R --problematic when reset, boot mode pin -- maybe not?!? + D4 (GPIO 2) RW + D5 (GPIO 14) R + D6 (GPIO 12) R + D7 (GPIO 13) R + D8 (GPIO 15) R--problematic when reset, boot mode pin -- maybe not?!? + RXD (GPIO 3) Somewhat strange, probably need to disconnect rs232 chip. + TXD (GPIO 1) RW + +*/ +const int pwmports[] = {16, 2, 14, 12, 13}; +//const int pwmports[] = {5, 16, 10, 4, 0, 2, 14, 12, 13, 15, 3, 1};//make all unused ports pwm outs +const int pwmcount = sizeof( pwmports ) / sizeof( int ); +int lastvalues[pwmcount] = {}; +#define RAW_UNIVERSE 10 //start on universe 10, we dont want to conflict with the strips below +espDMX RAWPort(2); + +//#define DMX_OFF //disable dmx handler a/b, free up those pins +#ifndef ULONG_MAX + #define ULONG_MAX 4294967295UL +#endif #ifdef ESP_01 - #define DMX_DIR_A 2 // Same pin as TX1 + #define DMX_DIR_A 255 // Tie high on max585, 255 disables gpio #define DMX_TX_A 1 #define ONE_PORT #define NO_RESET #define WS2812_ALLOW_INT_SINGLE false #define WS2812_ALLOW_INT_DOUBLE false - + #else - #define DMX_DIR_A 5 // D1 - #define DMX_DIR_B 16 // D0 - #define DMX_TX_A 1 - #define DMX_TX_B 2 - - #define STATUS_LED_PIN 12 -// #define STATUS_LED_MODE_WS2812 - #define STATUS_LED_MODE_APA106 - #define STATUS_LED_A 0 // Physical wiring order for status LEDs - #define STATUS_LED_B 1 - #define STATUS_LED_S 2 - + #define DMX_DIR_A 255 // Tie high on max585, 255 disables gpio + #define DMX_DIR_B 255 // Tie high on max585, 255 disables gpio + #define DMX_TX_A 5 //output A pin, not necessary dmx. + #define DMX_TX_B 4 //output B pin, not necessary dmx. + #define NO_RESET + #define WS2812_ALLOW_INT_SINGLE false #define WS2812_ALLOW_INT_DOUBLE false #endif #ifndef NO_RESET - #define SETTINGS_RESET 14 + //#define SETTINGS_RESET 14 #endif - // Definitions for status leds xxBBRRGG #define BLACK 0x00000000 #define WHITE 0x00FFFFFF @@ -110,7 +150,7 @@ extern "C" { #define ORANGE 0x0000FF33 #define STATUS_DIM 0x0F -uint8_t portA[5], portB[5]; +uint8_t portA[5], portB[5], portC[5]; uint8_t MAC_array[6]; uint8_t dmxInSeqID = 0; uint8_t statusLedData[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -126,23 +166,28 @@ bool statusLedsOff = false; pixPatterns pixFXA(0, &pixDriver); pixPatterns pixFXB(1, &pixDriver); +//get webserver data from spiffs (data folder), this allows gzip compressed content. smaller files=shorter connection and less heap usage. +//also disables upload of spiffsdata +#define spiffs -const char PROGMEM mainPage[] = "ESP8266 ArtNetNode Config
esp8266

ArtNet & sACN

to

DMX & LED Pixels