ArduinoWiFiServer "print" locks other tasks

Hi,
I am currently working on a sketch using AccelStepper to conrol a rotator in azimuth and elevation on an ESP8266 board, compliant with rotctld protocol:

#include <ESP8266WiFi.h>
#include <ArduinoWiFiServer.h>
#include <Arduino.h>
#include <WString.h>

#define BUFFER_SIZE   256
#define BAUDRATE      9600

#ifndef STASSID
#define STASSID "********"
#define STAPSK  "********"
#define PORT  4533
#endif

const char* ssid     = STASSID;
const char* password = STAPSK;

ArduinoWiFiServer server(PORT);

class rotctld {
public:
    void rotctld_init() {
	    Serial.begin(BAUDRATE);
        WiFi.begin(ssid, password);

        while (WiFi.status() != WL_CONNECTED) {
            delay(500);
            Serial.print(".");
        }
        digitalWrite(WIFI_LED, HIGH);
        server.begin();
        IPAddress ip = WiFi.localIP();
        Serial.println();
        Serial.println("Connected!");
        Serial.print("Telnet server listening on ");
        Serial.print(ip);
        Serial.print(":");
        Serial.println(PORT);
    }

    void rotctld_proc() {
        char buffer[BUFFER_SIZE];
        char incomingByte;
        char *Data = buffer;
        char *rawData;
        static uint16_t BufferCnt = 0;
        char data[100];
        String str1, str2;

        // Returns first client which has data to read or a 'false' client
        WiFiClient client = server.available();

        // client is true only if it is connected and has data to read
        if (client) {
            //ESP.wdtFeed();
            incomingByte = client.read();

            // Read new data until '\n'
            if (incomingByte == '\n' || incomingByte == '\r') {
                buffer[BufferCnt] = 0;
                if (buffer[0] == 'p') {
                    // Send current absolute position in deg
                    str1 = String(control_az.input, 1);
                    str2 = String(control_el.input, 1);
                    server.println(str1);
                    server.println(str2);
                } else if (buffer[0] == 'P' && buffer[1] == ' ') {
                    // Get the absolute position in deg for azimuth
                    rotator.control_mode = position;
                    rawData = strtok_r(Data, " ", &Data);
                    strncpy(data, rawData + 2, 10);
                    char* az = strtok(data, " ");
                    char* el = strtok(NULL, "\0");

                    if (isNumber(az) && isNumber(el)) {
                        control_az.setpoint = atof(az);
                        control_el.setpoint = atof(el);
                        server.println("RPRT 0");       // Return OK
                    } else {
                        server.println("RPRT 1");       // Return ERROR
                    }
                }
                // Reset the buffer an clean the buffer
                BufferCnt = 0;
                server.flush(); // flush the buffers
            } else {
                // Fill the buffer with incoming data
                buffer[BufferCnt] = incomingByte;
                BufferCnt++;
            }
        }
    }

private:
    bool isNumber(char *input) {
        for (uint16_t i = 0; input[i] != '\0'; i++) {
            if (isalpha(input[i]))
                return false;
        }
        return true;
    }
};

Basicaly it works like that:

"P 180 45" sets the rotator to azimuth 180 and elevation 45

"p" requests the current position, the result is displayed like this:

180.00

45.00

In the real life, the program which interacts with the rotator (Gpredict) sets the wanted position (P 180 54) and polls the current position (p) during the movement every 0.5 seconds.
My concern is that each time the position is polled with "p" the motors stop running then continue.
server.print() locks the rest of the program until it has finished to sent the data.

If I use Serial.print() instead of server.print(), the motors run flawlessly.

Is there a way to sort this out?

you have server.flush(). do you change it to client.flush() when you change server.println to client.println?

I didn't change to client.println but Serial.println to test if it worked better, and it did :wink:

If I replace everything to control it via Serial it works fine. When using telnet the problem appears.

try it without the server.flush()

Removing server.flush() definitely improves the situation, the motors run now normally.
But most of the requests don't work anymore:

-> P 350 90
RPRT 0
-> p
152.5
74.5
-> p
-> p
162.4
83.9
-> p
-> p
172.9
89.3
-> p
-> p
-> p
-> p
-> p
-> p
206.8
90.0

After the "set positon" command (P 350 90), many polls fail. :frowning:

maybe read all available bytes before returning from rotctld_proc

After having reduced the microsteps value and consequently the steps per revolution and max speed, it works far better.
This does not explain why it worked perfectly fine with Serial communication but my problem is solved.
Thanks a lot @Juraj

I am the author of the ArduinoWiFiServer class, so I am glad it is useful

1 Like

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