Arduino 血氧心率模块传感器数据采集

Arduino 血氧心率模块传感器数据采集,第1张

Arduino-185-windowsexe、HXDZ-30102-ACC

集成了LIS2DH12(ST的三轴加速传感器,用于记录运动数据)和MAX30102(血氧和心率检测记录)。

电路板尺寸:3816mm

电路板厚度:25mm

LED峰值波长:660nm/880nm

LED供电电压:33v~5v

检测信号类型:光反射信号(PPG)

输出信号接口:I 2 C接口(数字接口)

通信接口电压:3~5v

工作电路:15mA(33v 输入)

心率精确度:+/- 5bpm,+/- 10bpm(动态)

分辨率: 1bpm

采样率:100Hz(STM32程序)/ 25Hz(arduino程序)

VCC:LED电源输入端,也是I 2 C总线上拉电平,可以接33v或者5v

GND:地线

SCL:I 2 C总线的时钟引脚

SDA:I 2 C总线的数据引脚

I_L:LIS2DH12芯片的中断引脚

I_M:MAX30102芯片的中断引脚

传统的脉搏测量方法主要有三种:

1、从心电信号中提取

2、从测量血压时压力传感器测到的波动来计算脉率

3、光电容积法

前两种会限制病人的活动,长时间使用会加重病患的心理和生理负担,而光电容积法在实际中时普遍使用的一种有效方法,其特点:方法简单、佩戴方便、可靠性高。

光电容积法基本原理:

利用人体组织在血管搏动时造成透光率不同来进行脉搏和血氧饱和度测量的。其使用的传感器由光源和光电变换器两部分组成,通过绑带或夹子固定在病患的手指、手腕或耳垂上。光源一般采用对动脉血中氧合血红蛋白(Hb0 2 )和血红蛋白(Hb)有选择性的特定波长的发光二极管(一般使用660nm附近的红光和900nm附近的红外光)。当光束透过人体外周血管,由于动脉搏动充血容积变化导致这束光的透光率发生改变,此时由光电变换器接收经人体组织反射的光线,转变为电信号并将其放大和输出。

由于脉搏是随心脏的搏动而周期性变化的信号,动脉血管容积也周期性变化,因此光电变换器的电信号变化周期就是脉搏率。同时根据血氧饱和度的定义,其表示为:

注意:

1、SaO 2 :广义上的氧饱和度,常指血液样品中的氧含量对该样品血液最大氧含量的百分比(SpO2是经皮血氧饱和度, 而SaO2是动脉血氧饱和度,二者不同,但是相关性好,绝对值十分接近)。

2、HbO 2 :氧合血红蛋白

3、Hb:还原血红蛋白

MAX30102本身集成了完整的发光LED及其驱动部分,光感应和AD转换部分,环境光干扰消除及数字滤波部分,只将数字接口留给用户,极大地减轻了用户的设计负担。用户只需要使用单片机通过硬件I 2 C或者模拟I 2 C接口来读取MAX30102本身的FIFO,就可以得到转换后的光强度数值,通过编写相应的算法就可以得到心率值和血氧饱和度。

心率和血氧饱和度算法流程图:

首先连接开发板串口,波特率需要进行必要设置,奇偶校验位无,上电后,复位MAX30102,并开始对MAX30102进行功能初始化,此时Red LED和 IR LED交替点亮来检测人体皮肤下血液的搏动和血氧含量(此时可以看到MAX30102有红光亮起,说明初始化成功)。开发板将一段时间内MAX30102采集的LED反射数据存储在内部RAM中,然后分别计算Red LED和 IR LED的直流成分(DC)和交流成分(AC),最后算出数值R并通过预先存储在两波峰之间的时间差T来确定,每分钟心跳数BPM=60/T。(具体算法原理可以参考AN6409芯片手册中29~31页说明)

red和ir是红色LED,红外LED的原始数据,HR表示心率值,HRvalid是心率是否有效标识,SPO2是血氧数值,SPO2valid是血氧首付有效标识

血氧模块与Arduino连接说明:

接口连接说明:

实际连接图:

原理图管脚说明:

初始化:

无采集状态:

数据采集状态:

ps:这里由于整体软件和硬件的标准没有像医疗设备的标准一样,所以只是验证性测试。

新建一个工程

打开keil uVision5,并新建一个工程

建立一个名为Test的工程

2

新建一个s文件 (1) 工程创建完毕后,对Source Group文件点击右键再点击ADD new item to group (2) 选择文件类型,添加文件 (3)

3

编译 点击左上角编译按钮,开始编译程序,此时0错误,0警告,表示编译成功。

4

stm32程序仿真调试 (一)调试设置 1点击魔法棒设置output一栏,选择

