×

直接在Google表格中的血压监测仪

消耗积分:0 | 格式:zip | 大小:0.79 MB | 2022-11-10

李桂英

分享资料个

描述

介绍

沉默的杀手是医学界人士对高血压或高血压的称呼。他们还给糖尿病、前列腺癌甚至一氧化碳赋予了相同的名称。今天我们只关注高血压,因为根据美国心脏协会的说法,如果不被发现(或不受控制),高血压会导致很多事情,包括心脏病。根据疾病控制和预防中心 (CDC)的说法,这反过来又是美利坚合众国的主要死因。在其他组织中,国际高血压学会 (ISH)也赞同这些发现和准确测量的重要性。

既然我引起了您的注意,我虚构的法律团队建议我给出以下免责声明:

此处所做的声明尚未经过食品和药物管理局的评估。本产品不用于诊断、治疗、治愈或预防任何疾病。

我不是医生,我什至从来没有在电视上玩过。我还应该提到,与现实的任何相似之处纯属巧合。

我们都放弃了,让我们把这个节目放在路上吧。

比赛计划

这是我在 AVR-IoT WG 板上发布的第二个项目。在第一个项目中,我们将开发板连接到私有 Google 云,将所有接收到的数据保存在 Firebase 中,并在 Google 表格中仅显示最新的血压监测 (BPM) 数据。在这个项目中,我们将所有数据直接保存在 Google 表格中。我们将在这个项目中使用 Arduino IDE,因为它降低了许多新创客的进入门槛。在收到关于我之前的 AVR-IoT WG 项目和Helium Network GPS Tracking Directly In Google Sheets项目的良好反馈后,我正在使用 Google 表格

AVR-IoT WG 将连接到 Wi-Fi 并将数据发送到 Google Sheets,这意味着我们将仅在 Arduino IDE 和 Apps Script 中编码。建立连接后,BPM 将进行测量,结果将通过简单的 HTTPS POST 请求发送。Apps 脚本随后将解析数据并填充 Google 表格。

如果您还记得我们在介绍中谈到“准确测量的重要性”。美国卫生与公众服务部国立卫生研究院国家医学图书馆国家生物技术信息中心研究了环境温度对血压的影响:

pYYBAGNrpwSAEpG-AACMEqViuJ8140.png
 

因此,我们不仅会发送收缩压、舒张压和心率值,还会发送环境温度和时间戳,为我们的数据提供一些背景信息,以便医疗保健专业人员进行更准确的解释。最后,为了使数据更易于访问,我们将以 Google 表格格式呈现。

在我们深入之前需要注意的几点:

  • 本教程中将按照与产品发展相关的顺序介绍主题
  • 文本片段,即“#:~:text=, ”用于突出显示单个点,不应脱离上下文

收集信息

poYBAGNrpwiAXJZSAAK5M5EYZS0172.png
一张图片胜过千言万语
 

这是文档中最有用的图表之一。我们可以从AVR-IoT_WG_Schematics.pdf获得一些信息我们需要的第一件事是 CryptoAuthentication 的 I2C 地址,这样我们就可以获得序列号并避免在我们部署的每个设备中手动硬编码值。我们需要获取的下一个 I2C 地址是温度传感器的地址。

poYBAGNrpwqADYa7AADCSwHNk4o823.png
ATWINC15x0-MR210xB 数据表的第 18/59 页
 

我们不需要对 SPI 做任何事情,因为 ATmega4808 和 WINC1510 已经连接。但是,我们需要从原理图中找到 CHIP_EN、RESET、WAKE 和 IRQN 的引脚编号。我们也可以从 MPLAB X IDE 获得相同的信息。

pYYBAGNrpxCAahZnAAN_TITlo70746.png
 

硬件

AVR-IoT WG 开发板结合了功能强大的 ATmega4808 AVR® MCU、ATECC608A CryptoAuthentication™ 安全元件 IC 和完全认证的 ATWINC1510 Wi-Fi® 网络控制器 - 提供了将嵌入式应用程序连接到 Google 云端的最简单有效的方法物联网核心平台。该板将用于从非智能 BPM 中获取数据并将其发送到谷歌云。

pYYBAGNrpxKAOKNhAAB8qvqy4oo500.png
像他们一样通用
 

在等待我的 BPM 到达时,我偶然发现了 YouTube 上的一段视频,其中Circuit Desolator 拆解了三个不同的 BPM。他的目标是通过每个设备上的内部集成威廉希尔官方网站 (I2C) 总线接入电可擦除可编程只读存储器 (EEPROM)。一旦设备完成测量,它会将结果保存在 EEPROM 中,然后可以轻松检索数据。这种方法需要一些拆卸和精密焊接。对我来说,那将是 B 计划。

我的想法略有不同。我一收到并测试了 BPM,就拆开了它,然后我寻找了一个串行端口。最好的情况是,我会发现通用异步接收器/发送器 (UART) 的四个孔彼此相邻,我必须找出哪个是 Vcc、GND、Tx 和 Rx。

poYBAGNrpxiAGS7RAACKTNizAkM928.png
那太容易了
 

第二个挑战是确定电压电平。由于此 BPM 在两个 1.5 伏电池上运行,因此电压电平不太可能为 5 伏。我测量了 3.3 伏特,现在我已准备好迎接下一个挑战,即找到波特率。我使用我的 FTDI 和以下Python 脚本来回答这个问题:

