Sensor for DIY ventilator

Full number is XGZP684705KPG

The pressure range for that part # is only 5kPa, less than 1 PSI. What are you measuring the pressure of?

I need it to measure air pressure of about max 30cmH20. 5kpa is enough for this as 30cmH20 is roughly 2.941kPa

5kPa is about 51 cmH2O, see if this works. Watch the ADC value and set variable "offset" correctly if it's not 102 @ 0 pressure.

void setup()
{
  Serial.begin(9600);

}

void loop()
{
  int val, // ADC value
      offset = 102, // ADC value @ 0 pressure
      adcMax = 921, // ADC value @ 5kPa (51 cmH2O)
      span = adcMax - offset; // 819 here

  val = analogRead(A0);
  Serial.print(val); Serial.print("\t");
  val -= offset;
  float pressure = val * 51.0 / span;
  Serial.println(pressure,1); // cmH2O
  delay(2000);
}


This is the output i get

Hi,
Can you please post some images of your project?

The problem you have looks more like a loose connection rather than code problem.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

Did you change the "offset" variable to 107? What do you read with 15 cmH2O applied to the sensor?

Get about 80 or 90 cm of clear plastic tubing, a piece of plywood to mount it on, a t connector to allow you to connect the pressure sensor off the side, a small inline shutoff valve (aquarium stores have them) and a small hand pump or even just a squeeze bulb, and you can build a DIY U tube manometer for low cost and do a proper calibration of the sensor across your pressure range

I was going to suggest that if the OP reappeared. :slightly_smiling_face:

A quick question just for knowledge. Since all the XGZP6847 pressure sensors have the same minimum and maximum voltage, the offset and adcMax will be the same right? regardless of if it is a 5kpa or 100kpa sensor.

Just abit busy will try and do it tomorrow

At the moment i have no way of applying a set measured pressure to the pressure sensors.

Just fyi.

this is the code im running on my Arduino for my ventilator currently. NOTE: not my code


//Source code for the BIPAP/CPAP low cost device v1.0
//Arduino Nano
//Details of the hardware, connections and setup can be found in www.ub.edu/biofisica
//For code details contact jorge.otero@ub.edu / m.rodriguez@ub.edu

#include <PID_v1.h>    //PID library
double Setpoint, Input, Output, flow_hp, flow_bp;   //variables 
double Kp=0.38, Ki=0.75, Kd=0;    //variables and values for the PID controller KP(proportional),Ki(integral),Kd(derivative)

//Definitions

PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
#define analog  10            //define digital 10 as analog.
#define analog_flow  9        //define digital 9 as analog_flow.
#include <LiquidCrystal.h>    //LCD 2x16
LiquidCrystal lcd(12,11,5,4,3,2);    //LCD connections
#define switchPin  6          //define digital 6 as SwitchPin.
#define SwitchMode  13        //define digital 13 as SwitchMode.
#define led  8                //define digital 8 as led.

byte autoipap = 0,lcdmodecpap=1,lcdmodebipap=1,switchState = 0,switchModestate = 0,restard;  //byte variables
unsigned long t0 =micros(),tiempoahora =millis();
int Tm =10000;    //Sampling frequency in microseconds
float tiempo =0;
float fc_hp=0.125;              //cutoff frequency of the high-pass filter 
float fc_lp=1.125;              //cutoff frequency of the low-pass filter
float RC_hp =1/(2*PI*fc_hp);    
float RC_lp =1/(2*PI*fc_lp);    
double data_filt_hp[] = {0, 0};
double data_hp[] = {0, 0};
double data_filt_lp[] = {0, 0};
double data_lp[] = {0, 0};
double maximo=0,vmax=0,flow=0;
int pressure, epap,ipap,consigna=0;    
float porcentaje,P_sensor,P_epap,P_ipap,P_sensor_abs,P_sensor2;   
int ctroltime =0;
int gain_flow =100;   
char P_sensorstring[4];
char P_sensorstring2[4];
char P_EPAPstring[4];
char P_IPAPstring[4];
char porcentajestring[2];
char timestring[2];
int i,z=0;
int samplepressure[25];   //buffer of 25 positions for the pressure sensor 1 readout
int samplepressure2[25];  //buffer of 25 positions for the pressure sensor 2 readout

