मैं ArduinoIDE के लिए ESPAsyncWebServer लाइब्रेरी के साथ ESP32 हीप से 8192 मानों के साथ एक बड़े फ्लोट सरणी की सेवा करने का प्रयास कर रहा हूं। µC एक ESP32 देवकिट c है और मैं एक ब्राउज़र के साथ सरणी का उपयोग करना चाहता हूं। यहाँ सरणी के लिए कोड है:

#include "AsyncJson.h"
#include "ArduinoJson.h"
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

#define SAMPLES 8192

static float * vReal;

void setup() {
  vReal = (float *) malloc(SAMPLES * sizeof(float));
  assert(vReal != NULL);
}

void loop() {
  //Put something into the array
  for (int i = 0; i < SAMPLES; i++)
  {
    vReal[i] = 1.1;
  }
}

फिलहाल मैं "ArduinoJson बेसिक रिस्पांस" का उपयोग करता हूं और बड़े सरणी को 512 मानों के भागों में भेजता हूं। यदि मैं ब्राउज़र के साथ सरणी तक पहुंचने का प्रयास करता हूं, तो 1024 मानों के साथ मुझे कार्य async_tcp में एक स्टैक ओवरफ़्लो मिलता है, इसलिए मैंने इसे 512 मानों पर सेट किया है। इसके लिए कोड यहां दिया गया है:

server.on("/array1", HTTP_GET, [](AsyncWebServerRequest * request) {
AsyncResponseStream *response = request->beginResponseStream("application/json");
const size_t CAPACITY = JSON_ARRAY_SIZE(512); //Compute size of array
StaticJsonDocument<CAPACITY> vRealPart;
JsonArray array = vRealPart.to<JsonArray>();
for (int i = 0; i < 512; i++)
{
  vRealPart.add(vReal[i]);
}
serializeJson(vRealPart, *response); //Print to HTML
request->send(response);
});

मैं इसे पूरे सरणी की सेवा के लिए 16 बार करता हूं। बाद में, मैं पथ के "/ array1", "/ array2", "/ array3"... को जावास्क्रिप्ट के साथ कॉल करता हूं और JSON को पार्स करता हूं। यह आउटपुट है, यदि पथ में से किसी एक को वेबब्रोसर में कहा जाता है:

[0.334593,0.427480,0.181299,0.066654,0.271184,0.356220,0.374454,0.235625,...]

यह अब तक अधिकांश समय के लिए काम करता है, लेकिन मुझे लगता है कि यह बहुत लंबा है। यह अच्छा होगा, अगर पूरे सरणी के साथ केवल एक ही पथ हो। यह SPIFFS की एक स्थिर फ़ाइल के साथ काम करता है, उदाहरण के लिए:

server.serveStatic("/jsonArray1", SPIFFS, "/jsonArray1");

लेकिन पूरे ऐरे को फ्लैश करने के लिए लिखने में अधिक समय लगता है। हालांकि पढ़ना वास्तव में तेज है।

मैंने "ArduinoJson Advanced Response" की भी कोशिश की, लेकिन मैं इसे JsonArray के साथ चलाने के लिए नहीं मिला। दुर्भाग्य से ArduinoJson के लिए ESPAsyncWebServer से GitHub पृष्ठ पर उदाहरणों को हटा दिया गया है, क्योंकि उन्होंने नए संस्करण (v6) में सिंटैक्स को थोड़ा बदल दिया है।

संक्षेप में: ESPAsyncWebServer लाइब्रेरी के साथ ESP32 हीप से इतने बड़े सरणियों की सेवा करने का सबसे अच्छा तरीका क्या है? लक्ष्य वेबब्रोसर में जावास्क्रिप्ट के साथ बाद में सरणी को संसाधित करना है।

आपकी सहायताके लिए धन्यवाद!

बेंटीडेम

पुनश्च: अगर यह मदद करता है: मैं एक मोटर करंट से लाइब्रेरी arduinoFFT के साथ FFT कर रहा हूं। इसलिए मैं एक एडीसी करता हूं और 16384 मानों को एनालॉग से डिजिटल कनवर्टर में एक सरणी में सहेजता हूं। यह सरणी FFT लाइब्रेरी को पास कर दी गई है। आउटपुट 8192 मानों वाला एक सरणी है। यह परिणाम ढेर में है और परिणाम प्रदर्शित करने के लिए मेरे वेब इंटरफेस में स्थानांतरित किया जाना चाहिए। मैं सरणियों को गति के लिए RAM में रखना चाहता हूं। प्रत्येक माप के लिए आपको 8192 मानों के साथ एक परिणाम सरणी मिलती है।

2
Bentiedem 2 मई 2020, 15:57

2 जवाब

सबसे बढ़िया उत्तर

आखिरकार मुझे अब एक समाधान मिला जो खंडित प्रतिक्रिया का उपयोग करता है। इसके अलावा ArduinoJson का अब और उपयोग नहीं किया जाता है। मुझे इसे स्थिर करने के लिए बफर को सिकोड़ना पड़ा (maxLen = maxLen >> 1;)। पुस्तकालय मुझे एक गलत अधिकतम देता है। अधिकतम लंबाई के साथ बफर लंबाई। यह बग हो सकता है।
यह मेरे पिछले समाधान की तुलना में बहुत अधिक तेज़ है और बिना µC के किसी भी क्रैश के चलता है। 16384 मानों वाला एक सरणी 422 एमएस में μC से वेबब्राउज़र में एक टुकड़े में स्थानांतरित हो जाता है। यहाँ सर्वर प्रतिक्रिया के लिए कोड है:

