Is there a way to sense Heart Rate (BMP) with MAX30102 without the loop algorithm?

I was wondering if there is a way to sense the heart rate (beats per minute) and store it in a variable in order to send it through LoRa. I am currently sending GPS through cayenneLPP library, I'm using a Sodaq One V3 which is based on an arduino zero, so the code is based on arduino framework, the function to send the GPS is inside my void loop function and it sense GPS correctly:

data.addGPS(1, lat, lon, 0);
data.addAnalogInput(2, 3.14159);
sendPacket(data);

My entire code for sending GPS is (It works good and I understand everything on it, it is just to show my entire project):

#include <Arduino.h>
#include "CayenneLPP.h"
#include <Sodaq_RN2483.h>
#include <Sodaq_UBlox_GPS.h>
#include "ArduinoLowPower.h"

#define debugSerial SERIAL_PORT_MONITOR

#if defined(ARDUINO_AVR_SODAQ_MBILI)
#define loraSerial Serial1
#define BEE_VCC 20

#elif defined(ARDUINO_SODAQ_AUTONOMO) || defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA)
#define loraSerial Serial1

#elif defined(ARDUINO_SODAQ_EXPLORER)
#define loraSerial Serial2

#else
// please select a sodaq board
debugSerial.println("Please select a sodaq board!!");
#endif
CayenneLPP data(51); //se define el tamaño máximo del payload (51 bytes)
float lat = 16.0441087;
float lon = -92.9716481;
// ABP
const uint8_t devAddr[4] = {0x00, 0x00, 0x00, 0x00};
const uint8_t appSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t nwkSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// OTAA

// 0c13321786b9c36f272e7cbdbef2cd71
// sodaq 2  0004A30B0022f78c, 0004A30B00228B3B
//0004A30B0022D9F3
uint8_t DevEUI[8] = {0x00, 0x04, 0xA3, 0x0B, 0x00, 0x22, 0xD9, 0xF3};
uint8_t AppEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t AppKey[16] = {0x0C, 0x13, 0x32, 0x17, 0x86, 0xb9, 0xc3, 0x6f, 0x27, 0x2e, 0x7c, 0xbd, 0xbe, 0xf2, 0xcd, 0x71};
bool connected = false;
void setupLoRaABP()
{
    if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, false))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
    }
    else
    {
        debugSerial.println("Communication to LoRaBEE failed!");
    }
}

void setupLoRaOTAA()
{
    if (LoRaBee.initOTA(loraSerial, DevEUI, AppEUI, AppKey, true))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
        connected = true;
    }
    else
    {
        debugSerial.println("OTAA Setup failed!");
        connected = false;
    }
}
void setupLoRa()
{
    setupLoRaOTAA();
    LoRaBee.setSpreadingFactor(7);
}

void setup()
{
// Power up the LoRaBEE
#if defined(ARDUINO_AVR_SODAQ_MBILI) || defined(ARDUINO_SODAQ_AUTONOMO)
    pinMode(BEE_VCC, OUTPUT);
    digitalWrite(BEE_VCC, HIGH);
#endif
    delay(3000);

    while ((!SerialUSB) && (millis() < 10000))
    {
        // Wait 10 seconds for the Serial Monitor
    }

    // Set baud rate
    debugSerial.begin(57600);
    loraSerial.begin(LoRaBee.getDefaultBaudRate());
    LoRaBee.setDiag(debugSerial);
    sodaq_gps.init(GPS_ENABLE);
    debugSerial.println("Starting");
    setupLoRa();
}

void sendPacket(CayenneLPP &packet)
{
    connected = false;
    switch (LoRaBee.send(1, packet.getBuffer(), packet.getSize()))
    {

    case NoError:
        debugSerial.println("Successful transmission.");
        connected = true;
        break;
    case NoResponse:
        debugSerial.println("There was no response from the device.");
        setupLoRa();
        break;
    case Timeout:
        debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
        delay(20000);
        break;
    case PayloadSizeError:
        debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
        break;
    case InternalError:
        debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! Try restarting the device!\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case Busy:
        debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
        delay(10000);
        break;
    case NetworkFatalError:
        debugSerial.println("There is a non-recoverable error with the network connection. You should re-connect.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NotConnected:
        debugSerial.println("The device is not connected to the network. Please connect to the network before attempting to send data.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NoAcknowledgment:
        debugSerial.println("There was no acknowledgment sent back!");
        // When you this message you are probaly out of range of the network.
        break;
    default:
        break;
    }
}

void loop()
{
    if (connected)
    {
        data.reset();
        /*
            if (sodaq_gps.scan(true))
            {
                lat = sodaq_gps.getLat();
            lon = sodaq_gps.getLon();
            }
        */

        data.addGPS(1, lat, lon, 0);
        data.addAnalogInput(2, 3.14159);
        sendPacket(data);
        LoRaBee.sleep();
        USBDevice.detach();
        LowPower.sleep(1000);
        LoRaBee.wakeUp();
        USBDevice.attach();
    }
    else
    {
        setupLoRa();
    }
}

I was wondering if there is a way to sense the heart rate (beats per minute) and store it in a variable in order to send it through LoRa. I am currently sending GPS through cayenneLPP library, I'm using a Sodaq One V3 which is based on an arduino zero, so the code is based on arduino framework, the function to send the GPS is inside my void loop function and it sense GPS correctly:

data.addGPS(1, lat, lon, 0);
data.addAnalogInput(2, 3.14159);
sendPacket(data);

My entire code for sending GPS is (It works good and I understand everything on it, it is just to show my entire project):

#include <Arduino.h>
#include "CayenneLPP.h"
#include <Sodaq_RN2483.h>
#include <Sodaq_UBlox_GPS.h>
#include "ArduinoLowPower.h"

#define debugSerial SERIAL_PORT_MONITOR

#if defined(ARDUINO_AVR_SODAQ_MBILI)
#define loraSerial Serial1
#define BEE_VCC 20

#elif defined(ARDUINO_SODAQ_AUTONOMO) || defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA)
#define loraSerial Serial1

#elif defined(ARDUINO_SODAQ_EXPLORER)
#define loraSerial Serial2

#else
// please select a sodaq board
debugSerial.println("Please select a sodaq board!!");
#endif
CayenneLPP data(51); //se define el tamaño máximo del payload (51 bytes)
float lat = 19.0441087;
float lon = -95.9716481;
// ABP
const uint8_t devAddr[4] = {0x00, 0x00, 0x00, 0x00};
const uint8_t appSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t nwkSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// OTAA

// 0c13321786b9c36f272e7cbdbef2cd71
// sodaq 2  0004A30B0022f78c, 0004A30B00228B3B
//0004A30B0022D9F3
uint8_t DevEUI[8] = {0x00, 0x04, 0xA3, 0x0B, 0x00, 0x22, 0xD9, 0xF3};
uint8_t AppEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t AppKey[16] = {0x0C, 0x13, 0x32, 0x17, 0x86, 0xb9, 0xc3, 0x6f, 0x27, 0x2e, 0x7c, 0xbd, 0xbe, 0xf2, 0xcd, 0x71};
bool connected = false;
void setupLoRaABP()
{
    if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, false))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
    }
    else
    {
        debugSerial.println("Communication to LoRaBEE failed!");
    }
}

