Vi invio la successiva revisione del codice per il Saturimetro, come preannunciato ho levato la traccia e mi sono divertito ad hakerare il codice così ho mandato sul display una colonna blu che si attiva con il battito ed il calcolo empirico della SpO2 più i dati grezzi di Red e IR.
Ecco il codice rivisitato, successivamente cercherò di calcolare la SpO2 esclusivamente con il calcolo della DC Red e IR e AC Red e IR.
Buon divertimento!
/* MAX30105 Breakout: Output all the raw Red/IR/Green readings
By: Nathan Seidle @ SparkFun Electronics
Date: October 2nd, 2016
https://github.com/sparkfun/MAX30105_Breakout
Outputs all Red/IR/Green values.
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.
This code is released under the [MIT License](
http://opensource.org/licenses/MIT).
Per migliorare la sensibilità del sensore ed evitare contatti con i componenti della scheda,
usare un sottile strato di morbido silicone trasparente (i paracalli vanno bene)
Codice implementato empiricamente, non usarlo a scopo diagnostico/terapeutico!
*/
#include <Wire.h>
#include "MAX30105.h"
#include "Adafruit_GFX.h" // Libreria grafica per poul display
#include "Adafruit_ST7735.h"
#include "heartRate.h"
MAX30105 particleSensor;
const byte RATE_SIZE = 8 ; //Increase this for more averaging. [const byte] [4] is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; // [0]long
float beatsPerMinute;
int counterbeats =0;
int BPM; //media dei battiti per minuto
const float DCred = 17000;//17600 - 17600*2/100; // misurato senza polso [17600]+red da congestione venosa
const float DCir = 20000;//24200 - 24200*20/100; // misurato senza polso [24200]+ ir da congestione venosa
int O2; //saturazione O2 calcolata
// Le seguenti impostazioni impostano vari fattori riguardanti il display.
#
// Pins da usare per il ST7735 display
#define TFT_CS 10
#define TFT_RST 8 // Or set to -1 and connect to Arduino RESET pin
#define TFT_RS 9
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_RS, TFT_RST);
void setup()
{
//Serial.begin(115200); //decommentare per vedere i risultati sul monitor seriale
tft.initR(INITR_144GREENTAB); // inizializzazione del ST7735S chip, per il 128x128 display
tft.fillScreen(ST7735_BLACK);
tft.setTextSize(1);
tft.setTextColor(ST7735_WHITE);
// Initialize sensor
tft.setCursor(0,0);
if (!particleSensor.begin(Wire,I2C_SPEED_FAST)) // == false) --> //Usa di default la porta I2C, a 400kHz di frequenza
{
tft.println("MAX30105 non trovato"); // se evidente sul display ricaricare il codice oppure resettare Arduino.
while (1);
}
//tft.println("Collega il sensore");
particleSensor.setup(); //Configura il sensore. Use 6.4mA per comandare il LED
// Set up dei parametri per l'analisi dei dati grezzi
particleSensor.setPulseAmplitudeRed(0x0A);//RED LED impostato a "low"--> sensore attivo
particleSensor.setPulseAmplitudeGreen(0); // LED verde spento
// Titoli nel Display,
tft.setTextSize(2);
tft.setCursor(20,80);
tft.print("IR Red");
tft.setCursor(20,18);
tft.setTextColor(ST7735_YELLOW);
tft.print("%SpO");
tft.setCursor(20,48);
tft.print("BPM");
tft.setTextSize(1);
tft.setCursor(68,26);
tft.print("2");
tft.setCursor(1,0);
tft.setTextColor(ST7735_WHITE);
tft.print("IRedPulseMeter");
tft.fillRect(15,74,100,2,ST7735_CYAN);
//tft.drawRect(0,TRACE_MIN_Y-1,128,TRACE_HEIGHT+2,ST7735_BLUE); // Il bordo della casella per il tracciato
}
void loop()
{
uint16_t Diff=0; // La differenza tra InfraRossi (IR) e Red LED dati grezzi --> [int16_t Diff=0;]
uint16_t ir, red, green;//uint16_t ir, red, green; // dati grezzi restituiti
static int32_t SensorOffset=8300; // Limite del punto più basso sotto il quale il dato grezzo non deve andare, default [10000]
// Siccome i vari sensori sono diversi, il codice fa gli aggiustamenti del caso se la traccia va fuori schermo
// L'ottimale si ottiene aggiustando il valore in base all'analisi dei dati grezzi prodotti
red = particleSensor.getRed();
ir = particleSensor.getIR();
/*Serial.print(" Red "); //decommentare per vedere i risultati sul monitor seriale
Serial.print(red);
Serial.print(" IR ");
Serial.print(ir);
Serial.println();*/
if ((ir) <= 1000) // sensore non collegato alla cute
{
BPM=0;
O2=0;
tft.fillRect(0,100,128,28,ST7735_BLACK); // colore del fondo [0,104,128,16]
tft.fillRect(62,40,128,28,ST7735_BLACK);
tft.fillRect(78,15,128,28,ST7735_BLACK);
tft.setTextSize(2);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(82,18); // Mette O2 in questa posizione
tft.print(O2);
tft.setCursor(70,48); // Mette BPM in questa posizione
tft.print(BPM);
tft.setTextSize(1);//[2]
tft.setTextColor(ST7735_RED); //testo rosso
tft.setCursor(86,100);
tft.print(red);
tft.setTextColor(ST7735_YELLOW); // testo giallo --- else green [ST7735_GREEN]
tft.setCursor(20,100); // Set print position for the O2 value[72, 104]
tft.print(ir);
counterbeats = 0; // reset counterbeats
tft.setCursor(0,114); // provvisorio segna counterbeats = 0
tft.print(counterbeats);
delay(1000);
return;
}
else
if (checkForBeat(ir) == true)
{
//Rileviamo un battito!
long delta = millis() - lastBeat; // [long]
lastBeat = millis();
beatsPerMinute = 60 / (delta / 1000.0);
counterbeats = counterbeats + 1;
if (beatsPerMinute < 250 && beatsPerMinute > 40) // [<255 && >20]
{
rates[rateSpot++] = (byte)beatsPerMinute; //Immagazzina in un array questi dati grezzi
rateSpot %= RATE_SIZE; //Wrap variable
//Facciamo la media delle letture (BPM)
BPM = 0;
for (byte x = 0 ; x < RATE_SIZE ; x++)
BPM += rates[x];
BPM /= RATE_SIZE;
}
//Costruiamo la colonna BLUE di rilevazione del battito
if (delta >=200) // se < 300 BPM (delta di 1000 è = 60 BPM)
{tft.fillRect(2,51,12,25,ST7735_BLUE); // riempimento rettangolo (pixel dal lato sx, dal lato superiore, spessore dx->sx,lungh alto->basso
delay (10); // latenza in millisecondi
tft.fillRect(2,38,12,38,ST7735_BLUE);
delay (20);
tft.fillRect(2,25,12,51,ST7735_BLUE);
delay (30);
tft.fillRect(2,12,12,64,ST7735_BLUE); // sale rapido e scende più lentamente af ogni battito
delay (70);
tft.fillRect(2,12,12,25,ST7735_BLACK);
delay (50);
tft.fillRect(2,12,12,38,ST7735_BLACK);
delay (30);
tft.fillRect(2,12,12,51,ST7735_BLACK);
delay (20);
tft.fillRect(2,12,12,64,ST7735_BLACK);
}
if((red && ir) > -1) // Se i dati grezzi sono disponibili per IR and Red
Diff=(ir-red); // La differenza dei dati grezzi di IR e Red
//Diff=Diff-SensorOffset; // Aggiusta i valori grezzi rimuovendo l'offset (riporta i valori nella giusta scala di range)
//Diff=Diff/SCALING; // Modifica la differenza in modo che i valori stiano ad una buona altezza sullo schermo
if (ir > 1000) //// sensore collegato alla cute
{
//calcolo della SpO2% secondo la formula:110-(25*R)
//R=(ACrms del Red/DC del Red)/(ACrms del IR/DC del IR)
//DC corrisponde ai valori di Red e IR in assenza di polso e AC a valori grezzi meno DC (valore costante per soggetto)
//AC_Red = Red-DC_Red AC_IR = IR-DC_IR
float AC_Red = red - DCred;
float AC_IR = ir - DCir;
float R = ((AC_Red)/(DCred))/((AC_IR)/(DCir));
O2 = 110 - (21*R);// [110 - (25*R] (correzione/regolazione empirica x > attendibilità)
/*Serial.print(" Red "); //decommentare per vedere i risultati sul monitor seriale
Serial.print(red);
Serial.print(" IR ");
Serial.print(ir);
Serial.print(" AC_Red ");
Serial.print(AC_Red);
Serial.print(" AC_IR ");
Serial.print(AC_IR);
Serial.print(" R ");
Serial.print(R);
Serial.print(" SpO2 ");
Serial.print(O2);
Serial.println();*/
tft.fillRect(0,100,128,28,ST7735_BLACK); // colore del fondo [0,104,128,16]
tft.fillRect(62,40,128,28,ST7735_BLACK);
tft.fillRect(78,15,128,28,ST7735_BLACK);
tft.setTextColor(ST7735_WHITE); // colore del testo bianco
tft.setTextSize(1);//[2]
tft.setCursor(70,48); // Mette BPM in questa posizione
if (counterbeats < 10) // si stabilizza i valori di BPM all'inizio della misurazione
{
tft.print("Measuring");
}
else
{
if((BPM<60)|(BPM>110)) {
tft.setTextColor(ST7735_RED); // colore del testo rosso
}
else {
tft.setTextColor(ST7735_GREEN); // colore del testo verde
}
tft.setTextSize(2);//[2]
tft.print(BPM);
}
tft.setTextColor(ST7735_WHITE); // colore del testo verde
tft.setCursor(82,18); // Mette O2 in questa posizione
tft.print(O2);
tft.setTextSize(1);
tft.setCursor(46,114);
tft.print("Diff: ");
tft.setCursor(82,114); // Mette Diff Ir-Red in questa posizione
tft.print(Diff);
tft.setTextColor(ST7735_RED); // colore del testo rosso
tft.setCursor(86,100); // Mette Red in questa posizione
tft.print(red);
tft.setTextColor(ST7735_YELLOW); // colore del testo bianco
tft.setCursor(20,100); // Mette IR in questa posizione
tft.print(ir);
// tft.setCursor(0,114); // provvisorio segna counterbeats
//tft.print(counterbeats);
}}}