Датчик содержания кислорода в крови MAX30102

Пользовательские блоки расширяющие базовый функуионал программы по работе с различными датчиками и энкодерами
Правила форума
Рекомендации по размещению блоков:
Автор блока создает подробное описание блока, отличие от подобных(если есть на данный момент).Сложные блоки очень желательно с примерами.
При выходе новых версий редактирует/дополняет свой первый пост с указанием даты, версии, причины.
В каждой теме обсуждается только выложенный автором блок - баги, возможность (или предложение) доработки и прочие хотелки.
Свои блоки, переработанные, с другими библиотеками, протоколами и т.д.- размещаем либо сами отдельно, либо обсуждаем и дорабатываем в форуме Разработка блоков.
Пользователи улучшив блок автора и проверив его работоспособность - могут обратиться к автору или модераторам с просьбой добавить их версию блока в первое сообщение темы.
Аватара пользователя
НиколаМастер
Рядовой
Сообщения: 99
Зарегистрирован: 10.01.2018{, 12:36}
Репутация: 8
Контактная информация:

Датчик содержания кислорода в крови MAX30102

#1

Сообщение НиколаМастер » 01.08.2020{, 09:06}

Друзья, в свете последних событий, прикупил датчик MAX30102 и собрал схемку по образцу:
кислород и пульс
Данные читаются только в ком порту, экран не заводится, видимо нужна другая библиотека. Прошу помощи.
Можете изменить скетч с правильной библиотекой? Я не знаю как ее прописать дальше в теле...
И хорошо бы написать блок для такого датчика, всем бы пригодился.
Огромное спасибо тем кто откликнется!
Добра всем!
Brevis esse laboro, obscurus fiо - если я стараюсь быть кратким, я становлюсь непонятным

Ingwar
Полковник
Сообщения: 1929
Зарегистрирован: 28.10.2015{, 22:47}
Репутация: 223
Откуда: Ленобласть
Имя: Игорь

Датчик содержания кислорода в крови MAX30102

#21

Сообщение Ingwar » 29.10.2020{, 11:33}

Ardudue писал(а):
29.10.2020{, 11:28}
Ingwar, скетч для MAX30102 вдез в Atmega4808 -работает?
Бибки для проекта скиньте, проверю.

Отправлено спустя 20 минут 50 секунд:
Ingwar писал(а):
18.09.2020{, 15:18}
Как придут - потестю.
Если поняли, что по приезду контроллеров, я планировал проверить MAX30102, то ввел Вас в заблуждение, у меня нет такой микрухи.
Планировал потестить работу в целом и сравнить объемы памяти. О чем уже отписался. Вы можете самостоятельно, добавив ядро в IDE проверить компиляцию для 4808.
Еще раз извиняюсь.
Люди в своем большинстве живо интересуются всем на свете, за исключением того, что действительно стоит знать.

fsergei70
Капитан
Сообщения: 786
Зарегистрирован: 17.11.2015{, 20:36}
Репутация: 54
Имя: Сергей

Датчик содержания кислорода в крови MAX30102

#22

Сообщение fsergei70 » 29.10.2020{, 12:28}

Вот тема подключения MAX30102 к ESP8266 http://www.esp8266learning.com/max30102 ... desyntax_1
Вот библиотека с примерами для ESP8266 https://github.com/sparkfun/SparkFun_MA ... or_Library
Вот библиотека для Arduino https://github.com/catnull/Max30102Driver-For-Arduino

Если заморачиваться с MAX30102 то лучше наверно все таки использовать вариант с ESP8266, тогда можно данные в веб интерфейс вывести или через modbus в туже Kascada, а там хоть график строй хоть архивируй.

Отправлено спустя 2 минуты 55 секунд:
В догонку еще вариант на ATTINY85 https://www.rlocman.ru/shem/schematics.html?di=615757

Ardudue
Лейтенант
Сообщения: 423
Зарегистрирован: 13.04.2020{, 18:22}
Репутация: 24
Имя: Антон

Датчик содержания кислорода в крови MAX30102

#23

Сообщение Ardudue » 29.10.2020{, 15:17}