void setupLoRaOTAA()
{
    if (LoRaBee.initOTA(loraSerial, DevEUI, AppEUI, AppKey, true))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
        connected = true;
    }
    else
    {
        debugSerial.println("OTAA Setup failed!");
        connected = false;
    }
}
void setupLoRa()
{
    setupLoRaOTAA();
    LoRaBee.setSpreadingFactor(7);
}

void setup()
{
// Power up the LoRaBEE
#if defined(ARDUINO_AVR_SODAQ_MBILI) || defined(ARDUINO_SODAQ_AUTONOMO)
    pinMode(BEE_VCC, OUTPUT);
    digitalWrite(BEE_VCC, HIGH);
#endif
    delay(3000);

    while ((!SerialUSB) && (millis() < 10000))
    {
        // Wait 10 seconds for the Serial Monitor
    }

    // Set baud rate
    debugSerial.begin(57600);
    loraSerial.begin(LoRaBee.getDefaultBaudRate());
    LoRaBee.setDiag(debugSerial);
    sodaq_gps.init(GPS_ENABLE);
    debugSerial.println("Starting");
    setupLoRa();
}

void sendPacket(CayenneLPP &packet)
{
    connected = false;
    switch (LoRaBee.send(1, packet.getBuffer(), packet.getSize()))
    {

    case NoError:
        debugSerial.println("Successful transmission.");
        connected = true;
        break;
    case NoResponse:
        debugSerial.println("There was no response from the device.");
        setupLoRa();
        break;
    case Timeout:
        debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
        delay(20000);
        break;
    case PayloadSizeError:
        debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
        break;
    case InternalError:
        debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! Try restarting the device!\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case Busy:
        debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
        delay(10000);
        break;
    case NetworkFatalError:
        debugSerial.println("There is a non-recoverable error with the network connection. You should re-connect.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NotConnected:
        debugSerial.println("The device is not connected to the network. Please connect to the network before attempting to send data.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NoAcknowledgment:
        debugSerial.println("There was no acknowledgment sent back!");
        // When you this message you are probaly out of range of the network.
        break;
    default:
        break;
    }
}

void loop()
{
    if (connected)
    {
        data.reset();
        /*
            if (sodaq_gps.scan(true))
            {
                lat = sodaq_gps.getLat();
            lon = sodaq_gps.getLon();
            }
        */

        data.addGPS(1, lat, lon, 0);
        data.addAnalogInput(2, 3.14159);
        sendPacket(data);
        LoRaBee.sleep();
        USBDevice.detach();
        LowPower.sleep(1000);
        LoRaBee.wakeUp();
        USBDevice.attach();
    }
    else
    {
        setupLoRa();
    }
}

I need to add heart rate value (for example 65 beats per minute) and send it through CayenneLPP function such as data.addAnalogInput(2, bpm) //send the value through channel 2 with value bpm.

I was trying to reach it with a MAX30102 heart rate sensor, the code that is given with the library is:

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

#define Serial SerialUSB

#include "heartRate.h"

MAX30105 particleSensor;

const byte RATE_SIZE = 4; // Increase this for more averaging. 4 is good; siempre apunta al mismo byte
byte rates[RATE_SIZE];    // Array of heart rates; arreglo de 4 posiciones
byte rateSpot = 0;        //Ă­ndices de
long lastBeat = 0;        // Time at which the last beat occurred; entero de longitud extenso, 32 bits o 4 bytes

float beatsPerMinute; // flotante, latidos por minuto
int beatAvg;

void setup()
{

    while (!Serial)
    {
        /* code */
    }

    Serial.begin(115200);
    Serial.println("Initializing...");

    // Initialize sensor
    if (!particleSensor.begin(Wire, I2C_SPEED_FAST, 0x57)) // Use default I2C port, 400kHz speed
    {
        Serial.println("MAX30105 was not found. Please check wiring/power. ");
        while (1)
        {
            analogWrite(LED_RED, 0); //analogWrite(LED_RED, 255);
            analogWrite(LED_GREEN, 0); //analogWrite(LED_GREEN, 255);
            analogWrite(LED_BLUE, 0); //analogWrite(LED_BLUE, 255);
        }
    }
    Serial.println("Place your index finger on the sensor with steady pressure.");

    particleSensor.setup();                    // Configure sensor with default settings
    particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
    particleSensor.setPulseAmplitudeGreen(0);  // Turn off Green LED
}

void loop()
{
    analogWrite(LED_RED, 0);
    analogWrite(LED_GREEN, 0);

    analogWrite(LED_BLUE, 0);
    long irValue = particleSensor.getIR(); // se obtiene el valor inmediato de infrarojo

    if (checkForBeat(irValue) == true)
    {
        // We sensed a beat!
        long delta = millis() - lastBeat;
        lastBeat = millis();

        beatsPerMinute = 60 / (delta / 1000.0);

        if (beatsPerMinute < 255 && beatsPerMinute > 20)
        {
            rates[rateSpot++] = (byte)beatsPerMinute; // Store this reading in the array
            rateSpot %= RATE_SIZE;                    // Wrap variable

            // Take average of readings
            beatAvg = 0;
            for (byte x = 0; x < RATE_SIZE; x++)
                beatAvg += rates[x];
            beatAvg /= RATE_SIZE;
        }
    }

    Serial.print("IR=");
    Serial.print(irValue);
    Serial.print(", BPM=");
    Serial.print(beatsPerMinute);
    Serial.print(", Avg BPM=");
    Serial.print(beatAvg);

    if (irValue < 50000)
        Serial.print(" No finger?");

    Serial.println();
}

I was wondering if there is a way to sense the heart rate (beats per minute) and store it in a variable in order to send it through LoRa. I am currently sending GPS through cayenneLPP library, I'm using a Sodaq One V3 which is based on an arduino zero, so the code is based on arduino framework, the function to send the GPS is inside my void loop function and it sense GPS correctly:

data.addGPS(1, lat, lon, 0);
data.addAnalogInput(2, 3.14159);
sendPacket(data);

My entire code for sending GPS is (It works good and I understand everything on it, it is just to show my entire project):

#include <Arduino.h>
#include "CayenneLPP.h"
#include <Sodaq_RN2483.h>
#include <Sodaq_UBlox_GPS.h>
#include "ArduinoLowPower.h"

#define debugSerial SERIAL_PORT_MONITOR

#if defined(ARDUINO_AVR_SODAQ_MBILI)
#define loraSerial Serial1
#define BEE_VCC 20

#elif defined(ARDUINO_SODAQ_AUTONOMO) || defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA)
#define loraSerial Serial1

#elif defined(ARDUINO_SODAQ_EXPLORER)
#define loraSerial Serial2

#else
// please select a sodaq board
debugSerial.println("Please select a sodaq board!!");
#endif
CayenneLPP data(51); //se define el tamaño máximo del payload (51 bytes)
float lat = 16.0441087;
float lon = -92.9716481;
// ABP
const uint8_t devAddr[4] = {0x00, 0x00, 0x00, 0x00};
const uint8_t appSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t nwkSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// OTAA

// 0c13321786b9c36f272e7cbdbef2cd71
// sodaq 2  0004A30B0022f78c, 0004A30B00228B3B
//0004A30B0022D9F3
uint8_t DevEUI[8] = {0x00, 0x04, 0xA3, 0x0B, 0x00, 0x22, 0xD9, 0xF3};
uint8_t AppEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t AppKey[16] = {0x0C, 0x13, 0x32, 0x17, 0x86, 0xb9, 0xc3, 0x6f, 0x27, 0x2e, 0x7c, 0xbd, 0xbe, 0xf2, 0xcd, 0x71};
bool connected = false;
void setupLoRaABP()
{
    if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, false))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
    }
    else
    {
        debugSerial.println("Communication to LoRaBEE failed!");
    }
}

