Chat freely about anything...

User avatar
By Justloadit
#91077 Hi all,
I have a project in which a serial string with running values is sent every second from a controller, that is available to do diagnostics.
This information will then be formatted and displayed as a table on a soft server HTML page.
Using a cell phone, I log onto the local server on the ESP8266, set the IP address of the page, and see the data in the table as the data comes in, with out having to refresh manually. Once I am happy that the system being monitored is fine, I close the web page on my cellphone.
I have been at this for more than a week, doing research and looking for sample code, but have not been successful.

I have written the code on the Arduino IDE, for the serial incoming data, formatted and tested it on the ESP8266.
I verified the data by sending the formatted data out on the serial port and monitored it on a terminal.

I have written the code on the Arduino IDE, to draw up the table, and using local variables, am able to refresh the table with the values by creating a button, and only if I declare a local 'var DataLnx = "string";', and not from a global 'char DataLnx = "string";'.

However when I wish to marry the two sets of codes, using the Arduino IDE, I cannot get the formatted data into the table, and I also cannot get the table to update when the serial data is ready to be displayed in the table.
I know that the serial data is coming in and being formatted correctly, as I can see the serial debugger strings.

Here is the code, minus the Function which formats the data from the serial port string, as that section works.

Code: Select all#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

#define SerCnt  125                     // Serial string chars
uint8_t       NoComs;                   // Communications Active
uint8_t       Event;                    // Active event
uint8_t       RTime = 0;
const long    interval = 4000;          // interval at which Serial to update display is a fault(milliseconds)
unsigned long previousMillis = 0;       // will store last time Display was updated
unsigned long currentMillis;            // Current time
char          DisplayData[SerCnt];      // Incomming Serial Data String
char          WorkData[SerCnt];         // Working string
uint8_t       SerialPos;                // Incomming Serial Buffer Pointer


// Display Data Working RAM - Initialize values
char DataLn1[8] =  "0.0V" ;
char DataLn2[8] =  "0.0A" ;
char DataLn3[8] =  "0V" ;
char DataLn4[8] =  "0.0A" ;
char DataLn5[8] =  "0W" ;
char DataLn6[8] =  "0.0A" ;
char DataLn7[14] =  "Idle" ;
char DataLn8[9] =  "0.0Hz" ;
char DataLn9[8] =  "0.0" ;
char DataLn10[8] =  "0V" ;
char DataLn11[8] =  "0%" ;
char DataLn12[8] =  "0\xB0C" ;
char DataLn13[8] =  "0S" ;
char DataLn14[8] =  "0.0V" ;
char DataLn15[8] =  "0.0V" ;
char DataLn16[8] =  "0" ;
char DataLn17[8] =  "No Coms";

// Web Server Credentials
const char* ssid     = "Table Tester";
const char* password = "12345678";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");

// ***********************************************************************
// Server Web Page Format
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
 <style>
  <title>Aquaduty Display</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  body {background-color: white;}
  table, th, td {
  border: 1px solid black;
  border-collapse: collapse;
  }

  //Zebra Column generator
  thead {
  background: #395870;
  color: #fff;
  }
 
  tbody tr:nth-child(even) {
    background: #f0f0f2;
  }
  </style> 
 </head>
 
 <body>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <table id='myTable' style="width:75%">
      <colgroup>
        <col span="1" style="width: 40%;">
        <col span="1" style="width: 60%;">
      </colgroup>

      <tr>
          <th COLSPAN="2">
             <h3>Aquaduty Apricus Display</h3>
          </th>
      </tr>
     
      <tr>
        <th>Description</th>
        <th>Value</th>
        </tr>
     
      <tr>
        <td>PV Volts</td><td style="text-align:right">V</td>
      </tr>
     
      <tr>
        <td>PV Amps</td>
        <td style="text-align:right">A</td>
      </tr>
     
      <tr>
        <td>Link Volts</td>
        <td style="text-align:right">V</td>
      </tr>
     
      <tr>
        <td>Link Amps</td>
        <td style="text-align:right">A</td>
      </tr>
     
      <tr>
        <td>Motor Power</td>
        <td style="text-align:right">W</td>
      </tr>
     
      <tr>
        <td>Nom Amps </td>
        <td style="text-align:right">A</td>
      </tr>
   
      <tr>
        <td>Status</td>
        <td style="text-align:right"></td>
      </tr>
     
      <tr>
        <td>Frequency</td>
        <td style="text-align:right">Hz</td>
      </tr>
     
      <tr>
        <td>Mot Slope</td>
        <td style="text-align:right"></td>
      </tr>
     
      <tr>
        <td>Link Limit</td>
        <td style="text-align:right">V</td>
      </tr>
     
      <tr>
        <td>Amplitude</td>
        <td style="text-align:right">%</td>
      </tr>
     
      <tr>
        <td>Heatsink Temp</td>
        <td style="text-align:right">&#8451</td>
      </tr>
     
      <tr>
        <td>Wait Time</td>
        <td style="text-align:right">S</td>
      </tr>
     
      <tr>
        <td>O/C Volts</td>
        <td style="text-align:right">V</td>
      </tr>
     
      <tr>
        <td>MPPT Volts</td>
        <td style="text-align:right">V</td>
      </tr>
     
      <tr>
        <td>Software Ver</td>
        <td style="text-align:right"></td>
      </tr>
     
      <tr>
        <td style="text-align:center">No Coms</td>
        <td></td>
      </tr>
  </table>

   
  <script>
