ESP8266 (Server) to ESP8266 (Client) Communication FAILS

Hi,
I am in a desperate need for help.

What I want to do:

I have two ESP8266s, two Arduino UNOs, one ADXL335 Accelerometer.

  1. I want to get 3 readings (x, y, z) from the accelerometer (which is connected to Arduino),
  2. send the data via the client ESP8266 to the server ESP8266 via wifi (local network and not though the Internet),
    3)Print the data of the 3 readings on the Serial Monitor on my computer, which is connected to an Arduino (which is connected to the server ESP8266, which is getting the data wirelessly from the client ESP8266).

I used this tutorial to do this project.

The problem I’m having:

  1. The 2nd and the 3rd readings (for y and z axis) are not changing on the server side’s Serial Monitor. It’s completely static (e.g. printing out 100-200-ish number all the time). The 1st reading (input of the x-axis of the accelerometer) is being communicated to the server successfully, and I can see it changing on the Serial Monitor.

  2. Having said this, the changing of the 1st number (reading of x) being printed out on the Serial Monitor is extremely slow, and sometimes gets stuck on the same value for a long time even I tilt on the x-axis (which I want it to change the numbers immediately). It worked fine when I experimented with just one analog input (e.g. potentiometer, using just the x-input of the accelerometer…).

My code:

I have 3 codes below - I’m putting everything here because I’m such a noob and am not sure what’s causing the issue.
However, I’m guessing - what’s causing the issue could be to do with

  1. How I’m structuring the URI - the bit around “String url = “/data/”;” on the client side
  2. How I’m using server.hasArg on the server side
  3. How I’m using server.arg on the server side
  4. ‘HTTP GET’ requests on the client side

But this is just my guess, and I don’t know how to fix it.
How can I solve these issues? :’(

I would really appreciate your help!!

Server / Access Point ESP8266 Code:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
const char *ssid = "ESP";
ESP8266WebServer server(80);

void handleSentVar() {
  if (server.hasArg("sensor_reading")) { 

    Serial.print(server.arg("sensor_reading")); //THIS CHANGES EVEN IT'S SUPER SLOW
    Serial.print(",");
    Serial.print(server.arg("sensor_reading1"));  //THIS DOESN'T CHANGE
    Serial.print(",");
    Serial.println(server.arg("sensor_reading2"));  //THIS DOESN'T CHANGE

    server.send(200); //200 = OK

    delay(1);
  }
}

void setup() {
  delay(1000);
  Serial.begin(9600);
  Serial.println();
  Serial.print("Configuring access point...");

  WiFi.softAP(ssid);

  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.on("/data/", HTTP_GET, handleSentVar); 
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}

Client / Station Arduino Code:

#include <SoftwareSerial.h>
SoftwareSerial ESPserial(2,3); // RX | TX

const int ap1 = A5; 
const int ap2 = A4;
const int ap3 = A3;
const int numReadings = 30;
int inByte = 0;         // incoming serial byte

int readingsX[numReadings];      
int readingsY[numReadings];      
int readingsZ[numReadings];      

int readIndexX = 0;              
int readIndexY = 0;              
int readIndexZ = 0;              
int totalX = 0;                  
int totalY = 0;                  
int totalZ = 0;                  
int averageX = 0;                
int averageY = 0;                
int averageZ = 0;                
 
void setup() {
  Serial.begin(9600); //This must always be 9600
  ESPserial.begin(9600);  //This must match the baud rate of the Serial.begin for ESP8266

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readingsX[thisReading] = 0;
    readingsY[thisReading] = 0;
    readingsZ[thisReading] = 0;
  }
}

void loop() {

//  X------------------------------
   // subtract the last reading:
  totalX = totalX - readingsX[readIndexX];
  
  // read from the sensor:
  int calx = 347; //CALIBRATE X
  int x = analogRead(ap1)-calx;
  x = abs(x);
  int xMapped = map(x,0,50,0,50);

  readingsX[readIndexX] = xMapped;
  
  // add the reading to the total:
  totalX = totalX + readingsX[readIndexX];
  // advance to the next position in the array:
  readIndexX = readIndexX + 1;

  // if we're at the end of the array...
  if (readIndexX >= numReadings) {
    // ...wrap around to the beginning:
    readIndexX = 0;
  }

  // calculate the average:
  averageX = totalX / numReadings;
  // send it to the computer as ASCII digits
  ESPserial.write(averageX);
  ESPserial.write(",");

  delay(1);        // delay in between reads for stability

... SAME SET OF CODES FOR Y AND Z...
  
}//------End of Loop-----