void setupLoRaOTAA()
{
    if (LoRaBee.initOTA(loraSerial, DevEUI, AppEUI, AppKey, true))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
        connected = true;
    }
    else
    {
        debugSerial.println("OTAA Setup failed!");
        connected = false;
    }
}
void setupLoRa()
{
    setupLoRaOTAA();
    LoRaBee.setSpreadingFactor(7);
}

void setup()
{
// Power up the LoRaBEE
#if defined(ARDUINO_AVR_SODAQ_MBILI) || defined(ARDUINO_SODAQ_AUTONOMO)
    pinMode(BEE_VCC, OUTPUT);
    digitalWrite(BEE_VCC, HIGH);
#endif
    delay(3000);

    while ((!SerialUSB) && (millis() < 10000))
    {
        // Wait 10 seconds for the Serial Monitor
    }

    // Set baud rate
    debugSerial.begin(57600);
    loraSerial.begin(LoRaBee.getDefaultBaudRate());
    LoRaBee.setDiag(debugSerial);
    sodaq_gps.init(GPS_ENABLE);
    debugSerial.println("Starting");
    setupLoRa();
}

void sendPacket(CayenneLPP &packet)
{
    connected = false;
    switch (LoRaBee.send(1, packet.getBuffer(), packet.getSize()))
    {

    case NoError:
        debugSerial.println("Successful transmission.");
        connected = true;
        break;
    case NoResponse:
        debugSerial.println("There was no response from the device.");
        setupLoRa();
        break;
    case Timeout:
        debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
        delay(20000);
        break;
    case PayloadSizeError:
        debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
        break;
    case InternalError:
        debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! Try restarting the device!\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case Busy:
        debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
        delay(10000);
        break;
    case NetworkFatalError:
        debugSerial.println("There is a non-recoverable error with the network connection. You should re-connect.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NotConnected:
        debugSerial.println("The device is not connected to the network. Please connect to the network before attempting to send data.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NoAcknowledgment:
        debugSerial.println("There was no acknowledgment sent back!");
        // When you this message you are probaly out of range of the network.
        break;
    default:
        break;
    }
}

void loop()
{
    if (connected)
    {
        data.reset();
        /*
            if (sodaq_gps.scan(true))
            {
                lat = sodaq_gps.getLat();
            lon = sodaq_gps.getLon();
            }
        */

        data.addGPS(1, lat, lon, 0);
        data.addAnalogInput(2, 3.14159);
        sendPacket(data);
        LoRaBee.sleep();
        USBDevice.detach();
        LowPower.sleep(1000);
        LoRaBee.wakeUp();
        USBDevice.attach();
    }
    else
    {
        setupLoRa();
    }
}

I need to add heart rate value (for example 65 beats per minute) and send it through CayenneLPP function such as data.addAnalogInput(2, bpm) //send the value through channel 2 with value bpm.

I was trying to reach it with a MAX30102 heart rate sensor, the code that is given with the library is:

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

#define Serial SerialUSB

#include "heartRate.h"

MAX30105 particleSensor;

const byte RATE_SIZE = 4; // Increase this for more averaging. 4 is good; siempre apunta al mismo byte
byte rates[RATE_SIZE];    // Array of heart rates; arreglo de 4 posiciones
byte rateSpot = 0;        //Ă­ndices de
long lastBeat = 0;        // Time at which the last beat occurred; entero de longitud extenso, 32 bits o 4 bytes

float beatsPerMinute; // flotante, latidos por minuto
int beatAvg;

void setup()
{

    while (!Serial)
    {
        /* code */
    }

    Serial.begin(115200);
    Serial.println("Initializing...");

    // Initialize sensor
    if (!particleSensor.begin(Wire, I2C_SPEED_FAST, 0x57)) // Use default I2C port, 400kHz speed
    {
        Serial.println("MAX30105 was not found. Please check wiring/power. ");
        while (1)
        {
            analogWrite(LED_RED, 0); //analogWrite(LED_RED, 255);
            analogWrite(LED_GREEN, 0); //analogWrite(LED_GREEN, 255);
            analogWrite(LED_BLUE, 0); //analogWrite(LED_BLUE, 255);
        }
    }
    Serial.println("Place your index finger on the sensor with steady pressure.");

    particleSensor.setup();                    // Configure sensor with default settings
    particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
    particleSensor.setPulseAmplitudeGreen(0);  // Turn off Green LED
}

void loop()
{
    analogWrite(LED_RED, 0);
    analogWrite(LED_GREEN, 0);

    analogWrite(LED_BLUE, 0);
    long irValue = particleSensor.getIR(); // se obtiene el valor inmediato de infrarojo

    if (checkForBeat(irValue) == true)
    {
        // We sensed a beat!
        long delta = millis() - lastBeat;
        lastBeat = millis();

        beatsPerMinute = 60 / (delta / 1000.0);

        if (beatsPerMinute < 255 && beatsPerMinute > 20)
        {
            rates[rateSpot++] = (byte)beatsPerMinute; // Store this reading in the array
            rateSpot %= RATE_SIZE;                    // Wrap variable

            // Take average of readings
            beatAvg = 0;
            for (byte x = 0; x < RATE_SIZE; x++)
                beatAvg += rates[x];
            beatAvg /= RATE_SIZE;
        }
    }

    Serial.print("IR=");
    Serial.print(irValue);
    Serial.print(", BPM=");
    Serial.print(beatsPerMinute);
    Serial.print(", Avg BPM=");
    Serial.print(beatAvg);

    if (irValue < 50000)
        Serial.print(" No finger?");

    Serial.println();
}

I understand good the code since I have read the datasheet in order to optimize the lecture to use in the wrist instead of the finger (It is important to mention that for wrist applications we need to use a sensor with green led due to the DC component of the signal) but changing the following line inside the MAX30105.h library we can obtain a good heart rate average (it was taken from the information within the datasheet but basically, we need to set the powerlevel to 0xFF in order to get the maximum current in the led and change the other values according to the datasheet table).

 // Setup the IC with user selectable settings
  void setup(byte powerLevel = 0xFF, byte sampleAverage = 4, byte ledMode = 3, int sampleRate = 1000, int pulseWidth = 411, int adcRange = 16384);

My problem is when I try to integrate the code of GPS and the code of the heart rate to send them through LoRa (with CayenneLPP library) since the heart rate algorithm works on an infinity loop for sending the BPM, and the GPS is sent every time the loop is executed which generates conflict, I tried two possible solutions:

First one was to try to run the two codes with PROTOTHREAD in an arduino one but I could not get the value saved and send it though LoRa and unfortunately the Sodaq One V3 does not support PROTOTHREAD. The Second alternative I tried was compacting the heart rate code in a function but no success since was pretty similar to the original one, I needed infinity loops to get the value.

I show my attempts:

For the protothreads:

#include <Arduino.h>
#include <pt.h>
#include "MAX30105.h"
#include "heartRate.h"
#include "CayenneLPP.h"
#include <Sodaq_RN2483.h>
#include <Sodaq_UBlox_GPS.h>
#include "ArduinoLowPower.h"
#include <Wire.h>

#define debugSerial SERIAL_PORT_MONITOR

MAX30105 particleSensor; // instanciamos el objeto particleSensor de la clase MAX30105

const byte RATE_SIZE = 4; // Increase this for more averaging. 4 is good; siempre apunta al mismo byte
byte rates[RATE_SIZE];    // Array of heart rates; arreglo de 4 posiciones
byte rateSpot = 0;        //Ă­ndices de
long lastBeat = 0;        // Time at which the last beat occurred; entero de longitud extenso, 32 bits o 4 bytes

float beatsPerMinute; // flotante, latidos por minuto
int beatAvg;
struct pt hilo1;
static int count = 0;

#if defined(ARDUINO_AVR_SODAQ_MBILI)
#define loraSerial Serial1
#define BEE_VCC 20

#elif defined(ARDUINO_SODAQ_AUTONOMO) || defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA)
#define loraSerial Serial1

#elif defined(ARDUINO_SODAQ_EXPLORER)
#define loraSerial Serial2

#else
// please select a sodaq board
debugSerial.println("Please select a sodaq board!!");
#endif
CayenneLPP data(51); // se instancia el objeto data de la clase CayenneLPP con valor de 51 en el buffer de datos que se transmitirán por lora
float lat = 19.0441087;
float lon = -95.9716481;
// ABP
// constante unasigned int 8 bytes
const uint8_t devAddr[4] = {0x00, 0x00, 0x00, 0x00};
const uint8_t appSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t nwkSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// OTAA

// 0c13321786b9c36f272e7cbdbef2cd71
// sodaq 2  0004A30B0022f78c, 0004A30B00228B3B, device 2: 0004A30B00228B3B
uint8_t DevEUI[8] = {0x00, 0x04, 0xa3, 0x0b, 0x00, 0x22, 0xf7, 0x8a};
uint8_t AppEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t AppKey[16] = {0x0c, 0x13, 0x32, 0x17, 0x86, 0xb9, 0xc3, 0x6f, 0x27, 0x2e, 0x7c, 0xbd, 0xbe, 0xf2, 0xcd, 0x71};
bool connected = false;

void setupLoRaABP()
{
    if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, false))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
    }
    else
    {
        debugSerial.println("Communication to LoRaBEE failed!");
    }
}