/*
If i place this here then the values in the table do update when i use the
<button onclick="myFunction()">Try it</button> just before the <script> on the web page as a HTML server stand alone test code
  // Display Data Working RAM
  var  DataLn1 =  " 56.0V";
  var  DataLn2 =  "  0.0A";
  var  DataLn3 =  "    0V";
  var  DataLn4 =  "  0.0A";
  var  DataLn5 =  "    0W";
  var  DataLn6 =  "  0.0A";
  var  DataLn7 =  "        Idle";
  var  DataLn8 =  "  0.0Hz";
  var  DataLn9 =  "  0.0";
  var  DataLn10 = "    0V";
  var  DataLn11 = "    0%";
  var  DataLn12 = "    0\xB0C";
  var  DataLn13 = "    0S";
  var  DataLn14 = "  0.0V";
  var  DataLn15 = "  0.0V";
  var  DataLn16 = "    0";
  var  DataLn17 = "No Coms";
*/

      // Place new values in the respective table positions when (NoComs  == 1)
      function myFunction() {
        var myTable = document.getElementById('myTable');
        myTable.rows[2].cells[1].innerHTML = DataLn1;
        myTable.rows[3].cells[1].innerHTML = DataLn2;
        myTable.rows[4].cells[1].innerHTML = DataLn3;
        myTable.rows[5].cells[1].innerHTML = DataLn4;
        myTable.rows[6].cells[1].innerHTML = DataLn5;
        myTable.rows[7].cells[1].innerHTML = DataLn6;
        myTable.rows[8].cells[1].innerHTML = DataLn7;
        myTable.rows[9].cells[1].innerHTML = DataLn8;
        myTable.rows[10].cells[1].innerHTML = DataLn9;
        myTable.rows[11].cells[1].innerHTML = DataLn10;
        myTable.rows[12].cells[1].innerHTML = DataLn11;
        myTable.rows[13].cells[1].innerHTML = DataLn12;
        myTable.rows[14].cells[1].innerHTML = DataLn13;
        myTable.rows[15].cells[1].innerHTML = DataLn14;
        myTable.rows[16].cells[1].innerHTML = DataLn15;
        myTable.rows[17].cells[1].innerHTML = DataLn16;
        myTable.rows[18].cells[0].innerHTML = DataLn17;
      }
  </script>
</body>
</html>
)rawliteral";

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
} // notFound()

// ************************************************************************************

void setup() {
    Serial.begin(19200);     // Open serial port to read 
    // Clear Registers
    RTime = 0;
    NoComs = 0;
    previousMillis = 0;
    SerialPos = 0;
   
    // Set Receive Buffer with ' '
    memset(DisplayData, ' ', sizeof(DisplayData-2));
    DisplayData[SerCnt-1] = 0;
   
    // Set Up The Timer
    previousMillis = millis();

    // Start Web Server Credentials
    WiFi.softAP(ssid, password);
    IPAddress IP = WiFi.softAPIP();

// *****************************************
    // Clear Registers
    RTime = 0;
    NoComs = 0;
    previousMillis = 0;
    SerialPos = 0;
    // Set Receive Buffer with ' '
    memset(DisplayData, ' ', sizeof(DisplayData-2));
    DisplayData[SerCnt-1] = 0;
    // Set Up The Timer
    previousMillis = millis();
   
    // *****************************************
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html);
    }); // server.on
    server.begin();
   
    // *****************************************
    // Open serial communications and wait for port to open:
    Serial.begin(19200);    // Open Serial Comms to Tester serial port
} // setup()