double totalpress2 = 0.00, promediopress2 = 0.00, totalpress = 0.00, promediopress = 0.00;
double totalzero=0,totalzero2=0,samplezero,samplezero2,pressinzero,pressinzero2,zero,zero2;

#define sensorpress A0             //pressure sensor 1 output is connected to the analog input 0
#define sensorpress2 A1           //pressure sensor 2 output is connected to the analog input 1
#define analog_epap A2           //epap potentiometer adjustment is connected to the analog input 2
#define analog_ipap A3          //ipap potentiometer adjustment is connected to the analog input 3
#define analog_porcentaje A4   //cycling potentiometer adjustment is connected to the analog input 4


//Configuration

void setup() {

myPID.SetMode(AUTOMATIC);     //automatic mode in PID
consigna=ipap;
Serial.begin(115200);
for(i=0; i< 24; i++)          //array initialization 
{
      samplepressure[i] = 0;
      samplepressure2[i] = 0;
}
i=0;

lcd.begin(16,2); //LCD 2x16
pinMode(switchPin,INPUT);       //switchPin -> input
pinMode(SwitchMode,INPUT);      //switchMode -> input
pinMode(led,OUTPUT);            //led -> output

lcd.setCursor(0,0);                          
lcd.print("Calibrating zero");
lcd.setCursor(0,1); 

for(i=0; i< 91; i++)          //array initialization 
{
    Serial.println(i);

    if (i==0 || i==6 || i==12 || i==18 || i==24 || i==30 || i==36 || i==42 || i==48 || i==54 || i==60 ||  i==66 || i==72 || i==78 || i==84 || i==90)
    { 
        lcd.setCursor(i/6,1);
        lcd.print(".");
 
    }
    
    samplezero = 2.5*analogRead(sensorpress);   //zero reading for pressure sensor 1 
    totalzero = totalzero + samplezero; 
    samplezero2 = 2.5*analogRead(sensorpress2);   //zero reading for pressure sensor 2
    totalzero2 = totalzero2 + samplezero2; 
    delay(50);
}

zero=totalzero/i;
zero2=totalzero2/i;

lcd.setCursor(0,1);
lcd.print("                ");
lcd.setCursor(0,1);
lcd.print("P1:");
lcd.setCursor(8,1);
lcd.print("P2:");
lcd.setCursor(15,1);
lcd.print("  ");

for(i=0; i< 50; i++) 
{
    pressinzero =2.5*analogRead(sensorpress)-zero;         //zero adjustment for pressure sensor 1
    P_sensor=abs((pressinzero/1023)*5.0*4.8);
    dtostrf(P_sensor,1,1, P_sensorstring);
    pressinzero2 =2.5*analogRead(sensorpress2)-zero2;         //zero adjustment for pressure sensor 2
    P_sensor2=abs((pressinzero2/1023)*5.0*4.8);
    dtostrf(P_sensor2,1,1, P_sensorstring2);

    lcd.setCursor(4,1);
    lcd.print(P_sensorstring);
    lcd.setCursor(12,1);
    lcd.print(P_sensorstring2);

    delay(30);

    if (P_sensor >0.3 ||P_sensor2>0.3)
    {
        lcd.setCursor(0,0); 
        lcd.print("err calibrating ");  
        lcd.setCursor(0,1);
        lcd.print("                ");
        lcd.setCursor(4,1);
        lcd.print(P_sensorstring);
        lcd.setCursor(12,1);
        lcd.print(P_sensorstring2);
        lcd.setCursor(0,1);  
        delay(2000); 
        lcd.print("Restart sofware.");
        delay(1000);
        restard =1;
        i=50;
    }
}
i=0;
}


// Main program loop