void setupLoRaOTAA()
{
    if (LoRaBee.initOTA(loraSerial, DevEUI, AppEUI, AppKey, true))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
        connected = true;
    }
    else
    {
        debugSerial.println("OTAA Setup failed!");
        connected = false;
    }
}
void setupLoRa()
{
    setupLoRaOTAA();
    LoRaBee.setSpreadingFactor(7);
}

void setup()
{

    // Power up the LoRaBEE
#if defined(ARDUINO_AVR_SODAQ_MBILI) || defined(ARDUINO_SODAQ_AUTONOMO)
    pinMode(BEE_VCC, OUTPUT);
    digitalWrite(BEE_VCC, HIGH);
#endif
    delay(3000);

    PT_INIT(&hilo1);
    debugSerial.println("entrando a setup");

    // Initialize sensor
    if (!particleSensor.begin(Wire, I2C_SPEED_FAST, 0x57)) // Use default I2C port, 400kHz speed
    {
        //Serial.println("MAX30105 was not found. Please check wiring/power. ");
        while (1)
        {
            analogWrite(LED_RED, 0);   // analogWrite(LED_RED, 255);
            analogWrite(LED_GREEN, 0); // analogWrite(LED_GREEN, 255);
            analogWrite(LED_BLUE, 0);  // analogWrite(LED_BLUE, 255);
        }
    }
    //Serial.println("Place your index finger on the sensor with steady pressure.");

    particleSensor.setup();                    // Configure sensor with default settings
    particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
    particleSensor.setPulseAmplitudeGreen(0);  // Turn off Green LED
    

     // Set baud rate
    debugSerial.begin(57600);
    loraSerial.begin(LoRaBee.getDefaultBaudRate());
    LoRaBee.setDiag(debugSerial);
    sodaq_gps.init(GPS_ENABLE);
    debugSerial.println("Starting");
    setupLoRa();
}

