Saturimetro progetto rivista 245

Problemi legati alla programmazione dei microcontrollori.
Consigli su come realizzare routine dedicate.
Rispondi
AlbertoA
Messaggi: 2
Iscritto il: 16/08/2020, 15:16
Occupazione: pensionato
Home_Page: http://
Compleanno: 16 ott 1954
Città: Casnate con Bernate
Prov.: CO
Via: Tommaso grossi 21

Saturimetro progetto rivista 245

Messaggio da AlbertoA »

ciao a tutti
Come da oggetto i led del sensore MAX30102 non si accendono. Ho seguito tutte le istruzioni riportate nell'articolo.
ho pensato a un sensore difettoso, ne ho comprato un altro ma i led non si accendono.
grazie anticipatamente a chi potrà aiutarmi.
lucianoIV3WMM
Messaggi: 3
Iscritto il: 17/09/2020, 21:01
Cod. abbonamento Elettronica In: 7002B
Occupazione: Pensionato
Home_Page: http://
Compleanno: 13 dic 1941
Città: Cordenons
Prov.: PN
Via: Lozzetta, 47

Re: Saturimetro progetto rivista 245

Messaggio da lucianoIV3WMM »

Ciao Alberto.
Sono Luciano, é la prima volta che sono su questo forum come è la mia prima realizzazione di un progetto di ElettronicaIN ma l'ennesima di sessant'anni di attività elettronica amatoriale.
Ho appena terminato il cablaggio del tutto e il risultato mi sembra identico a quello da te lamentato.
Se nel tempo trascorso tra i nostri messaggi sei riuscito a risolvere il problema ti sarei grato se mi daresti una dritta.
Comunque ho notato che l'articolo presenta alcune incongruenze con conseguente mancanza di chiarezza e perdite di tempo.

Sul software: Uso delle librerie per il MAX30100. Non ci sono indicazioni su quale delle librerie messe a disposizione dall'IDE si debba usare. Con molta pazienza ho scoperto che ci sono due librerie messe a disposizione dall''IDE che purtroppo nella compilazione utilizza quella che non serve (risultato: impossibilità di procedere alla compilazione). Quindi l'inserimento nel listato l'ho fatto togliendo i due include suggeriti e inserendo il pacchetto di include della libreria MAX30100lib via menù dell'IDE. Questa ripropone tra tutte le sue fatture anche gli include disattivati. Risultato la compilazione è avvenuta senza più alcun problema. Tuttavia questa libreria ha diversi aggiornamenti. Ho usato il più recente ma chi ha scritto lo sketch quale ha usato? Con un uso così massiccio di librerie e comandi sintetici io perdo completamente il controllo del tutto e devo fare solo un atto di fede sul listato. La mancata accensione dei led è software?? Senza la possibilità di controllo del software è impossibile arrivare a qualcosa.

Schema di cablaggio e articolo. Alimentazione delle due schedine. Nel testo dell'articolo si legge che l'alimentazione è a 5V mentre nello schema di cablaggio l'alimentazione è connessa ai 3,3V. (?). Nell'articolo il testo ed un paio di foto indicano che si usano 5 dei pin del MAX30102 mentre nello schema di cablaggio ne vengono utilizzati 4. Il bus I2C mi sembra scambi dati nelle due direzioni per cui la connessione tralasciata potrebbe interdire il flusso di pilotaggio del MAX30102 determinando la mancata accensione dei led. Questa è solo una mia ipotesi non suffragata da conoscenze specifiche, non ho mai operato con questo tipo di bus. Se qualcuno che legge ha conoscenze specifiche in merito ed è disposto a dare qualche chiarimento avrà tutta la mia riconoscenza.

Ciao a tutti

PS.: Di solito non m'imbarco in una realizzazione se mi rendo conto di non essere in grado di avere il controllo di tutto. Ma, cavolo... sono 11 fili, due resistenze e due schedine che fanno tutto loro assieme ad Arduino e due paginette di listato. Un atto di fede si poteva anche fare...ma la legge di Murfy è sempre pronta a colpire purtroppo. Mal me ne incolse!
Avatar utente
Futura05
Messaggi: 106
Iscritto il: 29/01/2010, 10:18
Home_Page: http://

Re: Saturimetro progetto rivista 245

Messaggio da Futura05 »

ciao
rispondo ad entrambi, effettivamente sulla rivista c'è stato un errore nello schema per il collegamento, ma cosa più importante il modulino usato nel progetto era un max30100, di conseguenza il progetto è stato realizzato usando le librerie di quel modulo.

Ora il fornitore ci fornisce il MAX30102, le librerie precedenti non sono più compatibili, pertanto deve utilizzare queste nuove librerie:
https://github.com/sparkfun/SparkFun_MA ... or_Library

