查看: 1590|回复: 0

【转载】DIY简易急救呼吸机

[复制链接]

该用户从未签到

发表于 2020-10-9 16:03 | 显示全部楼层 |阅读模式
本帖最后由 vany5921 于 2020-10-9 16:05 编辑

主要电子器件:
- M5Stack
- BME280
- BME680- 直流小水泵
_MTtLkwBZtS.blob.jpg
我用空瓶子、一个塑料容器、两个水族箱水泵和电子产品组装了我的原型,你可以在淘宝或电子商店买到。呼吸机的基本设计是利用水柱在肺部产生气体交换,这种方法简单,使用的材料在任何商店都能找到。
在紧急情况下,正如我们目前对冠状病毒所做的那样,必须能够快速制造出足够可靠的设备,使用易于定位和组装的材料,而不必开发新材料,这种材料需要许多小时来检查其耐用性和操作性。
呼吸基本上是在一定的压力下将一定体积的空气引入肺部,使肺泡中的氧气交换成二氧化碳,并随后排出体外。有许多电动机械或简单的呼吸辅助器械,在所有这些装置中,调节空气引入的体积和压力是非常重要的。
一个不可忽视的问题是如何进行控制,使空气不会超过需要的量或不超过所需的压力。在机械或机电系统中,必须有电锁、转矩控制、保证这种控制的安全阀等。如果使用液压系统,我们有很多优势,因为在任何五金店,我们都能找到很多专门用于这个方面的材料,而不是用于空气控制的材料,所以在紧急情况下,我们会有很多材料、备件等。最重要的是,我们只需要很少的知识就可以制造出一个小型呼吸器。

工作原理
呼吸机的操作是基于使用一个水柱,以控制的压力和控制的体积来移动空气的体积。
这是一个最简单、最基本的ReaMima系统模型,一个小泵和三个容器。如果您想了解这个系统模型更多详细信息,请访问https://www.reamima.com/modelos/simple
考虑到我们必须引入肺部的空气量(潮气量)是7ml/kg体重,我们必须根据这个计算来设计系统。为避免并发症,最好在呼吸器上注明体重不超过100公斤的人使用,并规定最大空气量为700毫升。
在下图中,您可以看到700ml的体积是我们的工作体积,因此绿色条纹区域是我们的安全边界。我们必须留下至少一半或相等于我们将用作安全边际的体积。在最初的测试中,我用了一个空的塑料瓶,我切断了瓶盖的底部。有了更多的材料,你可以使用塑料或金属。必须指出的是,使用的容器必须清洁,不得释放有害气体、颗粒或元素,并且必须能够用酒精、漂白剂或类似物进行消毒。
image008_GIgbdnQl0d.jpg
同样地,它一定不能在压力下变形,因为它可以用吹出的体积骗过我们,压缩罐的尺寸必须足够大,以储存最小体积的水和最大体积的水,以使我们能够正常工作。