int parpadeo(struct pt *pt)
{
    PT_BEGIN(pt);
    // void setup() {
    //static long t = 0;
    do
    {
        long irValue = particleSensor.getIR(); // se obtiene el valor inmediato de infrarojo

        if (checkForBeat(irValue) == true)
        {
            // We sensed a beat!
            long delta = millis() - lastBeat;
            lastBeat = millis();

            beatsPerMinute = 60 / (delta / 1000.0);

            if (beatsPerMinute < 255 && beatsPerMinute > 20)
            {
                rates[rateSpot++] = (byte)beatsPerMinute; // Store this reading in the array
                rateSpot %= RATE_SIZE;                    // Wrap variable

                // Take average of readings
                beatAvg = 0;
                for (byte x = 0; x < RATE_SIZE; x++)
                    beatAvg += rates[x];
                beatAvg /= RATE_SIZE;
            }
        }

        /*debugSerial.print("IR=");
        debugSerial.print(irValue);
        debugSerial.print(", BPM=");
        debugSerial.print(beatsPerMinute);
        debugSerial.print(", Avg BPM=");
        debugSerial.print(beatAvg);
        */
        //if (irValue < 50000)
            //debugSerial.print(" No finger?");

        //debugSerial.println();
    } while (true)
        PT_END(pt);
}

void sendPacket(CayenneLPP &packet)
{
    connected = false;
    switch (LoRaBee.send(1, packet.getBuffer(), packet.getSize()))
    {

    case NoError:
        debugSerial.println("Successful transmission.");
        connected = true;
        break;
    case NoResponse:
        debugSerial.println("There was no response from the device.");
        setupLoRa();
        break;
    case Timeout:
        debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
        delay(20000);
        break;
    case PayloadSizeError:
        debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
        break;
    case InternalError:
        debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! Try restarting the device!\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case Busy:
        debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
        delay(10000);
        break;
    case NetworkFatalError:
        debugSerial.println("There is a non-recoverable error with the network connection. You should re-connect.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NotConnected:
        debugSerial.println("The device is not connected to the network. Please connect to the network before attempting to send data.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NoAcknowledgment:
        debugSerial.println("There was no acknowledgment sent back!");
        // When you this message you are probaly out of range of the network.
        break;
    default:
        break;
    }
}

void loop()
{
    //parpadeo(&hilo1);
  

    if (connected)
    {
        data.reset(); //reseteamos el tamaño del objeto que se instanció de la clase cayenneLPP (los 51 del bufer)
        /*
            if (sodaq_gps.scan(true))
            {
                lat = sodaq_gps.getLat();
            lon = sodaq_gps.getLon();
            }
        */
        Serial.println(beatAvg);
        data.addGPS(1, lat, lon, 0); //se envĂ­an los datos de gps
        data.addAnalogInput(2, 3.14159); //se agregan los datos al bufer
        sendPacket(data); //se envĂ­a el paquete
        //LoRaBee.sleep();
        //USBDevice.detach();
        //LowPower.sleep(1000);
        //LoRaBee.wakeUp();
        //USBDevice.attach();
    }
    else
    {
        setupLoRa();
    }
}

and for the heart rate function:

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

#define Serial SerialUSB
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; // Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

// sampling times
//unsigned long prevHRTime;


// Sensor object instantiation
MAX30105 particleSensor;

// Setup
void setup()
{

  // Initialize serial port and configure your sensor
  Serial.begin(115200);
  Serial.println("Initializing...");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST))
  {
    Serial.println("MAX30105 was not found. Please check wiring/power. ");
  }

  Serial.println("Place your index finger on the sensor with steady pressure.");

  particleSensor.setup();                    // Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0);  // Turn off Green LED

  //prevHRTime = millis();

}

void heart_rate()
{

  long irValue = particleSensor.getIR();

  if (checkForBeat(irValue) == true)
  {
    // We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20)
    {
      rates[rateSpot++] = (byte)beatsPerMinute; // Store this reading in the array
      rateSpot %= RATE_SIZE;                    // Wrap variable

      // Take average of readings
      beatAvg = 0;
      for (byte x = 0; x < RATE_SIZE; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

  Serial.print("IR=");
  Serial.print(irValue);
  Serial.print(", BPM=");
  Serial.print(beatsPerMinute);
  Serial.print(", Avg BPM=");
  Serial.print(beatAvg);

  if (irValue < 50000)
    Serial.print(" No finger?");

  Serial.println();
}

void loop()
{

  /*unsigned long now = millis();

  if (now - prevHRTime > 5000)
  {
    prevHRTime = now;

    heart_rate();
  } */

  heart_rate();


}

I was wondering if there is a way to sense the heart rate (beats per minute) and store it in a variable in order to send it through LoRa. I am currently sending GPS through cayenneLPP library, I'm using a Sodaq One V3 which is based on an arduino zero, so the code is based on arduino framework, the function to send the GPS is inside my void loop function and it sense GPS correctly:

data.addGPS(1, lat, lon, 0);
data.addAnalogInput(2, 3.14159);
sendPacket(data);

My entire code for sending GPS is (It works good and I understand everything on it, it is just to show my entire project):

#include <Arduino.h>
#include "CayenneLPP.h"
#include <Sodaq_RN2483.h>
#include <Sodaq_UBlox_GPS.h>
#include "ArduinoLowPower.h"

#define debugSerial SERIAL_PORT_MONITOR

#if defined(ARDUINO_AVR_SODAQ_MBILI)
#define loraSerial Serial1
#define BEE_VCC 20

#elif defined(ARDUINO_SODAQ_AUTONOMO) || defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA)
#define loraSerial Serial1

#elif defined(ARDUINO_SODAQ_EXPLORER)
#define loraSerial Serial2

#else
// please select a sodaq board
debugSerial.println("Please select a sodaq board!!");
#endif
CayenneLPP data(51); //se define el tamaño máximo del payload (51 bytes)
float lat = 19.0441087;
float lon = -95.9716481;
// ABP
const uint8_t devAddr[4] = {0x00, 0x00, 0x00, 0x00};
const uint8_t appSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t nwkSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// OTAA

// 0c13321786b9c36f272e7cbdbef2cd71
// sodaq 2  0004A30B0022f78c, 0004A30B00228B3B
//0004A30B0022D9F3
uint8_t DevEUI[8] = {0x00, 0x04, 0xA3, 0x0B, 0x00, 0x22, 0xD9, 0xF3};
uint8_t AppEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t AppKey[16] = {0x0C, 0x13, 0x32, 0x17, 0x86, 0xb9, 0xc3, 0x6f, 0x27, 0x2e, 0x7c, 0xbd, 0xbe, 0xf2, 0xcd, 0x71};
bool connected = false;
void setupLoRaABP()
{
    if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, false))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
    }
    else
    {
        debugSerial.println("Communication to LoRaBEE failed!");
    }
}