Al momento lo sketch della rivista non è corretto,per la visualizzazione dei dati sul display, ma andrebbe modificato per adattarlo alla nuova libreria, ma puoi visualizzare i dati sul monitor seriale di arduino, per verificarne il funzionamento.
AlbertoA
Messaggi: 2
Iscritto il: 16/08/2020, 15:16
Occupazione: pensionato
Home_Page: http://
Compleanno: 16 ott 1954
Città: Casnate con Bernate
Prov.: CO
Via: Tommaso grossi 21

Re: Saturimetro progetto rivista 245

Messaggio da AlbertoA »

ciao
io ho inserito le nuove librerie ma non è cambiato niente
i led non si accendono
Ho scaricato altri programmi ma non funzionano, il problema è in quel sensore max30102, ne ho comprati tre ma stesso risultato.
Sono in contatto con futura ma per il momento sono in attesa di loro suggerimenti.
ciao a tutti
lucianoIV3WMM
Messaggi: 3
Iscritto il: 17/09/2020, 21:01
Cod. abbonamento Elettronica In: 7002B
Occupazione: Pensionato
Home_Page: http://
Compleanno: 13 dic 1941
Città: Cordenons
Prov.: PN
Via: Lozzetta, 47

Re: Saturimetro progetto rivista 245

Messaggio da lucianoIV3WMM »

