Trying to visualize my graph through Chart.js

Hi everyone, I was trying to use an ESP32 to visualize data from some sensors trough wifi, I was able to recive and show the measurings, but when I tried to add a graphic via "chart.js" the page shows nothing in the readings, and in dev tools I'm getting this error in the DevTools, I leave the code and the capture of the code, I'm using an ESP32 and writing in Arduino IDE:

#include <WiFi.h>
#include <WebServer.h>

// WiFi
const char* ssid = "---";
const char* password = "---";
WebServer server(80);

// Pines
const int pinFase1 = 32;
const int pinFase2 = 34;
const int pinFase3 = 35;
const int pinNTC   = 33;
const int ledWifi  = 2;

// Calibración
const float factorCalibracion1 = 51.2;
const float factorCalibracion2 = 51.2;
const float factorCalibracion3 = 51.2;

// NTC
const float rAux = 10000.0;
const float beta = 3740.0;
const float temp0 = 298.0;
const float r0 = 22000.0;
const float offset = 1.54;
const float vcc = 3.315;

// LED parpadeo
unsigned long previousMillis = 0;
const long interval = 500;
bool ledState = false;

// ---------- PROTOTIPOS ----------
float get_corriente(int pin, float factorCalibracion);
float leer_temperatura();

const char* htmlPage = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Monitor ESP32</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <style>
    body {
      font-family: Arial, sans-serif;
      background-color: #f4f6f8;
      text-align: center;
      padding: 40px;
    }
    .card {
      background-color: #ffffff;
      border-radius: 12px;
      box-shadow: 0 4px 8px rgba(0,0,0,0.1);
      display: inline-block;
      padding: 20px;
      margin: 15px;
      width: 250px;
    }
    .value {
      font-size: 2em;
      color: #007BFF;
    }
    .label {
      color: #555;
    }
    canvas {
      margin-top: 30px;
    }
  </style>
</head>
<body>
  <h2>Monitor en Tiempo Real - ESP32</h2>

  <div class="card">
    <div class="label">Corriente Fase 1</div>
    <div class="value" id="i1">--</div>
  </div>
  <div class="card">
    <div class="label">Corriente Fase 2</div>
    <div class="value" id="i2">--</div>
  </div>
  <div class="card">
    <div class="label">Corriente Fase 3</div>
    <div class="value" id="i3">--</div>
  </div>
  <div class="card">
    <div class="label">Temperatura</div>
    <div class="value" id="temp">--</div>
  </div>

  <h3>Corriente Fase 1 (A)</h3>
  <canvas id="chartFase1" width="400" height="150"></canvas>

  <h3>Temperatura (°C)</h3>
  <canvas id="chartTemp" width="400" height="150"></canvas>

  <script>
    let fase1Data = [];
    let tempData = [];
    let labels = [];

    const ctxFase1 = document.getElementById('chartFase1').getContext('2d');
    const ctxTemp = document.getElementById('chartTemp').getContext('2d');

    const chartFase1 = new Chart(ctxFase1, {
      type: 'line',
      data: {
        labels: labels,
        datasets: [{
          label: 'Corriente Fase 1',
          data: fase1Data,
          borderColor: 'blue',
          fill: false
        }]
      },
      options: {
        animation: false,
        scales: {
          x: { display: false },
          y: { beginAtZero: true }
        }
      }
    });

    const chartTemp = new Chart(ctxTemp, {
      type: 'line',
      data: {
        labels: labels,
        datasets: [{
          label: 'Temperatura',
          data: tempData,
          borderColor: 'red',
          fill: false
        }]
      },
      options: {
        animation: false,
        scales: {
          x: { display: false },
          y: { beginAtZero: true }
        }
      }
    });

    function actualizarDatos() {
      fetch("/datos")
        .then(response => response.json())
        .then(data => {
          console.log("Datos recibidos:", data);
          const now = new Date().toLocaleTimeString();

          document.getElementById("i1").innerText = data.Irms1 + " A";
          document.getElementById("i2").innerText = data.Irms2 + " A";
          document.getElementById("i3").innerText = data.Irms3 + " A";
          document.getElementById("temp").innerText = data.temp + " °C";

          if (labels.length > 50) {
            labels.shift();
            fase1Data.shift();
            tempData.shift();
          }

          labels.push(now);
          fase1Data.push(data.Irms1);
          tempData.push(data.temp);

          chartFase1.update();
          chartTemp.update();
        });
    }

    setInterval(actualizarDatos, 500);
    window.onload = actualizarDatos;
  </script>