void setupLoRaOTAA()
{
    if (LoRaBee.initOTA(loraSerial, DevEUI, AppEUI, AppKey, true))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
        connected = true;
    }
    else
    {
        debugSerial.println("OTAA Setup failed!");
        connected = false;
    }
}
void setupLoRa()
{
    setupLoRaOTAA();
    LoRaBee.setSpreadingFactor(7);
}

void setup()
{
// Power up the LoRaBEE
#if defined(ARDUINO_AVR_SODAQ_MBILI) || defined(ARDUINO_SODAQ_AUTONOMO)
    pinMode(BEE_VCC, OUTPUT);
    digitalWrite(BEE_VCC, HIGH);
#endif
    delay(3000);

    while ((!SerialUSB) && (millis() < 10000))
    {
        // Wait 10 seconds for the Serial Monitor
    }

    // Set baud rate
    debugSerial.begin(57600);
    loraSerial.begin(LoRaBee.getDefaultBaudRate());
    LoRaBee.setDiag(debugSerial);
    sodaq_gps.init(GPS_ENABLE);
    debugSerial.println("Starting");
    setupLoRa();
}

void sendPacket(CayenneLPP &packet)
{
    connected = false;
    switch (LoRaBee.send(1, packet.getBuffer(), packet.getSize()))
    {

    case NoError:
        debugSerial.println("Successful transmission.");
        connected = true;
        break;
    case NoResponse:
        debugSerial.println("There was no response from the device.");
        setupLoRa();
        break;
    case Timeout:
        debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
        delay(20000);
        break;
    case PayloadSizeError:
        debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
        break;
    case InternalError:
        debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! Try restarting the device!\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case Busy:
        debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
        delay(10000);
        break;
    case NetworkFatalError:
        debugSerial.println("There is a non-recoverable error with the network connection. You should re-connect.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NotConnected:
        debugSerial.println("The device is not connected to the network. Please connect to the network before attempting to send data.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NoAcknowledgment:
        debugSerial.println("There was no acknowledgment sent back!");
        // When you this message you are probaly out of range of the network.
        break;
    default:
        break;
    }
}

void loop()
{
    if (connected)
    {
        data.reset();
        /*
            if (sodaq_gps.scan(true))
            {
                lat = sodaq_gps.getLat();
            lon = sodaq_gps.getLon();
            }
        */

        data.addGPS(1, lat, lon, 0);
        data.addAnalogInput(2, 3.14159);
        sendPacket(data);
        LoRaBee.sleep();
        USBDevice.detach();
        LowPower.sleep(1000);
        LoRaBee.wakeUp();
        USBDevice.attach();
    }
    else
    {
        setupLoRa();
    }
}

I need to add heart rate value (for example 65 beats per minute) and send it through CayenneLPP function such as data.addAnalogInput(2, bpm) //send the value through channel 2 with value bpm.

I was trying to reach it with a MAX30102 heart rate sensor, the code that is given with the library is:

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

#define Serial SerialUSB

#include "heartRate.h"

MAX30105 particleSensor;

const byte RATE_SIZE = 4; // Increase this for more averaging. 4 is good; siempre apunta al mismo byte
byte rates[RATE_SIZE];    // Array of heart rates; arreglo de 4 posiciones
byte rateSpot = 0;        //Ă­ndices de
long lastBeat = 0;        // Time at which the last beat occurred; entero de longitud extenso, 32 bits o 4 bytes

float beatsPerMinute; // flotante, latidos por minuto
int beatAvg;

void setup()
{

    while (!Serial)
    {
        /* code */
    }

    Serial.begin(115200);
    Serial.println("Initializing...");

    // Initialize sensor
    if (!particleSensor.begin(Wire, I2C_SPEED_FAST, 0x57)) // Use default I2C port, 400kHz speed
    {
        Serial.println("MAX30105 was not found. Please check wiring/power. ");
        while (1)
        {
            analogWrite(LED_RED, 0); //analogWrite(LED_RED, 255);
            analogWrite(LED_GREEN, 0); //analogWrite(LED_GREEN, 255);
            analogWrite(LED_BLUE, 0); //analogWrite(LED_BLUE, 255);
        }
    }
    Serial.println("Place your index finger on the sensor with steady pressure.");

    particleSensor.setup();                    // Configure sensor with default settings
    particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
    particleSensor.setPulseAmplitudeGreen(0);  // Turn off Green LED
}

void loop()
{
    analogWrite(LED_RED, 0);
    analogWrite(LED_GREEN, 0);

    analogWrite(LED_BLUE, 0);
    long irValue = particleSensor.getIR(); // se obtiene el valor inmediato de infrarojo

    if (checkForBeat(irValue) == true)
    {
        // We sensed a beat!
        long delta = millis() - lastBeat;
        lastBeat = millis();

        beatsPerMinute = 60 / (delta / 1000.0);

        if (beatsPerMinute < 255 && beatsPerMinute > 20)
        {
            rates[rateSpot++] = (byte)beatsPerMinute; // Store this reading in the array
            rateSpot %= RATE_SIZE;                    // Wrap variable

            // Take average of readings
            beatAvg = 0;
            for (byte x = 0; x < RATE_SIZE; x++)
                beatAvg += rates[x];
            beatAvg /= RATE_SIZE;
        }
    }

    Serial.print("IR=");
    Serial.print(irValue);
    Serial.print(", BPM=");
    Serial.print(beatsPerMinute);
    Serial.print(", Avg BPM=");
    Serial.print(beatAvg);

    if (irValue < 50000)
        Serial.print(" No finger?");

    Serial.println();
}

I understand good the code since I have read the datasheet in order to optimize the lecture to use in the wrist instead of the finger (It is important to mention that for wrist applications we need to use a sensor with green led due to the DC component of the signal) but changing the following line inside the MAX30105.h library we can obtain a good heart rate average (it was taken from the information within the datasheet but basically, we need to set the powerlevel to 0xFF in order to get the maximum current in the led and change the other values according to the datasheet table).

 // Setup the IC with user selectable settings
  void setup(byte powerLevel = 0xFF, byte sampleAverage = 4, byte ledMode = 3, int sampleRate = 1000, int pulseWidth = 411, int adcRange = 16384);

My problem is when I try to integrate the code of GPS and the code of the heart rate to send them through LoRa (with CayenneLPP library) since the heart rate algorithm works on an infinity loop for sending the BPM, and the GPS is sent every time the loop is executed which generates conflict, I tried two possible solutions:

First one was to try to run the two codes with PROTOTHREAD in an arduino one but I could not get the value saved and send it though LoRa and unfortunately the Sodaq One V3 does not support PROTOTHREAD. The Second alternative I tried was compacting the heart rate code in a function but no success since was pretty similar to the original one, I needed infinity loops to get the value.

I show my attempts:

For the protothreads:

#include <Arduino.h>
#include <pt.h>
#include "MAX30105.h"
#include "heartRate.h"
#include "CayenneLPP.h"
#include <Sodaq_RN2483.h>
#include <Sodaq_UBlox_GPS.h>
#include "ArduinoLowPower.h"
#include <Wire.h>

#define debugSerial SERIAL_PORT_MONITOR

MAX30105 particleSensor; // instanciamos el objeto particleSensor de la clase MAX30105

const byte RATE_SIZE = 4; // Increase this for more averaging. 4 is good; siempre apunta al mismo byte
byte rates[RATE_SIZE];    // Array of heart rates; arreglo de 4 posiciones
byte rateSpot = 0;        //Ă­ndices de
long lastBeat = 0;        // Time at which the last beat occurred; entero de longitud extenso, 32 bits o 4 bytes

float beatsPerMinute; // flotante, latidos por minuto
int beatAvg;
struct pt hilo1;
static int count = 0;

#if defined(ARDUINO_AVR_SODAQ_MBILI)
#define loraSerial Serial1
#define BEE_VCC 20

#elif defined(ARDUINO_SODAQ_AUTONOMO) || defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA)
#define loraSerial Serial1

#elif defined(ARDUINO_SODAQ_EXPLORER)
#define loraSerial Serial2

#else
// please select a sodaq board
debugSerial.println("Please select a sodaq board!!");
#endif
CayenneLPP data(51); // se instancia el objeto data de la clase CayenneLPP con valor de 51 en el buffer de datos que se transmitirán por lora
float lat = 19.0441087;
float lon = -95.9716481;
// ABP
// constante unasigned int 8 bytes
const uint8_t devAddr[4] = {0x00, 0x00, 0x00, 0x00};
const uint8_t appSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t nwkSKey[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// OTAA

// 0c13321786b9c36f272e7cbdbef2cd71
// sodaq 2  0004A30B0022f78c, 0004A30B00228B3B, device 2: 0004A30B00228B3B
uint8_t DevEUI[8] = {0x00, 0x04, 0xa3, 0x0b, 0x00, 0x22, 0xf7, 0x8a};
uint8_t AppEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t AppKey[16] = {0x0c, 0x13, 0x32, 0x17, 0x86, 0xb9, 0xc3, 0x6f, 0x27, 0x2e, 0x7c, 0xbd, 0xbe, 0xf2, 0xcd, 0x71};
bool connected = false;

void setupLoRaABP()
{
    if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, false))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
    }
    else
    {
        debugSerial.println("Communication to LoRaBEE failed!");
    }
}