Ciao
Le librerie nuove le avevo già individuate, caricate ed utilizzate per la compilazione dello sketch ovviamente con nessun risultato pratico come già segnalato. Penso sia pure ovvio che il fatto di superare la compilazione dell'IDE non sia garanzia che lo sketch funzioni.
L'utilizzo di quattro pin del MAX (due per l'alimentazione e due per il bus I2C) potrerbbe essere ininfluente per il funzionamento tutto dipende dagli algoritmi dello sketch e dalle priorità assegnate alle varie funzioni.
Da un controllo con l'oscilloscopio dello stato delle due linee del bus I2C (del MAX) su queste non risulta presente alcuna attività (neanche usandp il trigger dedicato all'I2C) La tensione è conforme alle note dell'articolo ma è fissa alta ed affetta da un rumore ciclico di alcune decine di millivolt.
Posso supporre che al MAX non vengano passati i parametri che all'inizio dello sketch viene raccomandato di non cambiare e che non si installi la comunicazione bidirezionale Arduino-MAX ,probabile causa per cui i led non si accendono.
Adesso c'è da capire se le librerie del Max gestiscono solo la sua comunicazione come slave o gestiscono anche le funzioni master di Arduino che tra l'altro, oltre a comunicare col MAX deve comunicare con il display via I2C. Questo si accende ma non dà alcun segno di vita ( un look iniziale a sfondo nero dovrebbe comparire anche in mancanza di dati suppongo con l'avviso di mancato funzionamento del MAX).

Adesso mentre scrivo queste considerazioni ho un flash: Il Bus I2C non dovrebbe essere unico ??!!. Le due linee SDA e SCL del MAX e del display non dovrebbero essere in parallelo su un unico bus e non a se stanti?! L'I2C non è nato apposta per gestire più periferiche sul suo doppino?

Mi sembra che ci sia parecchia confusione e parecchio da rivedere.

Saluti a tutti
lucianoIV3WMM
Messaggi: 3
Iscritto il: 17/09/2020, 21:01
Cod. abbonamento Elettronica In: 7002B
Occupazione: Pensionato
Home_Page: http://
Compleanno: 13 dic 1941
Città: Cordenons
Prov.: PN
Via: Lozzetta, 47

Re: Saturimetro progetto rivista 245

Messaggio da lucianoIV3WMM »

Ciao a tutti
Scusatemi.... nell'ultimo mio intervento l'osservazione sul display è sbagliata, La sua interfaccia è lSPI. Sono stato tratto in inganno dalle scritte sui piedini che sono state riportate per il clock e i dati con le stesse sigle dell'I2C e le indicazioni erano sul retro coperte dalla bredboard.
Salve a tutti
BarVanni
Messaggi: 1
Iscritto il: 11/10/2020, 18:14
Cod. abbonamento Elettronica In: 13216B
Occupazione: Pensionato
Home_Page: http://

Re: Saturimetro progetto rivista 245

Messaggio da BarVanni »

Salve a tutti. Anche io ho problemi con il saturimetro, il display funziona ma il programma si blocca al primo controllo di inizializzazione del sensore [if (!sensor.begin()) { tft.print("Could not initialise MAX30100");].
Ho provato la libreria SparkFun_MAX3010x_Sensor_Library-master il sensore si accende e funziona a monitor seriale ma non sul display, mi occorre un aiuto per fare funzionare il programma. Come posso fare? Grazie a tutti.
Avatar utente
Piero Davio
Messaggi: 2
Iscritto il: 19/01/2021, 21:20
Cod. abbonamento Elettronica In: 14946B
Occupazione: Pensionato
Home_Page: http://
Commento: Medico in pensione, da circa 2 anni mi sono avvicinato al mondo dei Maker ed ho cominciato a giocare con Arduino e RaspberryPi.
Compleanno: 28 giu 1953
Città: Alessandria
Prov.: AL
Via: Machiavelli 38

Re: Saturimetro progetto rivista 245

Messaggio da Piero Davio »

Ciao a tutti,
anch'io ho avuto gli stessi vostri problemi, mi sono iscritto da poco al forum ed ho capito che il MAX30102 non è idoneo per replicare il progetto pubblicato sulla rivista 245 anche se le foto e le descrizioni si riferiscono proprio a questo chip.
Ho contattato Futura shop che ha confermato la cosa e mi ha riferito che stanno lavorando ad un nuovo progetto con il MAX30102 che sara pubblicato tra qualche mese sulla rivista. Nel frattempo ho cercato di usare la libreria Sparkfun segnalata ma l'esempio per il calcolo della saturazione di O2 non dava dei valori attendibili. Ho cominciato quindi con l'esempio per la rilecazione del battito cardiaco ed ho poi aggiunto parte del listato pubblicato sulla rivista 245 riportatando i seguenti dati sul display: BPM (battiti x minuto), valori IR (infrarossi), valori del Red (rosso) e la differenza Diff calcolata + la sua traccia secondo lo schema riportato nel listato pubblicato. La traccia però permane un po' instabile e l'elaborazione diviene un po' lenta. Visto che la traccia ai fini del monitoraggio non serve a molto penso che la eliminerò per poi cercare invece di calcolare il valore dell'O2 dai dati grezzi.
Il cablaggio l'ho mantenuto come quello pubblicato sulla rivista ma con l'alimentazione del circuito sui 5 Volt.
Se qualcuno volesse utilizzare, per gioco, questo schema, di seguito vi copio il listato:

#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 = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //
float beatsPerMinute;
int BPM; //media dei battiti per minuto

// Le seguenti impostazioni impostano vari fattori riguardanti il display.
#define SCALING 12 // Scala l'ampiezza della traccia, riduci il valore per rendere l'altezza della traccia
// più grande, aumenta per rimpicciolire [12]
#define TRACE_SPEED 7 // Velocita della traccia sullo schermo, più alto=più veloce [0,5]
#define TRACE_MIDDLE_Y_POSITION 41 // y pos della traccia circa a metà schermo
#define TRACE_HEIGHT 64 // Max altezza della traccia in pixels [64]
#define HALF_TRACE_HEIGHT TRACE_HEIGHT/2 // Metà Max altexxa of traccia in pixels (ampiezza della traccia)
#define TRACE_MIN_Y TRACE_MIDDLE_Y_POSITION-HALF_TRACE_HEIGHT+1 // Min Y pos della traccia, calcolata dai valori precedenti
#define TRACE_MAX_Y TRACE_MIDDLE_Y_POSITION+HALF_TRACE_HEIGHT-1 // Max Y pos della traccia, calcolata dai valori precedenti

// 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()
{
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");
while (1);
}

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


// Intestazioni nel Display,
tft.setTextSize(2);
tft.setCursor(0,80);
tft.print("BPM IR Red");
tft.setTextSize(1);
tft.setCursor(1,0);
tft.print("IRedPulseMeter");
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 float lastx=1; // Posizione x della traccia Precedente
static int lasty=TRACE_MIDDLE_Y_POSITION; // Posizione y della traccia Precedente , di default nel mezzo del box
static float x=1; // Posizione x della traccia corrente
int32_t y; // Posizione x della traccia corrente
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();

if ((ir) <= 1000)
{
BPM=0;
tft.fillRect(0,100,128,22,ST7735_BLACK); // colore del fondo [0,104,128,16]
tft.setTextSize(2);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(8,100); // 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(44,100); // Set print position for the O2 value[72, 104]
tft.print(ir);
delay(1000);
return;
}
else
if (checkForBeat(ir) == true)
{
//Rileviamo un battito!
long delta = millis() - lastBeat;
lastBeat = millis();

beatsPerMinute = 60 / (delta / 1000.0);

if (beatsPerMinute < 255 && beatsPerMinute > 20)
{
rates[rateSpot++] = (byte)beatsPerMinute; //Immagazzina in un array questi dati grezzi
rateSpot %= RATE_SIZE; //Wrap variable

//Fa la media delle letture (BPM)
BPM = 0;
for (byte x = 0 ; x < RATE_SIZE ; x++)
BPM += rates[x];
BPM /= RATE_SIZE;
}


if((red && ir) > -1) // Se i dati grezzi sono disponibili per IR and Red
{
if(red<1000) // Nessun battito
y=TRACE_MIDDLE_Y_POSITION; // Mette Y come default sulla linea di mezzo
else
{
// Plot our new point
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


// Se il minimo o massimo va fuorischermo allora è necessario modificare il SensorOffset, riportandolo nello schermo
if(Diff<-HALF_TRACE_HEIGHT)
SensorOffset+=(SCALING*(abs(Diff)-32));
if(Diff>HALF_TRACE_HEIGHT)
SensorOffset+=(SCALING*(abs(Diff)-32));

y=Diff+(TRACE_MIDDLE_Y_POSITION-HALF_TRACE_HEIGHT); // Riportano la posizione di Y della traccia al centro del display
y+=TRACE_HEIGHT/4; // default è diviso per [4]
}

if(y>TRACE_MAX_Y) {
y=TRACE_MAX_Y; // se va oltre il bordo del box la traccia viene mozzata
//riduce l'ampiezza della traccia
}
if(y<TRACE_MIN_Y) {
y=TRACE_MIN_Y; // se va oltre il bordo del box la traccia viene mozzata
//riduce l'ampiezza della traccia
}
tft.drawLine(lastx,lasty,x,y,ST7735_YELLOW); // Riporta sul plotter la prossima parte della traccia
lasty=y; // Salva l'ultima posizione di Y
lastx=x; //Salva l'ultima posizione di X
x+=TRACE_SPEED; //Muove la traccia sul display
if(x>126) // Se la traccia raggiunge la fine del display allora riparte da capo
{
tft.fillRect(1,TRACE_MIN_Y,126,TRACE_HEIGHT,ST7735_BLACK); // L'area del box viene riempita di nero e la traccia cancellata
x=1; // Riparte da capo
lastx=x;
y= 52;
lasty=y;
}}

if (delta > 1000) //(millis() - lastBeat > 1000)
{
tft.fillRect(0,100,128,22,ST7735_BLACK); // colore del fondo [0,104,128,16]
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.setCursor(4,100); // Mette BPM in questa posizione
tft.print(BPM);
tft.setTextColor(ST7735_WHITE); // colore del testo bianco
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(44,100); // Mette IR in questa posizione
tft.print(ir);
}}}
Avatar utente
Piero Davio
Messaggi: 2
Iscritto il: 19/01/2021, 21:20
Cod. abbonamento Elettronica In: 14946B
Occupazione: Pensionato
Home_Page: http://
Commento: Medico in pensione, da circa 2 anni mi sono avvicinato al mondo dei Maker ed ho cominciato a giocare con Arduino e RaspberryPi.
Compleanno: 28 giu 1953
Città: Alessandria
Prov.: AL
Via: Machiavelli 38

Re: Saturimetro progetto rivista 245

Messaggio da Piero Davio »

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);
}}}
Avatar utente
maurodom
Messaggi: 1
Iscritto il: 13/05/2022, 10:46
Cod. abbonamento Elettronica In: 10990B
Occupazione: Pensionato
Home_Page: http://
Compleanno: 06 mar 1949
Città: Cesano Maderno
Prov.: MB
Via: Mazzucchelli 14