void loop() {

if (restard ==1)    
{
    i=0;
    totalzero=0;
    totalzero2=0;
    restard=0;  
    setup(); 
}

samplepressure[i] = 2.5*analogRead(sensorpress);   //Pressure sensor 1 sampling
totalpress = totalpress + samplepressure[i];      

samplepressure2[i] = 2.5*analogRead(sensorpress2);   //Pressure sensor 2 sampling
totalpress2 = totalpress2 + samplepressure2[i];      

ctroltime = 5;  

i++;

if (micros()-(t0)>=Tm)  
{                               
    tiempo=(micros()-t0);
    t0=micros();

    promediopress = (totalpress/i);           //pressure average for sensor 1
    promediopress2 = (totalpress2/i);         //pressure average for sensor 1

    pressinzero = promediopress-zero;         // zero adjustment for pressure sensor 1 -  sensor should be let with no pressure and the zero adjusted with the potentiometer
    pressinzero2 = promediopress2-zero2;      // zero adjustment for pressure sensor 2 -  sensor should be let with no pressure and the zero adjusted with the potentiometer
    P_sensor=(pressinzero2/1023)*5.0*4.8;     //conversion to pressure in cmH2O units.
    P_sensor_abs = abs(P_sensor); 
    Serial.println(P_sensor_abs);

    epap=0.833*analogRead(analog_epap)+170;     //epap range from 4 cmH2O to 24 cmH2O (170-1023)
    ipap= 0.833*analogRead(analog_ipap)+170;    //ipap range from 4 cmH2O to 24 cmH2O (170-1023)

    if (epap>ipap)
    {
        epap=ipap;        //epap value never can be higher than ipap value
    }

    P_epap =(epap/1023.00)*5.0*4.8;       //conversion of epap pressure to cmH2O units
    P_ipap =(ipap/1023.00)*5.0*4.8;       //conversion of ipap pressure to cmH2O units
    porcentaje=100*(analogRead(analog_porcentaje)/1023.00);     //conversion of the cycling value to percentage (0% - 100%)

    flow=gain_flow*(pressinzero2-pressinzero);       // flow calculation from the pressure difference in the sensors

    if (flow>0)
    { 
        flow=100*sqrt(flow);        //flow+ linearization
    }
    else
    {   
        flow=-100*sqrt(-flow);      //flow- linearization
    }  

    int flow_out = map(flow,-20000,40000,0,255);    // rescaling flow values (0-255) for PWM control in pin 9 
    analogWrite(analog_flow,flow_out);              


    Input =pressinzero2;       //pressure of the transducer is the input for the PID controller
    Setpoint= consigna;       //setpoint for the PID controller
    myPID.Compute();          //myPID function call 

    if (pressinzero2 < 250) 
    {            
        Output=200;  //if pressure is very low it is because there is no patient, so output is settled very low
    }

    analogWrite(analog,Output);                         //analog output 10 actuates the blower
    switchState = digitalRead(switchPin);             //adjust values switch readout
    switchModestate = digitalRead(SwitchMode);      //CPAP/BIPAP modes switch readout

    if (switchModestate == LOW && switchState == LOW) //CPAP mode is active when both switches are off  
    {         
        if (lcdmodecpap ==1)  
        {      
            myPID.SetTunings(Kp=0.12, Ki=0.75, Kd=0);       //PID values for CPAP mode
            lcd.setCursor(0,0);                          
            lcd.print("    CPAPmode    ");              
            lcd.setCursor(0,1);                    
            lcd.print("Press      ");             
            lcd.setCursor(11,1);                 
            lcd.print("CmH20");                 
            lcdmodecpap = 0;                       // no rewritting of the display until mode is switched again
        }
    
        digitalWrite(led , LOW);                          
        lcd.setCursor(7,1);                                             
        dtostrf(P_sensor_abs,2,0, P_sensorstring);                     
        lcd.print(String(P_sensorstring));                            
    
        consigna=ipap;                                //setpoint is adjusted by the ipap potentiometer                              
        lcdmodebipap=1;                              //allows switching to BIPAP mode 
    }   
   
    if (switchModestate == LOW && switchState == HIGH)  //CPAP mode, adjustment of the parameters 
    {           
        lcd.setCursor(0,0);                                         
        lcd.print("    Set CPAP    ");                              
        lcd.setCursor(0,1);                                       
        dtostrf(P_ipap,2,1, P_IPAPstring);                       
        lcd.print(String("IPAP " )+String(P_IPAPstring)+String("  CmH2O "));                //display the IPAP value 
        lcdmodebipap=1;                                                                    //allows mode switching                                                
        lcdmodecpap=1;                                                                    //allows mode switching
    }
   
    if ( switchModestate == HIGH && switchState == LOW) //BIPAP mode is active, no parameters setup 
    {                                
        if (lcdmodebipap ==1)  
        {     
            lcd.setCursor(0,0);                        
            lcd.print("BiPAPmode ");                  
            lcd.setCursor(12,0);                     
            lcd.print("%");                         
            lcd.setCursor(0,1);                    
            lcd.print("Press      ");             
            lcd.setCursor(11,1);                 
            lcd.print("CmH20");                 
            lcdmodebipap=0;                    // LCD is just written once 
        }

        dtostrf(porcentaje,2,0,porcentajestring);                          //conversion of % to string
        lcd.setCursor(10,0);                                              
        lcd.print(String(porcentajestring));                             
        lcd.setCursor(7,1);                                             
        dtostrf(P_sensor_abs,2,0, P_sensorstring);                     //conversion of pressure to string
        lcd.print(String(P_sensorstring));                            
        Serial.println(P_sensorstring);

        if (autoipap==0) 
        {
            lcd.setCursor(13,0);                               
            dtostrf(ctroltime,1,0,timestring);                //conversion of time to string
            lcd.print(String(" -")+String(timestring));      
        }
      
        lcdmodecpap=1;                                 //allows mode switching                                                     
    }
      
    if (switchModestate == HIGH && switchState == HIGH)   //BIPAP mode, parameter adjustment
    {                      
        lcd.setCursor(0,0);
        dtostrf(P_ipap,2,1, P_IPAPstring);
        lcd.print(String("IPAP ")+String(P_IPAPstring)+String(" CmH2O    ")); 
        lcd.setCursor(0,1);
        dtostrf(P_epap,2,1, P_EPAPstring);
        lcd.print(String("EPAP ")+String(P_EPAPstring)+String(" CmH2O     "));                
        lcdmodebipap=1;      
        lcdmodecpap=1; 
                                                     }
        flow_hp = mifiltroHP(flow,tiempo/1000000,RC_hp);                        //high-pass filtering flow signal
        flow_bp = mifiltroLP(flow_hp,tiempo/1000000,RC_lp);                    //low-pass filtering flow signal

        if (flow_bp>350 && switchModestate == HIGH && switchState == LOW) //detection of inspiratory flow > 350 when BIPAP mode is active 
        {                             
            myPID.SetTunings(Kp=0.1, Ki=0.45, Kd=0);                       //new PID parameters
            digitalWrite(led , HIGH);                                     //inspiration detection LED is active
            tiempoahora=millis();
            maximo = max(maximo, flow_bp);                                //maximum flow calculated
 
            if (maximo>1.05*flow_bp)
            {                                                           //detects a 5% flow reduction respect to the peak flow   
                vmax =porcentaje/100*maximo;                           //calculation of the change point to EPAP (Vmax) 
                if (flow_bp<vmax) 
                {   
                    consigna = epap;                                //if the flow is lower than the change point, switches to EPAP mode
                }
                myPID.SetTunings(Kp=0.65, Ki=0.2, Kd=0);     //new PID parameters 
            }
                              
            else
            {
                consigna=ipap;      //if the flow is inspiratory but not 5% reduced, it maintains IPAP mode
            }                                                     
        }


    if (flow_bp<350 && switchModestate == HIGH && switchState == LOW)   //detect flow  < 350 in BIPAP mode
    {                          
        digitalWrite(led , LOW);   //switch off inspiration led (flow<350 = expiration)

        if (millis()>(tiempoahora+(1000*ctroltime))&& millis() <= (tiempoahora+(1000*ctroltime)+1010)) //detects if the flow<350 time is greater than control time
        {                   
            autoipap=1;                                 //autoIPAP mode activated
            consigna=ipap;                             //IPAP mode activated
            lcd.setCursor(14,0);                      
            lcd.print(String(F("ON")));              
        
            if (millis()> tiempoahora+(1000*ctroltime)+1000)
            {           
                consigna=epap;                                     
                lcd.print(String(timestring));                                          
            }
                                                                       
        } 
        else
        {                                                 //no autoIPAP mode needed
            consigna=epap;                                     
            autoipap=0;                                       
        }
 
        if (millis()> tiempoahora+(1000*ctroltime)+3000)
        {
            tiempoahora=millis();   //time variable reset
        }                   
                                                                      
        maximo=0;                        //maximum varibles reset
        vmax=0;                         
    
    }

    if (switchModestate == LOW && switchState == LOW)   //CPAP mode active, maintains IPAP 
    {   
        consigna=ipap;
    }                  

    if (switchModestate == LOW && switchState == HIGH)  //CPAP mode active, setting parameters, maintains IPAP 
    {
        consigna=ipap;
    }               
 
    //variables reset
    promediopress=0;  
    totalpress=0;
    promediopress2=0;
    totalpress2=0;
    i=0;  
}
} //end of main program loop


