NAN value a BIG problem

Don’t attach the code, post it as described

Hi,

1 In the IDE select the “Edit” tab
2 Then select “copy for the Forum”
3 Then move to the post edit window of the forum and , right click your mouse then select “paste”

Tom… :grinning: :+1: :coffee: :australia:

Thank you very much, i put the link to the code in my post at the description. Now i think it’s ok.

Hi,

Sorry no sign of it.
Please post it in a new post, don’t go back and edit an old post.

Tom… :grinning: :+1: :coffee: :australia:

Hello!
I make one project but instead of the measured SOP2 value, NAN appears on the display. I really don’t know why, where the problem comes from.
What needs to be changed in the code?
I really need help, please!
Link for the code:
https://create.arduino.cc/editor/scarlatmd/e6851e31-06de-499c-9f12-6674c337c9e5/preview


This is circuit diagram.

Everything works on the board, the code doesn’t have errors but does not show me the value of oxygen on the display, NAN appears instead of that value.

I’ve merged your cross-posts @scarlatmd.

Cross-posting is against the rules of the forum. The reason is that duplicate posts can waste the time of the people trying to help. Someone might spend 15 minutes (or more) writing a detailed answer on this topic, without knowing that someone else already did the same in the other topic.

Repeated cross-posting will result in a suspension from the forum.

In the future, please take some time to pick the forum board that best suits the topic of your question and then only post once to that forum board. This is basic forum etiquette, as explained in the “How to get the best out of this forum” guide you will find at the top of every forum category. It contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

Hi,
OPs code, I think…

#include <heartRate.h>
#include <MAX30105.h>
#include <spo2_algorithm.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Adafruit_MLX90614.h>
#include <EEPROM.h>
#include "MAX30105.h" //sparkfun MAX3010X library
MAX30105 particleSensor;
LiquidCrystal_I2C lcd(0x27,20,4);
//#define MAX30105 //if you have Sparkfun's MAX30105 breakout board , try #define MAX30105 
Adafruit_MLX90614 mlx = Adafruit_MLX90614();

double avered = 0; double aveir = 0;
double sumirrms = 0;
double sumredrms = 0;
int i = 0;
int Num = 100;//calculate SpO2 by this sampling interval
int Temperature;
int temp;
float ESpO2;//initial value of estimated SpO2
float ESpO2_ROM;
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 USEFIFO
#define Greenled 8
#define Redled 9
void setup()
{
  Serial.begin(115200);
  
  lcd.init();
  lcd.backlight();
  lcd.setCursor(3,1);
  lcd.print("Running......");
  delay(3000);
  lcd.clear();
  ESpO2 = readEEPROM();
  Temperature = EEPROM.read(6);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  // Initialize sensor
  while (!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 = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int pulseWidth = 411; //Options: 69, 118, 215, 411
  int adcRange = 4096; //Options: 2048, 4096, 8192, 16384
  // Set up the wanted parameters
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings

  particleSensor.enableDIETEMPRDY();
  mlx.begin();
}

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(".");
        float temperature = particleSensor.readTemperatureF();
        
        if (ir < FINGER_ON){
        temp = Temperature;
        EEPROM.write(6,temp);
        ESpO2_ROM = ESpO2;
        writeEEPROM(&ESpO2_ROM);
        lcd.setCursor(0,2);
        lcd.print("Last test: ");
        lcd.setCursor(11,2);
        lcd.print(ESpO2_ROM);
        lcd.print(" ");
        lcd.print("% ");

        lcd.setCursor(0,3);
        lcd.print("Last temp: ");
        lcd.setCursor(11,3);
        lcd.print(temp);
        lcd.print(" ");
        lcd.print("*C");
        
        break;
        }
        if(ir > FINGER_ON){
        Temperature = mlx.readObjectTempC();
        lcd.setCursor(0,0);
        lcd.print("Oxygen % = ");
        lcd.setCursor(11,0);
        lcd.print(ESpO2);
        lcd.print(" ");
        lcd.print("% ");
       //Temperature = Temperature+2;
        lcd.setCursor(0,1);
        lcd.print("Temperature: ");
        lcd.print(Temperature);
        lcd.print(" *C");
        if((ESpO2 >= 90) && (Temperature < 38)){
          digitalWrite(9,LOW);
          digitalWrite(8,HIGH);
        }
        if((ESpO2 < 90) || (Temperature > 37)){
          digitalWrite(8,LOW);
          digitalWrite(9,HIGH);
          
        }

        }
        
      }
    }
    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);
  }
#endif
}

void writeEEPROM(float *data)
{
 byte ByteArray[4];
 memcpy(ByteArray, data, 4);
 for(int x = 0; x < 4; x++)
 {
   EEPROM.write(x, ByteArray[x]);
 }  

}

float readEEPROM()
{
  float ESpO2 = 85.0;
  byte ByteArray[4];
  for(int x = 0; x < 4; x++)
  {
   ByteArray[x] = EEPROM.read(x);    
  }
  memcpy(&ESpO2, ByteArray, 4);
  return ESpO2;
}

Tom… :grinning: :+1: :coffee: :australia:

Hi,
Can you please post some pictures of your project, so we can see your component layout?

Tom… :grinning: :+1: :coffee: :australia:

Yes, of course!!

Hi,
Have you placed your finger over the sensor to give it something to read?

Tom… :grinning: :+1: :coffee: :australia:

Yes, but it doesn’t show me value but NAN.
I tested every components that is on breadboard with the help of the Arduino examples and works.

Hi,
Is the code I posted in post #18 the same as yours?
Have you tried the code I posted in Post #18?

Thanks… Tom… :grinning: :+1: :coffee: :australia:
PS. If you are having trouble pasting your code the forum format, then just copy and paste it, like text, into a post and we will see what we can do.

Tom… :grinning: :+1: :coffee: :australia:

Yes but in post #18 it’s the same code as the one I posted.

This is probably due to dividing by zero - your code does division by various values and if
any of those happens to be zero the result will be a NaN. Its best to explicitly check for zero
before dividing by a variable.

readEEPROM () is not optimally edited, drop line 39 or change the subroutine from line 180-190

Is there a reason not to use EEPROM.put() and EEPROM.get() instead of messing around with bytes and converting to a float ?