Loss of first byte in data transfer

Dear all.
I send weather data from an ESP8266 via its RX/TX pins to SoftwareSerial pins 5/6 of an Arduino Uno. The data arrive, and I parse them into 8 strings and display them on the monitor: Everything is fine.

From the Arduino Uno, I send the complete data string via SoftwareSerial pins 7/8 to the RX/TX of an ESP01-S, which is programmed as a server to display the weather data on a “website”. Here, the data string is parsed again into the different temperature etc. values.

Problem: If the first temperature is, e.g., 20.7, the website only display 0.7; all other data are displayed correctly. So, only the first digit/byte of the sent data string is lost.

I am puzzled by this and cannot figure out, why the first digit is lost.

Any idea?

(I include below the code for the Arduino Uno and for the ESP01-S.

#include <SoftwareSerial.h>
float tmain; 
float tmainmin;
float tmainmax;
String tmainS;
String tmainminS;
String tmainmaxS;
float hmain;
float pmain;
String hmainS;
String pmainS;
float t2av;
float t2min;
float t2max;
String t2avS;
String t2minS;
String t2maxS;
String receivedStringserial;
String receivedStringserialm;
// Define SoftwareSerial pins: RX = pin 5: connect to TX of ESP8266, TX = pin 6: connect to RX of ESP8266
// for data transmission via serial from ESP8266 to Arduino Uno (temperatures, pressure)
SoftwareSerial ESP8266Serial(5, 6); 
// Define SoftwareSerial pins: RX = pin 7: connect to TX of ESP01-S, TX = pin 8: connect to RX of ESP01-S
// for data transmission via serial from Arduino Uno to ESP-01S to display on website
SoftwareSerial ESP01Serial(7, 8);

void setup() {
  // Open hardware serial communication for the PC serial monitor
  Serial.begin(19200);
  while (!Serial) {
    ; // Wait for serial port to connect
  }
  
  // Open communication with the ESP8266
  ESP8266Serial.begin(19200); // to later receive a string from ESP8266
  Serial.println("Arduino Uno Ready. Waiting for data...");
  ESP01Serial.begin(19200); // to later send the string to ESP01-S
}

void loop()
{
  ESP8266Serial.listen();
  // Check if data is available from the ESP8266
  while (ESP8266Serial.available() > 0)
    {
        char d = ESP8266Serial.read(); // reading the string bit by bit
        if (d != '\n') {receivedStringserial = receivedStringserial + d;}
        if (d == '\n') {break;}
    }
       if (receivedStringserial == "")
       {}
       else
       {
        Serial.println(receivedStringserial); // to print on monitor
        delay(5);
        ESP01Serial.println(receivedStringserial); // send data to ESP01-S
        receivedStringserialm = receivedStringserial; // "saved" version of receivedStringserial since receivedString later has to be set to ""
        delay(10);
    
       // Find the positions of the commas
     
       int index1 = receivedStringserialm.indexOf(',');
       int index2 = receivedStringserialm.indexOf(',', index1 + 1);
       int index3 = receivedStringserialm.indexOf(',', index2 + 1);
       int index4 = receivedStringserialm.indexOf(',', index3 + 1);
       int index5 = receivedStringserialm.indexOf(',', index4 + 1);
       int index6 = receivedStringserialm.indexOf(',', index5 + 1);
       int index7 = receivedStringserialm.indexOf(',', index6 + 1);

          // Extract each part using substring
       String tmainS = receivedStringserialm.substring(0, index1);
       String tmainminS = receivedStringserialm.substring(index1 + 1, index2);
       String tmainmaxS = receivedStringserialm.substring(index2 + 1, index3);
       String hmainS = receivedStringserialm.substring(index3 + 1, index4);
       String pmainS = receivedStringserialm.substring(index4 + 1, index5);
       String t2avS = receivedStringserialm.substring(index5 + 1, index6);
       String t2minS = receivedStringserialm.substring(index6 + 1, index7);
       String t2maxS = receivedStringserialm.substring(index7 + 1);
   receivedStringserial = "";
   Serial.println(tmainS); // to print on monitor, it is correctly printed
   Serial.println(tmainminS);
   Serial.println(tmainmaxS);
   Serial.println(hmainS);
   Serial.println(pmainS);
   Serial.println(t2avS);
   Serial.println(t2minS);
   Serial.println(t2maxS);
       }
}

ESP01-S code:

#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
const char* ssid = "***";
const char* password = "????";
float tmain; // just examples, the values will later be retrieved 
float tmainmin;
float tmainmax;
String tmainS;
String tmainminS;
String tmainmaxS;
float hmain;
float pmain;
String hmainS;
String pmainS;
float t2av;
float t2min;
float t2max;
String t2avS;
String t2minS;
String t2maxS;
String receivedStringserial;
String receivedStringserialm;
IPAddress local_IP(192,168,68,107);
IPAddress gateway(192,168,68,1);
IPAddress subnet(255,255,255,0);

char htmlfullContent[1250];
char e;
//SoftwareSerial ESP8266Serial(10, 11); // RX and TX pin for data transfer from ESP8266
ESP8266WebServer server(80);
// preliminary html content embedded as a raw string literal with placeholders
const char htmlpreContent[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>House in Ruimsig</title>
</head>
<body>
<h2>House in Ruimsig</h2>
<h3>Mainstation</h3>
<table>
  <tr>
    <td>current:</td>
    <td style="text-align: right;">%s <span>&#176;</span>C</td>
    </tr>
  <tr>
    <td>minimum:</td>
    <td style="text-align: right;">%s <span>&#176;</span>C</td>
   </tr>
  <tr>
    <td>maximum:</td>
    <td style="text-align: right;">%s <span>&#176;</span>C</td>
   </tr>
  <tr><td>------------</td><td>--------</td></tr>
  <tr>
    <td>humidity:</td>
    <td style="text-align: right;">%s <span>&#37</span></td>
   </tr>
  <tr>
    <td>pressure:</td>
    <td style="text-align: right;">%s hPa</td>
   </tr>
</table>

<h3>Outside</h3>
<table>
  <tr>
    <td>current:</td>
    <td style="text-align: right;">%s <span>&#176;</span>C</td>
    </tr>
  <tr>
    <td>minimum:</td>
    <td style="text-align: right;">%s <span>&#176;</span>C</td>
    </tr>
  <tr>
    <td>maximum:</td>
    <td style="text-align: right;">%s <span>&#176;</span>C</td>
   </tr>
</table>
<p><button onClick="window.location.href=window.location.href">Refresh</button></p>
</body>
</html>  
)rawliteral";

void setup()
{
  //ESP8266Serial.begin(38400);
  Serial.begin(19200);
  delay(10);
  WiFi.config(local_IP, gateway, subnet); // configure a fixed IP address for the server
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.begin();
  Serial.println("HTTP server started");

 // generate the full html content by sequentially replacing all placeholders (%s) with the respective strings
snprintf(htmlfullContent, sizeof(htmlfullContent), htmlpreContent, tmainS, tmainminS, tmainmaxS, hmainS, pmainS, t2avS, t2minS, t2maxS);
Serial.println(htmlfullContent);
receivedStringserial = "";
}

void loop()
{
//server.handleClient();
while (Serial.available() > 0)
       {
        //Core Command: Automatically parses the string stream into a native float
        char e = Serial.read(); 
        //Serial.print(e);
        if (e != '\n') {receivedStringserial = receivedStringserial + e;}
        if (e == '\n') {break;}
        Serial.println(receivedStringserial);
       }
if (receivedStringserial == "")
   {}
   else
   {
    Serial.println(receivedStringserial);
    receivedStringserialm = receivedStringserial; // "saved" version of receivedStringserial since receivedString later has to be set to ""
    
   
    delay(10);
    
       // Find the positions of the commas
     
   int index1 = receivedStringserialm.indexOf(',');
   int index2 = receivedStringserialm.indexOf(',', index1 + 1);
   int index3 = receivedStringserialm.indexOf(',', index2 + 1);
   int index4 = receivedStringserialm.indexOf(',', index3 + 1);
   int index5 = receivedStringserialm.indexOf(',', index4 + 1);
   int index6 = receivedStringserialm.indexOf(',', index5 + 1);
   int index7 = receivedStringserialm.indexOf(',', index6 + 1);
      // Extract each part using substring
   String tmainS = receivedStringserialm.substring(0, index1);
   String tmainminS = receivedStringserialm.substring(index1 + 1, index2);
   String tmainmaxS = receivedStringserialm.substring(index2 + 1, index3);
   String hmainS = receivedStringserialm.substring(index3 + 1, index4);
   String pmainS = receivedStringserialm.substring(index4 + 1, index5);
   String t2avS = receivedStringserialm.substring(index5 + 1, index6);
   String t2minS = receivedStringserialm.substring(index6 + 1, index7);
   String t2maxS = receivedStringserialm.substring(index7 + 1);
   receivedStringserial = "";
   // generate the full html content by sequentially replacing all placeholders (%s) with the respective strings
snprintf(htmlfullContent, sizeof(htmlfullContent), htmlpreContent, tmainS, tmainminS, tmainmaxS, hmainS, pmainS, t2avS, t2minS, t2maxS);
Serial.println(htmlfullContent);
   }
server.handleClient();  
}

// Function to handle root path
void handleRoot()
{
  server.send_P(200, "text/html", htmlfullContent); 
}

Why don't you run the webserver on the first ESP8266 rather than playing "pass the parcel" with the data ?

My ESP8266 is very busy, reading already data coming via wifi from another ESP01-S, which takes temperature and humidity data from a DHT22. I intend to use more such ESP01-S setups for my weather station.
When I tried to also run the website on the ESP8266, it did not work; therefore, I coupled to an Arduino Uno connected to a ESP01-S, dedicated to do the website.

Why are you using SoftwareSerial on the ESP01-S? It is usually problematic on an Arduino Uno, as well.

I did not want to use the hardware serial pins to avoid collisions with displaying on the monitor.

That makes no sense to me. Good luck with your project.

BUT! software serial is always blocking because it MUST use interrupts.

When you print receivedStringserial to the serial monitor on the ESP01-S, is the first character missing?

< edit >
What may be happening is that you receive the initial character, the "2" of "20.7", and then exit the while loop because the serial buffer is empty. The web page code is then run with invalid data, causing enough delay for the remainder of the data to fill the Serial receive buffer, so that when you get to the top of loop() your received data is missing the first character.

void loop()
{
  //server.handleClient();
  while (Serial.available() > 0)
  {
    //Core Command: Automatically parses the string stream into a native float
    char e = Serial.read();
    //Serial.print(e);
    if (e != '\n') {
      receivedStringserial = receivedStringserial + e;
    }
    if (e == '\n') {
      break;
    }
    Serial.println(receivedStringserial);
  }

The outdated ESP8266 is way more powerful than the UNO R3.
So why the UNO, while the ESP could likely do it all by itself.
The drawback of the ESP-01 is the lack of I/O.
Upgrading to a more current ESP32-C or -S series could be a better option.

I use the XIAO ESP32-C3 for my weather station.
Has a LiPo battery connection and built-in charger too and a 5volt solar panel can connect directly to the V-in or USB socket. Runs through several dark days on a 6Ah battery.

I would suggest moving to a ESP32 microcontroller which should be capable of supporting the sensors, WiFi and a web page reducing the overall complexity of the project

e.g. a river monitor based on a Heltec WiFi32 LoRa V4, a SR04M ultrasonic transducer (reads water level), a DS18B20 DallasTemperature sensors (river temperature) and a BME280 (air temperature and humidity) uploading data over LoRaWAN to the TTN network and then the ThingsBoard desktop - the system is powered by a Heltec Solar kit

desktop display

the river is tidal - rise and fall of 10 to 15cm

Hi Paul.
I am a newbie and not familiar with the concept of interrupts. I am just happy that I got that far already. I got it to work now with a dirty trick... see my other replies.

Hi David.
Hmm, I do not quite understand it and not sure how to solve it.
However, I used a dirty trick now and got it to work: I just added "?" in front of the string to be sent from Arduino Uno to ESP01-S (for the website), and voila... "?" is cut out instead of the first digit of the first temperature string.
Well, not very elegant...

Hi horace.
Very nice!
I came quite far already and do not want to start from scratch again with new hardware.
I got it to work with a "dirty trick"... see my replay to david...

Hi Wawa.
I am sure, my choice of hardware and code is not the best... I am just glad I came that far with the hardware I have.
I tried to do the website also on the ESP8266 but could not get it to work together with the ESP8266 also receiving data from a client. As a newbie, I do not really know why it did not work.
In any case... see my "dirty trick" in the reply to david_2018...

Do you think adding a delay somewhere would provide the time to fill the buffer... (not sure whether I understand you correctly)?

My suggestion would be to make your serial communications more robust by adding start and end characters to the data then using the techniques in Serial input basics - updated to read the data

maybe worth trying the AltSoftSerial library

Very useful, thank you!

Remember and implement these points in your UNO R3 sketch:
1. A Software Serial Port is recommended to be operated at Bd = 9600 for reliable service.
2. UNO R3 sketch is recommended not to contain String type data to avoid memory fragmentation, which ultimately crashes the system.

3.
I don't understand how you are reading the data from the buffer in the following quoted code without using --
receivedStringserial = ESP8266Serial.readStringUntil('\n');

    while (ESP8266Serial.available() > 0)
    {
        receivedStringserial = ESP8266Serial.readStringUntil('\n');``
       // receivedStringserial =  receivedStringserial + '\n';
    }

You can use strtok() function to isolate comma separated data items coming over ESP8266Serial port.

also worth looking at is EspSoftwareSerial