ESP32 combining two scripts - Page 1
Forum section: electronics / general

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 26, 2023, 02:59:34 pm
content: Hello allI am trying to combine two functions for an ESP32 into one program, which turned out to be not as easy, as one would think.Function 1 is a PWM-generator with a slider interface.Function 2 are multiple buttons for a binary output.Independently these programs work, but combined the ESP32 does not even establish a WiFi connection.This is the code in question (using the Arduino IDE):Code:#include <WiFi.h>#include <AsyncTCP.h>#include <ESPAsyncWebServer.h>//WiFi stuff censored ;-)const int pwm_pin = 15;String slider_value = "25";const int frequency = 1000;const int pwm_channel = 0;const int resolution = 8;const char* input_parameter = "value";const char* PARAM_INPUT_1 = "output";const char* PARAM_INPUT_2 = "state";AsyncWebServer server(80);const char index_html[] PROGMEM = R"rawliteral(<!DOCTYPE HTML><html><head><meta name="viewport" content="width=device-width, initial-scale=1"><title>ESP32 Control</title><style>html {font-family: Times New Roman; display: inline-block; text-align: center;}h2 {font-size: 2.3rem;}p {font-size: 1.9rem;}body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}.slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #38c0ff ;outline: none; -webkit-transition: .2s; transition: opacity .2s;}.slider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 35px; height: 35px; background:#01070a; cursor: pointer;}.slider::-moz-range-thumb { width: 35px; height: 35px; background: #01070a; cursor: pointer; }</style></head><body><h2>ESP32 Control</h2><p><span id="textslider_value">%SLIDERVALUE%</span></p><p><input type="range" onchange="updateSliderPWM(this)" id="pwmSlider" min="0" max="255" value="%SLIDERVALUE%" step="1" class="slider"></p>%BUTTONPLACEHOLDER%<script>function updateSliderPWM(element) {var slider_value = document.getElementById("pwmSlider").value;document.getElementById("textslider_value").innerHTML = slider_value;console.log(slider_value);var xhr = new XMLHttpRequest();xhr.open("GET", "/slider?value=" slider_value, true);xhr.send();}function toggleCheckbox(element) {var xhr = new XMLHttpRequest();if(element.checked){ xhr.open("GET", "/update?output=" element.id "&state=1", true); }else { xhr.open("GET", "/update?output=" element.id "&state=0", true); }xhr.send();}</script></body></html>)rawliteral";String processor(const String& var){if (var == "SLIDERVALUE"){return slider_value;}//Serial.println(var);if(var == "BUTTONPLACEHOLDER"){String buttons = "";buttons = "<h4>Output - GPIO 6</h4><label class="switch"><input type="checkbox" onchange="toggleCheckbox(this)" id="6" " outputState(6) "><span class="slider"></span></label>";buttons = "<h4>Output - GPIO 7</h4><label class="switch"><input type="checkbox" onchange="toggleCheckbox(this)" id="7" " outputState(7) "><span class="slider"></span></label>";buttons = "<h4>Output - GPIO 8</h4><label class="switch"><input type="checkbox" onchange="toggleCheckbox(this)" id="8" " outputState(8) "><span class="slider"></span></label>";return buttons;}return String();}String outputState(int output){if(digitalRead(output)){return "checked";}else {return "";}}void setup(){Serial.begin(115200);ledcSetup(pwm_channel, frequency, resolution);ledcAttachPin(pwm_pin, pwm_channel);ledcWrite(pwm_channel, slider_value.toInt());pinMode(6, OUTPUT);digitalWrite(6, LOW);pinMode(7, OUTPUT);digitalWrite(7, LOW);pinMode(8, OUTPUT);digitalWrite(8, LOW);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(1000);Serial.println("Connecting...");}Serial.println(WiFi.localIP());server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){request->send_P(200, "text/html", index_html, processor);});server.on("/slider", HTTP_GET, [] (AsyncWebServerRequest *request) {String message;if (request->hasParam(input_parameter)) {message = request->getParam(input_parameter)->value();slider_value = message;ledcWrite(pwm_channel, slider_value.toInt());}else {message = "No message sent";}Serial.println(message);request->send(200, "text/plain", "OK");});server.begin();}void loop() {}Any ideas are welcome. I have now idea how to troubleshoot those kind of things.

