My problem is that the sending function I use to send data through LoRa consumes about 2 seconds with a spreading factor of 7 and the node is close to the gateway, that time interferes with my estimation of the beats per minute (bpm) which is the variable we want to send through LoRa given we we need to know the elapsed time between two beats, if there is a delay between them due to LoRa functions since we can not get a correct result of the BPM
A possible solution could be using a thread where the bpm algorithm is executed all the time and sending though lora in another thread but I am using an Arduino where this is not possible (Sodaq One V3)
Our code is:
#include <Arduino.h>
#include "CayenneLPP.h"
#include <Sodaq_RN2483.h>
#include <Sodaq_UBlox_GPS.h>
#include "ArduinoLowPower.h"
#include "heartRate.h"
#include "MAX30105.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);
float lat = 56.0441087;
float lon = -90.9716481;
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; // Time at which the last beat occurred
float beatsPerMinute;
int beatAvg;
// OTAA
// 0c13321786b9c36f272e7cbdbef2cd71 0004A30B0022F78C
// sodaq 2 0004A30B0022f78c, 0004A30B00228B3B
uint8_t DevEUI[8] = {0x00, 0x04, 0xA3, 0x0B, 0x00, 0x22, 0xF7, 0x8C};
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};
void setupLoRaOTAA()
{
if (LoRaBee.initOTA(loraSerial, DevEUI, AppEUI, AppKey, true))
{
debugSerial.println("Communication to LoRaBEE successful.");
}
else
{
debugSerial.println("OTAA Setup failed!");
}
}
void setupLoRa()
{
long start = millis();
setupLoRaOTAA();
LoRaBee.setSpreadingFactor(7);
long end = millis();
debugSerial.println((end - start) / 1000);
}
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);
setupLoRa();
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) // Use default I2C port, 400kHz speed
{
while (1)
;
}
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
debugSerial.println("Starting");
}
void sendPacket(CayenneLPP &packet)
{
switch (LoRaBee.send(1, packet.getBuffer(), packet.getSize()))
{
case NoError:
debugSerial.println("Successful transmission.");
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:
setupLoRa();
break;
case Busy:
delay(10000);
break;
case NetworkFatalError:
setupLoRa();
break;
case NotConnected:
setupLoRa();
break;
case NoAcknowledgment:
debugSerial.println("There was no acknowledgment sent back!");
break;
default:
break;
}
}
void loop()
{
//obteniendo bpm
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;
}
}
//fin
data.reset();
/*
if (sodaq_gps.scan(true))
{
lat = sodaq_gps.getLat();
lon = sodaq_gps.getLon();
}
*/
data.addGPS(1, lat, lon, 0);
data.addAnalogInput(2, beatsPerMinute);
// auto start = millis();
sendPacket(data); //delay de aprox 2s con sf 7
// auto end = millis();
// debugSerial.println((end - start) / 1000);
// LoRaBee.sleep();
// LowPower.sleep(1000);
// LoRaBee.wakeUp();
}
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