Использование значения MAX30100 SpO2 для включения светодиода

датчик max30100 i2c выдает показания сердечного ритма и spo2 последовательно, а также может отображать значения на ЖК-дисплее. Я хочу показать его индикацию с помощью светодиода.

Если значение SpO2 <94 , то загорится красный светодиод на цифровом выводе 4

Если значение SpO2 >=94, он загорится зеленым светодиодом на цифровом выводе 5>

Здесь pox.getSpO2() дает значение SpO2.

Как я могу использовать это значение для переключения между двумя цифровыми выводами? Я понимаю, что для переключения легче считывать аналоговое значение вывода, но я ищу рекомендации по использованию значений I2C для этого условия.

Спасибо тебе.

Вот минималистичный код SpO2

#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS     1000

PulseOximeter pox;
uint32_t tsLastReport = 0;

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

    Serial.print("Инициализация пульсоксиметра..");

    if (!pox.begin()) {
        Serial.println("СБОЙ");
        for(;;);
    } else {
        Serial.println("УСПЕХ");
    }
}

void loop()
{

    pox.update();

    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        Serial.print("SpO2:");
        Serial.print(pox.getSpO2());
        Serial.println("%");

        tsLastReport = millis();
    }
}

, 👍2


1 ответ


Лучший ответ:

2

Вы уже проделали всю тяжелую работу, настроив датчик и научившись считывать данные с него.

Я бы определил константу для порога SpO2 в верхней части и удобные имена для контактов:

const uint8_t SpO2_threshold = 94;  // процент
const uint8_t red_pin = 4;
const uint8_t green_pin = 5;

Затем установите контакты в режим вывода в настройках (), как обычно. (Возможно, установите их оба слишком ВЫСОКО (или НИЗКО), чтобы указать, что чтение еще не было выполнено.)

В цикле, в разделе отчетов, просто возьмите значение и переключите контакты:

...
uint8_t spo2 = pox.getSpO2();
// Print it out to serial if needed, then:
if (spo2 < SpO2_threshold) {
  digitalWrite(green_pin, LOW);
  digitalWrite(red_pin, HIGH);
} else {
  digitalWrite(red_pin, LOW);
  digitalWrite(green_pin, HIGH);
}

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

Показания датчиков фиксируются (любое значение при spo2_min или ниже приведет к ускоренному времени мигания, при spo2_max-к самому медленному). Затем этот диапазон сопоставляется с диапазоном времени выключения светодиодов. Не используйте значения в этом примере, я не врач :-)

// сопоставление контактов
const uint8_t led_pin = LED_BUILTIN;

// показания датчика (%)
const int spo2_min = 85;
const int spo2_max = 100;

// время работы светодиода (мс)
const unsigned long led_off_min = 50;
const unsigned long led_off_max = 5000;

unsigned long led_off_time = led_off_max; // переменная времени выключения
const unsigned long led_on_time = 50;     // исправлено, короткое время

// время считывания показаний датчика (мс)
const unsigned long sensor_interval = 1000;

// состояние светодиода
uint8_t led_state = LOW;

// состояние "таймер"
unsigned long last_reading = 0;
unsigned long last_led_toggle = 0;

void setup() {
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, led_state);

  Serial.begin(9600);

  Serial.print("Инициализация пульсоксиметра..");
  if (!pox.begin()) {
    Serial.println("СБОЙ");
    for (;;);
  } else {
    Serial.println("УСПЕХ");
  }
}

void loop() {
  pox.update();
  unsigned long current_millis = millis();

  /* показания датчика "таймер" */
  if (current_millis - last_reading >= sensor_interval)
  {
    last_reading = current_millis;

    int spo2 = pox.getSpO2();

    // показания зажима в ожидаемом диапазоне
    int clamped = constrain(spo2, spo2_min, spo2_max);
    // отображение в диапазон нерабочего времени
    led_off_time = map(clamped,
                       spo2_min, spo2_max,
                       led_off_min, led_off_max);

    char buff[128];
    sprintf_P(buff, PSTR("reading: %d (%%) -> interval: %lu (ms)"),
              spo2, led_off_time);
    Serial.println(buff);
  }

  /* светодиод переключает "таймеры" */
  unsigned long led_elapsed = current_millis - last_led_toggle;

  if ((led_state == LOW) && (led_elapsed >= led_off_time))
  {
    last_led_toggle = current_millis;
    led_state = HIGH;
    digitalWrite(led_pin, led_state);
  }
  else if ((led_state == HIGH) && (led_elapsed >= led_on_time))
  {
    last_led_toggle = current_millis;
    led_state = LOW;
    digitalWrite(led_pin, led_state);
  }

}
,

Большое спасибо. Я уже пробовал ранее то же самое, что и этот способ, и это работает. Ваши объяснения сделали это более понятным для меня. Спасибо., @Sayzar

Здравствуйте, как насчет использования только одного красного светодиода при подаче импульса? Если <94, led will blink rapidly. if >=94, светодиод будет медленно мигать. Я попытался добавить delay(); но это работает при использовании задержки около 10 мс. но при задержке 500 мс петли spo2 также получают задержку, и она показывает только 0%. Не работает для большего цикла задержки. Есть какие-нибудь мысли ?, @Sayzar

задержка - не твой друг. Используйте ту же технику, что и для показаний датчика, т. Е. Проверьте время, прошедшее с момента последнего включения светодиода, и переключите его, если оно превышает ваш порог. Добавлен пример. Вероятно, это будет не очень хорошо, если вы будете получать только " int " в довольно небольшом диапазоне - у вас недостаточно детализации., @Mat

Другое примечание: если вам нужно что-то более сложное, чем это, я бы рекомендовал вам найти библиотеку таймеров, которая вам нравится, а также изучить конечные автоматы. Множество примеров и документов по обеим этим темам., @Mat

Привет, не могу отблагодарить тебя как следует. Потребуется время, чтобы понять, поскольку я немного не знаком с этим термином. Но я хочу указать на некоторые из них, которые я не смог понять , чар бафф[128]; sprintf_P(бафф, PSTR("чтение: %lu (%%) -> интервал: %lu (мс)"), spo2, led_off_time); Serial.println(buff); выдает этот вывод на последовательном мониторе, когда spo2 должен показывать 0% показаний: 3276800 (%) -> интервал: 1701969920 (мс) Итак, я напрямую вызвал Serial.print(pox.getSpO2());, @Sayzar

Еще одна вещь, которую я хотел показать, когда моргаю медленно, "здоровье в норме", а когда моргаю быстро,: критическое состояние здоровья" на последовательном мониторе. Сначала я попытался добавить последнюю инструкцию if else if, но последовательный монитор показывает обе строки. Итак, я создал еще один оператор if else для отображения на последовательном мониторе. Есть какие-нибудь улучшения и мысли по этому поводу?, @Sayzar

В строке формата printf была ошибка, исправлена, но я не могу воспроизвести то, что вы видите. Единственное место, где меняется скорость, находится в части обновления датчика. Если вы хотите напечатать что-то на основе значения считывания, оно должно быть указано там. Если вы хотите повторить его, вам нужно сохранить его, чтобы последнее чтение было доступно в другом месте цикла., @Mat