Exiting a while loop

I'm trying to execute two types of function based on Bluetooth selection.
E.G selection 10 and 20 both integer type.
When int 10 is received it will loop through the function 1 time for 20s and produce a value .
My question is how do i return to
"selection = ESP_BT.read();" at line 65. When I insert a "return;" at the end my code just stop checking for new value.

Here are the things i've tried
1.I've tried switch case but it wont loop through the heart rate and SpO2 calculation unless a while(1) is inserted which I can't exit from.
2. changed while to "if" again it wont loop through unless a while(1) is inserted

The main body of the loop

Please post your code, in code tags.
My microfilm reader is being repaired.

Welcome to the forum

Please do not post pictures of code

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

1 Like

why while (selection == 10)?

in general, loop() needs to do things that are non-block such as monitoring for input and executing some non-blocking operation.

the input can set a mode indicating what operation(s) are in effect. and set mode to something like IDLE or NONE when the operation is completed

operations can be invoked repeatedly if they need to monitor something. just like serial input checking if available(), checking for something using an "if" instead of a "while".

if the operation is time based, it can use millis() instead of delay to check if some time has expired to perform some action

#include <Wire.h>
#include "MAX30105.h"
#include "heartRate.h"
#include "BluetoothSerial.h" 

//Bluetooth setup
BluetoothSerial ESP_BT;
int selection =0;

MAX30105 particleSensor;
// Heartrate calculation
const byte RATE_SIZE = 4;
byte rates[RATE_SIZE]; // Array for heart rate
byte rateSpot = 0;
long lastBeat = 0; // Time for last beat occured
float beatsPerMinute;
int beatAvg;

//SpO2 calculation
double avered = 0;
double aveir = 0;
double sumirrms = 0;
double sumredrms = 0;
double SpO2 = 0;
int ESpO2 = 85.0; //initial value
double FSpO2 = 0.7; //filter factor for spo2 estimation
double frate = 0.95; // low pass filter for IR and RED led value to get DC value
int i = 0;
int Num = 40; // sample 40 times
#define FINGER_ON 7000 // minium reading for IR reading to turn on 
#define MINIMUM_SPO2 85.0 // Minimum reading for spo2
unsigned long Currentmillis;
unsigned long premillis =0;
int interval = 20000;
int mintimer = 30000;

void setup()
{
  Serial.begin(115200); // initialize serial communication at 115200 bits per second:
  ESP_BT.begin("ESP_OXIMETER");
  // 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);
        }

          byte ledBrightness = 0x7E; //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
          byte sampleRate = 200; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
          int pulseWidth = 411; //Options: 69, 118, 215, 411
          int adcRange = 16384; //Options: 2048, 4096, 8192, 16384
        
          particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
          particleSensor.enableDIETEMPRDY();
          particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
          particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
}

void loop()
{
  
  if(ESP_BT.available())
  {
    int selection = ESP_BT.read();
    if(selection == 10)
    {
        unsigned long Currentmillis = millis();
        long irValue = particleSensor.getIR();// get ir value from sensor
  if (irValue > FINGER_ON) // if finger is placed on sensor
  {       
          unsigned long Currentmillis = millis();
          Serial.println("Please wait...Measuring");
          if((unsigned long)(Currentmillis - premillis)<= interval)
          {
          //Heart rate calculation
           if(checkForBeat(irValue) == true)
              {
                 //sensed a beat
                 long delta = millis() - lastBeat;//
                 lastBeat = millis();
                  beatsPerMinute = 60 / (delta / 1000.0);//calculate avg heartrate
                    if (beatsPerMinute < 255 && beatsPerMinute > 20) 
                      {
                        //heartrate must be within 20 - 255
                        rates[rateSpot++] = (byte)beatsPerMinute; //store heartrate in array
                        rateSpot %= RATE_SIZE;
                        beatAvg = 0;//Avg calculation 
                            for (byte x = 0 ; x < RATE_SIZE ; x++) 
                                  beatAvg += rates[x];
                                  beatAvg /= RATE_SIZE;
                       }
                } 

    //SpO2 calculation
    uint32_t ir, red ;
    double fred, fir;
    particleSensor.check(); //Check the sensor, read up to 3 samples
    if (particleSensor.available()) 
        {
          i++;
          red = particleSensor.getFIFOIR(); //
          ir = particleSensor.getFIFORed(); //
          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 % Num) == 0)
          {
          
             double R = (sqrt(sumredrms) / avered) / (sqrt(sumirrms) / aveir);
             SpO2 = -23.3 * (R - 0.4) + 100;
              ESpO2 = FSpO2 * ESpO2 + (1.0 - FSpO2) * SpO2;//low pass filter
              if (ESpO2 <= MINIMUM_SPO2) ESpO2 = MINIMUM_SPO2; //indicator for finger detached
              if (ESpO2 > 100) ESpO2 = 99.9;
              sumredrms = 0.0; sumirrms = 0.0; SpO2 = 0;
              i = 0;
          }
          particleSensor.nextSample(); //We're finished with this sample so move to next sample
       } 
       
    }
    else
    {    
            Serial.print(ESpO2);
            Serial.println("%");
            Serial.print(beatAvg);
            Serial.println("bpm");
            ESP_BT.print("Result");
            ESP_BT.print("|");
            ESP_BT.print(ESpO2);
            ESP_BT.print("|");
            ESP_BT.print(beatAvg);
            Serial.println(Currentmillis);
            premillis = Currentmillis; 
     }      
    }
   }
  }
 }                   
                
    






          
         

I I've pasted my code below i have a few issues with it and i cant seems to reset my time Currentmillis to zero as well

when I changed it to if (selection ==10) my code stops looping the calculating function inside is there a better way of structing?
I'm using millis() as time as well I'm having trouble resetting it back to zero .

Why do you think that you need to set Currentmillis to zero ?

From its name it would seem to be the value of millis() as it is now and it will only be zero for 1 millisecond at the start of the sketch

My main goal is to measure both SpO2 and BPM at an interval of 10mins. I know if I used delay it would cause of drift in time and overflow will occur if I don't reset the time. The currentmillis act as a guild line for how long the sensor will be measuring its data from which is 20s.

My wristwatch overflows twice a day - hasn't caused me any problems

look at Using millis() for timing. A beginners guide and Several things at the same time

1 Like

But to measure elapsed time you do not need to set it to zero. Instead save the value of millis() when the period starts and compare it to the current value of millis() at any time to determine how much time has passed

So its not mandatory to reset the timer but im kinda lost on how to introduce the 10mins delay before the next measurements starts

is it still inside the condition or if (ESP_BT.available())?

you need to capture the a timestamp ( ts= millis()) from which you want to delay

The blink without delay example in the IDE will help you with that.

yes i've done that at the botton of the code by setting
premillis = Currentmillis. that allows me to go through the calculation loop again.

oh i mean using the millis() function

yes it is inside the condition

the timestamp do i put it inside a for loop ?
im sorry if i ask some weird question im very new to programming

then it's only going to execute when there's something available.

there needs to be a condition statement (e.g. switch) outside the if (ESP_BT.available()). that switch can execute the appropriate operation

the timestamp can be a global variable (so that it's value is not lost between iterations of loop()) and capture at the begin of the period you want to delay for or at the time of each execution to delay again

i don't see where you initially set "premillis" (why not call is msecLst) and would reset it immediately after the time expires

    if ((Currentmillis - premillis)<= interval)          {
        premiliis = Currentmillis;
        ...
    }

why capitalize "Currentmillis"? constants are Capitalized by convention and vairables are not capitalized

Then why and where do you want to set Currentmillis to zero as you say ?