Use this forum to chat about hardware specific topics for the ESP8266 (peripherals, memory, clocks, JTAG, programming)

User avatar
By PreethiSM
#85386 Hello!
I am trying to upload EMG (Electromyography) signal to the Asksensors cloud using the ESP8266-12E nodemcu board. My circuit is really simple, I am using the myoware muscle sensor which is connected to A0, then vcc- 3.3 v, gnd-gnd. The issue is EMG signal needs a sampling rate of 1000 Hz (1000 discrete sample points in one second) but right now I am able to get only 10 samples per second because ESP8266 12 E takes 100 ms to update a data to the cloud. My arduino code and serial monitor output is as below. Is there anyway to do a faster update? OR is there any mistake in my code?

Please do help me. Thanks in advance.

Code: Select all#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>

// user config: TODO
#define  MOISTURE_THRESHOLD     55   // moisture alert threshold
const char* wifi_ssid = "******";             // SSID
const char* wifi_password = "*******";         // WIFI
const char* apiKeyIn = "********";      // API KEY IN
const unsigned int writeInterval = 1; // write interval (in ms)

// ASKSENSORS config.
String host = "http://api.asksensors.com";         // ASKSENSORS API host name

ESP8266WiFiMulti WiFiMulti;

int moisture_Pin= 0; // Soil Moisture Sensor input at Analog PIN A0
int moisture_value= 0, moisture_state = 0xFF;

void setup() {

  Serial.begin(115200);
  Serial.println("*****************************************************");
  Serial.println("********** Program Start : Soil Moisture monitoring using ESP8266 and AskSensors IoT cloud");
  Serial.println("Wait for WiFi... ");
  Serial.print("********** connecting to WIFI : ");
  Serial.println(wifi_ssid);
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("-> WiFi connected");
  Serial.println("-> IP address: ");
  Serial.println(WiFi.localIP());
 
}


void loop() {


    Serial.print("MOISTURE LEVEL : ");
    moisture_value= analogRead(moisture_Pin);
    Serial.println(moisture_value);
   if(moisture_value > MOISTURE_THRESHOLD) moisture_state = 0;
   else moisture_state = 1;
   

    // wait for WiFi connection
  if (WiFi.status() == WL_CONNECTED){

        HTTPClient http;
        client.write(webFile);

        Serial.print("[HTTP] begin...\n");
       
        // Create a URL for the request
        String url = "";
        url += host;
        url += "/write/";
        url += apiKeyIn;
        url += "?module1=";
        url += moisture_value;
        url += "&module2=";
        url += moisture_state;
       
        Serial.print("********** requesting URL: ");
        Serial.println(url);
        http.begin(url); //HTTP
       
        Serial.println(">EMG were sent to ASKSENSORS");

        Serial.print("[HTTP] GET...\n");
        // start connection and send HTTP header
        int httpCode = http.GET();

        // httpCode will be negative on error
        if(httpCode > 0) {
            // HTTP header has been send and Server response header has been handled
            Serial.printf("[HTTP] GET... code: %d\n", httpCode);

            // file found at server
            if(httpCode == HTTP_CODE_OK) {
                String payload = http.getString();
                Serial.println(payload);
            }
        } else {
            Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }

        http.end();

        Serial.println("********** End ");
        Serial.println("*****************************************************");
    }

    delay(writeInterval);
}


SERIAL MONITOR OUTPUT

-> [HTTP] begin...
17:19:43.421 -> ********** requesting URL: http://api.asksensors.com/write/Mh2ehZ0 ... &module2=1
17:19:43.457 -> > EMG data were sent to ASKSENSORS
17:19:43.457 -> MOISTURE LEVEL : 2
17:19:43.457 -> [HTTP] begin...
17:19:43.457 -> ********** requesting URL: http://api.asksensors.com/write/Mh2ehZ0 ... &module2=1
17:19:43.457 -> > EMG data were sent to ASKSENSORS
17:19:43.457 -> MOISTURE LEVEL : 2
17:19:43.457 -> [HTTP] begin...
17:19:43.457 -> ********** requesting URL: http://api.asksensors.com/write/Mh2ehZ0 ... &module2=1
17:19:43.493 -> > EMG data were sent to ASKSENSORS
17:19:43.493 -> MOISTURE LEVEL : 3
17:19:43.493 -> [HTTP] begin...
17:19:43.493 -> ********** requesting URL: http://api.asksensors.com/write/Mh2ehZ0 ... &module2=1
17:19:43.493 -> > EMG data sent to ASKSENSORS
17:19:43.493 -> MOISTURE LEVEL : 2
17:19:43.493 -> [HTTP] begin...
17:19:43.493 -> ********** requesting URL: http://api.asksensors.com/write/Mh2ehZ0 ... &module2=1
17:19:43.529 -> > EMG data were sent to ASKSENSORS
17:19:43.529 -> MOISTURE LEVEL : 2
17:19:43.529 -> [HTTP] begin...
17:19:43.529 -> ********** requesting URL:
User avatar
By schufti
#85396 if you just look at simple "ping-times" in your local network and then ping-time to a remote host (first hop via wifi) you will see that when incurring some time overhead for server side processing and higher layer (html) overhead your request (1 spl/ms) is far from realistic. You may also try with traceroute for more realistic times to your desired host.
User avatar
By btidey
#85399 You really should be uploading multiple samples at a time to reduce the overheads.

If you only need a recording over a small period (e.g. less than 20 seconds) then your best bet would be to trigger a sample capture and store the results into a buffer, then subsequently upload the results from the buffer after the capture is complete.

If you need continuous streaming then I think you might be better using an ESP32 with dual core. Then you could sample results into a circular buffer while another task takes batches of results from the buffer and uploads them (multiple values in each upload. The two cores would help keep sampling more consistent while the extra memory on the ESP32 would help with the buffering.

Note that the inbuilt ADC is not very good and you will only get about 7 bits of real resolution not the 10 the converter nominally gives. If you need better and a more consistent sampling rate then you need to use an external ADC like an ADS1015. With that you can use the inbuilt sampling rate of the converter and use interrupts to store the results into a buffer. An ESP-12 might then work uploading batches of data as that won't disturb the on-going sampling.
User avatar
By davydnorris
#85410 I agree with btidey:
- you will never get the rate you need the way you're doing it now. You either need to buffer the samples and send in a chunk or open a socket and stream the data instead of constantly connecting.
- you need much better resolution than what the inbuilt ADC gives you. For instance, standard C3D files expect analog data streams to be 16 bit signed integers as standard, so you need at minimum 16 bit sampling, but you'd be better off using 24bit sampling and then shifting out the lowest 8 bits

A 1k sample rate is pretty easy to do and that would give you lots of time to buffer samples and send a compressed stream