该项目的其余部分介绍都在该页面上https://www.reamima.com/
  1. /*******************************************************************
  2. Prueba Miguel para ReaMima
  3.                 Marzo 2020
  4. V 0.6
  5. *******************************************************************/

  6. #include <M5Stack.h>
  7. #include <Wire.h>
  8. #include <Adafruit_Sensor.h>
  9. #include <Adafruit_BME280.h>

  10. /***************************************************************************
  11. This is a library for the BME280 humidity, temperature & pressure sensor
  12. Designed specifically to work with the Adafruit BME280 Breakout
  13. ----> http://www.adafruit.com/products/2650
  14. These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  15. to interface. The device's I2C address is either 0x76 or 0x77.
  16. Adafruit invests time and resources providing this open source code,
  17. please support Adafruit andopen-source hardware by purchasing products
  18. from Adafruit!
  19. Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  20. BSD license, all text above must be included in any redistribution
  21. See the LICENSE file for details.
  22. ***************************************************************************/

  23. #define BME_SCK 22 //SCL 22 el conector Grove Integrado
  24. #define BME_MOSI 21 //SDA 21 el connector Grove Integrado
  25. #define SEALEVELPRESSURE_HPA (1013.25)

  26. Adafruit_BME280 bme; // I2C

  27. float k = 2 * 3.1416 /360 ;

  28. unsigned long delayTime,prevMillis,interval,tacu;
  29. int temp;float presion;float humedad;
  30. int fase=1; // fase =1, inspiracion, 2 pausa, 3 expiracion.
  31. long resp=0; // contador de respiraciones
  32. int alarma=0; // Codigo de alarma

  33. float frecuencia = 1.5;
  34. int ciclo,volumenCorriente=500,ti,tp,te,tv,tc,tiempocambio,cambiando=0; // VolumenCorriente, 6-10 ml/kg de peso ideal
  35. int IE1=1,IE2=1;// IE, relacion inspiracion/expiracion, 1:3, epoc 1:4 IE1=1;IE2=3
  36. float presionInicio,presionPico,presionMeseta,PEEP = 2.0;
  37. float presionResistida,difPresion,alarmaMaxima=6.0,alarmaBanda=2.0,sensibilidad,IPAP,EPAP;
  38. float preInst [330],preMedia [330];
  39. float preAlarma;

  40. int bomba1 = 2 ;int bomba2 = 5; // Salidas digitales reles inspiracion

  41. // PresionPico, máximo inicial, Presion resistida = pico - meseta,
  42. // Velocidad flujo respiratorio, de 60 a 120 l/min
  43. // Peep aprox. 5cm+, presion base para mantener abiertos alveolos
  44. // Sensibilidad, si detecta -2cm aire ayuda a respirar
  45. // IPAP presion positiva inspiracion, 10-15 cm H2O , EPAP , presion de expiracion, 5-8 cm H2O
  46. // Para SDRA, 6ml/kg, F=25/min, Vflujo=60 L/min, Peep 15 cm H2O
  47. // ti,tp,te,tv,tc,tacu; tiempo de inspiracion,pausa,expiracion,visualización, ciclo=ti+tp+te, tacu tiempo acumulado


  48. //__________________________ SET UP __________________________________________________________
  49. void setup() {
  50.    M5.begin();
  51.   Serial.begin(115200);
  52.   Serial.println(F("Mig Mad "));
  53.   
  54.   pinMode(bomba1,OUTPUT);
  55.   pinMode(bomba2, OUTPUT);
  56.   
  57.   bool status;

  58.   status = bme.begin(0x76);  
  59.   if (!status) {
  60.     Serial.println("No se puede encontrar un sensor de presion valido, comprueba el cableado!");
  61.     while (1);
  62.   }

  63.   delayTime = 10;

  64.   Serial.println();
  65.   M5.Lcd.fillScreen(TFT_BLACK);
  66.    M5.Lcd.setTextColor(TFT_RED, TFT_BLACK);
  67.   M5.Lcd.drawString(" Espera inicio", 80, 160, 4);

  68.    M5.Lcd.setTextColor(TFT_BLACK,TFT_YELLOW ); M5.Lcd.fillTriangle(180, 120,250,0, 320, 120, TFT_YELLOW);
  69.    M5.Lcd.drawString("ESPERA", 200, 90, 4);  M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);

  70.    
  71.    M5.update();
  72. }


  73. //______________________________________________ Loop _________________________________________________
  74. void loop() {
  75.   calculos();
  76.   tiempos();
  77.   sensor();
  78.   dibuja();
  79.   cambia();
  80.   switch (fase){
  81.     case 1: //Inspiracion
  82.      inspiracion();
  83.     break;
  84.     case 3:  // Expiración
  85.      expiracion();
  86.     break;
  87.     default:
  88.     break;
  89.   }
  90.   
  91.   alarmas();
  92. M5.update();
  93. }
  94. //____________________________________________________________________________________________________

  95. void inspiracion(){
  96.    digitalWrite(bomba1, HIGH);digitalWrite(bomba2, LOW);
  97. if (preInst[ciclo]>=presionPico){presionPico=preInst[ciclo];}
  98. if (ciclo==1 && resp>=1){presionPico=0.0;}
  99. if (resp>=1){
  100. if (resp>=1){
  101. M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);
  102.    M5.Lcd.drawFloat(presionPico,2, 10, 190, 2);  M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);  
  103. Serial.print(" fase ");Serial.println(fase );

  104. }}}

  105. void pausa(){
  106.   
  107. }
  108. void expiracion(){
  109.    digitalWrite(bomba1, LOW);digitalWrite(bomba2, HIGH);
  110. }
  111. void cambia(){

  112. if (M5.BtnA.wasReleased()) {cambiando+=1;Serial.print(" Cambiando = ++++++1 ");}
  113. if (cambiando>10){cambiando=0;}

  114. Serial.print(" Cambiando ");Serial.println(cambiando);
  115. switch (cambiando){
  116.     case 1: //Frecuencia
  117.     M5.Lcd.setTextColor(TFT_BLACK,TFT_WHITE);
  118.     M5.Lcd.drawFloat(frecuencia,0, 60, 190, 2);
  119. if (M5.BtnB.wasReleased()) {frecuencia+=1;}
  120. if (M5.BtnC.wasReleased()) {frecuencia-=1;}
  121. if (frecuencia>9){frecuencia=9;}if (frecuencia<1){frecuencia=0;} // Limites
  122.     break;
  123.     case 2: //PEEP
  124.    M5.Lcd.setTextColor(TFT_WHITE,TFT_BLACK);
  125.    M5.Lcd.drawFloat(frecuencia,0, 60, 190, 2);
  126.    M5.Lcd.setTextColor(TFT_BLACK,TFT_WHITE);
  127.    M5.Lcd.drawFloat(PEEP,1, 98, 190, 2);
  128. if (M5.BtnB.wasReleased()) {PEEP+=0.2;}
  129. if (M5.BtnC.wasReleased()) {PEEP-=0.2;}
  130. if (PEEP>20.0){PEEP=20.0;}if (PEEP<0.2){PEEP=0.0;} // Limites
  131.     break;
  132.     case 3:  // Volumen medio
  133.    M5.Lcd.setTextColor(TFT_WHITE,TFT_BLACK);
  134.    M5.Lcd.drawFloat(PEEP,1, 98, 190, 2);
  135.    M5.Lcd.setTextColor(TFT_BLACK,TFT_WHITE);
  136.      M5.Lcd.drawFloat(volumenCorriente,0, 138, 190, 2);
  137. if (M5.BtnB.wasReleased()) {volumenCorriente+=50.0;}
  138. if (M5.BtnC.wasReleased()) {volumenCorriente-=50.0;}
  139. if (volumenCorriente>900.0){volumenCorriente=900.0;}if (volumenCorriente<100.0){volumenCorriente=100.0;} // Limites

  140.     break;
  141.      case 4:  // IE1
  142.    M5.Lcd.setTextColor(TFT_WHITE,TFT_BLACK);
  143.     M5.Lcd.drawFloat(volumenCorriente,0, 138, 190, 2);
  144.    M5.Lcd.setTextColor(TFT_BLACK,TFT_WHITE);
  145.      M5.Lcd.drawFloat(IE1,0, 185, 190, 2);
  146. if (M5.BtnB.wasReleased()) {IE1+=1;}
  147. if (M5.BtnC.wasReleased()) {IE1-=1;}
  148. if (IE1>10){IE1=10;}if (IE1<1){IE1=1;} // Limites

  149.     break;
  150.      case 5:  // IE1
  151.    M5.Lcd.setTextColor(TFT_WHITE,TFT_BLACK);
  152.      M5.Lcd.drawFloat(IE1,0, 185, 190, 2);
  153.    M5.Lcd.setTextColor(TFT_BLACK,TFT_WHITE);
  154.      M5.Lcd.drawFloat(IE2,0, 220, 190, 2);
  155. if (M5.BtnB.wasReleased()) {IE2+=1;}
  156. if (M5.BtnC.wasReleased()) {IE2-=1;}
  157. if (IE2>10){IE2=10;}if (IE2<1){IE2=1;} // Limites

  158.     break;
  159.         case 6:  // IE1
  160.    M5.Lcd.setTextColor(TFT_WHITE,TFT_BLACK);
  161.      M5.Lcd.drawFloat(IE2,0, 220, 190, 2);
  162.    M5.Lcd.setTextColor(TFT_BLACK,TFT_WHITE);
  163.      M5.Lcd.drawFloat(alarmaBanda,0, 270, 190, 2);
  164. if (M5.BtnB.wasReleased()) {alarmaBanda+=0.5;}
  165. if (M5.BtnC.wasReleased()) {alarmaBanda-=0.5;}
  166. if (alarmaBanda>10.0){alarmaBanda=10.0;}if (alarmaBanda<0.5){alarmaBanda=0.5;} // Limites

  167.     break;
  168.     default:
  169.           case 7:  // IE1
  170.    M5.Lcd.setTextColor(TFT_WHITE,TFT_BLACK);
  171.      M5.Lcd.drawFloat(alarmaBanda,0, 270, 190, 2);
  172.   cambiando=0;

  173.     break;
  174.   
  175.   
  176.    M5.Lcd.drawFloat(alarmaBanda,0, 270, 190, 2);
  177.     break;
  178.   }
  179.    }

  180. void calculos()
  181. {
  182.   tc=60000/frecuencia;  ti=(tc/(IE1+IE2))*IE1;  te=tc-ti; tv=tc/320;
  183.   alarmaMaxima= alarmaBanda + 2.0;
  184.   }   

  185. void tiempos(){
  186. // Va calculando el tiempo en milisegundos
  187. // Calculo de intervalo con proteccion de desborde
  188. if (millis() - prevMillis <= 0) {
  189.   interval = prevMillis - millis();
  190. }
  191. else
  192. {
  193.   interval = millis()-prevMillis;
  194.   }
  195. prevMillis = millis();

  196. tacu += interval;
  197. if (tacu>= tc){tacu=0;resp=resp+1;}
  198. if (tacu<=ti){fase=1;}else{fase=3;}
  199. ciclo = tacu/tv;
  200. if (ciclo<=1){presionInicio=presion;}
  201. if (presion-presionInicio>0){
  202. preInst[ciclo]=presion-presionInicio;}
  203. else
  204. {preInst[ciclo]=0;
  205.   }
  206. if (resp>1){preMedia[ciclo]=((preMedia[ciclo]*5.0)+preInst[ciclo])/6.0;}else{preMedia[ciclo]=preInst[ciclo];}

  207. Serial.print(" tiempo ciclo ");Serial.print(interval); Serial.print(" tacu ");Serial.print(tacu);
  208.   //Serial.print(" P inst");Serial.print(preInst[ciclo]); Serial.print(" P media");Serial.print(preMedia[ciclo]);
  209.   
  210.   Serial.print(" Respiraciones : ");Serial.print(resp);
  211. Serial.print(" ciclo ");Serial.println(ciclo);
  212. }
  213. void dibuja() {
  214. // Dibuja solo la primera vez
  215. if (ciclo==1){M5.Lcd.fillScreen(BLACK);  M5.Lcd.drawLine( 0,120,320,120,0x7bef);
  216.    M5.Lcd.drawLine( 0,165,320,165,WHITE);M5.Lcd.drawLine( 0,210,320,210,WHITE);M5.Lcd.drawLine( 319,165,319,210,WHITE);
  217.    M5.Lcd.drawLine( 0,165,0,210,WHITE);M5.Lcd.drawLine( 55,165,55,210,WHITE); // Frec
  218.    M5.Lcd.drawLine( 95,165,95,210,WHITE);M5.Lcd.drawLine( 135,165,135,210,WHITE);
  219.    M5.Lcd.drawLine( 178,165,178,210,WHITE);  M5.Lcd.drawLine( 255,165,255,210,WHITE);
  220.    M5.Lcd.drawLine( 0,0,0,120,0x7BEF);  M5.Lcd.setTextColor(TFT_RED, TFT_BLACK);
  221.    
  222.    M5.Lcd.drawString("P. Pico",5,170,2); M5.Lcd.drawString("Frec",60,170,2); M5.Lcd.drawString("PEEP",98,170,2);
  223.    M5.Lcd.drawString("Vm",148 ,170,2);
  224.    M5.Lcd.drawString("I E",205 ,170,2);
  225.    M5.Lcd.drawString("P .Desvio",260 ,170,2);
  226.    M5.Lcd.setTextColor(TFT_ORANGE, TFT_BLACK);
  227.    M5.Lcd.drawString("Temp C : ",5 ,140,2);
  228.    M5.Lcd.drawString("Hum % :",98 ,140,2);
  229.     M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK);
  230.    M5.Lcd.drawFloat(temp,1, 60, 140, 2);
  231.    M5.Lcd.drawFloat(humedad,1,160 , 140, 2);
  232.         
  233. // Valores
  234.    M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);
  235.    M5.Lcd.drawFloat(frecuencia,0, 60, 190, 2);
  236.    M5.Lcd.drawFloat(PEEP,1, 98, 190, 2);
  237.    M5.Lcd.drawFloat(volumenCorriente,0, 138, 190, 2);
  238.    M5.Lcd.drawFloat(IE1,0, 185, 190, 2);  M5.Lcd.drawString(":",210 ,190,2);
  239.    M5.Lcd.drawFloat(IE2,0, 220, 190, 2);
  240.    M5.Lcd.drawFloat(alarmaBanda,0, 270, 190, 2);
  241.    
  242.   // Cursores
  243.    M5.Lcd.fillTriangle(55, 215, 55, 235, 65, 225, WHITE);
  244.    M5.Lcd.fillTriangle(145, 239, 160, 215, 175, 239, WHITE);
  245.    M5.Lcd.fillTriangle(250, 215, 265, 239, 280, 215, WHITE);


  246.    ///// Grafica en tiempo real
  247.   if (resp>1){
  248.   for ( int  i = 1 ; i<320 ; i++)
  249.     {    float a2 = i , a1= i-1  ;
  250.          float b2= 100 -( preMedia[i]*50) , b1= 100 - (preMedia[(i-1)]*50) ;  
  251.           M5.Lcd.drawLine(a1, b1, a2, b2,0xFF80 );
  252.     }  
  253.   }
  254. }
  255. ///// Grafica en tiempo real y valores en tiempo real
  256.   else{
  257.   

  258.       float x2 = ciclo, x1 = x2-1  ;        
  259.       float y2= 120 - (preInst[ciclo]   * 50), y1= 120 - (preInst[(ciclo-1)]   * 50) ;
  260.       M5.Lcd.drawLine(x1, y1, x2, y2,RED );   
  261.   }
  262.   }


  263. void sensor()
  264. {
  265.     temp = bme.readTemperature();
  266.   presion = bme.readPressure() / 100.0F;
  267.   humedad = bme.readHumidity();
  268.   
  269.   Serial.print("Temperatura = ");  Serial.print(temp);  Serial.println(" *C");
  270.   
  271.   Serial.print("Presion = ");  Serial.print(presion);  Serial.println(" hPa");
  272.   
  273.   Serial.print("Presion = ");  Serial.print(presion / 98.0665F);  Serial.println(" cm H2O");

  274.   Serial.print("Humedad = ");  Serial.print(humedad);  Serial.println(" %");

  275.   Serial.println();
  276. }
  277. void alarmas()
  278. {
  279.   
  280. if(preInst[ciclo]>=preMedia[ciclo]+alarmaBanda && alarma==0){alarma=2;}  // Aviso presion superior a la tendencia 5 ultimas respiraciones  
  281. if(preInst[ciclo]> alarmaMaxima && resp>=1){alarma=1;preAlarma=preInst[ciclo];}  // Aviso presion > presion pico alarma


  282. if(alarma==1){   
  283.    M5.Speaker.tone(461, 50); //frequency 461, with a duration of 200ms
  284.    M5.Speaker.tone(661, 50); //frequency 661, with a duration of 200ms
  285.    M5.Lcd.setTextColor(TFT_BLACK,TFT_YELLOW ); M5.Lcd.fillRect(180, 0,320,40, TFT_YELLOW);
  286.    M5.Lcd.drawString("ALARMA", 200, 10, 4);  M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);
  287. Serial.print("*****************ALARMA 1 Sobrepresion= ");  Serial.println(preAlarma);

  288. if ((ciclo/25)*25==(ciclo/50)*50){M5.Lcd.setTextColor(TFT_BLACK,TFT_YELLOW);M5.Lcd.drawString("P.Pico Alta", 230, 210, 2);}
  289. else{M5.Lcd.setTextColor(TFT_YELLOW,TFT_BLACK);M5.Lcd.drawString("P.Pico Alta", 230, 210, 2);}

  290. if (M5.BtnC.wasReleased()) {
  291.     alarma=0;}
  292. }
  293. if(alarma==2){   
  294.    M5.Speaker.tone(461, 10); //frequency 461, with a duration of 200ms
  295.    M5.Speaker.tone(661, 50); //frequency 661, with a duration of 200ms
  296.    M5.Lcd.setTextColor(TFT_BLACK,TFT_ORANGE ); M5.Lcd.fillRect(220, 0 , 320, 40, TFT_ORANGE);
  297.    M5.Lcd.drawString("AVISO", 230, 10, 4);  M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);

  298. if ((ciclo/25)*25==(ciclo/50)*50){M5.Lcd.setTextColor(TFT_BLACK,TFT_ORANGE);M5.Lcd.drawString("Tendencia", 230, 210, 2);}
  299. else{M5.Lcd.setTextColor(TFT_ORANGE,TFT_BLACK);M5.Lcd.drawString("Tendencia", 230, 210, 2);}

  300. if (M5.BtnC.wasReleased()) {
  301.     alarma=0;}
  302. }


  303. }
复制代码







您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

arduino程序设计基础 blinker物联网解决方案

热门推荐

【教程】pico+hx711电子秤
【教程】pico+hx711电子秤
pico+hx711电子秤 【前言】 我做过多款电子秤,这次移植到pico上
ESP8266+Onenet平台远程数据传输和控制
ESP8266+Onenet平台远程数
这是我的第一个diy,主要功能实现了onenet云平台温湿度数据的传输和远程控制LED灯平台
【Arduino】108种传感器模块系列实验(48)---三轴ADXL345模块
【Arduino】108种传感器模
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是
ps2遥控小车——uno实现
ps2遥控小车——uno实现
前几天在阁楼发现了好久以前3d打印,激光切割的底盘,于是决定做这个东西 正好手上又
震惊!OLED菜单竟只用10行代码就可以完成到完美!!!
震惊!OLED菜单竟只用10行
震惊!OLED菜单竟只用10行代码就可
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表