(Arduino or NodeMcu) and PulseSensor and HTML
来源:互联网 发布:sql数据库还原 编辑:程序博客网 时间:2024/05/16 02:14
基本用法可见: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() endend)
其中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 endend
手指离开的做法也差不多,略。
接下来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) endend)
定时检查是否连上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 dataenddofile("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 endfunction getData() local d = userRate.."\r\n"..userPulse userPulse = "" return dend
获取数据后解出心率值和波形,前者直接在一个div里显示,后者是把各个波形数值添加进数组里,定时取出转为相应高度的图形,在新添加的div里滚动显示,说起来不好理解直接看末尾代码。
最后手指放上传感器开始测试,再用浏览器访问NodeMcu的ip,比如192.168.1.100,就可以看到结果了:
当然这个程序不够稳定,抛砖引玉。
源码地址:http://download.csdn.net/detail/romermsp/9566783
- (Arduino or NodeMcu) and PulseSensor and HTML
- Raspberry Pi controls Arduino Board with PHP, Bash and HTML
- and or
- AND & OR
- and ,or 和and-or
- python and or and-or
- SQLite AND/OR 运算符(http://www.w3cschool.cc/sqlite/sqlite-and-or-clauses.html)
- Arduino and the SPI bus
- Arduino and RS485 (ENGLISH VERSION)
- Python中的and、or、and-or
- 【转载】python 中的 and、or、and-or
- 条件or and并用
- or and test命令
- where and or
- and or join
- EXCEL IF AND OR
- python and or技巧
- and or技巧
- 【图像处理】SFR算法详解4
- 2.7 Python缩进
- gcd&exgcd O(∩_∩)O哈!
- HDG西安站|分享技术干货,打造开发者交流平台!
- 2.8 Python操作符
- (Arduino or NodeMcu) and PulseSensor and HTML
- ubuntu16.04下安装boost环境
- 如何用两种不同的方法动态绘制饼状图
- Android中AsyncTask异步交互的简单demo
- Unity3D研究院之两种方式播放游戏视频(二十五)
- Python - Selenium + Chromedriver
- 背景:妈妈给六岁的儿子出算术题做
- c#工作线程中去更新界面显示
- 2.9 Python运算符优先级