fsergei70 писал(а):
29.10.2020{, 12:31}
Вот тема подключения MAX30102 к ESP8266
кислород не выводит

fsergei70
Капитан
Сообщения: 786
Зарегистрирован: 17.11.2015{, 20:36}
Репутация: 54
Имя: Сергей

Датчик содержания кислорода в крови MAX30102

#24

Сообщение fsergei70 » 29.10.2020{, 16:10}

Ardudue писал(а):
29.10.2020{, 15:17}
кислород не выводит
В библиотеке для ESP есть пример с кислородом называется Example8_SPO2

Ardudue
Лейтенант
Сообщения: 423
Зарегистрирован: 13.04.2020{, 18:22}
Репутация: 24
Имя: Антон

Датчик содержания кислорода в крови MAX30102

#25

Сообщение Ardudue » 29.10.2020{, 16:47}

fsergei70 писал(а):
29.10.2020{, 16:10}
Example8_SPO2
это пример для ATmega
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)

Отправлено спустя 14 минут 28 секунд:
В комментах пишут что в ESP не работает пример.

fsergei70
Капитан
Сообщения: 786
Зарегистрирован: 17.11.2015{, 20:36}
Репутация: 54
Имя: Сергей

Датчик содержания кислорода в крови MAX30102

#26

Сообщение fsergei70 » 05.11.2020{, 16:14}

Проект для пробы (не проверял, нет сенсора), данные выводятся в монитор порта.
Вложения
MAX30102.flp
(27.33 КБ) 57 скачиваний

fsergei70
Капитан
Сообщения: 786
Зарегистрирован: 17.11.2015{, 20:36}
Репутация: 54
Имя: Сергей

Датчик содержания кислорода в крови MAX30102

#27

Сообщение fsergei70 » 17.11.2020{, 15:24}

Обновил блок в проекте, убрал вывод в монитор порта для экономии памяти, прикрутил выходы частоты пульса и содержания кислорода. Кто проверит отпишитесь, а то сенсора нет в наличии.

Не качайте блок с железом не работает, да и пример из библиотеки можно сказать не работает, показания прыгают. Ищем рабочий скетч.
Вложения
30102.flp
(61.53 КБ) 61 скачивание
Последний раз редактировалось fsergei70 21.11.2020{, 05:17}, всего редактировалось 1 раз.

Ardudue
Лейтенант
Сообщения: 423
Зарегистрирован: 13.04.2020{, 18:22}
Репутация: 24
Имя: Антон

Датчик содержания кислорода в крови MAX30102

#28

Сообщение Ardudue » 19.11.2020{, 13:52}

Приехала китайская плата, не определилалсь I2C.
Пришлось шаманить с подтяжкой I2C, китайцы почему то на резистоы подтяжки I2C подают 1,8V.
Перерезал дорожку подал на резисторы 3,3V.
Датчик завелся , но гонит пургу.
MAX30102 монитор.JPG
Отправлено спустя 3 часа 27 минут 20 секунд:
fsergei70 писал(а):
17.11.2020{, 15:24}
Обновил блок в проекте, убрал вывод в монитор порта для экономии памяти, прикрутил выходы частоты пульса и содержания кислорода. Кто проверит отпишитесь, а то сенсора нет в наличии.
прицепил LCD1602 - ничего не показывает.
MAX30102_пульс_О2_LCD1602.flp
(130.28 КБ) 48 скачиваний
Красный диод зажигает на MAX30102 - значит микросхема активирована.

fsergei70
Капитан
Сообщения: 786
Зарегистрирован: 17.11.2015{, 20:36}
Репутация: 54
Имя: Сергей

Датчик содержания кислорода в крови MAX30102

#29

Сообщение fsergei70 » 19.11.2020{, 19:38}

Ingwar писал(а):
29.10.2020{, 11:54}
Красный диод зажигает на MAX30102 - значит микросхема активирована.
Получил сегодня сенсор тоже. Попробовал пример с первого поста, показания очень нестабильные. Пример с первого поста с библиотекой для дисплея из описания не работает. Нашёл другую библиотеку для дисплея, по названию файла , текст на дисплее получился очень мелкий, но самое главное показания то есть то нет.

