您的位置:首页 > Web前端 > Node.js

(Arduino or NodeMcu) and PulseSensor and HTML

2016-06-30 10:05 549 查看
得知有个脉搏传感器(pulsesensor),可以感知手指处的脉搏,且有提供arduino程序,遂买来耍。



基本用法可见:http://www.arduino.cn/thread-3188-1-1.html

官方的arduino程序很好用,其中的代码做了一些事情让它更准确稳定。在串口监视器里运行起来波形是这样:

---------

---------

------------

------------

*** Heart-Beat Happened *** BPM: 72 --------------|-

--------------|-

--------------|-

--------------|-

------------

------------

---------

---------

纵轴向下是时间,横轴向右是幅度,文字部分是检测到的心跳值。当然图案是会继续滚动的。

本来一般横轴是时间,纵轴为幅度,但前面那种容易实现。

单独获取传感器信号,就是adc值,也是很稳定的,如程序:

int sv = 0;
const int LEN = 100;
char c[LEN] = "";
char cv[LEN] = "";

void setup() {
for (int i = 0; i < LEN; i++)
c[i] = '-';
Serial.begin(9600);
}

void loop() {
sv = analogRead(A0);
int v = sv / 12;
strncpy(cv, c, v);
cv[v] = ' ';
cv[v + 1] = '\0';

Serial.print(cv);
Serial.println(sv);

delay(50);
}


未放手指时它的波形是这样的,幅值在338左右:

---------------------------- 338

---------------------------- 337

---------------------------- 337

---------------------------- 337

---------------------------- 337

---------------------------- 337

---------------------------- 338

---------------------------- 340

---------------------------- 341

---------------------------- 339

---------------------------- 337

---------------------------- 336

---------------------------- 336

放上手指后,幅值变为个位数,然后是正常起伏的波形:

---------------------------- 336

-------------------------- 317

---------------------- 266

--------------- 185

4

0

0

1

0

......

0

0

0

0

0

------------------- 239

-------------------------------- 387

------------------------------- 379

-------------------------- 323

------------------------ 296

------------------------- 304

----------------------------- 357

----------------------------------- 420

------------------------------------ 439

---------------------------------- 408

------------------------------ 371

--------------------------- 326

--------------------------- 335

------------------------------- 381

-------------------------------------- 457

---------------------------------------- 491

-------------------------------------- 461

手指离开后,幅值先是在576附近然后回复到342左右:

------------------------------------------------ 576

------------------------------------------------ 576

----------------------------------------------- 575

----------------------------------------------- 575

------------------------------------------------ 576

----------------------------------------------- 575

----------------------------------------------- 575

----------------------------------------------- 575

----------------------------------------------- 575

----------------------------------- 422

------------------------ 292

------------------------ 295

--------------------------- 334

----------------------------- 354

----------------------------- 353

---------------------------- 347

---------------------------- 344

---------------------------- 342

---------------------------- 341

通过检查模拟输入值就可以知道用户状态和计算脉搏。所以不局限于arduino,其它板子也可以做,比如NodeMcu,基于esp8266,所以有wifi功能。

NodeMcu使用Lua,其语法看github里的例子基本足够,不够看下简易教程比如runoob.com。

固件烧写、程序上传等使用方法可见http://www.tinylab.org/nodemcu-kickstart/ ,该文是以linux环境为主。

如果在windows下,固件烧写可用https://github.com/nodemcu/nodemcu-flasher;

程序上传可用https://github.com/nodemcu/nodemcu-studio-csharp

串口工具好几种,putty那些,,arduino ide里的那个窗口监视器也可以。

计算心跳数的主过程是这样的:

init()  --初始化
tmr.alarm(0,50,tmr.ALARM_AUTO ,function () --定时器50毫秒循环
sv = adc.read(0)  --读取传感器信号
if(state~=0) then
savePulse(sv)  --存下信号值
end
if(state==0) then
getStart()      --检查手指是否放上
elseif (state==1) then
preGetPeak()    --预先取得信号峰值,为下一峰值的有效性作参照
elseif (state==2) then
getFirstBeat()  --取得第一个心跳
elseif(state==3) then
getNextBeat()   --下一个心跳
end
if (state~=0 and isNotTouch(sv)) then --检查手指是否离开
print('init')
init()
end
end)

其中getStart()这么做:

---------------------- 266

--------------- 185

4 <--读取的是低数值,计数器加1,下同

0

0

1

0

0

......

0