查看更多

     假设您使用无线串口控制小车,那么你需要设计一个串口指令协议,一般来说,通信协议的数据帧包括3部分,一是指令头,又叫做帧同步字;二是指令内容,也叫帧内容;三是校验码。

     同步字是为了便于程序分析连续传输的数据中,帧与帧之间的间隔,帧内容包含了所有经过16进制编码的各种控制指令和数据,校验码通常采用累加和与异或算法,为了计算本数据帧是否正确。(工业环境中,所有数据传输系统都存在一定的误码干扰,校验字能有效判别数据传输是否正确,进而通过错误处理机制,有效避免错误动作)。

     刚好前段时间写了个小车的控制程序,使用的是双路H桥来驱动电机的,不过不是控制履带式的,稍微改动了下。

  (注意,本程序仅适用于履带式小车,即左右电机正反转实现前后及转向,程序支持前后左右混控)

//

// 遥控帧协议和结构

// FB|80|51|AA|FF|BB|FF|BY|BY|BY|BY|BY|BY|CR

// 00|01|02|03|04|05|06|07|08|09|10|11|12|13

// 14 byte

//FB 80 51 遥控帧同步字                 00-02

//AA 前后控制量 128为中立位             03

//FF 恒定为0xFF                         04

//BB 左右控制量 128为中立位             05

//FF 恒定为0xFF                         06

//BY 备用控制指令 本程序为空            07-12

//CR 校验码,从00至12字节逐字节位异或   13

//

// 遥测帧协议结构

// FB|80|61|AA|FF|BB|FF|BY|BY|BY|BY|BY|BY|CR

// 00|01|02|03|04|05|06|07|08|09|10|11|12|13

// 14 byte

// 重复遥控指令,除帧头外,其定义与遥控指令相同

#define BR 9600       //定义串口波特率

//遥控指令接收处理相关定义

#define TCDL 14       //定义遥控数据帧长度字节数

#define BUFF_LONG 30  //定义串口接收缓存的长度

byte BUFF[BUFF_LONG]; //定义串口数据接收存储缓存

int BUFF_IDX = 0;     //定义串口数据接收存储缓存的指针

//遥测指令发送处理相关定义

#define TMFQ 80         //定义遥测数据帧发送间隔为80ms

#define TMDL 14         //定义遥测数据帧长度字节数

byte TM_Data[TMDL];     //定义遥测数据缓存

int TM_Index = 0;       //定义遥测数据指针

unsigned long Time = 0; //定义遥测发送计时器为0

//定义左、右电机与Arduino的驱动信号接口

//注意,这里用了4个PWM输出,部分Arduino板可能不支持,请查看手册

int Moto_Right_A = 3;

int Moto_Right_B = 5;

int Moto_Left_A = 6;

int Moto_Left_B = 9;

//数据接收指示灯相关定义

boolean IS_Blink = false;     //定义是否闪烁LED灯的变量

int LED = 13;         //定义LED灯接口为13

//指令变量定义

byte RunPWM = 128;   //定义前进、后退控制PWM指令变量

byte TurnPWM = 128;  //定义左转、右转控制PWM指令变量

void setup()

{

pinMode(Moto_Right_A, OUTPUT); //定义输出

pinMode(Moto_Right_B, OUTPUT); //定义输出

pinMode(Moto_Left_A, OUTPUT); //定义输出

pinMode(Moto_Left_B, OUTPUT); //定义输出

pinMode(LED, OUTPUT); //定义LED管脚为数字输出

Port_Init();  //初始化串口

Blink_LED(false); //关闭指示灯

}

void loop()

{

byte c;

if (Serialavailable() > 0)  //如果接收到串口数据

{

  c = Serialread();   //读一个字节

  Buff_AddChar(c);     //塞进缓存进行存储、校验和解码

}

TM_Freq();             //尝试按要求逐字节发送遥测数据

Driver_CAR(RunPWM, TurnPWM); //驱动左右电机正反转,实现运动控制

}

//驱动左右电机调速运行,实现左右正反转组合,实现控制

//前后、左右混控

void Driver_CAR(byte Run, byte Turn)

{

byte Run_L, Run_R;  //定义左右前进混合值

byte PWM_R_A, PWM_R_B, PWM_L_A, PWM_L_B; // 定义4个信号的独立PWM

Run_L = Run - (128 - Turn);  //将转向PWM混合到左路

Run_R = Run - (Turn - 128);  //将转向PWM混合到右路

PWM_L_A = (255 / 128) Run_L - 255;         //左路混合值结算为左路A信号PWM

PWM_L_B = (-1 255 / 128) Run_L + 255;    //左路混合值结算为左路B信号PWM

PWM_R_A = (255 / 128) Run_R - 255;         //右路混合值结算为右路A信号PWM

PWM_R_B = (-1 255 / 128) Run_R + 255;    //右路混合值结算为右路B信号PWM

analogWrite(Moto_Right_A, PWM_R_A);    //输出右路A信号

analogWrite(Moto_Right_B, PWM_R_B);    //输出右路B信号

analogWrite(Moto_Left_A, PWM_L_A);     //输出左路A信号

analogWrite(Moto_Left_B, PWM_L_B);     //输出左路B信号

}

//

//子程序 Port_Init()

//功能:初始化串口通信

void Port_Init()

{

BUFF_IDX = 0;  //初始化串口缓存指针为0

TM_Data[0] = 0xFB;  //初始化遥测数据帧头

TM_Data[1] = 0x80;  //初始化遥测数据帧头

TM_Data[2] = 0x61;  //初始化遥测数据帧头

Serialbegin(BR);  //定义波特率并启动串口

}

//

// 子程序 Buff_AddChar(byte b)

// 功能:串口接收字节加入缓存

// 1、加入字节到缓存;

// 2、检测到帧头则尝试检测遥控帧;

// 3、管理缓存指针

void Buff_AddChar(byte b)

{

BUFF[BUFF_IDX] = b;  //  缓存[缓存指针] = 接收字节

if (BUFF_IDX >= 2)

{

  if (BUFF[BUFF_IDX] == 0x51 && BUFF[BUFF_IDX - 1] == 0x80 && BUFF[BUFF_IDX - 2] == 0xFB) //  检测遥控帧头

  {

    if (BUFF_IDX == (TCDL - 1))

    {

      Buff_DCHK();  //  检测校验码

    }

    BUFF_IDX = 0;  //  缓存指针归零

    return;

  }

}

BUFF_IDX++;

if (BUFF_IDX > (BUFF_LONG - 1)) //  缓存指针越界

{

  BUFF_IDX = 0;  //  缓存指针归零

}

}

//

//子程序 Buff_DCHK()

//功能:校验遥控帧校验字是否正确

void Buff_DCHK()

{

byte DCHK = 0x00;

// 0xFB XOR 0x80 XOR 0x51

DCHK = BUFF[0];

DCHK = DCHK ^ BUFF[1];

DCHK = DCHK ^ BUFF[2];

int i;

for (i = 0; i < (TCDL - 4); i++)

{

  DCHK = DCHK ^ BUFF[i];

}

if (DCHK == BUFF[TCDL - 4])

{

  //校验字正确

  Blink_LED(true); //闪烁LED

  Get_CMD();       //解码指令

}

}

//

// 子程序 Get_CMD()

// 功能:解码遥控指令

void Get_CMD()

{

RunPWM = BUFF[0];

TurnPWM = BUFF[2];

//后面可以自己添加关于BY指令的解码处理

}

//

//子程序 TM_Freq()

//功能:遥测数据发送帧率控制

void TM_Freq()

{

unsigned long t;

if (TM_Index < TMDL) //如果一帧数据还没有发完

{

  Serialwrite(TM_Data[TM_Index]); //继续发数据

  TM_Index++;  //指针累加

}

else  //如果发完

{

  if (Time == 0)  //检测计时器是否为0

  {

    Time = millis(); //是则赋予计时器初始值

  }

  else  //不是

  {

    t = millis();

    if (t - Time >= TMFQ) //检测计时器是否到达帧率控制的时间

    {

      Time = t;

      TM_Make_Data();    //到达发送时间,则组一帧遥测数据,并开始发送

    }

  }

}

}

//

// 子程序 TM_Make_Data()

// 功能:发送遥测数据

void TM_Make_Data()

{

// 遥测帧协议结构

//FB|80|61|AA|FF|BB|FF|BY|BY|BY|BY|BY|BY|CR

//00|01|02|03|04|05|06|07|08|09|10|11|12|13

byte CHK = 0xFB;  //赋值帧头

CHK = CHK ^ 0x80; //赋值帧头

CHK = CHK ^ 0x61; //赋值帧头

TM_Data[3] = RunPWM;    //回写前后指令

TM_Data[4] = 0xFF;

CHK = CHK ^ TM_Data[3]; //计算校验码

CHK = CHK ^ TM_Data[4]; //计算校验码

TM_Data[5] = TurnPWM;   //回写转向指令

TM_Data[6] = 0xFF;

CHK = CHK ^ TM_Data[5]; //计算校验码

CHK = CHK ^ TM_Data[6]; //计算校验码

CHK = CHK ^ TM_Data[7]; //计算校验码

CHK = CHK ^ TM_Data[8]; //计算校验码

CHK = CHK ^ TM_Data[9]; //计算校验码

CHK = CHK ^ TM_Data[10]; //计算校验码

CHK = CHK ^ TM_Data[11]; //计算校验码

CHK = CHK ^ TM_Data[12]; //计算校验码

TM_Data[13] = CHK; //计算校验码

TM_Index = 0; //清除遥测发送指针位置

}

//

//子程序 Blink_LED()

//功能:闪烁内置LED灯

void Blink_LED(boolean Blink)

{

if (Blink == false)

{

  IS_Blink = false;

}

else

{

  IS_Blink = !IS_Blink;

}

digitalWrite(LED, IS_Blink);

}

以上就是关于Arduino 血氧心率模块传感器数据采集全部的内容,包括:Arduino 血氧心率模块传感器数据采集、stm32写arduino程序怎么调试、哪位大神能帮我写一个arduino 控制两个直流电机正反转,加减速和拐弯的程序啊arduino程序,非常感谢。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/9740298.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存