author: CountChocula
author_rank: Unknown
timestamp: March 26, 2023, 06:32:28 pm
content: Hiya! The only obvious problem that jumps out at me is that you're trying to write to GPIOs 6, 7, and 8 — on some ESP32 chips (like the WROOM, for example), these pins are connected to the onboard Flash interface, and if you try writing to them you will cause the CPU to crash. If I take this code out:Code:pinMode(6, OUTPUT);digitalWrite(6, LOW);pinMode(7, OUTPUT);digitalWrite(7, LOW);pinMode(8, OUTPUT);digitalWrite(8, LOW);The script compiles and connects to WiFi without problem. I can open up the web page and it seems to work fine, and the PWM is running as expected (on other pins).I also had to change theprocessor()function so that it compiles the output string properly:Code:String processor(const String& var){if (var == "SLIDERVALUE"){return slider_value;}//Serial.println(var);if(var == "BUTTONPLACEHOLDER"){String buttons = "";buttons = "<h4>Output - GPIO 6</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"6\" ";buttons += outputState(6);buttons += "><span class=\"slider\"></span></label>";buttons += "<h4>Output - GPIO 7</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"7\" ";buttons += outputState(7);buttons += "><span class=\"slider\"></span></label>";buttons += "<h4>Output - GPIO 8</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"8\" ";buttons += outputState(8);buttons += "><span class=\"slider\"></span></label>";return buttons;}return String();}Without these changes, the script doesn't compile, but that might just be because I don't use the Arduino IDE.—CC

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 27, 2023, 07:08:03 am
content: Jeeeeesus...I would have never thought of thatThanks a lot.I saw, that these pins (it's a ESP32 DevKitC V4 by the way) also share the Flash-functionality (but so do all pins share different functionalities).

author: tooki
author_rank: Super Contributor
timestamp: March 27, 2023, 07:24:20 am
content: The “available but not really” pins on many ESP32 models is one of the bigger “traps for young players” with the ESP32. The pins for flash memory are one, the pins for external PSRAM on WROVER models is another, and another are the bootstrapping pins, which control the boot process and are usable after startup, but are tricky to use if your circuit pulls them high or low. That’s GPIOs 0, 2, 4, 5, 12, and 15, though usually only 0 and 2 are critical. Another common trap is that ADC2 is somehow involved in wifi, so if you enable wifi, you cannot use the second ADC.This is a good overview of the pin restrictions:https://randomnerdtutorials.com/esp32-pinout-reference-gpios/Some, but not all, of these limitations are addressed in the newer ESP32 models like the S3 (which I need to try out more).I HIGHLY suggest creating an IO assignment spreadsheet for any ESP32 project that needs more pins than the few that are totally unencumbered. Paste an image of the ESP32 in the middle and scale it to match the cell sizes. (Basically, make a diagram similar to the one at the top of the link above, then add a column or two for your own signal names.)Believe it or not, though, the ESP32’s pin assignment capability is otherwise quite flexible, more so than many MCUs. (On many, especially older ones, many things like SPI, I2C, and UART cannot be moved at all.)P.S. Pro tip: add a 1-10uF capacitor from the EN pin to ground. This will ensure it enters firmware programming mode reliably. I don’t know why sometimes it’s needed and sometimes it’s not (sometimes it even appears to depend on what code is running on the ESP32 already!), so when designing anything with an ESP32, I just add it as a matter of course since it costs peanuts. (The cap’s function is to ensure the ESP32 is held in reset long enough for GPIO0 to be pulled lowbeforeit tries to boot. The cap takes time to charge, extending the time the EN pin is held at a voltage considered “low”.)

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 27, 2023, 10:21:30 am
content: QuoteIndeed, it is. Thank you too.I've changed the output pins to 0,2,4 and everything works fine. 'Funny business' at boot up (as it occurs at GPIO 0) is not an issue for the particular application.Now I only have to figure out a proper HTML-layout. Luckily, there are HTML-previewer available

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 27, 2023, 03:30:43 pm
content: Ones again, not so easy, even with HTML-preview, since the switches are defined in a sub-routine.Here are the two parts, which style the slider and the switches.Code:<style>//Slider parthtml {font-family: Times New Roman; display: inline-block; text-align: center;}h2 {font-size: 2.3rem;}p {font-size: 1.9rem;}body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}.slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #38c0ff ;outline: none; -webkit-transition: .2s; transition: opacity .2s;}.slider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 35px; height: 35px; background:#01070a; cursor: pointer;}.slider::-moz-range-thumb { width: 35px; height: 35px; background: #01070a; cursor: pointer; }//switch part.switch {position: relative; display: inline-block; width: 120px; height: 68px}.switch input {display: none}.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}input:checked+.slider {background-color: #b30000}input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}</style>But how do I define it properly?This code obviously doesn't work...

author: tooki
author_rank: Super Contributor
timestamp: March 27, 2023, 03:41:25 pm
content: Quote from: PSR B1257 on March 27, 2023, 03:30:43 pmWhat is “it”?Quote from: PSR B1257 on March 27, 2023, 03:30:43 pmIt is not obvious at all that it would or wouldn’t work, since that is just the CSS style sheet. There’s no HTML code.We aren’t clairvoyant, you need to show clearly how the result differs from your expectations.

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 27, 2023, 05:22:32 pm
content: I've just pasted the <style>part of the code. The whole code is in the initial post.What I commented as slider part and switch part are the sections of the original codes, which I try to combine.This is "it".The slider should get it's <style> and below should be the switches with there own <style>.

author: tooki
author_rank: Super Contributor
timestamp: March 27, 2023, 05:44:21 pm
content: Quote from: PSR B1257 on March 27, 2023, 05:22:32 pmThat is obvious. What isn’t obvious is what isn’t working:Quote from: tooki on March 27, 2023, 03:41:25 pmIs my sentence there unclear?Sayingit’s not working doesn’t tell us anything really.Showanddescribewhat is not working. That means you need to explain your expected results, so we can understand what you’re even trying to get.

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 27, 2023, 07:25:55 pm
content: Here is a screenshot of the HTML-page.The slider and switches are all tugged away in the upper left corner. If I delete the "switch-part" the slider is centered and the switches are reasonable positioned but with 'no style'.This is the example code I've used:https://randomnerdtutorials.com/esp32-async-web-server-espasyncwebserver-library/And there is also a screenshot of the HTML-page with the switches.

author: tooki
author_rank: Super Contributor
timestamp: March 27, 2023, 07:55:22 pm
content: Ok, now that I know what to look for:In your code in reply #5, you define .slider multiple times, first:Code:.slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #38c0ff ;outline: none; -webkit-transition: .2s; transition: opacity .2s;}And then a few lines later:Code:.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}If memory serves me correctly, CSS “overwrites” from top to bottom, so the second declaration overwrites the first.The second one is setting an absolute position at 0,0 which seems to be where they’re showing up.

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 28, 2023, 06:17:40 am
content: QuoteYes, I expected such a behavior, but put together the "pseudo code" anyway, just to see how bad the result is.So the question would be, how to define more than one style to different objects.I tried to put the switch-part in brackets like "h2 {...}" as it is typically done for different styles.That does make no difference. The HTML-page looks exactly the same as in the code where I deleted the whole switch-style.Code:<style>html {font-family: Times New Roman; display: inline-block; text-align: center;}h2 {font-size: 2.3rem;}p {font-size: 1.9rem;}body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}.slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #38c0ff ;outline: none; -webkit-transition: .2s; transition: opacity .2s;}.slider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 35px; height: 35px; background:#01070a; cursor: pointer;}.slider::-moz-range-thumb { width: 35px; height: 35px; background: #01070a; cursor: pointer; }switch {.switch {position: relative; display: inline-block; width: 120px; height: 68px}.switch input {display: none}.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}input:checked .slider {background-color: #b30000}input:checked .slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}}</style></head><body><h2>ESP32 Control</h2><p><span id="textslider_value">%SLIDERVALUE%</span></p><p><input type="range" onchange="updateSliderPWM(this)" id="pwmSlider" min="I_min" max="I_max" value="%SLIDERVALUE%" step="1" class="slider"></p><switch>%BUTTONPLACEHOLDER%</switch><script>