double mifiltroHP(double dato,double dt,double RC)  //high-pass filtering of flow function 
{       
    double alpha = RC/(RC+dt);
    data_hp[1] = dato;
    
    // High Pass Filter
    data_filt_hp[1] = alpha * (data_filt_hp[0] + data_hp[1] - data_hp[0]);

    // Store the previous data in correct index
    data_hp[0] = data_hp[1];
    data_filt_hp[0] = data_filt_hp[1];

    return (data_filt_hp[1]);
}

double mifiltroLP(double dato,double dt,double RC) //low-pass filtering of flow function
{      
    double alpha = dt/(RC+dt);
    data_lp[1] = dato;
    
    // low Pass Filter
    data_filt_lp[1] = alpha *data_lp[1]+(data_filt_lp[0]*(1-alpha));

    // Store the previous data in correct index
    data_lp[0] = data_lp[1];
    data_filt_lp[0] = data_filt_lp[1];

    return (data_filt_lp[1]);
}


If anyone needs more context about the project code, i can provide

Hi,

Google;

manometer diy

Your code in post #14 is a good start to calibrating and getting reliable measurements from your sensor.

Tom.. :grinning: :+1: :coffee: :australia:

But this sensor was already calibrated. Plus im not receiving any values its just '????..". Is there any way of checking if ive maybe shorted or fried the pressure sensor module?

