Использование значения 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();
}
}
@Sayzar, 👍2
1 ответ
Лучший ответ:
Вы уже проделали всю тяжелую работу, настроив датчик и научившись считывать данные с него.
Я бы определил константу для порога 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);
}
}
- Несколько неблокирующих таймеров обратного отсчета?
- Проблема с последовательностью воздушных поршней
- Esp8266 Vin контакт
- (Код ультразвукового датчика: такого файла или каталога нет)
- Датчик HC-SR505 PIR выдает только HIGH уровень
- Отправка данных из ESP8266 в PHP
- Определение уровня заряда с помощью датчика тока (ACS758) с arduino uno
- Использование YS-IRTM с Arduino Uno
Большое спасибо. Я уже пробовал ранее то же самое, что и этот способ, и это работает. Ваши объяснения сделали это более понятным для меня. Спасибо., @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