Отправлено спустя 3 минуты 21 секунду:
Пример из библиотеки так же работает нестабильно, и сжирает всю память. В общем нужен рабочий пример а потом из него делать уже блок.

Ardudue
Лейтенант
Сообщения: 423
Зарегистрирован: 13.04.2020{, 18:22}
Репутация: 24
Имя: Антон

Датчик содержания кислорода в крови MAX30102

#30

Сообщение Ardudue » 19.11.2020{, 20:52}

Запустил с ESP32, два датчика гонят что попало. При включенном свете что то показывают и потом -999.
Скетч подрулил для ESP32 "Вывод значений уровня SpO2 в монитор порта":
СпойлерПоказать

Код: Выделить всё

/*
Вывод значений уровня SpO2 в монитор порта
-------------------------------------------------------------
ESP32 компилируется 18.11.2020 (Ядро Release Version 1.0.4).
ESP32 подключение I2C
SDA: SDA (default is GPIO 21)
SCL: SCL (default is GPIO 22)
-------------------------------------------------------------
ESP8266 компилируется 18.11.2020 (Ядро Release Version 2.7.4).
STM32F103C8 компилируется 18.11.2020 (Ядро Release Version 1.9.0).
*/
#define  MAX_BRIGHTNESS 255                         //  Задаём переменную максимальной яркости свечения светодиода
//--------------------------------------------------//
#include "Wire.h"                                   //  Подключаем библиотеку для работы с шиной I2C
#include "MAX30105.h"                               //  Подключаем библиотеку для работы с модулем. Библиотека SparkFun_MAX3010x_Sensor_Library
#include "spo2_algorithm.h"                         //  Подключаем блок работы с насыщением крови кислородом
MAX30105 PARTICLE_SENSOR;                           //  Создаём объект для работы с библиотекой
//--------------------------------------------------//
//  32-битная переменная занимает в памяти 4 байта. Дальше используется 2 массива, каждый из которых содержит 100 значений.
//  Если эти переменные будут 32-х битные, то они займут 100*4*2 = 800 байт. Arduino UNO имеет всего 2 Килобайт (2048 байт) памяти,
//  поэтому при создании всех остальных переменных её объёма памяти не хватит. В связи с этим при запуске скетча выполняется проверка
//  типа платы. Если это Arduino UNO (имеющая на борту микроконтроллер ATmega328), то будут созданы 16-битные массивы, чтобы занимать
//  в 2 раза меньше места. Так как данные с сенсора считываются в 32-битном формате, то при записи в 16-битный массив эти значения
//  будут автоматически обрезаны.
/* #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
uint16_t irBuffer[100];                             //  16-битный массив данных от сенсора со значениями от ИК-светодиода
uint16_t redBuffer[100];                            //  16-битный массив данных от сенсора со значениями от красного светодиода
#else
*/
uint32_t irBuffer[100];                             //  32-битный массив данных от ИК-фотодиода (сенсора) со значениями от засветки на палец ИК-светодиодом
uint32_t redBuffer[100];                            //  32-битный массив данных от фотодиода (сенсора) со значениями от красного светодиода
// #endif
//--------------------------------------------------//
int32_t bufferLength;                               //  длина буфера данных
int32_t spo2;                                       //  значение SpO2 (насыщенности крови кислородом)
int8_t  validSPO2;                                  //  флаг валидности значений сенсора по SpO2
int32_t heartRate;                                  //  значение ЧСС
int8_t  validHeartRate;                             //  флаг валидности значений сенсора по ЧСС
//--------------------------------------------------//
void setup() {
  Serial.begin(115200);                             //  инициируем работу с монитором последовательного порта на скорости 115200 бод
  if (!PARTICLE_SENSOR.begin()) {                   //  инициируем работу с сенсором. Если этого не произошло, то
    Serial.println(F("MAX30105 was not found."));   //  Выводим сообщением об этом и
    while (1);                                      //  останавливаем дальнейшее выполнение скетча
  }
  Serial.println(F("Press any key!"));              //  Прежде, чем переходить к считыванию, выводим в монитор порта сообщение и
  while (Serial.available() == 0);                  //  ждём отправки любого символа в монитор порта (нажмите Enter, находясь в строке отправки)
  Serial.read();                                    //  Если символ получен, то скетч будет выполнен дальше
  //------------------------------------------------//
  //  Блок настроек сенсора для работы в режиме определения насыщенности крови кислородом и определения ЧСС:
  byte ledBrightness  = 60;                         //  60 -Задаём яркость работы светодиода, при этом потребление тока будет следующим: 0 - 0мА, 255 - 50 мА
  byte sampleAverage  = 4;                          //  Устанавливаем коэффициент усреднения. Возможные варианты значений: 1, 2, 4, 8, 16, 32
  byte ledMode        = 2;                          //  Устанавливаем режим работы светодиодов на сенсоре: 1 - только красный (Red only), 2 - красный и ИК (Red + IR), 3 - красный, ИК и зелёный (Red + IR + Green)
  byte sampleRate     = 100;                        //  Устанавливаем частоту дискретизации (сглаживания сигнала). Варианты: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int  pulseWidth     = 411;                        //  Устанавливаем ширину импульса. Варианты: 69, 118, 215, 411
  int  adcRange       = 4096;                       //  Устанавливаем диапазон значений с АЦП. Варианты: 2048(11 бит), 4096(12 бит), 8192(13 бит), 16384(14 бит)
  //------------------------------------------------//
  //  Настраиваем сенсор согласно вышеуказанным настройкам
  PARTICLE_SENSOR.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
}
//----------------------------------------------------//
void loop() {
  bufferLength = 100;                                 //  Устанавливаем длину буфера равным 100 (куда будут записаны пакеты по 25 значений в течении 4 секунд)
  //  считываем первые 100 значений и определяем диапазон значений сигнала:
  for (byte i = 0 ; i < bufferLength ; i++) {         //  проходим в цикле по буферу и
    while (PARTICLE_SENSOR.available() == false)      //  отправляем сенсору запрос на получение новых данных
      PARTICLE_SENSOR.check();
    redBuffer[i] = PARTICLE_SENSOR.getRed();          //  Записываем в массив значения сенсора, полученные при работе с КРАСНЫМ светодиодом
    irBuffer[i] = PARTICLE_SENSOR.getIR();            //  Записываем в массив значения сенсора, полученные при работе с ИК      светодиодом
    PARTICLE_SENSOR.nextSample();                     //  Как только в буфер было записано 100 значений - отправляем сенсору команду начать вычислять значения ЧСС и SpO2
    Serial.print(F("red="));                          //  Выводим текст в монитор последовательного порта
    Serial.print(redBuffer[i], DEC);                  //  Выводим значение переменной redBuffer[i] в монитор последовательного порта
    Serial.print(F(", ir="));                         //  Выводим текст в монитор последовательного порта
    Serial.println(irBuffer[i], DEC);                 //  Выводим значение переменной irBuffer[i] в монитор последовательного порта
  }

  //  Вычисляем значения ЧСС и SpO2 по первым полученным 100 значениям:
  maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

  //  Непрерывно считываем значений с сенсора и вычисляем значения ЧСС и SpO2 каждую секунду
  while (1) {
    //  Сбрасываем первые полученные 25 значений из буфера, а оставшиеся 75 сдвигаем влево в массиве
    for (byte i = 25; i < 100; i++) {
      redBuffer[i - 25] = redBuffer[i];
      irBuffer[i - 25] = irBuffer[i];
    }
    //  Получаем новые 25 значений прежде чем переходить к вычислению ЧСС
    for (byte i = 75; i < 100; i++) {
      while (PARTICLE_SENSOR.available() == false) {  //  Опрашиваем сенсор на предмет наличия новых значений
        PARTICLE_SENSOR.check();
      }
      redBuffer[i] = PARTICLE_SENSOR.getRed();        //  Записываем в массив значения сенсора, полученные при работе с КРАСНЫМ светодиодом
      irBuffer[i] = PARTICLE_SENSOR.getIR();          //  Записываем в массив значения сенсора, полученные при работе с ИК      светодиодом
      PARTICLE_SENSOR.nextSample();                   //  Как только в буфер было записано 100 значений - отправляем сенсору команду начать вычислять значения ЧСС и SpO2

      Serial.print(F("red="));                        //  Выводим текст в монитор последовательного порта
      Serial.print(redBuffer[i], DEC);                //  Выводим значение переменной   redBuffer[i](красный-фотодиод)в монитор последовательного порта
      Serial.print(F(", ir="));                       //  Выводим текст в монитор последовательного порта
      Serial.print(irBuffer[i], DEC);                 //  Выводим значение переменной   irBuffer[i] (ИК-фотодиод)в монитор последовательного порта
      Serial.print(F(", HR="));                       //  Выводим текст в монитор последовательного порта
      Serial.print(heartRate, DEC);                   //  Выводим значение переменной   heartRate      в монитор последовательного порта
      Serial.print(F(", HRvalid="));                  //  Выводим текст в монитор последовательного порта
      Serial.print(validHeartRate, DEC);              //  Выводим значение переменной   validHeartRate в монитор последовательного порта
      Serial.print(F(", SPO2="));                     //  Выводим текст в монитор последовательного порта
      Serial.print(spo2, DEC);                        //  Выводим значение переменной   spo2           в монитор последовательного порта
      Serial.print(F(", SPO2Valid="));                //  Выводим текст в монитор последовательного порта
      Serial.println(validSPO2, DEC);                 //  Выводим значение переменной   validSPO2      в монитор последовательного порта
    }
    //  После получения очередного пакета из 25 значений повторно считаем значения ЧСС и SpO2
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
  }
}

