Minimizing Latency in ESP-NOW Communication for Robot Control

Hello everyone,

I'm working on a robot control project that uses two ESP devices communicating via ESPNOW. One ESP reads input from a gamepad joystick, and the other processes the motor controls. While the system works, I'm experiencing a significant delay of 1-3 seconds during operation, which is affecting performance.

Has anyone encountered a similar issue or found a way to reduce this latency? Would using timing functions like millis() help, or is there another solution to improve the responsiveness of the ESP-NOW communication?

Thanks in advance for any suggestions!

This as tx that reads the gamepad (SENDER)

#include <esp_now.h>
#include <WiFi.h>
#include <ArduinoJson.h>
#include <Bluepad32.h>

// MAC Address ESP Penerima
uint8_t receiverMAC[] = {0xEC, 0x62, 0x60, 0x33, 0xFA, 0xD0};

GamepadPtr myGamepad = nullptr;

// Callback saat gamepad terhubung
void onConnectedGamepad(GamepadPtr gp) {
    Serial.println("Gamepad Connected!");
    myGamepad = gp;
}

// Callback saat gamepad terputus
void onDisconnectedGamepad(GamepadPtr gp) {
    Serial.println("Gamepad Disconnected!");
    myGamepad = nullptr;
}

// Callback saat ESP-NOW mengirim data
void onSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
    Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Sent Successfully" : "Send Failed");
}

void setup() {
    Serial.begin(115200);
    WiFi.mode(WIFI_STA);

    if (esp_now_init() != ESP_OK) {
        Serial.println("ESP-NOW Init Failed!");
        return;
    }
    esp_now_register_send_cb(onSent);

    esp_now_peer_info_t peerInfo;
    memset(&peerInfo, 0, sizeof(peerInfo));
    memcpy(peerInfo.peer_addr, receiverMAC, 6);
    peerInfo.channel = 0;
    peerInfo.encrypt = false;
    peerInfo.ifidx = WIFI_IF_STA;

    if (esp_now_add_peer(&peerInfo) != ESP_OK) {
        Serial.println("Failed to add peer");
        return;
    }

    BP32.setup(&onConnectedGamepad, &onDisconnectedGamepad);
}

void loop() {
    BP32.update();

    if (myGamepad && myGamepad->isConnected()) {
        // Ambil data joystick
        int xLeft = myGamepad->axisX();
        int yLeft = -myGamepad->axisY() + 4;
        int z = myGamepad->axisRX();
        int btnA = myGamepad->a() ? 1 : 0;
        int btnB = myGamepad->b() ? 1 : 0;

        // Serialize data ke JSON
        StaticJsonDocument<200> doc;
        doc["xLeft"] = xLeft;
        doc["yLeft"] = yLeft;
        doc["z"] = z;
        doc["A"] = btnA;
        doc["B"] = btnB;

        char jsonBuffer[256];
        size_t jsonLen = serializeJson(doc, jsonBuffer, sizeof(jsonBuffer));

        esp_err_t result = esp_now_send(receiverMAC, (uint8_t *)jsonBuffer, jsonLen);
        if (result != ESP_OK) {
            Serial.println("Error sending data");
        }

        Serial.printf("Sent JSON: %s\n", jsonBuffer);
    }

    delay(10);
}

This as rx which processes the motor (RECEIVER)

#include <WiFi.h>
#include <esp_now.h>
#include <ArduinoJson.h>

#define RPWM_PIN1 18
#define LPWM_PIN1 19
#define RPWM_PIN2 21
#define LPWM_PIN2 22
#define RPWM_PIN3 23
#define LPWM_PIN3 25
#define RPWM_PIN4 26
#define LPWM_PIN4 27

void setMotorSpeed(int pin_r, int pin_l, int speed, const char* motorName) {
    int pwmValue = abs(speed);
    bool maju = (speed > 0);

    if (speed == 0) {
        analogWrite(pin_r, 0);
        analogWrite(pin_l, 0);
        Serial.printf("%s: STOP\n", motorName);
    } else {
        analogWrite(pin_r, maju ? pwmValue : 0);
        analogWrite(pin_l, maju ? 0 : pwmValue);
        Serial.printf("%s: %s dengan PWM %d\n", motorName, maju ? "MAJU" : "MUNDUR", pwmValue);
    }
}

// Callback saat menerima data
void onReceiveData(const esp_now_recv_info_t *info, const uint8_t *data, int len) {
    Serial.print("Data received from: ");
    for (int i = 0; i < 6; i++) {
        Serial.printf("%02X", info->src_addr[i]);
        if (i < 5) Serial.print(":");
    }
    Serial.println();

    // Parsing JSON
    StaticJsonDocument<200> doc;
    DeserializationError error = deserializeJson(doc, data, len);
    if (error) {
        Serial.print("JSON Parsing failed: ");
        Serial.println(error.c_str());
        return;
    }

    int x = doc["xLeft"] ;
    int xLeft = x * -1;
    int yLeft = doc["yLeft"];
    int z = doc["z"];
    int btnA = doc["A"];
    int btnB = doc["B"];

    Serial.printf("xLeft: %d | yLeft: %d | z: %d | A: %d | B: %d\n", xLeft, yLeft, z, btnA, btnB);

    // Hitung kecepatan motor
    int m1 = xLeft + yLeft + z;
    int m2 = xLeft - yLeft + z;
    int m3 = -xLeft + yLeft + z;
    int m4 = -xLeft - yLeft + z;

    m1 = constrain(m1, -255, 255);
    m2 = constrain(m2, -255, 255);
    m3 = constrain(m3, -255, 255);
    m4 = constrain(m4, -255, 255);

    Serial.printf("M1: %d | M2: %d | M3: %d | M4: %d\n", m1, m2, m3, m4);

    setMotorSpeed(RPWM_PIN1, LPWM_PIN1, m1, "M1");
    setMotorSpeed(RPWM_PIN2, LPWM_PIN2, m2, "M2");
    setMotorSpeed(RPWM_PIN3, LPWM_PIN3, m3, "M3");
    setMotorSpeed(RPWM_PIN4, LPWM_PIN4, m4, "M4");

    delay(10);
}

void setup() {
    Serial.begin(115200);

    pinMode(RPWM_PIN1, OUTPUT);
    pinMode(LPWM_PIN1, OUTPUT);
    pinMode(RPWM_PIN2, OUTPUT);
    pinMode(LPWM_PIN2, OUTPUT);
    pinMode(RPWM_PIN3, OUTPUT);
    pinMode(LPWM_PIN3, OUTPUT);
    pinMode(RPWM_PIN4, OUTPUT);
    pinMode(LPWM_PIN4, OUTPUT);

    WiFi.mode(WIFI_STA);
    if (esp_now_init() != ESP_OK) {
        Serial.println("Error initializing ESP-NOW");
        return;
    }
    esp_now_register_recv_cb(onReceiveData);
}

void loop() {
}

Some testers report tiny latency (<10ms) for small (250 byte) payloads. What's your payload? If it is small, then your problem is probably elsewhere.

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