------------------- 239 <--读取出非小数值时 若计数器超过一定量 说明手指已放上,此步骤完成

-------------------------------- 387

代码是:

function getStart()
if (sv <10) then
zeroCount = zeroCount+1;
else
if (zeroCount > 20) then
state = 1;
else
zeroCount = 0;
end
end
end


手指离开的做法也差不多,略。

接下来3个步骤preGetPeak()、 getFirstBeat() 、getNextBeat()都依赖于获取峰值函数getPeak(checkTimes):

-------------------------- 329

--------------------------- 325

--------------------------- 325 <--若读取数值比之前大,取当前值为峰值,记下峰值时间,下同

--------------------------- 332

----------------------------------- 423

-------------------------------------------- 537 <--此为峰值

------------------------------------------- 516 <--若不比之前峰值大,再取几次值确认

----------------------------------- 422

----------------------------- 357

--------------------------- 333 <--经以上几次比较,确认已经找到峰值

---------------------------- 339

------------------------------ 368

------------------------------- 383

------------------------------- 373

此函数有个参数checkTimes, 用于设定检查次数。

preGetPeak调用getPeak时,checkTimes可以设得比较大,超过1秒,以预先取得参考峰值。

若getFirstBeat取得的峰值比参考峰值小很多,则重新取firstBeat。

function getFirstBeat()
if(getPeak(3)) then
if (peak>lastPeak*0.8) then
lastPeakTime = peakTime
lastPeak     = peak
state        = 3
end
end
end


然后getNextBeat比getFirstBeat多做的事情就是计算心率了,得到两次心跳时刻(就是峰值时间)后,相减即为一次心跳时间,60秒去除则得出心率:

local r = math.floor(60000000 / (peakTime - lastPeakTime))

然后getNextBeat不断计算,更新心率变化。

这时程序已经可以用了,命名为pulse.lua运行,在PC端串口观察结果。

如果利用wifi模块,可以脱离PC,用手机浏览器察看结果。

过程是 :

1.NodeMcu以station方式连接wifi得到ip地址。

2.手机访问这个地址,得到html内容以知道如何获取和处理心率信息。

3.手机运行html,定时获取心率信息,解出心率数值、波形并显示。

具体是:

1. init.lua是NodeMcu启动后自动运行的程序,在这里连接wifi:

wifi.setmode(wifi.STATION)
wifi.sta.config("ssid","password")

tmr.alarm(0,3000,tmr.ALARM_AUTO ,function ()
if (pcall(function() print('ip:'..wifi.sta.getip()) end)==true) then
tmr.stop(0)
pcall(function() dofile("pulseServer.lua") end)
end
end)

定时检查是否连上wifi得到ip,是就可以做心率检测了。

2.在pulseServer.lua里与浏览器交互:

html = [[
--略......
]]
function pro(pl)
local p    = string.match(pl,"GET /(.*) HTTP")
local data = ""
if (p=="") then
data = html
elseif (p=="p") then
data =  getData()
end
return data
end

dofile("pulse.lua")

srv = net.createServer(net.TCP)
srv:listen(80, function(c)
c:on("receive", function(c, pl)
local d = pro(pl)
c:send(d)
end)
c:on("sent",function(conn) conn:close() end)
end)


这里运行pulse.lua,并建一个TCP服务器在80端口,如果接收的http数据里路径是'/',把html发给浏览器;如果路径是'/p',则发送心率数据。

3.html主要是用XMLHttpRequest定时访问'/p'地址获取数据,数据格式是"心率值\r\n波形",其中波形数据是每两位字符为1个数字,数据拼装在pulse.lua里做:

function savePulse(sv)
local vv = math.floor((sv-350)/13)
if(vv<0) then vv=0 end
local p   = string.sub("0"..vv,-2) --数值是两位数,只有1位的在前面补零
userPulse = userPulse..p
end

function getData()
local d   = userRate.."\r\n"..userPulse
userPulse = ""
return d
end

获取数据后解出心率值和波形,前者直接在一个div里显示,后者是把各个波形数值添加进数组里,定时取出转为相应高度的图形,在新添加的div里滚动显示,说起来不好理解直接看末尾代码。

最后手指放上传感器开始测试,再用浏览器访问NodeMcu的ip,比如192.168.1.100,就可以看到结果了:



当然这个程序不够稳定,抛砖引玉。

源码地址:http://download.csdn.net/detail/romermsp/9566783
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  pulsesensor NodeMcu