fsergei70
Капитан
Сообщения: 786
Зарегистрирован: 17.11.2015{, 20:36}
Репутация: 54
Имя: Сергей

Датчик содержания кислорода в крови MAX30102

#31

Сообщение fsergei70 » 20.11.2020{, 09:09}

Ardudue писал(а):
19.11.2020{, 20:52}
Запустил с ESP32, два датчика гонят что попало. При включенном свете что то показывают и потом -999.
Скетч подрулил для ESP32 "Вывод значений уровня SpO2 в монитор порта":
Подредактировал проект данные пошли на ардуино, но все так же нестабильно. Пример бы нормальный а то, тот что в библиотеке работает ужасно нестабильно.
Вложения
MAX30102_2_(Code_-_Basic).ubi
(47.36 КБ) 58 скачиваний
Последний раз редактировалось fsergei70 21.11.2020{, 05:20}, всего редактировалось 1 раз.

Ardudue
Лейтенант
Сообщения: 423
Зарегистрирован: 13.04.2020{, 18:22}
Репутация: 24
Имя: Антон

Датчик содержания кислорода в крови MAX30102

#32

Сообщение Ardudue » 20.11.2020{, 20:36}

На форуме японский товарищ подсказал плату MAX30102 засунуть в полиэтиленовый пакет
СпойлерПоказать
ESP32_MAX30102.jpeg
На ESP32 этот скетч работает четко(показания смотрим в плоттере)
СпойлерПоказать

