DIY пульсоксиметр на Arduino (MAX30102 + OLED) для мониторинга SpO2
Компоненты и материалы
| Arduino Nano R3 | 1 | |
| MAX30102 — датчик пульса и SpO2 (Maxim Integrated) | 1 | I2C, 5V/3.3V |
| OLED-дисплей 128x64 I2C (DFRobot Gravity) | 1 |
Инструменты
- 3D-принтер (для корпуса)
- Паяльник
Программное обеспечение
- Arduino IDE
- Autodesk Fusion 360 (модели корпуса)
О проекте
COVID-19 поражает дыхательную систему. Пульсоксиметр помогает отслеживать насыщение кислородом (SpO2) и пульс дома, чтобы вовремя обратиться к врачу. Важно: это не медицинский прибор, точность ниже профессиональных образцов.
Электроника
- MAX30102 — оптический датчик (красный + IR светодиоды), измеряет пульс и SpO2 по отражению от пальца.
- OLED 128x64 — вывод значений HR и SpO2.
- Arduino Nano — управление, расчёт алгоритмов.
Сборка пошагово
- Печать корпуса — STL-файлы в разделе CAD. Заполнение 70–80%, поддержки, PLA. После печати — удаление поддержек, шлифовка.
- Пайка — Nano на перфоплате 44×30 мм. Провода от MAX30102 (VIN, GND, SDA=A4, SCL=A5) под платой к Nano. OLED — разъём на Nano, провода к дисплею. Всё закрепляется винтами M3.
- Сборка — вставка электроники в корпус, крепление OLED крышкой, проверка движения клапана.
- Прошивка — установите библиотеки:
Wire,MAX30105(SparkFun),spo2_algorithm,SSD1306Ascii. Выберите плату Arduino Nano, загрузите скетч. - Использование — приложите палец к датчику, аккуратно закройте крышку, подайте питание (USB). Подождите калибровки (~4 сек) — появятся HR и SpO2.
Код (C/C++)
/* Подключение: VCC=5V, GND=GND, SDA=A4, SCL=A5, INT=NC */
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
MAX30105 particleSensor;
SSD1306AsciiWire oled;
#define MAX_BRIGHTNESS 255
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
uint16_t irBuffer[50], redBuffer[50]; // 16-bit для Uno/Nano (мало RAM)
#else
uint32_t irBuffer[50], redBuffer[50];
#endif
int32_t spo2; int8_t validSPO2;
int32_t heartRate; int8_t validHeartRate;
void setup() {
Serial.begin(115200);
oled.begin(&Adafruit128x64, 0x3C);
oled.setFont(Arial14);
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
Serial.println(F("MAX30105 not found!"));
while (1);
}
particleSensor.setup(55, 4, 2, 200, 411, 4096); // настройки датчика
}
void loop() {
// Первые 50 сэмплов — калибровка диапазона
for (byte i = 0; i < 50; i++) {
while (!particleSensor.available()) particleSensor.check();
redBuffer[i] = particleSensor.getRed();
irBuffer[i] = particleSensor.getIR();
particleSensor.nextSample();
Serial.print(F("red=")); Serial.print(redBuffer[i]);
Serial.print(F(", ir=")); Serial.println(irBuffer[i]);
}
maxim_heart_rate_and_oxygen_saturation(irBuffer, 50, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
// Основной цикл: скользящее окно 25 новых сэмплов
while (1) {
for (byte i = 25; i < 50; i++) { // сдвиг старых
redBuffer[i-25] = redBuffer[i];
irBuffer[i-25] = irBuffer[i];
}
for (byte i = 25; i < 50; i++) { // 25 новых
while (!particleSensor.available()) particleSensor.check();
redBuffer[i] = particleSensor.getRed();
irBuffer[i] = particleSensor.getIR();
particleSensor.nextSample();
Serial.print(F("red=")); Serial.print(redBuffer[i]);
Serial.print(F(", ir=")); Serial.print(irBuffer[i]);
Serial.print(F(", HR=")); Serial.print(heartRate);
Serial.print(F(", HRv=")); Serial.print(validHeartRate);
Serial.print(F(", SPO2=")); Serial.print(spo2);
Serial.print(F(", SPO2v=")); Serial.println(validSPO2);
}
maxim_heart_rate_and_oxygen_saturation(irBuffer, 50, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
printToScreen();
}
}
void printToScreen() {
oled.clear(); oled.setCursor(0,0);
if (validSPO2 && validHeartRate) {
oled.print(F("HR: ")); oled.println(heartRate);
oled.print(F("SPO2: ")); oled.println(spo2);
} else {
oled.print(F("Not valid"));
}
}
3D-модели корпуса
Файлы STL в разделе Custom parts (Fusion 360). Две половины корпуса + крышка с окном для OLED.
Схема подключения
Простая I2C: MAX30102 и OLED параллельно на A4/A5. Питание 5V от Nano. Схема в разделе Schematics.
Производственный процесс
- Журнал проекта FirePick Delta: создание открытого микрозавода с OpenPnP
- Цифровые кости на Arduino: генератор случайных чисел с LCD-дисплеем и кнопкой
- Строим Iron Man на Arduino: компоненты, сенсоры и пошаговый гайд
- Find Me: Умный поисковик вещей на Arduino и Bluetooth
- Сборка функционального 3D-печатного манипулятора на Arduino: пошаговое руководство
- Портативный пульсоксиметр для экстренного использования в условиях COVID-19
- DIY-контроллер увлажнителя на Arduino с реле: безопасная работа с высоким напряжением
- NeoPixel Matrix Pong на Arduino Nano: неоновая игра Pong на матрице 15×10
- Health Band: умный браслет для мониторинга пожилых людей на Arduino Nano и DPS310
- Почему открытый исходный код движет инновациями на периферии — важная электронная книга