</body>
</html>
)rawliteral";

// --------- SETUP ----------
void setup() {
  Serial.begin(115200);
  pinMode(ledWifi, OUTPUT);

  WiFi.begin(ssid, password);
  Serial.print("Conectando a WiFi...");

  while (WiFi.status() != WL_CONNECTED) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      ledState = !ledState;
      digitalWrite(ledWifi, ledState);
    }
    delay(10);
  }

  digitalWrite(ledWifi, HIGH);
  Serial.println("");
  Serial.print("Conectado a: ");
  Serial.println(WiFi.localIP());

  server.on("/", []() {
    server.send(200, "text/html", htmlPage);
  });

  server.on("/datos", []() {
    float Irms1 = get_corriente(pinFase1, factorCalibracion1);
    float Irms2 = get_corriente(pinFase2, factorCalibracion2);
    float Irms3 = get_corriente(pinFase3, factorCalibracion3);
    float temperatura = leer_temperatura();

    String json = "{";
    json += "\"Irms1\":" + String(Irms1, 2) + ",";
    json += "\"Irms2\":" + String(Irms2, 2) + ",";
    json += "\"Irms3\":" + String(Irms3, 2) + ",";
    json += "\"temp\":" + String(temperatura, 1);
    json += "}";

    server.send(200, "application/json", json);
  });

  server.begin();
}

// --------- LOOP ----------
void loop() {
  server.handleClient();

  if (WiFi.status() != WL_CONNECTED) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      ledState = !ledState;
      digitalWrite(ledWifi, ledState);
    }
  } else {
    digitalWrite(ledWifi, HIGH);
  }
}

// -------- FUNCIONES --------
int voltaje_promedio(int pin, int n){
  long suma = 0;
  for (int i = 0; i < n; i++) {
    suma += analogRead(pin);
  }
  return suma / n;
}

float senal_escalada(int pin, float factorCalibracion){
  float voltaje = voltaje_promedio(pin, 10) * (vcc / 4095.0);
  float senal = voltaje - offset;
  return senal * factorCalibracion;
}

float get_corriente(int pin, float factorCalibracion){
  float corriente = 0;
  float sumatoria = 0;
  long tiempo = millis();
  int N = 0;

  while (millis() - tiempo < 500) {
    corriente = senal_escalada(pin, factorCalibracion);
    sumatoria += sq(corriente);
    N++;
    delay(1);
  }

  float Irms = sqrt(sumatoria / N);
  if (Irms < 0.5) Irms = 0.0;
  return Irms;
}

float leer_temperatura() {
  float vm = (vcc / 4095.0) * analogRead(pinNTC);
  float rntc = rAux / ((vcc / vm) - 1.0);
  float temperaturaK = beta / (log(rntc / r0) + (beta / temp0));
  return temperaturaK - 273.15;
}



I think the error is saying "line is not a type" so maybe look at "graph types" for chart.js.

@mauriro08

Hi,

With the html you have posted, I cannot reproduce the error you are getting in your browser. With a few adjustments to the markup and some dummy data...

<h3>Corriente Fase 1 (A)</h3>
  <p align="center">
  <canvas id="chartFase1" style="max-width:800px;max-height:300px;border:1px solid #000000;"></canvas>
  </p>
  
  <h3>Temperatura (°C)</h3>
  <p align="center">
  <canvas id="chartTemp" style="max-width:800px;max-height:300px;border:1px solid #000000;"></canvas>
  </p>


  <script>
    let fase1Data = [7.2,8.4,8.0,7.1,7.5,7.9,8.0,7.5,7.2,7.3,7.5,7.3];
    let tempData = [20.1,20.2,21,20.6,20.3,20.4,20.6,20.8,21,20.7,20.6,20.5];
    let labels = [5,10,15,20,25,30,35,40,45,50,55,60];

