收藏官网首页
查看: 3735|回复: 14

【Arduino】+智能健康计

4

主题

60

帖子

621

积分

版主

Rank: 7Rank: 7Rank: 7

积分
621
发表于 2016-7-19 10:29:54 | 显示全部楼层 |阅读模式
ESP8266模块首单6.8元
本帖最后由 林林 于 2016-8-25 18:04 编辑

【开源硬件】机智云智能硬件创新大赛  http://club.gizwits.com/thread-2646-1-1.html

一、作品说明及使用场景
        目前国内的老年化问题越来越突出,老年人的健康问题已经不容小视,如何借助快速发展的科技水平来解决老年人的看病难的问题,这在国内得到了广泛的关注和讨论。在这样的背景下智慧医疗的出现,希望能够为医疗行业的发展带来一次变革。何谓智能医疗?它是通过打造健康档案区域医疗信息平台,利用最先进的物联网技术,实现患者与医务人员、医疗机构、医疗设备之间的互动,逐步达到信息化。在不久的将来医疗行业将融入更多人工智慧、传感技术等高科技,使医疗服务走向真正意义的智能化,推动医疗事业的繁荣发展。
随着智能硬件的发展,将极大的降低开发者的开发流程和开发门槛,届时任何人都能够DIY 出自己的作品。我的创意就是来自于中老年人一方面对于自身健康的重视,另一方面就是就医的难度增大(需要坐车去医院、排队挂号等等十分繁琐)。我想借助云服务的平台和DIY硬件打造一个集方便、快捷的本地检测、本地显示、云端查看等方式来将为中老年人的健康提供保障。让他们足不出户也能够实时的检测自己的心率、体重等数据,数据同时上传到医院患者的电子病历(假设)和子女的手机端显示,以及历史查询等功能。以期帮助中老年人打造健康的生活环境。

二、作品所使用的BOM清单以及硬件部分
         硬件清单:
         两块arduino开发板;
        一块gokit的扩展板;
        一个心率脉搏传感器;
        一个4针的OLED显示模块;
        一个轻触式按键开关;
        开发板的供电线两根;
        面包板一块;
        杜邦线若干。
        

BOM清单

BOM清单

        工作原理光电容积法的基本原理是利用人体组织在血管搏动时造成透光率不同来进行脉搏测量的。其使用的传感器由光源和光电变换器两部分组成,通过绑带或夹子固定在病人的手指或耳垂上。光源一般采用对动脉血中氧和血红蛋白有选择性的一定波长(500nm~700nm)的发光二极管。当光束透过人体外周血管,由于动脉搏动充血容积变化导致这束光的透光率发生改变,此时由光电变换器接收经人体组织反射的光线,转变为电信号并将其放大和输出。由于脉搏是随心脏的搏动而周期性变化的信号,动脉血管容积也周期性变化,因此光电变换器的电信号变化周期就是脉搏率。
       这里先连接上实物电路:gokit中下载好源码Pulse_arduino进行连接,这里选择的是arduino作为底板,然后将预留的A1引脚作为心率脉搏传感器的连接口:
Pulse Sensor——>A1;

本地显示模块的连接,将Menulib源码下载到另一块的arduino中,将4针IICD的OLED显示模块按照以下方式连接:
IIC  OLED:     VCC ­——VCC             Arduino
GND ——GND
SCL ——SCL
SDA ——SDA
Pulse Sensor S-pin——>A0;
                                                                                                                                                                                                                                                     之所以用到两块arduino是因为源码占用了很大一部分的内存,这里就将他们分开来执行相应的功能。在Pulse_arduino.zip\Pulse_arduino\libraries\GizWits\GizWits.h中修改下我们的pk(这里是我们的Pk                                                                      号:7fc4e47382514c518c44e4fc36f4fcd3,欢迎测试),然后将源码下载成功之后,长按key2进入AirLink模式,RGB灯绿色,进入到对应的配置步骤中,配置过程参照机智云的官网介绍,这里不必累述。
        这里是我设定的三个数据点,它分别用来测量测试者周围的温湿度和使用者的心率(及脉搏,这里没有列出,它是可以测量脉搏的,后续大家可以添加试试,我自己还增加了称重模块、人体温度,这里不一一上传)。

数据点描述

数据点描述
这里是显示模块的连接,连线之间略显有点乱,所以呢小伙伴呢要重点注意布线,当然小伙伴也可以向我一样散漫些昂:

Gokit连线

Gokit连线

显示模块

