Serial Parsing and Ajax web server

I am working on some code to read some serial input data from a battery monitor and output it to an arduino web page using AJAX to update the data. I believe the AJAX requests are interrupting the recvWithStartEnd Markers() function because the receivedChars string is no longer properly being formed with the serial data. How do I prevent the AJAX requests from interupting the incoming serial data and where is the best place to call my recvWithStartEndMarkers() function?

I split the code into 2 parts due to post length.

#include <SPI.h>
#include <Ethernet.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 2); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80

String HTTP_req;            // stores the HTTP request


const byte numChars = 96;
char receivedChars[numChars];
char percent_Full[10] = {0};
char watts[10] = {0};
char dayCharge[10] = {0};
char dayEqual[10] = {0};
char PW_1[10] = {0};
char Volts [10] = {0};
char filtered_Volts[10] = {0};
char v2[10] = {0};
char a[10] = {0};
char fa[10] = {0};
char PW_2[10] = {0};
char AH[10] = {0};
boolean newData = false;

void setup()
{
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600); // for diagnostics
   Serial1.begin(2400);
    Serial.println("<Arduino is ready>");
}

Here is Part 2 of the code:

void loop()
{
  recvWithStartEndMarkers();
  parseData();
  
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {

            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                HTTP_req += c;  // save the HTTP request 1 char at a time
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: keep-alive");
                    client.println();
                    // AJAX request for switch state
                    if (HTTP_req.indexOf("ajax_switch") > -1) {
                        // read switch state and analog input
                    
                        GetAjaxData(client);
                    }
                    else {  // HTTP request for web page
                        // send web page - contains JavaScript with AJAX calls
                        
                        client.println("<!DOCTYPE html>");
                        client.println("<html>");
                        client.println("<head>");
                        client.println("<title>Arduino Web Page</title>");
                        client.println("<script>");
                        client.println("function GetSwitchAnalogData() {");
                        client.println(
                            "nocache = \"&nocache=\" + Math.random() * 1000000;");
                        client.println("var request = new XMLHttpRequest();");
                        client.println("request.onreadystatechange = function() {");
                        client.println("if (this.readyState == 4) {");
                        client.println("if (this.status == 200) {");
                        client.println("if (this.responseText != null) {");
                        client.println("document.getElementById(\"sw_an_data\")\
.innerHTML = this.responseText;");
                        client.println("}}}}");
                        client.println(
                        "request.open(\"GET\", \"ajax_switch\" + nocache, true);");
                        client.println("request.send(null);");
                        client.println("setTimeout('GetSwitchAnalogData()', 1000);");
                        client.println("}");
                        client.println("</script>");
                        client.println("</head>");
                        client.println("<body onload=\"GetSwitchAnalogData()\">");
                        client.println("<h1>Arduino AJAX Input</h1>");
                        client.println("<div id=\"sw_an_data\">");
                        client.println("</div>");
                        client.println("</body>");
                        client.println("</html>");
                    }
                    // display received HTTP request on serial port
                    Serial.print(HTTP_req);
                    HTTP_req = "";            // finished with request, empty string
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)



}

// send the state of the switch to the web browser
void GetAjaxData(EthernetClient cl)
{
    if (newData == false) {                   
   cl.print("<p>");
  cl.print("Current Voltage: ");
  cl.print(Volts);
  cl.print("<p>");
  cl.print("Current Amps: ");
  cl.print(a);
    cl.print("<p>");
  cl.print("Battery Percent Full: ");
  cl.print(percent_Full);
    cl.print("<p>");
  cl.print("Net Power (watts): ");
  cl.print(watts);
    }
  
  
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '%';
    char endMarker = '%';
    char rc;
 
 // if (Serial.available() > 0) {
    while (Serial1.available() > 0 && newData == false) {
        rc = Serial1.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
                Serial.print(receivedChars);
            }
        }

        else if (rc == startMarker) {
          receivedChars[ndx] = rc;
                ndx++;
                recvInProgress = true;
        }
        
}
}

void parseData() {


 if (newData== true){
char *strtokIndx;
 strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  strcpy(percent_Full, strtokIndx); // copy it to messageFromPC
   Serial.println(strtokIndx);
  Serial.println(percent_Full);
   
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  strcpy(watts, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(watts);
  
  strtokIndx = strtok(NULL, ","); 
  strcpy(dayCharge, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(dayCharge);

strtokIndx = strtok(NULL, ","); 
  strcpy(dayEqual, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(dayEqual);
  
  strtokIndx = strtok(NULL, ","); 
  strcpy(PW_1, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(PW_1);

  strtokIndx = strtok(NULL, ","); 
  strcpy(Volts, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(Volts);

  strtokIndx = strtok(NULL, ","); 
  strcpy(filtered_Volts, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(filtered_Volts);

strtokIndx = strtok(NULL, ","); 
  strcpy(v2, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(v2);

strtokIndx = strtok(NULL, ","); 
  strcpy(a, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(a);

  strtokIndx = strtok(NULL, ","); 
  strcpy(fa, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(fa);
  
  strtokIndx = strtok(NULL, ","); 
  strcpy(PW_2, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(PW_2);

  strtokIndx = strtok(NULL, ","); 
  strcpy(AH, strtokIndx); // copy it to messageFromPC
  Serial.println(strtokIndx);
  Serial.println(AH);

strtokIndx = strtok(NULL, ","); 
  Serial.println(strtokIndx);
  //strcpy(filteredV, strtokIndx); // copy it to messageFromPC
newData =false;
printParse();
}
}


void printParse(){

Serial.println("----Parse Print-----");
Serial.println(percent_Full);
Serial.println(watts);
//Serial.println(dayCharge);
//Serial.println(dayEqual);
//Serial.println(PW_1);
Serial.println(Volts);
//Serial.println(filtered_Volts);
//Serial.println(v2);
Serial.println(a);
//Serial.println(fa);
//Serial.println(PW_2);
//Serial.println(AH);
}

I'm not familair with the Ethernet library but I strongly suspect this line is the problem

while (client.connected()) {

I think you should be able to make another function similar to recvWithStartEndMarkers() (perhaps only an end-marker) to receive the Ethernet data without blocking.

Then you could have loop() like

  recvWithStartEndMarkers();
  parseData();
  recvEthernetdata().
  // etc

Another potential strategy is to ensure that you never send more than 64 bytes to Serial1 (60, might be safer) - i.e. there is no risk of the Serial1 input buffer being overflowed. If you can do that it does not matter how long you spend reading the Ethernet data. After reading the Serial1 buffer the Arduino can send a message to Serial1 to say it is ready for more data.

...R

I suspect you are correct about overflowing the serial buffer. I think my stripped down code is fast enough where that isn't a problem but once I add more to it, I start losing data. I unfortunately cannot control the incoming serial data as it is a 3rd party piece of equipment.

I'll do some research about the ethernet library command and see what I can come up with.

Perhaps there is another serial reading strategy that will allow me to store serial data and parse it separately. I don't need to receive 100% of the data all of the time. I just need to get chunks of complete data every so often.

mntnmanga:
unfortunately cannot control the incoming serial data as it is a 3rd party piece of equipment

Then you need to make changes to your Ethernet code. Can you do like I suggested?

...R