I get this...

I was trying to get something like the graphs you get, with the sensors I'm using (SCT-013-100A and a NTC 22k), the problem seems to be that I don't receive the measurements from the sensors (altought I log the ip/Datos from the fetch function and got the json with reading), and also the error in the devtools. You don't have that error in the browser, but did you get any type of error? Also from what I understand there is a problem in the enclosing class, I see you got some readings that you put by hand, you think there is a way I can obtain that graph with my code?

I'm confused.

@mauriro08

Hi,

There is nothing wrong in your implementation of the chart.js script. So the problem, is in data reception and/or parsing. Add some console logs to the actualizarDatos() function. As I have added in this version of the page markup. Console log is for debugging, so debug.
Copy/paste this to notepad, save as 'something.html'
I have added a data generator function to show your script working. Click on the file to open in your browser, and watch the demo.

Edit: Please note I am not familiar with json parsing or chart.js. What I do know is you must pass numerical 'values' to charting apps, not ascii strings!
js parseInt() and parseFloat() will do that for you.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Monitor ESP32</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <style>
    body {
      font-family: Arial, sans-serif;
      background-color: #f4f6f8;
      text-align: center;
      padding: 40px;
    }
    .card {
      background-color: #ffffff;
      border-radius: 12px;
      box-shadow: 0 4px 8px rgba(0,0,0,0.1);
      display: inline-block;
      padding: 20px;
      margin: 15px;
      width: 250px;
    }
    .value {
      font-size: 2em;
      color: #007BFF;
    }
    .label {
      color: #555;
    }
    canvas {
      margin-top: 30px;
    }
  </style>
</head>
<body>
  <h2>Monitor en Tiempo Real - ESP32</h2>

  <div class="card">
    <div class="label">Corriente Fase 1</div>
    <div class="value" id="i1">--</div>
  </div>
  <div class="card">
    <div class="label">Corriente Fase 2</div>
    <div class="value" id="i2">--</div>
  </div>
  <div class="card">
    <div class="label">Corriente Fase 3</div>
    <div class="value" id="i3">--</div>
  </div>
  <div class="card">
    <div class="label">Temperatura</div>
    <div class="value" id="temp">--</div>
  </div>

  <h3>Corriente Fase 1 (A)</h3>
  <p align="center">
  <canvas id="chartFase1" style="max-width:800px;max-height:300px;border:1px solid #000000;"></canvas>
  </p>
  
  <h3>Temperatura (°C)</h3>
  <p align="center">
  <canvas id="chartTemp" style="max-width:800px;max-height:300px;border:1px solid #000000;"></canvas>
  </p>


  <script>
    let fase1Data = [7.2,8.4,8.0,7.1,7.5,7.9,8.0,7.5,7.2,7.3,7.5,7.3];
    let tempData = [20.1,20.2,21,20.6,20.3,20.4,20.6,20.8,21,20.7,20.6,20.5];
    let labels = [5,10,15,20,25,30,35,40,45,50,55,60];
    let xaxis = 60;


    const ctxFase1 = document.getElementById('chartFase1').getContext('2d');
    const ctxTemp = document.getElementById('chartTemp').getContext('2d');

    const chartFase1 = new Chart(ctxFase1, {
      type: 'line',
      data: {
        labels: labels,
        datasets: [{
          label: 'Corriente Fase 1',
          data: fase1Data,
          borderColor: 'blue',
          fill: false
        }]
      },
      options: {
        animation: true,
        scales: {
          x: { display: true },
          y: { beginAtZero: false }
        }
      }
    });

    const chartTemp = new Chart(ctxTemp, {
      type: 'line',
      data: {
        labels: labels,
        datasets: [{
          label: 'Temperatura',
          data: tempData,
          borderColor: 'red',
          fill: false
        }]
      },
      options: {
        animation: true,
        scales: {
          x: { display: true },
          y: { beginAtZero: false }
        }
      }
    });

    function dataGen(){
      var numI = Math.random() * (8.0 - 5.0) + 5.0;
      var curI = parseFloat(numI.toFixed(1));
      var numT = Math.random() * (22.0 - 20.0) + 20.0;
      var temT = parseFloat(numT.toFixed(1));
      xaxis += 5;

      document.getElementById("i1").innerText = curI.toFixed(2) + " A";
      document.getElementById("i2").innerText = (curI - 0.2).toFixed(2) + " A";
      document.getElementById("i3").innerText = (curI + 0.25).toFixed(2) + " A";
      document.getElementById("temp").innerText = temT + " °C";
      
      if (labels.length > 10) {
            labels.shift();
            fase1Data.shift();
            tempData.shift();
         }

       labels.push(xaxis);
       fase1Data.push(curI);
       tempData.push(temT);

       chartFase1.update();
       chartTemp.update();
     };




    function actualizarDatos() {
      fetch("/datos")
        .then(response => response.json())
        .then(data => {
          console.log("Datos recibidos:", data);
          const now = new Date().toLocaleTimeString();
                               
          document.getElementById("i1").innerText = data.Irms1 + " A";
          document.getElementById("i2").innerText = data.Irms2 + " A";
          document.getElementById("i3").innerText = data.Irms3 + " A";
          document.getElementById("temp").innerText = data.temp + " °C";

          if (labels.length > 50) {
            labels.shift();
            fase1Data.shift();
            tempData.shift();
          }
          console.log(now);         
          console.log(data.Irms1);  
          console.log(data.temp);   

          labels.push(now);
          fase1Data.push(data.Irms1);
          tempData.push(data.temp);

          chartFase1.update();
          chartTemp.update();
        });
     }

    setInterval(dataGen, 1000);
    //window.onload = actualizarDatos;
  </script>
