Pressure sensor wont calibrate zero

Hey guys,

Ive built a non invasive ventilator and it uses 2 pressure sensors to measure the pressure of the exit valve of the ventilator which leads to the mask. This is a project im doing for school and its due very soon and i need this to be working so any help would be appreciated.

The issue on startup the pressure sensors are calibrated, sometimes the works and the pressure sensors are zeroed but one of them sometimes does not calibrate and has random fluctuating output. This then stops my ventilator from functioning as it does not start until they are calibrated.

here is the schematic im using:


Here is my circuit diagram for the main board:

Here is the circuit diagram for the pressure sensor board which is connected to the main board via jumpers:


NOTE: I have removed the 5k and 5ohm resistors and the diodes this was a suggestion from someone on another forum

here is the code im using:

//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=85;  //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]);
}

Here is what i see on my LCD when it doesnt seem to want to calibrate:


I ran this code to test the output of the A1 pressure sensor the one that seems to give a fluctuating value at times:

int Rawval; // ADC value
int Pressoffset = 102; // ADC value @ 0 pressure
int adcMax = 921; // ADC value @ 5kPa (51 cmH2O)
int span;
int Newval;

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

void loop()
{
  span = adcMax - Pressoffset; // 819 here
  Rawval = analogRead(A0);
  Serial.print(" Rawval = \t");
  Serial.print(Rawval);
  Newval = Rawval - Pressoffset;
  Serial.print("\t Pressure  = \t");
  float pressureVal = (float)Newval * 51.0 / (float)span;
  Serial.print(pressureVal, 1); // cmH2O
  Serial.println(" cmH2O");
  delay(2000);
}

Here are the results:

Check the connections to that badly behaving sensor. Eventually replace it.

this is a new one that i just installed.

New things aew usually working, but not always...
Disconnect and connect it again paying attention to every step?

  • Avoid using the pressure sensors in an environment where condensation may form. Furthermore, its output may fluctuate if any moisture adhering to it freezes.

  • The pressure sensor is constructed in such a way that its output will fluctuate when it is exposed to light. Especially when pressure is to be applied by means of a transparent tube, take steps to prevent the pressure sensor chip from being exposed to light.

No, same project on this forum.

What is the distance between the two boards.

I suggest you add some decoupling caps on the sensor boards,
like 100uF between 5volt and ground.

Adding 100uF between 5volt and ground of the Nano (close to the Nano pins) might also be a good idea.
Leo..

I suspect noise which really can't be filtered out digitally.

I believe you need a filter between the sensors and the ADC inputs. I would start with a 10k series and a 0.1µF to ground. The cap should be very near the actual Arduino input pins.

Interfering with the ratiometric behaviour of the sensor could be a bad idea.
I would filter in the digital domain, with smoothing code.

But look at the returned raw values of the sensor. Jumping from 150 to 300 is not noise.
There must be something else wrong.
Leo..

the two boards are probably only roughly 5cm apart

Rawvalue jumps between 150 and 300. That's about 0.75volt to 1.5volt on the sensor output.
Do you also see that jumping when you power a disconnected sensor with a clean 5volt supply and measure it's output voltage with a digital multimeter.
Leo..

Hi,
Have you got the ventilator pump turned OFF while you do a calibration?

Thanks... Tom.. :smiley: :+1: :coffee: :australia:
PS, From the other thread.

Yes, ventilator pump does not turn on until calibration is completed

also just an update i did sort out all of those messy cables:

No i do not

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.