Код Arduino для термисторного респираторного монитора

Я разработал термисторный респираторный монитор, который определяет изменения температуры во время дыхания, но у меня возникли проблемы с кодированием. Может кто-нибудь помочь, мой код, приведенный ниже, не работает.

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);
  }
}

Показания датчика составляют 600-800 во время вдоха и около 100 во время выдоха.

, 👍1

Обсуждение

Вы хотите знать, сколько времени занимает истечение? Пожалуйста, объясните, что вы хотите сделать. Вы хотите подсчитать количество выдохов в минуту? Тогда потребуется минута, прежде чем можно будет вычислить первое число. Решение в этом: https://www.arduino.cc/en/Tutorial/StateChangeDetection и это: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay Я думаю, вы хотите измерить полный цикл вдохновения и выдох, и с этим рассчитать количество вдохов в минуту, что приведет к. Если это так, отредактируйте свой вопрос и объясните его., @Jot

ОП хочет рассчитать мгновенную частоту дыхания. Он почти там, с несколькими небольшими проблемами. Смотрите мой ответ ниже, @Craig.Feied

Могу ли я узнать, что значение установлено на основе чего? -Serial.begin(9600) -значение датчика > 300 -частота дыхания = 60000 -значение датчика < 200, @user49711


3 ответа


1

В этом коде отсутствуют 2 важных компонента. Во-первых, без некоторой формы гистерезиса маловероятно, что программа будет реагировать надежным образом. Во-вторых, было бы лучше, если бы для сбора данных и расчета ставка репарации. В этом случае 4 состояния для отслеживания выдоха, перехода от выдоха к вдоху, вдоха и выдоха. переход от вдоха к выдоху.

,

4

Основная причина, по которой ваш код не работает, очень проста: каждый раз, когда вы проходите заданный вами цикл

timer = millis();

и если показания больше 200, вы устанавливаете

currentTime = millis();

но эти два оператора выполняются с разницей всего в несколько микросекунд, поэтому разница между ними (в миллисекундах) почти всегда будет равна нулю (иногда она может быть равна единице, если вы случайно пересекли границу тика, но больше этого никогда не будет).

Есть несколько других проблем с логикой вашего кода, которые, я думаю, вы поймете, когда посмотрите на код, который будет работать. Попробуйте что-то вроде этого:

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

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


void loop()
{
    // задержка (500);
    // не нужно задерживать, потому что мы сработаем только один раз на вдохе и один раз на выдохе
    int sensorValue = analogRead(A0);

    if ((sensorValue > 300) && (currentRespState == Exhaling))
    {
        currentRespState = Inhaling;
        prevRespTime = currRespTime;  // сохранить время с последнего цикла
        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");
    }
}

Приведенный выше код даст вам мгновенную частоту дыхания, которая, вероятно, будет прыгать немного больше, чем вам хотелось бы. Вы, вероятно, захотите добавить некоторую зависимость от предыдущей истории (гистерезис), чтобы немного сгладить ее. Один из простых способов — провести это через алгоритм фильтра нижних частот, чтобы получить скользящее среднее значение частоты дыхания. Таким образом, скорость увеличивается, когда вы дышите быстрее, и снижается, когда вы дышите медленнее, но не прыгает мгновенно при каждом вдохе. Вот как это может выглядеть:

// Глобальные переменные
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()
{
    // задержка (500);
    // не нужно задерживать, потому что мы сработаем только один раз на вдохе и один раз на выдохе
    int sensorValue = analogRead(A0);

    if ((sensorValue > 300) && (currentRespState == Exhaling))
    {
        currentRespState = Inhaling;
        prevRespTime = currRespTime;  // сохранить время с последнего цикла
        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");
    }
}

Этот код компилируется, но я не оказался рядом с Arduino с датчиком, поэтому я не запускал его — могут быть проблемы, но этого должно быть достаточно, чтобы направить вас на правильный путь. Удачи!

,

0

Помимо всего предоставленного полезного кода, вот некоторые дополнительные данные для относительно точного измерения расхода с использованием термисторов. Измерение Sage предоставляет полезный обзор наиболее популярных режимов работы. Вам понадобится массив из двух или более термисторов; нагревая центральный элемент и измеряя смещение температурного поля, вызванное потоком, с помощью других термисторов, вы получите действительно точные показания. В Google Scholar есть много статей о расходомерах с постоянной температурой и постоянным током.

Кроме того, я полагаю, что вы используете какую-то короткую трубку для вдоха/выдоха; у этой трубы есть критическая длина, где вы хотели бы разместить свои датчики для измерения хорошего, устойчивого потока (это называется ламинарным потоком). Вы можете посмотреть число Рейнольдса и ламинарно-турбулентное течение в трубах; По опыту могу сказать, что через ок. 15 см вы бы хорошо измерили, но почитайте, это действительно интересная информация о настройке правильной настройки измерения.

,

Этот ответ интересен, но не затрагивает вопрос OP, который явно касается кода (следовательно, помещенного в обмен стеками Arduino)., @MichaelT

Да, я согласен, но жалко писать весь код и каждый день измерять по-разному или чтобы ваш код выдавал разные результаты для любого человека, дышащего на него. Я получил ваш комментарий, хотя, спасибо., @dBm