显示模块

       连线完成后我满简单的介绍下,这里我的显示模块有一个小小的菜单功能,为了实现这个功能占用了对于arduino来说自身很大的内存,这点我是比较心疼的,但是丝毫呢不影响它的处理。绿色的这个就是我们简单的心率脉搏传感器,我们将其固定在面包板上,这里原本我是打算做一个精巧的包装给它打扮一下,结果未能够使实现,动手能力强或者有一定基础的可以自己打印一个美美的外壳。因为考虑到它的输出端要供给两块板子,所以需要在面包板上跳线接到两块板子上。完成上述之后会发现如来它是如此简单,因此它也将会是非常时候自己DIY使用的。

       给设备上电完成完成系统的初始化,可将中指或者食指轻放到Pulse Sensor 白色的心型部分,然后我们就可以通过本地模块以及手机端的APP进行测量者自身的心率等情况以及结合周围的环境温度给病人制定一个合理的解决方案。
APP端实时显示界面:

系统初始化前 APP段查看1.png
数据上传之后数据实时的显示 APP段查看2.png


本地显示:
系统初始化:

设备上电显示菜单

设备上电显示菜单
按下按键之后接入到测量界面:

测量界面1

测量界面1
实时的测量中:

测量中

测量中

三、代码分析以及功能分析
   Pulse_arduino.zip\Pulse_arduino\libraries\GizWits\GizWits.h中修改下我们的pk,这里可以使用我的PK号:7fc4e47382514c518c44e4fc36f4fcd3。这里重点的要说明下这部分的代码,其他的都是基于宠物屋的arduino版本进行修改的,不需要进行太多的说明。
       这里是利用定时器每2ms产生一个中断信号,然后来检测Pulse Sensor传感器的数据引脚输出的电信号,按照光电容积的原理算法处理后得到人体的心率,并将其通过串口打印或者显示模块等方式来将数据信息显示出来。
       interruptSetup()是使用arduino的定时器1,我发现宠物屋的源码中,定时器2已经被使用了,这时我们就需要其他定时器来做定时中断处理(arduino  UNO内部有3个定时器,time0不可被使用)。配置完定时器之后,我们需要在ISR( )函数接口中说明我们使用到了哪一个接口,这里在附录中列一些定时器1、2的地址和对应的ISR(   )入口:

复制代码
  1. /*******************************************************************************
  2. * Function Name  : interruptSetup
  3. * Description    : Set Time1
  4. * Input          : None
  5. * Output         : None
  6. * Return         : None
  7. * Attention     :
  8. *******************************************************************************/
  9. void interruptSetup(){     
  10.         // Initializes Timer1 to throw an interrupt every 2mS.
  11.         TCCR1A = 0x00; // DISABLE OUTPUTS AND PWM ON DIGITAL PINS 9 & 10
  12.         TCCR1B = 0x11; // GO INTO 'PHASE AND FREQUENCY CORRECT' MODE, NO PRESCALER
  13.         TCCR1C = 0x00; // DON'T FORCE COMPARE
  14.         TIMSK1 = 0x01; // ENABLE OVERFLOW INTERRUPT (TOIE1)
  15.         ICR1 = 16000;  // TRIGGER TIMER INTERRUPT EVERY 2mS  
  16.         sei();         // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED   
  17. }

  18. /*******************************************************************************
  19. * Function Name  : ISR(TIMER1_COMPA_vect)
  20. * Description    : Callback function , Judge Wifi statue
  21. * Input          : None
  22. * Output         : None
  23. * Return         : None
  24. * Attention     :
  25. *******************************************************************************/
  26. ISR(TIMER1_OVF_vect){                         // triggered when Timer2 counts to 124
  27.   cli();                                      // disable interrupts while we do this
  28.   Signal = analogRead(pulsePin);              // read the Pulse Sensor
  29.   sampleCounter += 2;                         // keep track of the time in mS with this variable
  30.   int N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise

  31.     //  find the peak and trough of the pulse wave
  32.   if(Signal < thresh && N > (IBI/5)*3){       // avoid dichrotic noise by waiting 3/5 of last IBI
  33.     if (Signal < T){                        // T is the trough
  34.       T = Signal;                         // keep track of lowest point in pulse wave
  35.     }
  36.   }

  37.   if(Signal > thresh && Signal > P){          // thresh condition helps avoid noise
  38.     P = Signal;                             // P is the peak
  39.   }                                        // keep track of highest point in pulse wave

  40.   //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
  41.   // signal surges up in value every time there is a pulse
  42.   if (N > 250){                                   // avoid high frequency noise
  43.     if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){        
  44.       Pulse = true;                               // set the Pulse flag when we think there is a pulse
  45.       digitalWrite(blinkPin,HIGH);                // turn on pin 13 LED
  46.       IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
  47.       lastBeatTime = sampleCounter;               // keep track of time for next pulse

  48.       if(secondBeat){                        // if this is the second beat, if secondBeat == TRUE
  49.         secondBeat = false;                  // clear secondBeat flag
  50.         for(int i=0; i<=9; i++){             // seed the running total to get a realisitic BPM at startup
  51.           rate[i] = IBI;                     
  52.         }
  53.       }

  54.       if(firstBeat){                         // if it's the first time we found a beat, if firstBeat == TRUE
  55.         firstBeat = false;                   // clear firstBeat flag
  56.         secondBeat = true;                   // set the second beat flag
  57.         sei();                               // enable interrupts again
  58.         return;                              // IBI value is unreliable so discard it
  59.       }   


  60.       // keep a running total of the last 10 IBI values
  61.       word runningTotal = 0;                  // clear the runningTotal variable   

  62.       for(int i=0; i<=8; i++){                // shift data in the rate array
  63.         rate[i] = rate[i+1];                  // and drop the oldest IBI value
  64.         runningTotal += rate[i];              // add up the 9 oldest IBI values
  65.       }

  66.       rate[9] = IBI;                          // add the latest IBI to the rate array
  67.       runningTotal += rate[9];                // add the latest IBI to runningTotal
  68.       runningTotal /= 10;                     // average the last 10 IBI values
  69.       BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
  70.       QS = true;                              // set Quantified Self flag
  71.       // QS FLAG IS NOT CLEARED INSIDE THIS ISR
  72.     }                       
  73.   }

  74.   if (Signal < thresh && Pulse == true){   // when the values are going down, the beat is over
  75.     digitalWrite(blinkPin,LOW);            // turn off pin 13 LED
  76.     Pulse = false;                         // reset the Pulse flag so we can do it again
  77.     amp = P - T;                           // get amplitude of the pulse wave
  78.     thresh = amp/2 + T;                    // set thresh at 50% of the amplitude
  79.     P = thresh;                            // reset these for next time
  80.     T = thresh;
  81.   }

  82.   if (N > 2500){                           // if 2.5 seconds go by without a beat
  83.     thresh = 512;                          // set thresh default
  84.     P = 512;                               // set P default
  85.     T = 512;                               // set T default
  86.     lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date        
  87.     firstBeat = true;                      // set these to avoid noise
  88.     secondBeat = false;                    // when we get the heartbeat back
  89.   }

  90.   sei();                                   // enable interrupts when youre done!
  91. }// end isr