Код: Выделить всё

/*
 ## Hardware Connections (Breakoutboard to ESP32 Arduino):
  -VIN = 3.3V
  -GND = GND
  -SDA = 21 (or SDA)
  -SCL = 22 (or SCL)
  -INT = Not connected
  */
  
  
#include <Wire.h>
#include "MAX30105.h" //sparkfun MAX3010X library
MAX30105 particleSensor;

//#define MAX30105 //if you have Sparkfun's MAX30105 breakout board , try #define MAX30105 

#define USEFIFO
void setup()
{
  Serial.begin(115200);
  Serial.println("Initializing...");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
  {
    Serial.println("MAX30102 was not found. Please check wiring/power/solder jumper at MH-ET LIVE MAX30102 board. ");
    while (1);
  }

  //Setup to sense a nice looking saw tooth on the plotter
  byte ledBrightness = 0x7F; //Options: 0=Off to 255=50mA
  byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
  byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
  //Options: 1 = IR only, 2 = Red + IR on MH-ET LIVE MAX30102 board
  int sampleRate = 200; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int pulseWidth = 411; //Options: 69, 118, 215, 411
  int adcRange = 16384; //Options: 2048, 4096, 8192, 16384
  // Set up the wanted parameters
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
}
double avered = 0; double aveir = 0;
double sumirrms = 0;
double sumredrms = 0;
int i = 0;
int Num = 100;//calculate SpO2 by this sampling interval