Client / Station ESP8266 Code (for ESP8266):

#include <ESP8266WiFi.h>
const char *ssid = "ESP";

int outputValue = 0;        // value sent to server
int outputValue1 = 0;        // value sent to server
int outputValue2 = 0;        // value sent to server

byte data; 
byte data1;
byte data2;

void setup() {
  Serial.begin(9600);
  delay(1000);
  /* Explicitly set the ESP8266 to be a WiFi-client */
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid);

}

void loop() {
  char inData[15];
  char outData[3];
  byte index = 0;

  if(Serial.available()){  //When there is data from Arduino available...
    
     char aChar = Serial.read();
     if(aChar == '\n') {
        // End of record detected. Time to parse
           char *p = inData; //making p point to the string "x,y,z" 

           char *str;        // declaring str
           int counter = 0; //initialise the counter
           
           while ((str = strtok_r(p, ",", &p))) {// delimiter is the comma. NULL is the terminator
                 outData[counter] = *str; //use the counter as an index to add each value to the array. data[0]=x, data[1]=y...
                 counter++; //increment the counter

              p = NULL;
           }
           data = outData[0];
           data1 = outData[1];
           data2 = outData[2];
           
          index = 0;
          inData[index] = NULL;
          
     } else {
        inData[index] = aChar;  //Store current character. inData[current index] = current character
        index++;  //move onto next index untill \n
        inData[index] = '\0'; // Keep the string NULL terminated
     }  //---end of parsing---

  }

  outputValue = data; //int = byte
  outputValue1 = data1; 
  outputValue2 = data2; 

  char intToPrint[5];
  itoa(outputValue, intToPrint, 10); 
  char intToPrint1[5];
  itoa(outputValue1, intToPrint1, 10); 
  char intToPrint2[5];
  itoa(outputValue2, intToPrint2, 10); 
  //^integer to string conversion. itoa(int val, Char s, int redix/base).
  //buffer (intToPrint) must have sufficient storage.


  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const char * host = "192.168.4.1";
  const int httpPort = 80;

  if (!client.connect(host, httpPort)) {
    return;
  }

  
  // We now create a URI for the request
  String url = "/data/";
  url += "?sensor_reading=";  //send key-value pairs by adding "?", followed by 'key=value' 
  url += intToPrint;
  url += "&sensor_reading1=";  
  url += intToPrint1; //THIS DOESN'T CHANGE ON SERVER'S SERIAL MONITOR
  url += "&sensor_reading2="; 
  url += intToPrint2; //THIS DOESN'T CHANGE ON SERVER'S SERIAL MONITOR

  // This will send the GET request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
               
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }
  delay(1);
}//------End of Loop-----

copy the value returned from strtok. not only store the pointer

some other leads:

use IPAddress class for ip address, not string stop the client's client, not only in timeout case

Hi Juraj! Thank you so much for your reply. I'll try out what you've told me, but before that....

Juraj: copy the value returned from strtok. not only store the pointer

Do you mean by copy outData[counter] to somewhere? Copy to where though? It would be great if you could suggest me after what specific line I should insert this?

Juraj: stop the client's client, not only in timeout case

This is super embarrassing to ask but - how do I do that??

cloudurchin: Hi Juraj! Thank you so much for your reply. I'll try out what you've told me, but before that.... Do you mean by copy outData[counter] to somewhere? Copy to where though? It would be great if you could suggest me after what specific line?

This is super embarrassing to ask but - how do I do that??

client.stop(); after printing the data you wait for a response there with a while (available), but you send no response so you have 5 secs waiting and the stop

you parse 3 values. don't make in loop with conuter. make 3 outData char arrays and call strtok 3 times. strcpy(outData2, str);