Hi,
Disconnect the sensor.
Connect A0 to gnd and see what readings you get.
Then;
Connect A0 to 3V3 and see what readings you get.
Then;
Connect A0 to 5V and see what readings you get.

Please post the code you are using at the moment.

Thanks.. Tom.. :grinning: :+1: :coffee: :australia:

I'm OUT.



I have done what you suggested:

Code im using:

void setup()
{
  Serial.begin(9600);

}

void loop()
{
  int val, // ADC value
      offset = 102, // ADC value @ 0 pressure
      adcMax = 921, // ADC value @ 5kPa (51 cmH2O)
      span = adcMax - offset; // 819 here

  val = analogRead(A0);
  Serial.print(val); Serial.print("\t");
  val -= offset;
  float pressure = val * 51.0 / span;
  Serial.println(pressure,1); // cmH2O
  delay(2000);
}

When A0 pin connected to GND:
Screen Shot 2023-05-31 at 5.55.45 pm

At 3.3v:
Screen Shot 2023-05-31 at 5.53.55 pm

At 5V:
Screen Shot 2023-05-31 at 5.56.35 pm

Hi,
Thanks for the reply.
Can you please run this code and do the process in post #38 again;

int RawVal = 0;
int PressPin = A0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  RawVal = analogRead(A0);
  Serial.print("RawVal \t");
  Serial.println(RawVal);
  delay(2000);
}

You can easily copy it by left clicking on the icon that appears in the top right corner of the code window then paste into the IDE.
image

Thanks.. Tom.. :smiley: :+1: :coffee: :australia: