How to display Sensor data in real time on Web

 In Internet of Things applications we often need to display sensor data in real time on the web browser. There are many solution such as using cloud IoT hosting. But here we will illustrate an alternative to IoT cloud hosting. We show how we can host the web application using home server and display the sensor data on the internet for free.

To do this we need the following:

1. Server at home like XAMPP Apache server

2. Localhost tunnel like pagekite

3. Program & coding for

- webpage & chart(chart.js)

- serial port capability(p5.js, p5.serial.port, p5 serial monitor)

Video Demonstration

 

1. Xampp is a open source software that allows one to run web server, email server, etc. This is used by commercial companies as well as developers. First we need install the XAMPP web server in home PC. 

For this step see the tutorial How to host website from home.

2. Next we need a local tunnel solution like pagekite that allows us to access the external internet from our local server(XAMPP). This is only required if you cannot for some reason port forward the external IP address to your internal IP address via your router/switch.

3. We need to write program codes that takes in sensor data from sensor and displays the sensor data on a graph. Sensor data can be acquired using Arduino via its analog pin. For simplicity we will connect a 10KOhm potentiometer to the analog pin of Arduino. The Arduino will transfer the sensor data serially to the PC. On the PC we will have program code written in P5.js that reads in the sensor data and sends to the local web server(XAMPP/Apache). For this in the P5.js sketch we need two things- the p5.serial.js library and the p5 serial monitor. The p5.serial.js library allows us to connect the web page application to the serial communication port. The p5 serial monitor which is serial server is required to fetch the serial data and communicate with the p5.serial.js library. These two p5.serial.js library and the p5 serial monitor is required because a webpage cannot directly communicate with serial port.

Once you have the above requirements you should have a folder in the XAMPP htdoc folder that contains your program codes and libraries.

Arduino Code

The following is the Arduino program which sends sensor data to the PC serially.


void setup() {
Serial.begin(9600);
}

void loop() {
int pot= analogRead(A1);
Serial.println(pot);
delay(1);
}


HTML code

The following is the index.html code.



<html>
<head>  
	<meta charset="utf-8"></meta>  
	<meta content="width=device-width, initial-scale=1.0" name="viewport"></meta> 
 
	<script language="javascript" src="libraries/p5.min.js" type="text/javascript"></script>  
	<script language="javascript" src="libraries/chart.js" type="text/javascript"></script>  
	<script language="javascript" src="libraries/chartjs-adapter-date-fns.bundle.min.js" type="text/javascript"></script>  
	<script language="javascript" src="libraries/p5.serialport.js" type="text/javascript"></script>  
	<script language="javascript" src="libraries/chartjsEg.js" type="text/javascript"></script>  

<style> 
	body{ 
		padding: 50; 
		margin: center; 
		display: block;
		background-color: black;
		}   
	
	.chartbox{    
		position: relative;    
		width:100%;  
		}  
	
	canvas{  
		width: 100% !important;   
		display: inline;       
		background-color: black;   
		}

	div{  
	position: relative;
	text-align: center;
	display: block;
	}      
</style>

</head>

	<body>
		<div class="chartbox" id="cid"></div>
	</body>
	
</html>

sketch.js code

The following is the sketch.js code


let serial;
let portSelector;

let dataSize = 400;
let readings = new Array(dataSize);
let options = { baudRate: 9600}; // change the data rate to whatever you wish

let chart;

// data object for the chart:
const data = {
  // X axis labels
  labels: new Array(dataSize),
  datasets: [{
    label: 'Serial data',  // chart label
    data: readings,         // the data to chart
    backgroundColor: '#C1142B',
    borderColor: '#C1142B',
    borderWidth: 1.2,
    pointBorderColor: '#C1142B',
    pointRadius: 0.2         // point size
  }]
};

const config = {
  type: 'line',         // type of chart
  data: data,           // the data
  options: {
    animation: false,   // remove animation to speed drawing up
    responsive: true,
    maintainAspectRatio: false,
    plugins:{
      legend:{
        display: true,
      position: 'top',
      align: 'end'
      },
      title: {
      display: true,
      text: 'Potentiometer Real Time Values',
      font:{
              size: 20
              },
       padding:{
                bottom: 0
              },
        color: '#fff'
      },
    },
    scales: {           // axis ranges:
      y: {
        title: {
        display: true,
        text: 'Amplitude',
        font:{
              size: 20
              },
        color: '#fff'
        },
        ticks:{
            font: {
                  size: 14
                  },
            color: '#fff'
          },
        grid: { display: true, color: "#131c2b", borderColor: '#ffcc33' },
        min: 0,
        max: 1040
      },
      
      x:{
          title: {
            display: true,
            text: 'Time(s:us)',
            font: {
                  size: 20
                  },
            color: '#fff'
          },
          ticks:{
            font: {
                  size: 10,
                  },
            color: '#fff'
          },
          grid: { display: true, color: "#131c2b", borderColor: '#ffcc33' },
          min:0
      }
    }
  }
};

function setup() {
  createCanvas(540, 370).parent("cid");
  serial = new p5.SerialPort();
 
  serial.on('list', printList);
  
  serial.list();
   
   serial.on('data', serialEvent);

  chart = new Chart(
    this,   // context: this sketch
    config  // config from the global variables
  );

}

function draw() {
  chart.update();
}

function printList(portList) {
  portSelector = createSelect();
  portSelector.position(10, 10);
  for (var i = 0; i < portList.length; i++) {
    portSelector.option(portList[i]);
  }
  portSelector.changed(mySelectEvent);
}

function mySelectEvent() {
  let item = portSelector.value();
  portSelector.visible = true;
  if (serial.serialport != null) {
    serial.close();
  }
  serial.open(item, options);
}

function keyPressed() {
  // if port selector is visible, hide it, else show it:
  if (portSelector) {
    if (portSelector.visible) {
      portSelector.hide();
      portSelector.visible = false;
    } else {
      portSelector.show();
      portSelector.visible = true;
    }
  }
}


function serialEvent() {
  let today = new Date();
  let t = today.getSeconds() + ":" + today.getMilliseconds();
  let potData = Number(serial.readLine());
  if (potData) {
  readings.push(potData);
    data.labels.push(t);
    if (readings.length > dataSize) {
      readings.shift();
      data.labels.shift();
    }
  }
}


Once we have the website running and tested in the local web server we then can run the pagekit.py  program to the local IP tunneled url as shown below.


This url is redirected to the website hosted in the local XAMPP Apache server and we can see the sensor data displayed on the external IP address or external URL.

Live Sensor data display illustration

Below is real time sensor data displayed on this webpage. Note that this is available only when local server is running, see the above video demonstration.

Follow up video:


Recommended similar tutorials:

- ESP8266 PWM Example with Javascript and AJAX

- Read & Display Switch State on Web Page with ESP8266 Web Server

Post a Comment

Previous Post Next Post