基于arduino 用ESP8266获取实时MAX30102 血氧数据动态曲线显示在网页上
原理: ESP8266获取MAX30102 血氧数据(R,IR,G的值)发送到路由器局域网内,局域网内的手机电脑,访问ESP的ip地址,获取实时的血氧数据动态曲线显示在网页上
网页显示内容:
代码见最后,打开arduino创建一个文件,将C语言部分的代码拷贝到arduino中,另存为AXJXDemo4,在文件夹中新建txt,打开讲HTML部分代码粘贴到txt中,另存为index.h ,如图所示:
用arduino打开AXJXDemo4.ino,如图所示;
添加相关的库文件,添加wifi,密码。打开串口监视器,编译上传。串口监视器显示局域网的ip 地址。
连接MAX30102,接线信息:-5V = 5V (3.3V is allowed) -GND = GND -SDA = A4 (or SDA) -SCL = A5 (or SCL)
重启ESP, 局域网内的手机电脑访问ip地址,如图一所示,
串口监视器打印了MAX30102 的三种数据R,IR,G值)示例显示的是G,可以根据实际情况修改,位置在html: y = parseFloat(document.getElementById(“adc_G”).innerText);
Html网页显示代码:
const char webpage[] PROGMEM = R"=====(
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<TITLE>心电图DEMO演示</TITLE>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="http://code.highcharts.com/highcharts.js"></script>
<script type="text/javascript">
$(function () {
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
var display_value= parseFloat(document.getElementById("adc_R").innerText);
$('#container').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function() {
var series = this.series[0];
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = parseFloat(document.getElementById("adc_G").innerText);
series.addPoint([x, y], true, true);
}, 1000);// 间隔
}
}
},
title: {
text: '心电动态图'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 100
},
yAxis: {
title: {
text: '纵轴'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
// 数据在这里初始化
for (i = -9; i <= 0; i++) {
data.push({
x: time + i * 10000,
y: Math.random()*5 //Math.random()*500 // y: 5
});
}
return data;
})()
}]
});
});
});
setInterval(function() {
getData_R();
getData_IR();
getData_G();
}, 1000);
function getData_R() {
var xhttp_R = new XMLHttpRequest();
xhttp_R.onreadystatechange = function() {if (this.readyState == 4 && this.status == 200) {
document.getElementById("adc_R").innerHTML = this.responseText; } };
xhttp_R.open("GET", "adcread_R", true);
xhttp_R.send();
}
function getData_IR() {
var xhttp_IR = new XMLHttpRequest();
xhttp_IR.onreadystatechange = function() {if (this.readyState == 4 && this.status == 200) {
document.getElementById("adc_IR").innerHTML = this.responseText; } };
xhttp_IR.open("GET", "adcread_IR", true);
xhttp_IR.send();
}
function getData_G() {
var xhttp_G = new XMLHttpRequest();
xhttp_G.onreadystatechange = function() {if (this.readyState == 4 && this.status == 200) {
document.getElementById("adc_G").innerHTML = this.responseText; } };
xhttp_G.open("GET", "adcread_G", true);
xhttp_G.send();
}
function getData_value() {
var a=document.getElementById("test").value;
if (a==1) {
parseFloat(document.getElementById("adc_span").innerText=a);
} else if (a==2) {
parseFloat(document.getElementById("adc_span").innerText=a);
} else {
parseFloat(document.getElementById("adc_span").innerText=a);
}
}
</script>
<style>
/* 隐藏原生的select样式 */
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 5px;
border: 0px solid #999;
border-radius: 5px;
background-color: #f1f1f1;
color: #333;
font-size: 16px;
width: 50px;
text-align: center;
float: right;
}
</style>
</HEAD>
<BODY>
<div name="status" style="text-align:center"><b>
MAX30105:_R:<span type="text" id="adc_R" style="color:#F00" >6</span> <!--网页测试期间值为6,其他时间为空-->
_IR:<span id="adc_IR" style="color:rgb(9, 226, 56)">7</span>
_G:<span id="adc_G" style="color:rgb(15, 7, 228)">8</span>
</b></div>
<select id="test" onchange="getData_value()">
<option value ="1">R</option>
<option value ="2">IR</option>
<option value ="3">G</option>
</select><span id="adc_span" style="float: right;">3</span><br>
<div id="container" style="width:100%;height:calc(100vh - 60px);margin:0 auto;"></div>
</BODY>
</HTML>
)=====";
C语言部分:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include "index.h"
#include "MAX30105.h"
MAX30105 particleSensor;
const char* ssid = " "; // WIFI名和密码
const char* password = " ";
ESP8266WebServer server(80);
void handleRoot(){
String s = webpage;
server.send(200, "text/html", s);
}
void MAX30105_R(){
server.send(200, "text/plane", String(particleSensor.getRed()));
}
void MAX30105_IR(){
server.send(200, "text/plane", String(particleSensor.getIR()));
}
void MAX30105_G(){
server.send(200, "text/plane", String(particleSensor.getGreen()));
}
void setup(){
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println(); // Connect to WiFi network
Serial.println();
Serial.print("Connecting to "); Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(".");}
Serial.println("");
Serial.println("WiFi connected");
server.begin();
Serial.println(WiFi.localIP());
Serial.println("MAX30105 is running!!!");
if (particleSensor.begin() == false){
Serial.println("MAX30105 was not found. Please check wiring/power. "); while (1); }
particleSensor.setup(); //Configure sensor. Use 6.4mA for LED drive
server.on("/", handleRoot);
server.on("/adcread_R", MAX30105_R);
server.on("/adcread_IR", MAX30105_IR);
server.on("/adcread_G", MAX30105_G);
server.begin();
}
void loop(){
// put your main code here, to run repeatedly:
Serial.print(" R["); Serial.print(particleSensor.getRed());
Serial.print("] IR["); Serial.print(particleSensor.getIR());
Serial.print("] G["); Serial.print(particleSensor.getGreen()); Serial.print("]"); Serial.println();
//delay(1000);
server.handleClient();
}