double ESpO2 = 95.0;//initial value of estimated SpO2
double FSpO2 = 0.7; //filter factor for estimated SpO2
double frate = 0.95; //low pass filter for IR/red LED value to eliminate AC component
#define TIMETOBOOT 3000 // wait for this time(msec) to output SpO2
#define SCALE 88.0 //adjust to display heart beat and SpO2 in the same scale
#define SAMPLING 5 //if you want to see heart beat more precisely , set SAMPLING to 1
#define FINGER_ON 30000 // if red signal is lower than this , it indicates your finger is not on the sensor
#define MINIMUM_SPO2 80.0
void loop()
{

  uint32_t ir, red , green;
  double fred, fir;
  double SpO2 = 0; //raw SpO2 before low pass filtered

#ifdef USEFIFO
  particleSensor.check(); //Check the sensor, read up to 3 samples

  while (particleSensor.available()) {//do we have new data
#ifdef MAX30105
   red = particleSensor.getFIFORed(); //Sparkfun's MAX30105
    ir = particleSensor.getFIFOIR();  //Sparkfun's MAX30105
#else
    red = particleSensor.getFIFOIR(); //why getFOFOIR output Red data by MAX30102 on MH-ET LIVE breakout board
    ir = particleSensor.getFIFORed(); //why getFIFORed output IR data by MAX30102 on MH-ET LIVE breakout board
#endif
    i++;
    fred = (double)red;
    fir = (double)ir;
    avered = avered * frate + (double)red * (1.0 - frate);//average red level by low pass filter
    aveir = aveir * frate + (double)ir * (1.0 - frate); //average IR level by low pass filter
    sumredrms += (fred - avered) * (fred - avered); //square sum of alternate component of red level
    sumirrms += (fir - aveir) * (fir - aveir);//square sum of alternate component of IR level
    if ((i % SAMPLING) == 0) {//slow down graph plotting speed for arduino Serial plotter by thin out
      if ( millis() > TIMETOBOOT) {
        float ir_forGraph = (2.0 * fir - aveir) / aveir * SCALE;
        float red_forGraph = (2.0 * fred - avered) / avered * SCALE;
        //trancation for Serial plotter's autoscaling
        if ( ir_forGraph > 100.0) ir_forGraph = 100.0;
        if ( ir_forGraph < 80.0) ir_forGraph = 80.0;
        if ( red_forGraph > 100.0 ) red_forGraph = 100.0;
        if ( red_forGraph < 80.0 ) red_forGraph = 80.0;
        //        Serial.print(red); Serial.print(","); Serial.print(ir);Serial.print(".");
        if (ir < FINGER_ON) ESpO2 = MINIMUM_SPO2; //indicator for finger detached
        Serial.print(ir_forGraph); // to display pulse wave at the same time with SpO2 data
        Serial.print(","); Serial.print(red_forGraph); // to display pulse wave at the same time with SpO2 data
        Serial.print(",");
        Serial.print(ESpO2); //low pass filtered SpO2
        Serial.print(","); Serial.print(85.0); //reference SpO2 line
        Serial.print(","); Serial.print(90.0); //warning SpO2 line
        Serial.print(","); Serial.print(95.0); //safe SpO2 line
        Serial.print(","); Serial.println(100.0); //max SpO2 line
      }
    }
    if ((i % Num) == 0) {
      double R = (sqrt(sumredrms) / avered) / (sqrt(sumirrms) / aveir);
      // Serial.println(R);
      SpO2 = -23.3 * (R - 0.4) + 100; //http://ww1.microchip.com/downloads/jp/AppNotes/00001525B_JP.pdf
      ESpO2 = FSpO2 * ESpO2 + (1.0 - FSpO2) * SpO2;//low pass filter
      //  Serial.print(SpO2);Serial.print(",");Serial.println(ESpO2);
      sumredrms = 0.0; sumirrms = 0.0; i = 0;
      break;
    }
    particleSensor.nextSample(); //We're finished with this sample so move to next sample
    //Serial.println(SpO2);
  }
#else

  while (1) {//do we have new data
#ifdef MAX30105
   red = particleSensor.getRed();  //Sparkfun's MAX30105
    ir = particleSensor.getIR();  //Sparkfun's MAX30105
#else
    red = particleSensor.getIR(); //why getFOFOIR outputs Red data by MAX30102 on MH-ET LIVE breakout board
    ir = particleSensor.getRed(); //why getFIFORed outputs IR data by MAX30102 on MH-ET LIVE breakout board
#endif
    i++;
    fred = (double)red;
    fir = (double)ir;
    avered = avered * frate + (double)red * (1.0 - frate);//average red level by low pass filter
    aveir = aveir * frate + (double)ir * (1.0 - frate); //average IR level by low pass filter
    sumredrms += (fred - avered) * (fred - avered); //square sum of alternate component of red level
    sumirrms += (fir - aveir) * (fir - aveir);//square sum of alternate component of IR level
    if ((i % SAMPLING) == 0) {//slow down graph plotting speed for arduino IDE toos menu by thin out
      //#if 0
      if ( millis() > TIMETOBOOT) {
        float ir_forGraph = (2.0 * fir - aveir) / aveir * SCALE;
        float red_forGraph = (2.0 * fred - avered) / avered * SCALE;
        //trancation for Serial plotter's autoscaling
        if ( ir_forGraph > 100.0) ir_forGraph = 100.0;
        if ( ir_forGraph < 80.0) ir_forGraph = 80.0;
        if ( red_forGraph > 100.0 ) red_forGraph = 100.0;
        if ( red_forGraph < 80.0 ) red_forGraph = 80.0;
        //        Serial.print(red); Serial.print(","); Serial.print(ir);Serial.print(".");
        if (ir < FINGER_ON) ESpO2 = MINIMUM_SPO2; //indicator for finger detached
        Serial.print((2.0 * fir - aveir) / aveir * SCALE); // to display pulse wave at the same time with SpO2 data
        Serial.print(","); Serial.print((2.0 * fred - avered) / avered * SCALE); // to display pulse wave at the same time with SpO2 data
        Serial.print(","); Serial.print(ESpO2); //low pass filtered SpO2
        Serial.print(","); Serial.print(85.0); //
        Serial.print(","); Serial.print(90.0); //warning SpO2 line
        Serial.print(","); Serial.print(95.0); //safe SpO2 line
        Serial.print(","); Serial.println(100.0); //max SpO2 line
        //#endif
      }
    }
    if ((i % Num) == 0) {
      double R = (sqrt(sumredrms) / avered) / (sqrt(sumirrms) / aveir);
      // Serial.println(R);
      SpO2 = -23.3 * (R - 0.4) + 100; //http://ww1.microchip.com/downloads/jp/AppNotes/00001525B_JP.pdf
      ESpO2 = FSpO2 * ESpO2 + (1.0 - FSpO2) * SpO2;
      //  Serial.print(SpO2);Serial.print(",");Serial.println(ESpO2);
      sumredrms = 0.0; sumirrms = 0.0; i = 0;
      break;
    }
    particleSensor.nextSample(); //We're finished with this sample so move to next sample
    //Serial.println(SpO2);
  }
#endif
}
  
