Oksimeter Nadi Open-Source DIY untuk COVID-19: Build Arduino
Komponen dan Perlengkapan
Arduino Nano R3
1
Maxim Integrated MAX30102 Pulse and Heartrate Sensor
1
DFRobot Gravity I2C OLED-2864 Display
1
Alat dan Mesin yang Diperlukan
3D Printer (umum)
Soldering iron (umum)
Aplikasi dan Layanan Online
Arduino IDE
Autodesk Fusion 360
Tentang Proyek
Tantangan COVID-19
COVID-19 adalah penyakit yang disebabkan oleh virus SARS-CoV-2 yang terutama menyerang sistem pernapasan seseorang. Beberapa gejala ringan dapat termasuk demam, nyeri, dan menggigil, tetapi dapat juga mengakibatkan kondisi yang lebih serius seperti pneumonia. Seseorang yang memiliki pneumonia atau bahkan sesak napas ringan mungkin tidak tahu kapan harus pergi ke rumah sakit, terutama saat mereka mulai semakin tertekan. Itulah sebabnya saya membuat oksimeter nadi open source ini, yang dapat membantu mendapatkan bantuan yang diperlukan dan mendapatkan informasi akurat tentang kondisi saat ini mereka.
Sedikit Disclaimer
Perangkat/proyek ini tidak boleh digunakan sebagai alat diagnostik medis yang akurat!
Elektronika
MAX30102
128x64 Pixel OLED
Arduino Nano
Membangun Perangkat Langkah demi Langkah
Ini adalah walkthrough langkah demi langkah cara membangun proyek ini.
1. Cetak dan Bersihkan Bagian
Mulai dengan mengunduh setiap bagian dari bagian lampiran pada proyek ini dan memuatnya ke slicer pilihan Anda. Saya menggunakan infill sekitar 70-80% dan support medium, semuanya dengan PLA. Setelah selesai dicetak, saya menghapus support dan melakukan penggerusan ringan untuk memastikan semuanya pas dengan rapi.
2. Pasang Elektronika
Seluruh perangkat dirancang di sekitar Arduino Nano yang dipasang pada papan perfboard 44mm x 30mm. Pertama, kabel disolder ke pin VIN, GND, SDA, dan SCL sensor dan kemudian dijalankan di bawah potongan kasar ke Arduino Nano.
Selanjutnya, konektor untuk OLED dipasang ke Nano dan kemudian dijalankan ke layar itu sendiri.
Dan akhirnya, seluruh rangkaian elektronika dimasukkan ke dalam casing dan dijamin dengan beberapa skru 3mm.
3. Rangkai Perangkat
Setelah elektronika dimasukkan, cukup pasang layar OLED ke bagian atas dan jamin ke sisa chassis dengan beberapa skru 3mm. Anda dapat menguji geraknya dengan menggerakkan tutup ke atas dan ke bawah dengan lembut.
4. Mengunggah Sketch
Sketch yang disertakan melakukan beberapa tindakan untuk menampilkan detak jantung dan saturasi oksigen saat ini pengguna. Untuk mengunggahnya, cukup instal library yang diperlukan dan pilih Arduino Nano dari daftar papan di menu Tools dan klik Upload.
Seperti yang diketahui tentang sketch itu sendiri, pertama-tama menginisialisasi OLED dan MAX30102, sambil melaporkan kesalahan apa pun yang mungkin timbul. Selanjutnya, membaca 100 nilai untuk mengkalibrasi sensor dan mulai menampilkannya. Perangkat kemudian memasuki loop di mana membaca 25 nilai baru dan menghitung rata-rata bergerak dengan mereka. Akhirnya, memeriksa apakah nilai-nilai valid dan mencetaknya ke layar jika valid.
5. Menggunakannya
Untuk menggunakan oksimeter nadi, letakkan ujung jari Anda di atas sensor dan tutup tutup atas dengan lembut. Kemudian colok sumber daya dan tunggu sampai Anda melihat data ditampilkan.
Kode
Pulse Oximeter Code
Pulse Oximeter CodeC/C++
/* Hardware Connections (Breakoutboard to Arduino): -5V = 5V (3.3V is allowed) -GND = GND -SDA = A4 (or SDA) -SCL = A5 (or SCL) -INT = Not connected The MAX30105 Breakout can handle 5V or 3.3V I2C logic. We recommend powering the board with 5V but it will also run at 3.3V. */ #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__) //Arduino Uno doesn't have enough SRAM to store 50 samples of IR led data and red led data in 32-bit format //To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data. uint16_t irBuffer[50]; //infrared LED sensor data uint16_t redBuffer[50]; //red LED sensor data #else uint32_t irBuffer[50]; //infrared LED sensor data uint32_t redBuffer[50]; //red LED sensor data #endif int32_t spo2; //SPO2 value int8_t validSPO2; //indicator to show if the SPO2 calculation is valid int32_t heartRate; //heart rate value int8_t validHeartRate; //indicator to show if the heart rate calculation is valid void setup() { Serial.begin(115200); // initialize serial communication at 115200 bits per second: oled.begin(&Adafruit128x64, 0x3C); oled.setFont(Arial14); // Initialize sensor if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed { Serial.println(F("MAX30105 was not found. Please check wiring/power.")); while (1); } particleSensor.setup(55, 4, 2, 200, 411, 4096); //Configure sensor with these settings } void loop() { //read the first 50 samples, and determine the signal range for (byte i = 0 ; i < 50 ; i++) { while (particleSensor.available() == false) //do we have new data? particleSensor.check(); //Check the sensor for new data redBuffer[i] = particleSensor.getRed(); irBuffer[i] = particleSensor.getIR(); particleSensor.nextSample(); //We're finished with this sample so move to next sample Serial.print(F("red=")); Serial.print(redBuffer[i], DEC); Serial.print(F(", ir=")); Serial.println(irBuffer[i], DEC); } //calculate heart rate and SpO2 after first 50 samples (first 4 seconds of samples) maxim_heart_rate_and_oxygen_saturation(irBuffer, 50, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate); //Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second while (1) { //dumping the first 25 sets of samples in the memory and shift the last 25 sets of samples to the top for (byte i = 25; i < 50; i++) { redBuffer[i - 25] = redBuffer[i]; irBuffer[i - 25] = irBuffer[i]; } //take 25 sets of samples before calculating the heart rate. for (byte i = 25; i < 50; i++) { while (particleSensor.available() == false) //do we have new data? particleSensor.check(); //Check the sensor for new data redBuffer[i] = particleSensor.getRed(); irBuffer[i] = particleSensor.getIR(); particleSensor.nextSample(); //We're finished with this sample so move to next sample Serial.print(F("red=")); Serial.print(redBuffer[i], DEC); Serial.print(F(", ir=")); Serial.print(irBuffer[i], DEC); Serial.print(F(", HR=")); Serial.print(heartRate, DEC); Serial.print(F(", HRvalid=")); Serial.print(validHeartRate, DEC); Serial.print(F(", SPO2=")); Serial.print(spo2, DEC); Serial.print(F(", SPO2Valid=")); Serial.println(validSPO2, DEC); } //After gathering 25 new samples recalculate HR and SP02 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, DEC); oled.print(F("SPO2: ")); oled.println(spo2, DEC); } else { oled.print(F("Not valid")); } }