复制代码
  1. <b><font size="4">附录:</font></b>

  2. Timer2
  3.   
  4.     Pulse Sensor Arduino UNO uses Timer2 by default.
  5.     Use of Timer2 interferes with PWM on pins 3 and 11.
  6.     There is also a conflict with the Tone library, so if you want tones, use Timer1 below.
  7.    
  8.       void interruptSetup(){     
  9.         // Initializes Timer2 to throw an interrupt every 2mS.
  10.         TCCR2A = 0x02;     // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE
  11.         TCCR2B = 0x06;     // DON'T FORCE COMPARE, 256 PRESCALER
  12.         OCR2A = 0X7C;      // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE
  13.         TIMSK2 = 0x02;     // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A
  14.         sei();             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED      
  15.       }
  16.   
  17.     use the following interrupt vector with Timer2
  18.    
  19. <font color="#ff0000">      ISR(TIMER2_COMPA_vect)</font>
  20.       
  21. >> Timer1
  22.    
  23.     Use of Timer1 interferes with PWM on pins 9 and 10.
  24.     The Servo library also uses Timer1, so if you want servos, use Timer2 above.
  25.    
  26.       void interruptSetup(){     
  27.         // Initializes Timer1 to throw an interrupt every 2mS.
  28.         TCCR1A = 0x00; // DISABLE OUTPUTS AND PWM ON DIGITAL PINS 9 & 10
  29.         TCCR1B = 0x11; // GO INTO 'PHASE AND FREQUENCY CORRECT' MODE, NO PRESCALER
  30.         TCCR1C = 0x00; // DON'T FORCE COMPARE
  31.         TIMSK1 = 0x01; // ENABLE OVERFLOW INTERRUPT (TOIE1)
  32.         ICR1 = 16000;  // TRIGGER TIMER INTERRUPT EVERY 2mS  
  33.         sei();         // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED     
  34.       }
  35.       
  36.     Use the following ISR vector for the Timer1 setup above
  37.    
  38. <font color="#ff0000">      ISR(TIMER1_OVF_vect)</font>