void setupLoRaOTAA()
{
    if (LoRaBee.initOTA(loraSerial, DevEUI, AppEUI, AppKey, true))
    {
        debugSerial.println("Communication to LoRaBEE successful.");
        connected = true;
    }
    else
    {
        debugSerial.println("OTAA Setup failed!");
        connected = false;
    }
}
void setupLoRa()
{
    setupLoRaOTAA();
    LoRaBee.setSpreadingFactor(7);
}

void setup()
{

    // Power up the LoRaBEE
#if defined(ARDUINO_AVR_SODAQ_MBILI) || defined(ARDUINO_SODAQ_AUTONOMO)
    pinMode(BEE_VCC, OUTPUT);
    digitalWrite(BEE_VCC, HIGH);
#endif
    delay(3000);

    PT_INIT(&hilo1);
    debugSerial.println("entrando a setup");

    // Initialize sensor
    if (!particleSensor.begin(Wire, I2C_SPEED_FAST, 0x57)) // Use default I2C port, 400kHz speed
    {
        //Serial.println("MAX30105 was not found. Please check wiring/power. ");
        while (1)
        {
            analogWrite(LED_RED, 0);   // analogWrite(LED_RED, 255);
            analogWrite(LED_GREEN, 0); // analogWrite(LED_GREEN, 255);
            analogWrite(LED_BLUE, 0);  // analogWrite(LED_BLUE, 255);
        }
    }
    //Serial.println("Place your index finger on the sensor with steady pressure.");

    particleSensor.setup();                    // Configure sensor with default settings
    particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
    particleSensor.setPulseAmplitudeGreen(0);  // Turn off Green LED
    

     // Set baud rate
    debugSerial.begin(57600);
    loraSerial.begin(LoRaBee.getDefaultBaudRate());
    LoRaBee.setDiag(debugSerial);
    sodaq_gps.init(GPS_ENABLE);
    debugSerial.println("Starting");
    setupLoRa();
}

int parpadeo(struct pt *pt)
{
    PT_BEGIN(pt);
    // void setup() {
    //static long t = 0;
    do
    {
        long irValue = particleSensor.getIR(); // se obtiene el valor inmediato de infrarojo

        if (checkForBeat(irValue) == true)
        {
            // We sensed a beat!
            long delta = millis() - lastBeat;
            lastBeat = millis();

            beatsPerMinute = 60 / (delta / 1000.0);

            if (beatsPerMinute < 255 && beatsPerMinute > 20)
            {
                rates[rateSpot++] = (byte)beatsPerMinute; // Store this reading in the array
                rateSpot %= RATE_SIZE;                    // Wrap variable

                // Take average of readings
                beatAvg = 0;
                for (byte x = 0; x < RATE_SIZE; x++)
                    beatAvg += rates[x];
                beatAvg /= RATE_SIZE;
            }
        }

        /*debugSerial.print("IR=");
        debugSerial.print(irValue);
        debugSerial.print(", BPM=");
        debugSerial.print(beatsPerMinute);
        debugSerial.print(", Avg BPM=");
        debugSerial.print(beatAvg);
        */
        //if (irValue < 50000)
            //debugSerial.print(" No finger?");

        //debugSerial.println();
    } while (true)
        PT_END(pt);
}