Re: Saturimetro progetto rivista 245

Messaggio da maurodom »

... o anche "Pulsiossimetro WiFi" nella rivista N.253 (Aprile 2022).

Ciao. Ottimo thread!

Sono abbonato alla rivista e ho qualche quesito sull'uno o l'altro apparecchio (ho apnee notturne e mi occorre).
Ho comperato recentemente sensore MAX30102, batterie, etc. NodeMCU, ESP32, etc li avevo già.

Chiedo se qualcuno ha provato ad espanderne un modello e magari si è già posto le seguenti problematiche.

A) Registrazione dei dati su memoria SD?

B) Aggiunta di un sensore di dilatazione del torace (polmoni) per registrarne i dati: quale tipo e modello scegliere da poter montare su una cintura pseudoelastica da applicare al petto?

C) Aggiunta di un piccolo buzzer per allarme in caso di superamento di soglie dell' SpO2 o per mancanza di respiro per un tot secondi?

E per non usare una SD...

D) Come implementare l'upload dei dati - in realtime o in differita dopo una serie di campionamenti - su Google Spreadsheet?

E) Al di là di Google Spreadsheet non vorrei utilizzare un server provider in Internet come ad es. Blynk. Allora, è praticabile implementare un server da installare in una VM Windows10, per la ricezione WiFi ed archiviazione dei dati (realtime o differita)? Dove si può trovare documentazione su come installare un qualche tipo di semplice server (FTP etc.) e le relative librerie Arduino, per collegarcisi e salvare/richiamare i dati?

F) Qualcuno ha provato a formattare i dati in modo da poterli salvare in formato adatto ad essere visualizzati nel programmino "SpO2 Assistant", ottenendo così una report un po' più user-friendly?
Rispondi