author: tooki
author_rank: Super Contributor
timestamp: March 28, 2023, 06:44:06 am
content: Quote from: PSR B1257 on March 28, 2023, 06:17:40 amYou can assign multiple classes to an element, or you can nest it inside another element (like a div) to which you’ve assigned another class.Seehttps://www.w3schools.com/tags/att_global_class.asphttps://stackoverflow.com/questions/13444647/css-class-definition-with-multiple-identifiers

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 28, 2023, 08:11:07 am
content: Thank you, but I don't get the code to work.Something is still not right in the syntax.Code:<title>ESP32 Control</title><style>html {font-family: Times New Roman; display: inline-block; text-align: center;}h2 {font-size: 2.3rem;}p {font-size: 1.9rem;}body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}.slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #38c0ff ;outline: none; -webkit-transition: .2s; transition: opacity .2s;}.slider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 35px; height: 35px; background:#01070a; cursor: pointer;}.slider::-moz-range-thumb { width: 35px; height: 35px; background: #01070a; cursor: pointer; }p.switch {.switch {position: relative; display: inline-block; width: 120px; height: 68px}.switch input {display: none}.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}input:checked .slider {background-color: #b30000}input:checked .slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}}</style></head><body><h2>ESP32 Control</h2><p><span id="textslider_value">%SLIDERVALUE%</span></p><p><input type="range" onchange="updateSliderPWM(this)" id="pwmSlider" min="I_min" max="I_max" value="%SLIDERVALUE%" step="1" class="slider"></p><p class="switch">%BUTTONPLACEHOLDER%</p><script>This code also gives the same result, as the code with no switch-style.

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 28, 2023, 11:01:03 am
content: Haaaaaaang on a second..... the switch-style is defined in the BUTTONPLACEHOLDER sub-routine.....yeah, I knowI just had to rename the variable for the slider in the switch-part to prevent a redefinition of the variable.Code:<style>html {font-family: Times New Roman; display: inline-block; text-align: center;}h2 {font-size: 2.3rem;}p {font-size: 1.9rem;}body {max-width: 400px; margin:0px auto; padding-bottom: 25px;}.slider { -webkit-appearance: none; margin: 14px; width: 360px; height: 25px; background: #38c0ff ;outline: none; -webkit-transition: .2s; transition: opacity .2s;}.slider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 35px; height: 35px; background:#01070a; cursor: pointer;}.slider::-moz-range-thumb { width: 35px; height: 35px; background: #01070a; cursor: pointer; }.switch {position: relative; display: inline-block; width: 120px; height: 68px}.switch input {display: none}.sliderSwitch {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}.sliderSwitch:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}input:checked .sliderSwitch {background-color: #b30000}input:checked .sliderSwitch:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}</style></head><body><h2>ESP32 Control</h2><p><span id="textslider_value">%SLIDERVALUE%</span></p><p><input type="range" onchange="updateSliderPWM(this)" id="pwmSlider" min="I_min" max="I_max" value="%SLIDERVALUE%" step="1" class="slider"></p>%BUTTONPLACEHOLDER%<script>function updateSliderPWM(element) {var slider_value = document.getElementById("pwmSlider").value;document.getElementById("textslider_value").innerHTML = slider_value*0.24;console.log(slider_value);var xhr = new XMLHttpRequest();xhr.open("GET", "/slider?value=" slider_value, true);xhr.send();}function toggleCheckbox(element) {var xhr = new XMLHttpRequest();if(element.checked){ xhr.open("GET", "/update?output=" element.id "&state=1", true); }else { xhr.open("GET", "/update?output=" element.id "&state=0", true); }xhr.send();}</script></body></html>)rawliteral";String processor(const String& var){if (var == "SLIDERVALUE"){return slider_value;}//Serial.println(var);if(var == "BUTTONPLACEHOLDER"){String buttons = "";buttons = "<h4>Output - AusgangL1</h4><label class="switch"><input type="checkbox" onchange="toggleCheckbox(this)" id="AusgangL1" " outputState(AusgangL1) "><span class="sliderSwitch"></span></label>";buttons = "<h4>Output - AusgangL2</h4><label class="switch"><input type="checkbox" onchange="toggleCheckbox(this)" id="AusgangL2" " outputState(AusgangL2) "><span class="sliderSwitch"></span></label>";buttons = "<h4>Output - AusgangL3</h4><label class="switch"><input type="checkbox" onchange="toggleCheckbox(this)" id="AusgangL3" " outputState(AusgangL3) "><span class="sliderSwitch"></span></label>";return buttons;}return String();}

author: CountChocula
author_rank: Unknown
timestamp: March 28, 2023, 11:56:11 am
content: Glad you were able to figure it out! In general, if I can offer a bit of very unsolicited advice, I'd say your code could use a little refactoring

author: PSR B1257
author_rank: Frequent Contributor
timestamp: March 29, 2023, 09:04:32 am
content: I'm glad the code is (finally) working at all, after I figured out, that I have forgotten a "server.on ......" subroutineTo make the browser-layout a little more compact, I tried to arrange the switches side by side.Therefore I changed one code line from "inline-block" to "inline":Code:.switch {position: relative; display: inline; width: 120px; height: 68px}Would be too nice, if that had worked.But now it looks like that:

author: tellurium
author_rank: Frequent Contributor
timestamp: April 02, 2023, 03:41:21 pm
content: Quote from: tooki on March 27, 2023, 07:24:20 amMy ESP32 pinout diagram is attached - for anyone who find it helpful. Compiled from the ESP32 TRM.