Home > Mobile >  Using ESP_NOW with loop and delays
Using ESP_NOW with loop and delays

Time:10-21

I'm trying to receive a data from one esp32 to another. I'm also doing some looping with delays for reading a sensor data and switch on/off relay cooling. This device also use ESPAsyncWebServer as API server (not included in code for the size). I'm receiving the data from one eps32 in POST request to API right now. I would like to change this as to be able to recieve with esp_now. I was doing some experiments, but the data receving is delayed because of delay method in loop. Is there a way to make this asynchronized as for example the ESPA above?

I also tried a way with comparing a milis() (time) to wait for a loop, but I thing that is too "resource consuming" task, to let it compare in full speed in loop like a vortex forever.

here is my loop it's just a simple loop with some vars and delay function for example


void loop() {
    if (WiFi.status() == WL_CONNECTED) {
        float temp_check = dht.readTemperature();

        if (temp_check == 0) {
            delay(1000);
            temp_check = dht.readTemperature();
        }

        if (temp_check > 32.0 && *cooling_switch_p == false) {
            Serial.println("[ INF ] Too high temperature, switch on a cooling system");
            digitalWrite(COOLING_RELAY, LOW);
            *cooling_switch_p = true;
        }
        else if (temp_check < 30.0  && *cooling_switch_p == true) {
            Serial.println("[ INF ] Normal temperature, switch off a cooling system");
            digitalWrite(COOLING_RELAY, HIGH);
            *cooling_switch_p = false;
        }

        Serial.print("[ DBG ] Light Switch: ");
        Serial.println(String(light_switch));
        Serial.println("");

        Serial.print("[ DBG ] Pump Switch: ");
        Serial.println(String(pump_switch));
        Serial.println("");
        delay(5000);
    }

    else {
        Serial.println("[ ERR ] Wifi not connected. Exiting program");
        delay(9999);
        exit(0);
    }
}

CodePudding user response:

I assume you're trying to send your sensor data from this device to another one while more or less accurately maintaining the 5-second sampling interval. You can create a simple asynchronous architecture yourself using 2 threads.

The existing thread (created by Arduino) runs your current loop() which reads the sensor every 5 seconds. You add a second thread which deals with transmitting the sample to other devices. The first thread posts the sample to the second thread through a FreeRTOS queue; second thread immediately goes to work transmitting. The first thread continues to mind its own business without waiting for transmission to complete.

Using the FreeRTOS documentation on creating tasks and queues:

#include <task.h>
#include <queue.h>
#include <assert.h>

TaskHandle_t hTxTask;
QueueHandle_t hTxQueue;

constexpr size_t TX_QUEUE_LEN = 10;

// The task which transmits temperature samples to wherever needed
void txTask(void* parm) {
  while (true) {
    float temp;
    // Block until a sample is posted to queue
    const BaseType_t res = xQueueReceive(hTxQueue, static_cast<void*>(&temp), portMAX_DELAY);
    assert(res);
    // Here you write your code to send the temperature to other device
    // e.g.: esp_now_send(temp);
  }
}

void setup() {
  // Create the queue
  hTxQueue = xQueueCreate(TX_QUEUE_LEN, sizeof(float));
  assert(hTxQueue);
  // Create and start the TX task
  const BaseType_t res = xTaskCreate(txTask, "TX task", 8192, nullptr, tskIDLE_PRIORITY, &hTxTask);
  assert(res);
  // ... rest of your setup()
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    float temp_check = dht.readTemperature();
    // Post fresh sample to queue
    const BaseType_t res = xQueueSendToBack(hTxQueue, &temp_check, 0);
    if (!res) {
      Serial.println("Error: TX queue full!");
    }
    // ... Rest of your loop code
  }
}
  • Related