import serial.tools.list_ports as ports
import serial

BaudRates=[110, 150, 300, 600, 1200, 2400, 4800, 9600,
           14400, 19200, 28800, 31250, 38400, 57600,
           115200, 128000, 230400, 256000, 460800, 921600]

for p in ports.comports():
    for b in BaudRates:
        with serial.Serial(p.device,b,timeout=3) as s:
            print(s.name + ' ' + str(s.baudrate) + ' ' +
                  s.read(100).decode('unicode_escape'))
exit()

我必须打开 BPM 才能开始从 UART 读取数据。给我可读文本的波特率为 38400。AVR-IoT WG 的一个 USART 将使用该数字从 BPM 读取数据。

poYBAGNrpxqAWmQ5AACSNVYclcA658.png
答对了
 

如果您对 Python 感到不舒服(恐惧症),您也可以通过使用 Arduino IDE 串行监视器并尝试窗口右下角的所有波特率来得出相同的结论。

pYYBAGNrpx6AHX4cAAC4YFkiqxw011.jpg
 

在我们离开本节之前,我想指出我更喜欢使用 UART 而不是 I2C,因为我希望能够在未来扩展这个项目。除了从设备读取之外,我们还可以通过 UART 向设备写入。目前,我们只需将 AVR-IoT WG 的电源和接地连接到 BPM,并将 BPM 的 Tx 连接到 AVR-IoT WG 的 Rx。AVR-IoT WG 和 BPM 开/关按钮之间还需要一个连接。我们需要它,因为一旦我们为 BPM 供电,它就会进入设置模式。因此,我们需要退出该模式,然后打开设备以开始测量过程。

软件 - Arduino IDE

poYBAGNrpyGAA5_GAAEH-ukblM4196.png
 

首先; 我们需要按照此处列出的步骤在 Arduino IDE 中安装开发板我们还需要为 CryptoAuthentication、Wi-Fi 和温度传感器安装三个库。

 
 
 
pYYBAGNrpySAGiiIAAB1Y1gbDmQ479.jpg
 
1 / 3
 

需要在 Arduino IDE 之外进行的唯一修改是在 C:\Users\\Documents\Arduino\libraries\ArduinoECCX08\src\ECCX08.cpp 中,因为该文件使用 0x60 作为 I2C 地址。我们上面得到的 CryptoAuthentication 的 I2C 地址是 0x58。因此,我们需要改变:

ECCX08Class ECCX08(Wire, 0x60);

ECCX08Class ECCX08(Wire, 0x58);

这里需要注意的一点是 MPLAB X IDE 中的 I2C 地址是 7 位左对齐 (0xB0),因此我们不能在不先右移(除以 2)的情况下使用它。

pYYBAGNrpyiAEZLnAAMQMIi0PIs101.png
 

请注意,我们在 C:\Users\\AppData\Local\Arduino15\packages\MegaCoreX\hardware\megaavr\1.0.6\variants\32pin-standard\pins_arduino.h 中使用了引脚号

软件 - PlatformIO(可选)

相同的 Arduino 代码适用于 PlatformIO。文件 platformio.ini 应包括以下内容:

[env:avr_iot_wg]
platform = atmelmegaavr
board = avr_iot_wg
framework = arduino
build_flags = -DARDUINO_AVR_ATmega4808
upload_protocol = pkobn_updi
lib_deps =
arduino-libraries/WiFi101@^0.16.1
adafruit/Adafruit MCP9808 Library@^2.0.0
arduino-libraries/ArduinoECCX08@1.3.5

请注意,一旦 PlatformIO 为我们安装了库,我们必须更新 I2C,如上所示

软件 - Apps 脚本

当您与医生预约时,他们会要求您提前 15 分钟到场,以填写三份与您在网上注册时提供的相同信息的文件。也就是说,你在没人会看的纸上写下你的姓名、地址、电话号码和社会安全号码三遍。如果你在走进之前没有高血压,现在你有。

不过说真的,期望具有这种技术意识水平的人直接从纸张过渡到云端是不现实的。我们使用了与上一个项目相同的 Google Sheets 和 Apps 脚本我们添加了 doPost 函数来处理 AVR-IoT WG 发出的 POST 请求。

结论

我们可能无法像 Dwight Schrute 声称的那样使用 BPM 作为测谎仪。尽管如此,我们还是能够使用 AVR-IoT WG 通过简单且安全的流程将 BPM 读数发送到 Google 表格。

患者可以在就诊前几天或几周内使用该设备。当更换药物对血压至关重要时,也可以使用它。我们在这里要提到的最后一个用例是在流行病学调查中的使用,例如强调环境温度对血压读数的影响的案例。

演示

全面披露:Hackster 好心只给了我一台 AVR-IoT WG 设备。我必须在数据库中再创建 6 个读数来模拟来自多个设备的条目。在每一行的末尾,我根据我对下面图表的解释添加了一种颜色。

poYBAGNrpzCAfkzFAACpI39j2Ew429.png
 

前几行来自上一个项目,并保留在这里以供比较。我们几乎听不见声音,但只要 BPM 读完,数据就会立即显示在 Google 表格中。

 

 


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'直接在Google表格中的血压监测仪',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);