ESP-01 inconsistent WiFi performance

Thank you for your reply @Deva_Rishi!

I rewrote the reading and parsing of the Serial input and this did increase the performance a lot! Using an AP I now get about 100ms for each request-response cycle, which is more than good enough for my use case.

I have kept the server.on part of the code, because I would like the students to be able to dynamically build up the HTML from the Pico code. This way I can pre-program the ESP-01S modules and have the kids specify the name of the AP (and their password), as well as which buttons to display and what message they should send back over Serial.println() to the Pico.

In the setup() function of the Pico, the students can simply send the follwing to set up the buttons and the AP.

+AP;ESP-01S;Password
+B;/ON;ON;ON_OK;50;50;100;50
+B;/OFF;OFF;OFF_OK;50;150;100;50

This will build up the UI that was in the screenshot above. A very simple UI, but a working one :slight_smile:

I am attaching the code (which needs some TLC and refactoring at this point) :slight_smile: I will also look over the example you gave above...

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

ESP8266WebServer server(80);
String htmlContent = "";
const int led = 2;
boolean isConnected = false;

const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;

void handleRoot() {
  digitalWrite(led, 1);
  server.send(200, "text/html", htmlContent);
  digitalWrite(led, 0);
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

void setupAP(String ssid, String  pass) {
  digitalWrite(led, 1);
  delay(200);
  digitalWrite(led, 0);
  delay(200);
  digitalWrite(led, 1);
  delay(200);

  WiFi.softAP(ssid, pass);
  
  Serial.print("IP;");
  Serial.println(WiFi.localIP());
  
  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");
  digitalWrite(led, 0);

  isConnected = true;
}

void setupWifi(String ssid, String pass) {
  digitalWrite(led, 1);
  delay(299);
  digitalWrite(led, 0);
  delay(299);
  digitalWrite(led, 1);
  delay(299);

  Serial.print("Setting WiFi Connection... ");
  Serial.println(WiFi.softAP(ssid, pass) ? "Ready" : "Failed!");

  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);

  WiFi.mode(WIFI_STA);
  WiFi.begin("Skynett", "frittvilt");
  
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  
  Serial.print("IP;");
  Serial.println(WiFi.localIP());

  server.begin();
  digitalWrite(led, 0);
}

void setup() {
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);
  
  Serial.begin(115200);
  Serial.println("Setup complete");
}

void loop() {
  server.handleClient();
  
  readFromSerial();

  handleNewData();
}

void readFromSerial() {
 static byte ndx = 0;
 char endMarker = '\n';
 char rc;
 
  while (Serial.available() && newData == false) {
    digitalWrite(led, 1);
    rc = Serial.read();
    if (rc != endMarker) {
       receivedChars[ndx] = rc;
       ndx++;
       if (ndx >= numChars) {
        ndx = numChars - 1;
       }
    } else {
     receivedChars[ndx] = '\0'; // terminate the string
     ndx = 0;
     newData = true;
     digitalWrite(led, 0);
    }   
  }

  delay(25);
}

void handleNewData() {
  if (newData == true) {

    String buttonValues[8];
     int index = 0;
    if (strstr(receivedChars, "+B")) {
      char* command = strtok(receivedChars, ";");
      while (command != NULL) {
        buttonValues[index] = command;
        index++;
        command = strtok(NULL, ";");
      }

      if (index == 8) {
        String returnVal = buttonValues[3];
        server.on(buttonValues[1], [returnVal]() { Serial.println(returnVal); server.send(200, "text/plain", returnVal); });  
        htmlContent += "<button style=\"position:absolute; top: " + buttonValues[5] + "px; left: " + buttonValues[4] + "px; width: " + buttonValues[6] + "px; height: " + buttonValues[7] + "px;\" onclick=\"fetch('" + buttonValues[1] + "');\">" + buttonValues[2] + "</button>";
      }
      
    }

    if (strstr(receivedChars, "+AP")) {
      char* command = strtok(receivedChars, ";");
      while (command != NULL) {
        buttonValues[index] = command;
        index++;
        command = strtok(NULL, ";");
      }

      if (index == 3) {
        setupAP(buttonValues[1], buttonValues[2]);
      }
    }

    if (strstr(receivedChars, "+WF")) {
      char* command = strtok(receivedChars, ";");
      while (command != NULL) {
        buttonValues[index] = command;
        index++;
        command = strtok(NULL, ";");
      }

      if (index == 3) {
        setupWifi(buttonValues[1], buttonValues[2]);
      }
    }

     newData = false;
  }
}

That can also be done without the server.on, but if this works i guess it's fine. My concern is that you are just not really meant to do it like that, and you are dynamically adding to the server object, which possibly could cause memory issues.
The ESP's RAM is vast but not infinite. The variables that the students send can also populate a webpage dynamically.

Got it working through the Pi Pico as well using the code for the ESP-01S. Round-trip times from the Pico is less than 50ms mostly :slight_smile:

int led = 25;
int enable = 22;


const byte numChars = 60;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;


void setup() {
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);

  Serial1.begin(115200);
  Serial.begin(9600);

  Serial.println("Toggling Enabled");
  pinMode(enable, OUTPUT);
  digitalWrite(enable, HIGH);
  delay(1000);
  digitalWrite(enable, LOW);
  delay(1000);
  digitalWrite(enable, HIGH);
  delay(1000);
  
  Serial.println("Starting Wifi");
  Serial1.print("+AP;ESP-01S;Password\n");
  delay(3000);
  Serial1.print("+B;/ON;ON;ON_OK;50;50;150;50\n");
  delay(150);
  Serial1.print("+B;/OFF;OFF;OFF_OK;50;150;150;50\n");
  delay(150);
}

void loop() {
  
  if (Serial.available()) { 
    Serial1.write(Serial.read());
  }

  readFromSerial();
  handleNewData();
  
  delay(25);
}

void readFromSerial() {
 static byte ndx = 0;
 char endMarker = '\n';
 char rc;
 
  while (Serial1.available() && newData == false) {
    digitalWrite(led, 1);
    rc = Serial1.read();
    if (rc != endMarker) {
       receivedChars[ndx] = rc;
       ndx++;
       if (ndx >= numChars) {
        ndx = numChars - 1;
       }
    } else {
     receivedChars[ndx] = '\0'; // terminate the string
     ndx = 0;
     newData = true;
     digitalWrite(led, 0);
    }   
  }

  delay(25);
}

void handleNewData() {
  if (newData == true) {
    String received = String(receivedChars);
    received.trim();
    Serial.println(receivedChars);

    if (received == "ON_OK") {
      Serial.println("ON");
      digitalWrite(led, HIGH);
    }

    if (received == "OFF_OK") {
      Serial.println("OFF");
      digitalWrite(led, LOW);
    }

    newData = false;
  }
}

What happens when they do ?

for (uin8_t i =0; i < 255; i++) {
  Serial1.print("+B;/OFF;OFF;OFF_OK;50;150;150;50\n");
  delay(150);
}

In that case I guess they get 150 buttons on the same location :slight_smile:

Joking aside, I do need to build in some safety, which I intend to do. A working prototype was a first priority for the project, though!

In the end, though, the kids will program the Pico via an online Blockly environment, so even though they can access loops and other structures, they are somewhat limited...

All those buttons are created on the heap, hopefully not as a part of the same object, but if that, in combination with the global String might just eat quite a lot of it.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.