В плоттере
fingerOffOn.png
теперь можно и блоком заняться.

fsergei70
Капитан
Сообщения: 786
Зарегистрирован: 17.11.2015{, 20:36}
Репутация: 54
Имя: Сергей

Датчик содержания кислорода в крови MAX30102

#33

Сообщение fsergei70 » 21.11.2020{, 05:14}

Ardudue писал(а):
20.11.2020{, 20:36}
теперь можно и блоком заняться.
Попробуйте. Под ESP32 и arduino компилируется нормально и памяти жрет в 2 раза меньше.
Вложения
max30102 ESP32.flp
(35.4 КБ) 79 скачиваний

Dmabst
Сержант
Сообщения: 149
Зарегистрирован: 08.12.2018{, 16:49}
Репутация: 10
Имя: Дмитрий

Датчик содержания кислорода в крови MAX30102

#34

Сообщение Dmabst » 30.11.2020{, 02:05}

Ardudue, а что может означать в даташите MAX30102 картинка на стр. 6 с названием:DC COUNTS vs. DISTANCE FOR WHITE HIGH-IMPACT STYRENE CARD ?

Ardudue
Лейтенант
Сообщения: 423
Зарегистрирован: 13.04.2020{, 18:22}
Репутация: 24
Имя: Антон

Датчик содержания кислорода в крови MAX30102