void sendPacket(CayenneLPP &packet)
{
    connected = false;
    switch (LoRaBee.send(1, packet.getBuffer(), packet.getSize()))
    {

    case NoError:
        debugSerial.println("Successful transmission.");
        connected = true;
        break;
    case NoResponse:
        debugSerial.println("There was no response from the device.");
        setupLoRa();
        break;
    case Timeout:
        debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
        delay(20000);
        break;
    case PayloadSizeError:
        debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
        break;
    case InternalError:
        debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! Try restarting the device!\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case Busy:
        debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
        delay(10000);
        break;
    case NetworkFatalError:
        debugSerial.println("There is a non-recoverable error with the network connection. You should re-connect.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NotConnected:
        debugSerial.println("The device is not connected to the network. Please connect to the network before attempting to send data.\r\nThe network connection will reset.");
        setupLoRa();
        break;
    case NoAcknowledgment:
        debugSerial.println("There was no acknowledgment sent back!");
        // When you this message you are probaly out of range of the network.
        break;
    default:
        break;
    }
}

void loop()
{
    //parpadeo(&hilo1);
  

    if (connected)
    {
        data.reset(); //reseteamos el tamaño del objeto que se instanció de la clase cayenneLPP (los 51 del bufer)
        /*
            if (sodaq_gps.scan(true))
            {
                lat = sodaq_gps.getLat();
            lon = sodaq_gps.getLon();
            }
        */
        Serial.println(beatAvg);
        data.addGPS(1, lat, lon, 0); //se envĂ­an los datos de gps
        data.addAnalogInput(2, 3.14159); //se agregan los datos al bufer
        sendPacket(data); //se envĂ­a el paquete
        //LoRaBee.sleep();
        //USBDevice.detach();
        //LowPower.sleep(1000);
        //LoRaBee.wakeUp();
        //USBDevice.attach();
    }
    else
    {
        setupLoRa();
    }
}

and for the heart rate function:

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

#define Serial SerialUSB
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; // Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

// sampling times
//unsigned long prevHRTime;


// Sensor object instantiation
MAX30105 particleSensor;

// Setup
void setup()
{

  // Initialize serial port and configure your sensor
  Serial.begin(115200);
  Serial.println("Initializing...");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST))
  {
    Serial.println("MAX30105 was not found. Please check wiring/power. ");
  }

  Serial.println("Place your index finger on the sensor with steady pressure.");

  particleSensor.setup();                    // Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0);  // Turn off Green LED

  //prevHRTime = millis();

}

void heart_rate()
{

  long irValue = particleSensor.getIR();

  if (checkForBeat(irValue) == true)
  {
    // We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20)
    {
      rates[rateSpot++] = (byte)beatsPerMinute; // Store this reading in the array
      rateSpot %= RATE_SIZE;                    // Wrap variable

      // Take average of readings
      beatAvg = 0;
      for (byte x = 0; x < RATE_SIZE; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

  Serial.print("IR=");
  Serial.print(irValue);
  Serial.print(", BPM=");
  Serial.print(beatsPerMinute);
  Serial.print(", Avg BPM=");
  Serial.print(beatAvg);

  if (irValue < 50000)
    Serial.print(" No finger?");

  Serial.println();
}

void loop()
{

  /*unsigned long now = millis();

  if (now - prevHRTime > 5000)
  {
    prevHRTime = now;

    heart_rate();
  } */

  heart_rate();


}

I was thinking on changing the sensor for a PulseSensor (https://pulsesensor.com/) since I read it works pretty different, realizing I need to read an analog signal and I do not have to get the inifity loop but still reading.

If you could help me with your experience and advise, I would appreciate it so much! Also I hope this could help for other people trying to work something similar

What’s wrong with your post ??

Hi J-M-L! I was wondering if would it be possible to sense the heart rate of the MAX30102 without the loop default function as shown in the next code since I am not able to store the value in a variable, I would like to get the average heart rate every time the loop is executed, thank you so much

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

#define Serial SerialUSB

#include "heartRate.h"

MAX30105 particleSensor;

const byte RATE_SIZE = 4; // Increase this for more averaging. 4 is good; siempre apunta al mismo byte
byte rates[RATE_SIZE];    // Array of heart rates; arreglo de 4 posiciones
byte rateSpot = 0;        //Ă­ndices de
long lastBeat = 0;        // Time at which the last beat occurred; entero de longitud extenso, 32 bits o 4 bytes

float beatsPerMinute; // flotante, latidos por minuto
int beatAvg;

void setup()
{

    while (!Serial)
    {
        /* code */
    }

    Serial.begin(115200);
    Serial.println("Initializing...");

    // Initialize sensor
    if (!particleSensor.begin(Wire, I2C_SPEED_FAST, 0x57)) // Use default I2C port, 400kHz speed
    {
        Serial.println("MAX30105 was not found. Please check wiring/power. ");
        while (1)
        {
            analogWrite(LED_RED, 0); //analogWrite(LED_RED, 255);
            analogWrite(LED_GREEN, 0); //analogWrite(LED_GREEN, 255);
            analogWrite(LED_BLUE, 0); //analogWrite(LED_BLUE, 255);
        }
    }
    Serial.println("Place your index finger on the sensor with steady pressure.");

    particleSensor.setup();                    // Configure sensor with default settings
    particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
    particleSensor.setPulseAmplitudeGreen(0);  // Turn off Green LED
}

void loop()
{
    analogWrite(LED_RED, 0);
    analogWrite(LED_GREEN, 0);

    analogWrite(LED_BLUE, 0);
    long irValue = particleSensor.getIR(); // se obtiene el valor inmediato de infrarojo

    if (checkForBeat(irValue) == true)
    {
        // We sensed a beat!
        long delta = millis() - lastBeat;
        lastBeat = millis();

        beatsPerMinute = 60 / (delta / 1000.0);

        if (beatsPerMinute < 255 && beatsPerMinute > 20)
        {
            rates[rateSpot++] = (byte)beatsPerMinute; // Store this reading in the array
            rateSpot %= RATE_SIZE;                    // Wrap variable

            // Take average of readings
            beatAvg = 0;
            for (byte x = 0; x < RATE_SIZE; x++)
                beatAvg += rates[x];
            beatAvg /= RATE_SIZE;
        }
    }

    Serial.print("IR=");
    Serial.print(irValue);
    Serial.print(", BPM=");
    Serial.print(beatsPerMinute);
    Serial.print(", Avg BPM=");
    Serial.print(beatAvg);

    if (irValue < 50000)
        Serial.print(" No finger?");

    Serial.println();
}

Please edit your post(s) to remove all but one copy of the message. Your post will probably be ignored if you don't, because it is mostly incomprehensible.

Actually, your posting in the forum is in a loop!

1 Like

You can’t instantly read the BPM so you need to structure the code differently. A state machine might be appropriate

1 Like

Thank you so much J-M-L, I will definitely research about state machines in order to try it!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.