void loop() {
  // put your main code here, to run repeatedly:
  // Read serial input:
  if (Serial.available() > 0)                 // Any bytes in Serial Port
  {
      char Temp;
      Temp = Serial.read();
      DisplayData[SerialPos] = Temp;
      SerialPos++;
      if (Temp == '\r')
        {
          // Carriage Return - End of Msg
          SerialPos = 0;                      // First position for serial Data       
          /* This Function not included for discussion
          DoSerial();                         // Transfer Serial Msg to Display Steings DataLnx
          // Returns NoComs True if message succesfully received and formated
          */
          if (NoComs == 0)                        // Clear No Coms Msg
            {
              Serial.println("StrError");         // Debug Print
              // DataLn17 = "No Coms";            // Clear No Coms Message
              strcpy(DataLn17,"No Coms");
            } // (NoComs == 0)
          else
            {
              Serial.println("StrGood");          // Debug Print
              // Print a changing charater (-,/,-,\,*) to alert user that Comms running
              if (RTime == 0)                     // No CHar
                {
                  strcpy(DataLn17,"- ");
                } // (RTime == 0)
              else if (RTime == 1)
                {
                  strcpy(DataLn17,"/ ");
                } // (RTime == 1)
              else if (RTime == 2)
                {
                  strcpy(DataLn17,"- ");       
                } // (RTime == 2)
              else if (RTime == 3)
                {
                  strcpy(DataLn17,"\ ");
                } // (RTime == 3)
              else if (RTime == 4)
                {
                  strcpy(DataLn17,"* ");
                } // (RTime == 4)
              RTime ++;
              if (RTime > 4)
                {
                  RTime = 0;
                } // (RTime > 4)
            } // else - (NoComs == 0)
          currentMillis = millis();           // Read reference Time counts
          previousMillis = currentMillis;     // Store reference Time Counts
          Event = 1;                          // Run myFunction
          // websocket.function = myFunction();
        } // (DisplayData[InSerialPtr] == '\r')
      else if (SerialPos > SerCnt)
        {
          Serial.println("StrOver");          // Debug Print
          // Clear Serial Receive Buffer
          memset(DisplayData, 0, sizeof(DisplayData));
          SerialPos = 0;                      // First position for serial Data
          strcpy(DataLn17,"No Coms");         // Clear No Coms Message         
          currentMillis = millis();           // Read reference Time counts
          previousMillis = currentMillis;     // Store reference Time Counts
          Event = 1;                          // Run myFunction
          // websocket.function = myFunction();
        } // else if (InSerialPtr > SerCnt)
  } // (Serial.available() > 0)

  // -------------------------------------------------
  // Time out if no Comms
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval) // 4 seconds
    {
      Serial.println("Timeout");                  // Debug Print
      // save the last time display updated
      previousMillis = currentMillis;
      NoComs = 0;                                 // No Comms
      // Clear Serial Receive Buffer
      memset(DisplayData, 0, sizeof(DisplayData));
      SerialPos = 0;                          // First position for serial Data
      strcpy(DataLn17,"No Coms");             // Clear No Coms Message
      Event = 1;                          // Run myFunction
      // websocket.function = myFunction();
    } // (currentMillis - previousMillis >= interval)

} // loop()


I am very new to HTML so there may be some funnies in the above code.
Not sure if a softserver operation or websocket should be used for this application.

Any help to get the HTML myFunction() to use the global char DataLnx= "string" and web page refresh when (Event == 1) would be appreciated.
User avatar
By Justloadit
#91460 It has been some time, still not there, but my journey has brought me to this wonderful site full of invaluable information

https://randomnerdtutorials.com/
Many good example code and short training examples.

I have purchased one of his books, Build Web Servers with ESP32 & ESP8266 from this range of books https://randomnerdtutorials.com/courses/

Well worth a visit.
From the information so far, the solution is to use the ESP as a Async Websocket using JSON commands.