Fastest way to send Accelerometer data over WiFi to webserver?

Hello,

I am working on a project where I'm using an GPU-6050 accelerometer as a microphone, converting the acceleration data into audio data. I'm using a Wemos D1 board, and right now I can get samples from the accelerometer as fast as 700 samples/second without sending the data over wifi. However, the accelerometer will have to be remotely located and ideally not connected to a computer or ethernet. So, I'm trying to find a way to send the accelerometer data over wifi to a xampp server I have running on my machine. The issue with my code right now is I can only update my mysql table with accelerometer values using http.get() about 15 times a second. I also made a simple webpage that only takes the value from the get request and stores it in a php variable, and it looks like with that I'm only sending about 30 accelerometer values a second. I'd really like to preserve the sample rate of 700 samples/second that I get just using serial as best as I can and I'm wondering what the best way to do that is. Here is the code I'm currently using:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include "Wire.h" // This library allows you to communicate with I2C devices.
const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.
int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data

// replace the MAC address below by the MAC address printed on a sticker on the Arduino Shield 2
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

const char* ssid = "XXXX";
const char* pass = "XXXXXXXX";

HTTPClient http;
WiFiClient wifiClient;
//
String HTTP_METHOD = "GET";
String  HOST_NAME = "XXXXX";
//String PATH_NAME   = "/insert_accel.php";
//String queryString = "";

void setup() {
  Serial.begin(115200);
  delay(10);
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
  Wire.write(0x6B); // PWR_MGMT_1 register
  Wire.write(0); // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  // Begin WiFi section

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  
}

void loop() {
  String link;
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3F); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
  Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
  Wire.requestFrom(MPU_ADDR, 2, true); // request a total of 7*2=14 registers
  
  // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
  //accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
  //accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
  accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
  
  // print out data

  Serial.println(accelerometer_z);

  //queryString = "?accel_x=" + String(accelerometer_x) + "&accel_y=" + String(accelerometer_y) + "&accel_z=" + String(accelerometer_z);

  link = HOST_NAME + "?accel_z=" + String(accelerometer_z);
  http.begin(wifiClient, link);
  int httpCode = http.GET();
  //String payload = http.getString();
  //Serial.println(httpCode);   //Print HTTP return code
  //Serial.println(payload);    //Print request response payload
  

  http.end();  //Close connection
  

}

Is there a faster way to do this? Any and all suggestions would be great.

Thanks

I'm even surprised you get 15 data per second...

You probably need to drop the idea of HTTP and go to UDP and keep the connexion alive

1 Like

This is a partial answer, but have you heard of operating the esp8266 as a wifi-uart bridge?
Check this out: WiFi-UART Serial Bridge Using ESP8266 or ESP32 - Atadiat

1 Like

Yeah I figured :confused: thank you!

Ooo this looks promising! From my understanding this might allow me to write the accel values to serial and read them from the esp-link server remotely?

Side question:

How do you visualize the accelerometer data from a webpage if it's being refreshed at lets say 50 times a second? I'm interested since I want to do the same thing. I already have the data and can stream it via UDP, I just don't have the software application to "visualize" it.

Yup, just a stream of data.
Also check out what @J-M-L said about UDP as I don't know which is faster or better suited for your application.

Have a look at this project Remote High Speed Data Logging which achieves ~40Kb/sec (~2000 samples/sec.) via WiFi to an Android mobile.
The project covers the various bottlenecks you will come across.

UDP is a non-reliable transfer method which can drop or re-arrange packets, but may be ok on a small local network, but you will never know if the data is all arriving or in the correct order, so not recommended.

Correct - UDP does not guarantee delivery

I've never used UDP. Do you think adding a time index in the first few bytes of each message would help with sorting the data on the PC side as well as detecting lost messages by way of gaps in the time sequence?

sure, you'll know you've lost something but won't be able to get it back :wink:

Ah, but at that sample rate so long as you know a sample is missing you can account for the hole when calculating averages in comparing time periods?
x pieces + y lost messages = the total period
the average for that period is calculated by the total of the x pieces over x instead of over x + y

You must decide what is more important to your application. You can choose between the two basic transport layer protocols.

  • UDP you can lose packets, but you get a short delay. This is good for real-time streaming. By the time you could receive a retry packet the packet is useless because it is out of date. The error checking has to be done at the user level or application level.

  • TCP you get a "longer" delay, but you will receive all packets. This is good for file type of transfers where you need all data.

I would start with TCP and only switch to UDP when you find you cannot accept the delay.

I would second that and would be surprised if TCP was not fast enough.

I worked on a commercial system that used UDP to distribute data to mulitple workstations, but it had sequence numbers for each packet and a buffer to store are re-sequence the packets in the correct order AND if it found missing packets it then made a TCP connection to pick them up.
A lot of software (and logic errors) to be sorted out to get that to work.

That was the ask

The reason I suggested UDP à was to be as fast as possible to create the audio stream.

My assumption was that lost packet would just be missed opportunity for fine tuning the sound generation but not critical

I had the possible wrong idea in my mind that TCP over WiFi will not be fast enough for 700 Hz in the general case.

Agree it’s worth starting with TCP though