0
votes

i am new to Node.JS and Arduino. I have an Arduino setup with a temperature sensors on it. I am reading temperature values with Arduino. My serial monitor output like this:

serial Monitor:

0.05
0.10
0.15
0.20
0.25
0.30
0.34

I send data from a Arduino to my terminal with serialport then displayed data on my webbrowser in chart form. I'm using the express and socket.io. here is the connection with the arduino and browser with index.js. And a index.html

index.js:


    var express = require('express');

    var app = express();
    var http = require('http').Server(app);
    var server = http.listen(4000, "0.0.0.0", () => { //Start the server, listening on port 4000.
        console.log("Listening to requests on port 4000...");
    })

    var io = require('socket.io')(server); //Bind socket.io to our express server.

    app.use(express.static('public')); //Send index.html page on GET /

    const SerialPort = require('serialport');
    const Readline = SerialPort.parsers.Readline;
    const port = new SerialPort('/dev/ttyUSB0'); //Connect serial port to port COM3. Because my Arduino Board is connected on port COM3. See yours on Arduino IDE -> Tools -> Port
    const parser = port.pipe(new Readline({delimiter: '\r\n'})); //Read the line only when new line comes.
    parser.on('data', (temp) => { //Read data
        console.log(temp);
        var today = new Date();
        io.sockets.emit('temp', {date: today.getDate()+"-"+today.getMonth()+1+"-"+today.getFullYear(), time: (today.getHours())+":"+(today.getMinutes()), temp:temp}); //emit the datd i.e. {date, time, temp} to all the connected clients.
    });

    io.on('connection', (socket) => {
        console.log("Someone connected."); //show a log as a new client connects.
    })

The temperature data is recieved from the serialport Arduino is displayed in the index.html (webbrowser).

index.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Temperature Plot</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <h1>Temperature Graph</h1>
        <h4>Date: <span id="date"></span></h4>
        <div class="chart-container" style="position: relative; width:75vw; margin: auto;">
            <canvas id="myChart"></canvas>
        </div>
        <link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
        <script>
            var socket = io.connect('http://192.168.1.3:4000'); //connect to server
            var ctx = document.getElementById('myChart').getContext('2d');
            var chart = new Chart(ctx, {
                // The type of chart we want to create
                type: 'line',
                // The data for our dataset
                data: {
                labels: [],
                datasets: [{
                    label: "Temperature",
                    borderColor: "#FF5733",
                    data: [],
                    fill: false,
                    pointStyle: 'circle',
                    backgroundColor: '#3498DB',
                    pointRadius: 5,
                    pointHoverRadius: 7,
                    lineTension: 0,
                }]
                },
                // Configuration options go here
                options: {}

            });
            socket.on('temp', function(data) { //As a temp data is received
                console.log(data.temp);
                document.getElementById('date').innerHTML = data.date; //update the date
                if(chart.data.labels.length != 15) { //If we have less than 15 data points in the graph
                    chart.data.labels.push(data.time);  //Add time in x-asix
                    chart.data.datasets.forEach((dataset) => {
                        dataset.data.push(data.temp); //Add temp in y-axis
                    });
                }
                else { //If there are already 15 data points in the graph.
                    chart.data.labels.shift(); //Remove first time data
                    chart.data.labels.push(data.time); //Insert latest time data
                    chart.data.datasets.forEach((dataset) => {
                        dataset.data.shift(); //Remove first temp data
                        dataset.data.push(data.temp); //Insert latest temp data
                    });
                }
                chart.update(); //Update the graph.
            });
        </script>
    </body>
    <style>
        h1 {
            text-align: center;
            font-family: 'Lato', sans-serif;
        }
        h4 {
            text-align: center;
            font-family: 'Lato', sans-serif;
        }
        p {
            text-align: center;
            font-family: 'Lato', sans-serif;
        }
    </style>
</html>

everything works fine if there is only 1 sensor temperature on Arduino, but when I add another temperature sensor with the serial monitor results as below, make sensors data unable to appear in the form of chart in index.html, and the console browser also only displays the same data as the serial monitor.

serial monitor with 2 temperature sensor (the results of reading between temperature sensors with each other are separated by spaces)

0.05 1.00
0.10 1.00
0.15 0.99
0.20 0.98
0.25 0.97
0.30 0.96
0.34 0.94

I have tried to solve this problem for almost a week, I have tried many ways to solve this problem but it didn't work, I do need your help

arduino code:

double x; //I simulate 2 temperature sensor values
    void setup() {
      Serial.begin(115200);
      x = 0;
    }

    void loop() {  
      Serial.print(sin(x));
      Serial.print(" ");
      Serial.println(cos(x));
      delay(50);

      // seting batasan input fungsi sinus
      x += 0.05;
      if(x>= 2*3.14){
        x = 0;
      }  
    }
1
The format of output by the serial port will depend on your arduino code. What you can do is prefix "Sensor 1 :" like string to the sensor data and then parse the output based on this .zeekhuge
For better help, please post your arduino code.zeekhuge
@ZeekHuge, I have updated my question by adding the arduino codeuser8646839
So you mean 'sin(×)' is sensor1-data and 'cos(x)' is sensor 2 data ?zeekhuge
yes right @ZeekHugeuser8646839

1 Answers

0
votes

There are basically 2 questions in it.

  1. How to format the data and use the express server and send it to the front-end
  2. How to display more than one data-set in in the graph using chart.js

For 1st

The line in your code

...
const parser = port.pipe(new Readline({delimiter: '\r\n'}));
...

Actually captures each line of data. But since your output from arduino contains data in the same line, we will have to split() it at the space character. So to get an array of more than one temperature values, you can use tempArray = temp.split(" ");. This array then can be sent to the front-end.

For 2nd

After you have the array of the temperature values, you can send that array itself to the front end using

// Notice I have replaced `temp` with `tempArray`
io.sockets.emit('temp', {date:today.getDate()+"-"+today.getMonth()+1+"-"+today.getFullYear(), time: (today.getHours())+":"+(today.getMinutes()), temp:tempArray}); });

In the front-end, the dataset in the Chart object is an array. And if you want to add more than one datasets to the chart, you can add them simply by adding one more dataset object :

....
datasets: [{
           label: "Sensor1",
           borderColor: "#FF5733",
           data: [],
           fill: false,
           pointStyle: 'circle',
           backgroundColor: '#3498DB',
           pointRadius: 5,
           pointHoverRadius: 7,
           lineTension: 0,
          },
....
....

          {
           label: "Sensor2",
           borderColor: "#FFFF33",
           data: [],
           fill: false,
           pointStyle: 'circle',
           backgroundColor: '#34FFDB',
           pointRadius: 5,
           pointHoverRadius: 7,
           lineTension: 0,
          },
]
....

Now, inside the socket.on('temp', function(data){...}) you can push data like this :

chart.dataset[i].data.push(data.temp[i]) // looping over i

Edit

To put in the data into the datasets, you can use a 'for' loop as follows :

for (var i = 0; i < datasets.length; i++) {
    chart.datasets[i].data.push(data.temp[i]);
}