</body>
</html>

I tried the debug you gave me (the datagen), and I'm still getting no responde, I leave what I get in the nav with the devtools, I'm still getting the same error from the beginnig

Kinda of a misunderstanding there, I meant I receive the measurings when I'm not using chart.js, when I use it, I get nothing


In addition to the last response, I get this in the tab "Sources", I don't really get the error it shows or why it shows a direction to my foulders

Hi,

Your browser is baulking at the semicolon @ line 115. Are you running a Mac or Linux version of Chrome? On Windows this error does not show, and using the semicolon would appear to be the correct syntax. However, the Markup will run without error, if the semicolons are removed. I have revised the page script to reflect this and now included a Json string construction and parsing to prove it should all work.
Copy/paste the following markup to W3Schools tryit page here
Paste over the default script, adjust the width of the output pane and click run. You should see this...

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Monitor ESP32</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
      body {
      font-family: Arial, sans-serif;
      background-color: #f4f6f8;
      text-align: center;
      padding: 40px;
      }
      .card {
      background-color: #ffffff;
      border-radius: 12px;
      box-shadow: 0 4px 8px rgba(0,0,0,0.1);
      display: inline-block;
      padding: 20px;
      margin: 15px;
      width: 250px;
      }
      .value {
      font-size: 2em;
      color: #007BFF;
      }
      .label {
      color: #555;
      }
      canvas {
      margin-top: 30px;
      }
    </style>
  </head>
  <body>
    <h2>Monitor en Tiempo Real - ESP32</h2>
    <div class="card">
      <div class="label">Corriente Fase 1</div>
      <div class="value" id="i1">--</div>
    </div>
    <div class="card">
      <div class="label">Corriente Fase 2</div>
      <div class="value" id="i2">--</div>
    </div>
    <div class="card">
      <div class="label">Corriente Fase 3</div>
      <div class="value" id="i3">--</div>
    </div>
    <div class="card">
      <div class="label">Temperatura</div>
      <div class="value" id="temp">--</div>
    </div>
    <h3>Corriente Fase 1 (A)</h3>
    <p align="center">
      <canvas id="chartFase1" style="max-width:800px;max-height:300px;border:1px solid #000000;"></canvas>
    </p>
    <h3>Temperatura (°C)</h3>
    <p align="center">
      <canvas id="chartTemp" style="max-width:800px;max-height:300px;border:1px solid #000000;"></canvas>
    </p>
    <script>
      let fase1Data = [];
      let tempData = [];
      let labels = [];
      
      const ctxFase1 = document.getElementById('chartFase1').getContext('2d');
      const ctxTemp = document.getElementById('chartTemp').getContext('2d');
      
      const chartFase1 = new Chart(ctxFase1, {
        type: 'line',
        data: {
          labels: labels,
          datasets: [{
            label: 'Corriente Fase 1',
            data: fase1Data,
            borderColor: 'blue',
            fill: false
          }]
        },
        options: {
          animation: true,
          scales: {
            x: { display: true },
            y: { beginAtZero: false }
          }
        }
      })
      
      const chartTemp = new Chart(ctxTemp, {
        type: 'line',
        data: {
          labels: labels,
          datasets: [{
            label: 'Temperatura',
            data: tempData,
            borderColor: 'red',
            fill: false
          }]
        },
        options: {
          animation: true,
          scales: {
            x: { display: true },
            y: { beginAtZero: false }
          }
        }
      })
      
      function dataGen(){
        var numI = Math.random() * (8.0 - 5.0) + 5.0;
        var curI = parseFloat(numI.toFixed(2));
        var numT = Math.random() * (22.0 - 20.0) + 20.0;
        var temT = parseFloat(numT.toFixed(1));
        const now = new Date().toLocaleTimeString("en-GB");
      
        var jsondemo = "{\"Irms1\":" + curI.toFixed(2) + ",\"Irms2\":" + (curI - 0.2).toFixed(2) + ",\"Irms3\":" + (curI + 0.25).toFixed(2) + ",\"temp\":" + temT + "}";
      
        console.log(jsondemo);
        const data = JSON.parse(jsondemo);
        console.log(data.Irms1);
        console.log(data.Irms2);
        console.log(data.Irms3);
        console.log(data.temp);
      
        document.getElementById("i1").innerText = data.Irms1 + " A";
        document.getElementById("i2").innerText = data.Irms2 + " A";
        document.getElementById("i3").innerText = data.Irms3 + " A";
        document.getElementById("temp").innerText = data.temp + " °C";
        
        if (labels.length > 10) {
              labels.shift();
              fase1Data.shift();
              tempData.shift();
           }
      
         labels.push(now);
         fase1Data.push(data.Irms1);
         tempData.push(data.temp);
      
         chartFase1.update();
         chartTemp.update();
       }
      
      
      
      function actualizarDatos() {
        
        fetch("/datos")
          .then(response => response.json())
          .then(data => {
            console.log("Datos recibidos:", data);
            const now = new Date().toLocaleTimeString();
                                 
            document.getElementById("i1").innerText = data.Irms1 + " A";
            document.getElementById("i2").innerText = data.Irms2 + " A";
            document.getElementById("i3").innerText = data.Irms3 + " A";
            document.getElementById("temp").innerText = data.temp + " °C";
      
            if (labels.length > 50) {
              labels.shift();
              fase1Data.shift();
              tempData.shift();
            }
      
            labels.push(now);
            fase1Data.push(data.Irms1);
            tempData.push(data.temp);
      
            chartFase1.update();
            chartTemp.update();
          });
       }
      //setInterval(actualizarDatos, 1000);
      setInterval(dataGen, 1000);
      //window.onload = actualizarDatos;
    </script>
  </body>
</html>

I'm running on Windows, I've tried with Chrome, Firefox, Edge and Brave, and in all of the browsers I got the error, I'll try your solution in the afternoon, I'll update the post, thanks!

That was the problem, incredible how a character was causing the problem, thanks a lot for the help!!

Great,

pleased it's working for you now. That was my last throw of the dice. Does your function actualizarDatos() work properly now?

Yes, all is working perfectly now. I used the datagen once and then try with my function :clap:t3::clap:t3: