当我在键盘上打下第一个字时,连我自己都感到惊讶。这种东西我能做吗?但另一个声音在我耳畔悄悄的说,不试试怎么知道?也是,现在全球有十亿人缺乏医疗保健系统;每年有36000000人死于非传染性疾病造成的,如心血管疾病,癌症,糖尿病和慢性肺疾病;超过7500000个的5岁以下儿童死于营养不良和一些常见的可预防的疾病。每年死于肺结核的人数超过1700000。另外有1600000人死于肺炎球菌疾病,其中一半以上的受害者是儿童。疟疾每年造成780000多人死亡。33400000艾滋病毒感染者…
我们需要获得最基本的医疗保障,而不是仅仅依赖于医生或护士。
医学手持便携式检测仪是一种可以由患者进行自我诊断的医疗设备,只需要几秒钟便可以得出一些初步的诊断。该设备的主要功能包括:传感,计算和记录。
作为人类会有3个基本生命体征,即体温、脉搏和呼吸速率。我们将处理数据,并将记录数据在SD卡上。
这个医疗检测仪的使用不需要诸如互联网、智能手机或者电脑的辅助,因为有些需要使用它的地方可能并没有这些辅助设备。
一、直接诊断疾病:
有些疾病是可以通过以上三项基本生命特征直接进行诊断的。
体温 | 心率 | 呼吸速率 | |
直接诊断 | 低温 | 心动过缓 | 呼吸过缓 |
发烧(低烧,高烧) | 心动过速 |
呼吸急促 |
- 核心体温诊断的判断标准
类型 | 核心体温(摄氏度) |
低温 | <35 |
正常 | 36.5~37.5 |
发烧 | >38.3 |
高烧 | >40 |
很高烧 | >41.5 |
- 不同年龄段的心率标准:
年龄 | 心率(bpm) |
0-1个月 | 70-190 |
1-11个月 | 80-160 |
1-2岁 | 80-130 |
3-4岁 | 80-120 |
5-6岁 | 75-115 |
7-9岁 | 70-110 |
大于10岁 | 60-100(对于专业运动员:40-60) |
- 不同年龄段的呼吸速率标准:
年龄 | 呼吸速率(bpm) |
0-2个月 | 25-60 |
3-5个月 | 25-55 |
6-11个月 | 25-55 |
1岁 | 20-40 |
2-3岁 | 20-40 |
4-5岁 | 20-40 |
6-7岁 | 16-34 |
8-9岁 | 16-34 |
10-11岁 | 16-34 |
12-13岁 | 14-26 |
14-16岁 | 14-26 |
大于17岁 | 14-26 |
二、朴素贝叶斯分类器:
以下高能,慎入。若不想看可直接略过此章节。
朴素贝叶斯分类器经常在自动医学诊断中的应用。这里有很多关于朴素贝叶斯分类的教程,所以我把它放在这里。当然能不想了解的话可以跳过。
三、普通感冒和流感的分类:
贝叶斯定律:h:假设
d:数据
P(h):基于数据d的假设h的概率
P(h/d):假设h成立的概率
数据可以通过以下公式得到:
一般来说,我们希望得到最有可能的假设数据,通过以下公式得到:
H:假设集合
当然,我们可以简化这个公式为:
如果我们的数据有几个属性,那可以用ï朴素贝叶斯假设。属性描述数据可以有条件独立分类:
一般按年龄来分每个人每年会感冒3-15次。平均一年9次。总的算来,大约每年会有5000000人得感冒。以下公式可以计算得到:
这个该概率的公式,我们也可以通过查表得到相关的概率:
概率 | 流感 | 普通感冒 |
P(h) | 0.00008 | 0.99992 |
P(疲劳|h) | 0.8 | 0.225 |
P(发烧|h) | 0.9 | 0.005 |
P(寒战|h) | 0.9 | 0.1 |
P(喉咙痛|h) | 0.55 | 0.5 |
P(咳嗽|h) | 0.9 | 0.4 |
P(头痛|h) | 0.85 | 0.25 |
P(肌肉痛|h) | 0.675 | 0.1 |
P(打喷嚏|h) | 0.25 | 0.9 |
因此:
没有感冒的概率:
取对数,得到:
所以可以 计算出相关的概率:
相关的程序以出来了:
void setup() {
Serial.begin(9600);
}
void loop() {
flu_cold_classifier();
}
void diagnosis(boolean fatigue, boolean fever, boolean chills, boolean sore_throat, boolean cough, boolean headache, boolean muscle_pain, boolean sneezing) {
// probability-look-up table
float Prob[] = {0.00008, 0.99992};
float P_fatigue[] = {0.8, 0.225};
float P_fever[] = {0.9, 0.005};
float P_chills[] = {0.9, 0.1};
float P_sore_throat[] = {0.55, 0.5};
float P_cough[] = {0.9, 0.4};
float P_headache[] = {0.85, 0.25};
float P_muscle_pain[] = {0.675, 0.1};
float P_sneezing[] = {0.25, 0.9};
// P(¬A) = 1 – P(A)
for(byte i = 0; i < 2; i ++) {
if(fatigue == false) P_fatigue[i] = 1.0 – P_fatigue[i];
if(fever == false) P_fever[i] = 1.0 – P_fever[i];
if(chills == false) P_chills[i] = 1.0 – P_chills[i];
if(sore_throat == false) P_sore_throat[i] = 1.0 – P_sore_throat[i];
if(cough == false) P_cough[i] = 1.0 – P_cough[i];
if(headache == false) P_headache[i] = 1.0 – P_headache[i];
if(muscle_pain == false) P_muscle_pain[i] = 1.0 – P_muscle_pain[i];
if(sneezing == false) P_sneezing[i] = 1.0 – P_sneezing[i];
}
// computing arg max
float P_flu = log(Prob[0]) + log(P_fatigue[0]) + log(P_fever[0]) + log(P_chills[0]) +
log(P_sore_throat[0]) + log(P_cough[0]) + log(P_headache[0])+ log(P_muscle_pain[0]) +
log(P_sneezing[0]);
float P_cold = log(Prob[1]) + log(P_fatigue[1]) + log(P_fever[1]) + log(P_chills[1]) +
log(P_sore_throat[1]) + log(P_cough[1]) + log(P_headache[1])+ log(P_muscle_pain[1]) +
log(P_sneezing[1]);
/* If we want to know the exact probability we can normalize these values by computing base-e exponential1s and having them sum to 1: */
float P_flu_percentage = (exp(P_flu) / (exp(P_flu) + exp(P_cold))) * 100.0;
float P_cold_percentage = (exp(P_cold) / (exp(P_flu) + exp(P_cold))) * 100.0;
if(P_flu > P_cold) {
Serial.print(“Diagnosis: Flu (Confidence: “);
Serial.print(P_flu_percentage);
Serial.println(“%)”);
}
if(P_cold > P_flu) {
Serial.print(“Diagnosis: Common cold (Confidence: “);
Serial.print(P_cold_percentage);
Serial.println(“%)”);
}
Serial.println(“”);
}
void flu_cold_classifier() {
Serial.println(“If you have flu/cold like symptoms, answer following questions”);
Serial.println(“Enter ‘y’ for ‘yes’ and ‘n’ for ‘no'”);
Serial.println(“”);
char *symptoms[] ={“Fatigue?”, “Fever?”, “Chills?”, “Sore throat?”, “Cough?”, “Headache?”, “Muscle pain?”, “Sneezing?”};
boolean answ[8];
for(byte i = 0; i < 8; i ++) {
Serial.println(symptoms[i]);
while(1) {
char ch;
if(Serial.available()){
delay(100);
while( Serial.available()) {
ch = Serial.read();
}
if(ch == ‘y’) {
Serial.println(“Your answer: yes”);
Serial.println(“”);
answ[i] = true;
break;
}
if(ch == ‘n’) {
Serial.println(“Your answer: no”);
Serial.println(“”);
answ[i] = false;
break;
}
}
}
}
diagnosis(answ[0], answ[1], answ[2], answ[3], answ[4], answ[5], answ[6], answ[7]);
}
四、体温检测:
通常我们在发烧的时候会通过额头来检测体温。所以会有很多红外感应的非接触体温计。然后额头温度往往和人体的核心体温又所不同。所以通过接触式的体温计会比较准。
所以,核心温度一般我们会通过以下公式得到:
q=每单位换热的时间
h=对流换热系数
A=皮肤的传热面积
TS=皮肤温度
TA=环境温度
这个转换公式我们也能这样表示:
w=血流量
c=血容量
TC=人体核心温度
通过公式一和公式二能得到:
通过一系列变换,我们最后得到公式:
身体核心温度将由一个非接触式温度测量的红外温度计MLX90614监测。
相关原理图:
五、心跳监测
心跳监测使用的原理框图。
耳垂脉搏传感器hrm-2511b是从kyto电子购买。R1和R2偏置LED和红外耳叶传感器,通过3.5mm的手机连接器连接到光电晶体管。安全电阻R6和二极管D1和D2构成了一个参考电压发生器。参考电压的二极管的正向电压的两倍(约0.7 V的硅二极管)连接到GND。C6和C8 / R10 R9/R7构成一阶高通滤波器(HPF)。给出了截止频率
使用低通滤波器之后截止频率为:
运算放大器级输出的模拟信号传递到Arduino模拟引脚进行进一步处理,去除高频噪声阈值电压。噪声低于阈值是不容忽视的,通过反馈输出锁存器状态直到对方超过阈值。比较器的输出通过一个LED显示的心跳和Arduino数字引脚。
关于心跳得算法有一个叫做Poincare plot ,我们可以使用这个算法。
在一般情况下,可以测量两个心跳之间的时间确定心跳。庞加莱曲线的形状可用于可视化的心率变异(HRV)。在本文中,庞加莱图能显示健康人和病人的不同。
主要算法:
for(byte i = 1; i < sample_size – 1; i ++) {
unsigned int delta_x = time[i + 1] – time[i];
unsigned int delta_y = time[i + 2] – time[i + 1]; // compute measurement as a function of previous one
unsigned int pixel_x = map(delta_x, 0, 2000, 0, 63); // map elapsed time in ms into pixel x coordinate
unsigned int pixel_y = map(delta_y, 0, 2000, 63, 0); // map elapsed time in ms into pixel y coordinate
display.drawPixel(pixel_x, pixel_y, WHITE); // print pixel
display.display();
}
六、呼吸速率检测
基本的设备包括一次性防护口罩-半面罩,三维打印的连接接头,一块硅胶管和压力传感器MPXV4006GP。这种设置的优点是,在活动时,也能对呼出气体的呼吸速率通过气体传感器进行分析。下面的效果图说明
以下是3D打印接的实物:
成品是这样的:
呼气时产生的压力是很小的,所以需要将放大器的信号进性放大,原理图:
相关代码:
unsigned long resp_delta[2];
unsigned int resp_counter = 0;
byte led = 13;
byte resp_sense = A0;
void setup() {
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop() {
boolean resp_state = 0;
if(analogRead(resp_sense) > 650) {
resp_state = 1;
while(analogRead(resp_sense) > 630) {
digitalWrite(led, HIGH);
delay(300);
}
}
if(resp_state == 1) {
resp_counter ++;
if(resp_counter == 1) {
resp_delta[0] = millis();
}
if(resp_counter == 11) {
resp_delta[1] = millis();
unsigned int respiratory_rate = 600000 / (resp_delta[1] – resp_delta[0]);
Serial.print(“Respiratory rate: “);
Serial.print(respiratory_rate);
Serial.println(” bpm”);
resp_counter = 0;
}
resp_state = 0;
}
digitalWrite(led, LOW);
}
七、用户接口设置:
用户界面有5个按键,一个OLED。
使用一个HEF4050芯片做SD卡的接口:
DS1307 芯片是一个RTC芯片:
还有一个蜂鸣器:
八、硬件设计:
下面是硬件图和实物图:
九、一些辅助工作:
下面是结构设计
以上是所有的设计。
優態客(Yourtechnic)的博客:www.yourechnic.com
優態客(Yourtechnic)的联系方式:postmaster@yourtechnic.com