server.on("/array", HTTP_GET, [](AsyncWebServerRequest * request)
  {
    indexvReal = 0;
    AsyncWebServerResponse* response = request->beginChunkedResponse(contentType,
                                       [](uint8_t* buffer, size_t maxLen, size_t index)
    {
      maxLen = maxLen >> 1;
      size_t len = 0;
      if (indexvReal == 0)
      {
        len += sprintf(((char *)buffer), "[%g", vReal[indexvReal]);
        indexvReal++;
      }
      while (len < (maxLen - FLOATSIZE) && indexvReal < LEN(vReal))
      {
        len += sprintf(((char *)buffer + len), ",%g", vReal[indexvReal]);
        indexvReal++;
      }
      if (indexvReal == LEN(vReal))
      {
        len += sprintf(((char *)buffer + len), "]");
        indexvReal++;
      }
      return len;
    });
    request->send(response);
  });

परीक्षण उद्देश्यों के लिए यहां एक पूर्ण उदाहरण दिया गया है:

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

const char *ssid = "...";
const char *password = "...";
int counter_wifi = 0;
AsyncWebServer server(80);

#define LEN(arr) ((int) (sizeof (arr) / sizeof (arr)[0]))
#define SAMPLES 16384
static float vReal[SAMPLES]; //Stack
uint16_t indexvReal = 0;

#define FLOATSIZE 20
const char *contentType = "application/json";
//const char *contentType = "text/plain";

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
    counter_wifi++;
    if (counter_wifi >= 10) { //after 5 seconds timeout - reset board (on unsucessful connection)
      ESP.restart();
    }
  }
  Serial.println("WiFi connected.");
  Serial.println("IP Address: ");
  Serial.println(WiFi.localIP());

  for (int i = 0; i < SAMPLES; i++)
  {
    vReal[i] = random(20) * 3.2357911;
  }

  server.on("/array", HTTP_GET, [](AsyncWebServerRequest * request)
  {
    indexvReal = 0;
    AsyncWebServerResponse* response = request->beginChunkedResponse(contentType,
                                       [](uint8_t* buffer, size_t maxLen, size_t index)
    {
      maxLen = maxLen >> 1;
      size_t len = 0;
      if (indexvReal == 0)
      {
        len += sprintf(((char *)buffer), "[%g", vReal[indexvReal]);
        indexvReal++;
      }
      while (len < (maxLen - FLOATSIZE) && indexvReal < LEN(vReal))
      {
        len += sprintf(((char *)buffer + len), ",%g", vReal[indexvReal]);
        indexvReal++;
      }
      if (indexvReal == LEN(vReal))
      {
        len += sprintf(((char *)buffer + len), "]");
        indexvReal++;
      }
      return len;
    });
    request->send(response);
  });

  DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  // put your main code here, to run repeatedly:

}
0
Bentiedem 16 मई 2020, 18:16

यहां एक प्रस्ताव है कि आप फ्लैश के लिए संकलित सरणी का उपयोग कैसे कर सकते हैं:

const uint16_t SAMPLESPERSEND = 8196;
const uint8_t SAMPLESNUMSIZE = 8; // as your nums are 0.271184 so 8 chars

float myMeasureVals [SAMPLESPERSEND];
char myValueArray[SAMPLESPERSEND * (SAMPLESNUMSIZE + 1) + 2 + 1] = {'\0'};
char numBufferArray[SAMPLESNUMSIZE + 1] = {'\0'}; // Converter helper array

फिर आप उस कोड मानों के साथ जोड़ते हैं

server.on("/array", HTTP_GET, [](AsyncWebServerRequest * request) {
AsyncResponseStream *response = request->beginResponseStream("application/json");
  strcpy (myValueArray, "[");
  for (uint16_t i = 0; i < SAMPLESPERSEND; i++) {
    if (i!=0) strcat (myValueArray, ",");
    // float myTempValue = function2GetValues(); // direct froma function
    float myTempValue = myMeasureVals [i];
    // dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf);
    dtostrf(myTempValue, 2, 6, numBufferArray);
    strcat (myValueArray, numBufferArray);
  }
  strcat (myValueArray, "]");
  myValueArray [strlen(myValueArray)] = '\0'; // terminate correct
  Serial.println(myValueArray);  // Only debug
 request->send(myValueArray);
  myValueArray[0] = '\0';  // empty array for next part
});

कोड संकलित करता है, भेजने का परीक्षण नहीं किया है उस तरह से संसाधित किया जा सकता है या खंडित विधि का उपयोग किया जाना है। आम तौर पर मैं केवल सेटअप में ऐसे बड़े सरणी का उपयोग करता हूं और फाइल सिस्टम से पढ़ता हूं। यहां हैंडलिंग "समान" है जैसा कि ArduinoJson करता है, लेकिन कोड की कुछ पंक्तियों के साथ और यदि आपको लंबे और स्थिर चलने वाले ऐप की आवश्यकता है तो कोई ढेर विखंडन नहीं है।
संपादित करें
मेरा पसंदीदा समाधान SPIFFS में एक फ़ाइल को लगातार लिखना होगा (SD उदाहरण डेटा लकड़हारा देखें या इस पोस्ट को) और फ़ाइल को परोसें। ~ 10.000 मानों के लिए यह सबसे साफ तरीका है। कोष्ठक और कोमा कैसे जोड़ें ऊपर दिए गए कोड में दिखाया गया है, इसलिए उस फ़ाइल की सामग्री एक बड़ा JSON है जिसे जावास्क्रिप्ट के माध्यम से जल्दी से संसाधित किया जा सकता है। और उदाहरण के लिए 10 अलग-अलग लॉग फ़ाइलों का उपयोग करके आप नेटवर्क त्रुटियों या इसी तरह के मामले में पुनर्प्राप्त करने की संभावना रखते हैं

0
Codebreaker007 3 मई 2020, 01:55