复制代码
           除此之外细心的小伙伴还会发现在我的源码中还定义了一个int blinkPin = 13; 这个引脚可以接一个小灯,它会随着信号值的改变而随着改变,通过它你也能够直观的看到自己的心跳哦~
          最后附上本次的代码。这一个是基于Gokit2的心率测量和连接入网功能的源码: Pulse_arduino.zip (64.51 KB, 下载次数: 100)

21

主题

30

帖子

254

积分

中级会员

Rank: 3Rank: 3

积分
254
发表于 2016-7-19 10:45:58 | 显示全部楼层
楼主加油!期待楼主的新成果

26

主题

136

帖子

1600

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1600
发表于 2016-7-19 10:39:37 | 显示全部楼层
帅气的林林 感觉作品会很棒很实用

4

主题

60

帖子

621

积分

版主

Rank: 7Rank: 7Rank: 7

积分
621
 楼主| 发表于 2016-7-19 10:59:09 | 显示全部楼层
admin 发表于 2016-7-19 10:39
帅气的林林 感觉作品会很棒很实用

谢谢谢谢我会加油的

4

主题

60

帖子

621

积分

版主

Rank: 7Rank: 7Rank: 7

积分
621
 楼主| 发表于 2016-7-19 11:00:37 | 显示全部楼层
教您5分钟接入机智云,实现傻瓜式开发
jan 发表于 2016-7-19 10:45
楼主加油!期待楼主的新成果

谢谢支持,到时我尽力开源出来大家一起玩昂,这套东西加起来也不过几十块钱,极大的提高了开发效率同时极低的成本管理。

4

主题

60

帖子

621

积分

版主

Rank: 7Rank: 7Rank: 7

积分
621
 楼主| 发表于 2016-8-25 18:05:00 | 显示全部楼层
完成咯,虽然很Low,还是咬牙提交了

0

主题

1

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2016-8-25 22:39:38 | 显示全部楼层
看了一下,感觉还不错,期待可以上市

4

主题

60

帖子

621

积分

版主

Rank: 7Rank: 7Rank: 7

积分
621
 楼主| 发表于 2016-8-26 13:02:50 | 显示全部楼层
安安 发表于 2016-8-25 22:39
看了一下,感觉还不错,期待可以上市

距离市场还有很大的差距呢

45

主题

89

帖子

2074

积分

金牌会员

Rank: 6Rank: 6

积分
2074
发表于 2016-9-9 15:14:46 | 显示全部楼层
非常棒的Arduino项目

4

主题

60

帖子

621

积分

版主

Rank: 7Rank: 7Rank: 7

积分
621
 楼主| 发表于 2016-9-9 23:09:40 | 显示全部楼层
免费使用STM32、APP自动代码生成工具
true 发表于 2016-9-9 15:14
非常棒的Arduino项目

但是有个小小的不足,就是arduino的flash只有32k,本地显示再加原本的代码之后,容量远远的不够,考虑是否添加一个外部存储器来处理。另外考虑用bmd101来试试,换种测量当时可能会很好。谢谢你的评价。

0

主题

29

帖子

271

积分

中级会员

Rank: 3Rank: 3

积分
271
发表于 2016-10-1 21:24:38 | 显示全部楼层
也很想做一个医疗物联网方面的项目 加油

10

主题

99

帖子

1440

积分

金牌会员

Rank: 6Rank: 6

积分
1440
发表于 2016-11-26 00:18:55 | 显示全部楼层
arduino的项目啊,支持到底,arduino的项目太少了,感觉官方的案例也很少,谢谢楼主的分享

4

主题

60

帖子

621

积分

版主

Rank: 7Rank: 7Rank: 7

积分
621
 楼主| 发表于 2016-11-29 14:44:52 | 显示全部楼层
maomaodemao 发表于 2016-11-26 00:18
arduino的项目啊,支持到底,arduino的项目太少了,感觉官方的案例也很少,谢谢楼主的分享 ...

嘿嘿嘿,arduino的太简单了其实

0

主题

1

帖子

41

积分

新手上路

Rank: 1

积分
41
发表于 2017-1-25 19:30:04 | 显示全部楼层
厉害!学习了!

3

主题

8

帖子

177

积分

注册会员

Rank: 2

积分
177
发表于 2017-5-14 09:21:14 | 显示全部楼层
教您5分钟接入机智云,实现傻瓜式开发
您好大佬,我现在在做一个类似的项目,非常渴望得到您的帮助,由于我是小白,有很多不懂得地方,非常希望能够得到跟您讨教的机会!也不知道您的联系方式,只能麻烦您看到这个消息之后加一下我QQ了,249172993,若能得到您的帮助,定将感激不尽!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

© 2011-2017 Gizwits ( 粤ICP备11090211号 )

快速回复 返回顶部 返回列表