1

I have designed a thermistor-based respiratory monitor which detects changes in temperature during respiration, but I am having problems with the coding part. Can someone help, my code given below is not working.

void setup() {
  Serial.begin(9600);
}
unsigned long timer; 
void loop(void) 
{
    delay (500)
  int sensorValue = analogRead(A0);
timer=millis ();
    if ( sensorValue<200) {
unsigned long currentTime = millis();
float period_respiration = currentTime-timer;
float breathrate= 60000/period_respiration;
Serial.println("Respirations per minute:");
Serial.println(breathrate);
  }
}

The sensor value is 600-800 during inspiration, and about 100 during expiration.

  • 1
    Do you want to know how long the expiration takes ? Please explain what you want to do. Do you want to count the number of expirations per minute ? Then it would take a minute before the first number can be calculated. The solution is in this: arduino.cc/en/Tutorial/StateChangeDetection and this: arduino.cc/en/Tutorial/BlinkWithoutDelay I think you want to measure a full cycle of inspriration and expiration and with that calculate the number of respirations per minute that would result into. If that is the case, please edit your question and explain it. – Jot Oct 15 '17 at 18:10
  • The OP wants to calculate the instantaneous respiratory rate. He's almost there, with a few little problems. See my answer below – Craig.Feied Oct 16 '17 at 11:47
  • may i know the value is set based on what? -Serial.begin(9600) -sensorValue > 300 -breathrate = 60000 -sensorValue < 200 – user49711 Sep 21 '18 at 15:58
3

The primary reason your code doesn't work is very simple: every time you go around the loop you set

timer = millis();

and if the reading is greater than 200 you set

currentTime = millis();

but those two statements are executed just a few microseconds apart, so the difference between them (in milliseconds) will almost always be zero (it might occasionally be one if you happened to cross a tick boundary, but it will never be more than that).

There are a few other problems with the logic of your code, which I think you'll understand when you look at some code that will work. Try something like this:

enum respState {
    Inhaling,
    Exhaling
};
unsigned long prevRespTime = 0;
unsigned long currRespTime = 0;
respState currentRespState;
int movingAvgRespRate = 0;

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


void loop()
{
    //delay(500);  
    // don't need to delay because we'll only fire once per inhalation and once per exhalation
    int sensorValue = analogRead(A0);

    if ((sensorValue > 300) && (currentRespState == Exhaling))
    {
        currentRespState = Inhaling;
        prevRespTime = currRespTime;  // save time from last cycle
        currRespTime = millis();

        float period_respiration = currRespTime - prevRespTime;
        float breathrate = 60000 / period_respiration;
        Serial.print("Inhaling /tRespirations per minute: ");
        Serial.println(breathrate);
    }
    else if ((currentRespState == Inhaling) && (sensorValue < 200))
    {
        currentRespState = Exhaling;
        Serial.println("Exhaling");
    }
}

The above code will give you the instantaneous respiratory rate, which probably will jump around a bit more than you would like. You probably want to add some dependency on prior history (hysteresis) to smooth it out a bit. One easy way is to put this through a low-pass filter algorithm to get a moving average value for the respiratory rate. That way the rate goes up when you breathe faster and down when you breathe slower but it doesn't instantaneously jump around on every breath. Here's what that might look like:

// Global variables
enum respState {
    Inhaling,
    Exhaling
};
unsigned long prevRespTime = 0;
unsigned long currRespTime = 0;
respState currentRespState = Exhaling;
float breathrate = 0;
int movingAvgRespRate = 0;


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


void loop()
{
    //delay(500);  
    // don't need to delay because we'll only fire once per inhalation and once per exhalation
    int sensorValue = analogRead(A0);

    if ((sensorValue > 300) && (currentRespState == Exhaling))
    {
        currentRespState = Inhaling;
        prevRespTime = currRespTime;  // save time from last cycle
        currRespTime = millis();

        float period_respiration = currRespTime - prevRespTime;

        if (period_respiration == 0)
            breathrate = 0;
        else 
            breathrate = 60000 / period_respiration;

        Serial.print("Inhaling /tResp Rate: ");
        Serial.print(breathrate);

        if (movingAvgRespRate == 0)
            movingAvgRespRate = breathrate;
        else 
            movingAvgRespRate = (int) ((0.2 * breathrate) + (0.8 * movingAvgRespRate));

        Serial.print("/tAvg Resp Rate: ");
        Serial.println(movingAvgRespRate);
    }
    else if ((currentRespState == Inhaling) && (sensorValue < 200))
    {
        currentRespState = Exhaling;
        Serial.println("Exhaling");
    }
}

This code compiles, but I did not happen to be near an arduino with a sensor, so I didn't run it -- there could be issues, but this should be enough to put you on the right track. Good Luck!

1

This code is missing 2 critical components. First, with out some form of hysteresis it is unlikely the program will respond in a dependable manner. Second, it would be best if a finite state machine were utilized to assist in the collection of data and calculation of a reparation rate. In this case, 4 states to track exhale, transition from exhale to inhale, inhale & transition from inhale to exhale.

0

Aside from all the useful code provided, here is some additional input for a relatively accurate flow measurement using thermistors. Sage metering provides a useful overview of the most established modes of operation. You'd need an array of two or more thermistors; by heating the central element and measuring the temperature field displacement induced by the flow using the other thermistors you would get a really accurate reading. Google Scholar has a lot of papers on constant temperature and constant current flow meters.

Also, I suppose you are using some short of tubing where you inhale/exhale; there is a critical length for this tube, where you would want to place your sensors to measure a good, steady flow (this is called laminar flow). You can look up Reynolds number and laminar - turbulent flow in pipes; I can say from experience that after approx. 15cm you would measure well, but have a reading, this is really interesting information on setting up a proper measurement setup.

  • This answer is interesting, but does not address the question of the OP which is explicitly about the code (hence placed on the Arduino stack exchange). – MichaelT Sep 22 '18 at 18:54
  • Yeah, I agree, but it's a pitty to write all the code and go measure differently everyday, or have your code spitting out different results for any person breathing on it. I get your comment though, thanks. – dBm Sep 22 '18 at 19:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.