#35

Сообщение Ardudue » 08.12.2020{, 08:34}

Dmabst писал(а):
30.11.2020{, 02:05}
Ardudue, а что может означать в даташите MAX30102 картинка на стр. 6
у меня на 6странице только графики, картинок никаких нет.

Аватара пользователя
rw6cm
Полковник
Сообщения: 2283
Зарегистрирован: 06.09.2015{, 20:25}
Репутация: 334
Имя: Владимир

Датчик содержания кислорода в крови MAX30102

#36

Сообщение rw6cm » 08.12.2020{, 09:32}

Dmabst писал(а):
30.11.2020{, 02:05}
а что может означать в даташите MAX30102 картинка на стр. 6 с названием:
Пока не вникал в тонкости его работы(на днях выписал такой датчик)
Но думаю это график зависимости суммарной точности от расстояния между датчиком,
и стерильной прозрачной пластины, которая контактирует с телом.
Win10-64, FLProg (portable)

Dmabst
Сержант
Сообщения: 149
Зарегистрирован: 08.12.2018{, 16:49}
Репутация: 10
Имя: Дмитрий

Датчик содержания кислорода в крови MAX30102

#37

Сообщение Dmabst » 09.12.2020{, 02:50}

Ardudue писал(а):
08.12.2020{, 08:34}
Dmabst писал(а):
30.11.2020{, 02:05}
Ardudue, а что может означать в даташите MAX30102 картинка на стр. 6
у меня на 6странице только графики, картинок никаких нет.
Я его и имел в виду.

Dmabst
Сержант
Сообщения: 149
Зарегистрирован: 08.12.2018{, 16:49}
Репутация: 10
Имя: Дмитрий

Датчик содержания кислорода в крови MAX30102

#38

Сообщение Dmabst » 14.12.2020{, 23:39}

"Делаем пульсоксиметр и фотоплетизмограф на микроконтроллере ATtiny85"
https://www.rlocman.ru/shem/schematics.html?di=615757

Ardudue
Лейтенант
Сообщения: 423
Зарегистрирован: 13.04.2020{, 18:22}
Репутация: 24
Имя: Антон

Датчик содержания кислорода в крови MAX30102

#39

Сообщение Ardudue » 15.12.2020{, 09:13}

В общем применительно к MAX30102 примеры из библиотеки sparkfun MAX3010X нерабочие. Не знаю как с MAX30105 -нет такой железки.
И MAX30102 отлично работает с ESP32 и STM32. На Atmega328 вообще никак.

Отправлено спустя 2 часа 57 минут 15 секунд:
Протестировал
Dmabst писал(а):
14.12.2020{, 23:39}
"Делаем пульсоксиметр и фотоплетизмограф на микроконтроллере ATtiny85"
https://www.rlocman.ru/shem/schematics.html?di=615757
Вернуться к началу
из-за отсутствия ATtiny85 , нашёлся у автора скетч для нано , собрал на нано этот проект https://github.com/jeffmer/tinyPulsePPG ... noPulsePPG , как то работает , но показания скачут на трех подопытных :yes:

Ответить

Вернуться в «Датчики и энкодеры»