Monitoring 2 SPO2 signals using module afe4490

I'm making a project monitoring 2 spo2 signals, here I use the protocentral afe4490 module. where the two afe4490 modules I connect to the arduino mega, when I try 1 module the resulting signal is correct, as shown below, it still has additional electrical mesh noise.

but when I use 2 modules to monitor simultaneously, the signal reading becomes random,

program

#include <SPI.h>
#include "protocentral_afe44xx.h"

afe44xx_data data_modul1;
afe44xx_data data_modul2;

// Konfigurasi pin untuk modul 1
#define AFE44XX_CS_PIN_1     7
#define AFE44XX_PWDN_PIN_1   4
#define AFE44XX_INTNUM_PIN_1 2
AFE44XX afe44xx_modul1(AFE44XX_CS_PIN_1, AFE44XX_PWDN_PIN_1);

// Konfigurasi pin untuk modul 2
#define AFE44XX_CS_PIN_2     6
#define AFE44XX_PWDN_PIN_2   9
#define AFE44XX_INTNUM_PIN_2 3
AFE44XX afe44xx_modul2(AFE44XX_CS_PIN_2, AFE44XX_PWDN_PIN_2);

int32_t heart_rate_prev1 = 0;
int32_t spo2_prev1 = 0;
int32_t heart_rate_prev2 = 0;
int32_t spo2_prev2 = 0;

void setup()
{
  // Konfigurasi pin CS untuk modul
  pinMode(AFE44XX_CS_PIN_1, OUTPUT);
  pinMode(AFE44XX_CS_PIN_2, OUTPUT);

  digitalWrite(AFE44XX_CS_PIN_1, HIGH); // Nonaktifkan CS modul 1
  digitalWrite(AFE44XX_CS_PIN_2, HIGH); // Nonaktifkan CS modul 2

  Serial.begin(57600);
  SPI.begin();

  digitalWrite(AFE44XX_CS_PIN_1, LOW); // aktifkan CS modul 1
  afe44xx_modul1.afe44xx_init();
  digitalWrite(AFE44XX_CS_PIN_1, HIGH); // Nonaktifkan CS modul 1

  digitalWrite(AFE44XX_CS_PIN_2, LOW); // aktifkan CS modul 2
  afe44xx_modul2.afe44xx_init();
  digitalWrite(AFE44XX_CS_PIN_2, HIGH); // Nonaktifkan CS modul 2
}

void loop()
{
  // Membaca data dari modul 1
  digitalWrite(AFE44XX_CS_PIN_1, LOW);  // Aktifkan CS modul 1
  afe44xx_modul1.get_AFE44XX_Data(&data_modul1);
  digitalWrite(AFE44XX_CS_PIN_2, HIGH); // Nonaktifkan CS modul
  delay(8);  // Tunggu agar data stabil

  {
    heart_rate_prev1 = data_modul1.heart_rate;
    spo2_prev1 = data_modul1.spo2;

    //    Serial.print("Module 1 - SpO2: ");
    //    Serial.println(data_modul1.spo2);
//    Serial.print(data_modul2.heart_rate);
    //    Serial.print(",");
    Serial.print(data_modul1.RED_data);
    Serial.println(",");

  }
  // Membaca data dari modul 2
  digitalWrite(AFE44XX_CS_PIN_2, LOW); // Nonaktifkan CS modul 1
  afe44xx_modul2.get_AFE44XX_Data(&data_modul2);
  digitalWrite(AFE44XX_CS_PIN_1, HIGH);  // Aktifkan CS modul 2
  delay(8);  // Tunggu agar data stabil

  {
    heart_rate_prev2 = data_modul2.heart_rate;
    spo2_prev2 = data_modul2.spo2;
    //
    //    Serial.print("Module 2 - SpO2: ");
    //    Serial.println(data_modul2.spo2);
//    Serial.print(data_modul2.heart_rate);
    Serial.print(",");
    Serial.println(data_modul2.RED_data);

  }
}

I'm confused I have to fix which part, please help.

You marked the problem as solved.
Did you forget what you did?

this is a different problem, so I asked again

both modules have indeed been read, here I ask why when the 2 modules are connected to the mega does not produce a PPG signal

How are you plotting that chart? The Mega is outputting Serial data.
Is the plotter software using CSV? If so, you have too many CR/LFs
The CR/LF (Serial.println(",")) after the mdule1 send is the culprit.
Only the modul2 send should have the CR/LF.

    Serial.print(data_modul1.RED_data);
# remove this 
//    Serial.println(",");

This presumes it is a CSV string terminated with a CR/LF.

Edit: You are also sending too many commas. I changed that above.

1 Like

I did not plot the graph using CSV, the data used was based on what was read from the nellcor fingertip attached to the finger, so the data read is realtime.

I'll bet they used Comma Separated Variables, usually terminated with only a newline.
What does it look like if you use the IDE Serial Monitor? It should show something like this, replacing modul1 and modul2 with the values over and over.
modul1,modul2
modul1,modul2

I've tried it, but the reading is still random, as if the modules affect each other. the modules should be able to read each other without affecting each other.

the result is still the same as the picture I sent at the beginning

What does the Serial Monitor show? Is it showing the correct values?

displayed on the serial monitor shows an incorrect value

I think you do not need to set pin mode or write to these pins at any point in your code. The pin numbers are given to the AFE44XX objects so that they will control these pins as needed. By writing to them, it's possible you are causing a problem, so I suggest commenting all such lines out and re-testing.

this pin is to set the module in a low/high state so that SPI communication between modules does not collide

The CS pins for the devices should be set HIGH in setup before calling the init functions or there will be a SPI bus contention. But that SHOULD BE the only time they need to be set.

I think PaulRB may have pointed out the problem in a way. I missed the CS pins.

The instances are sharing the _cs_pin, _pwdn_pin and _drdy_pin values. They probably should be moved to the typedef also.
I'll think about it. Here is the suspect code:

class AFE44XX
{
  public:
    AFE44XX(int cs_pin, int pwdn_pin);
    void afe44xx_init();
    
    boolean get_AFE44XX_Data (afe44xx_data *afe44xx_raw_data);
  
  private:
    void afe44xxWrite (uint8_t address,uint32_t data);
    unsigned long afe44xxRead (uint8_t address);
    
    int _cs_pin;
    int _pwdn_pin;
    int _drdy_pin;
};

Happy Holidays!

okeyy thank you, so I have to modify that part, can you help me again on that?

I'm working on the library right now. I just got it to compile. Bunch of changes.

The problem was the library was using the cs pin of the latest init call, so it used modul2 cs pwdn and drdy pins for both devices.

Here is protocentral_afe44xx.h

//////////////////////////////////////////////////////////////////////////////////////////
//
//    Arduino library for the AFE4490 Pulse Oxiometer Shield

//    Copyright (c) 2018 ProtoCentral
//
//    This software is licensed under the MIT License(http://opensource.org/licenses/MIT).
//
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
//   NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
//   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//   For information on how to use, visit https://github.com/Protocentral/AFE4490_Oximeter
/////////////////////////////////////////////////////////////////////////////////////////
#ifndef _AFE4490
#define _AFE4490

#include "Arduino.h"
#include <SPI.h>
#include <string.h>
#include <math.h>

typedef struct afe44xx_Record{
  int32_t heart_rate;
  int32_t spo2;
  signed long IR_data;
  signed long RED_data;
  boolean buffer_count_overflow = false;
  int8_t n_buffer_count=0;
  int dec=0;
  int cs_pin;
  int pwdn_pin;
  uint16_t aun_ir_buffer[100];
  uint16_t aun_red_buffer[100];
} afe44xx_data;

class AFE44XX
{
  public:
    AFE44XX(int cs_pin, int pwdn_pin, afe44xx_data *afe44xx_raw_data);
    void afe44xx_init(afe44xx_data *afe44xx_raw_data);
    
    boolean get_AFE44XX_Data (afe44xx_data *afe44xx_raw_data);
  
  private:
    void afe44xxWrite (uint8_t address,uint32_t data, int cs);
    unsigned long afe44xxRead (uint8_t address, int cs);
    
};

//afe44xx Register definition
#define CONTROL0      0x00
#define LED2STC       0x01
#define LED2ENDC      0x02
#define LED2LEDSTC    0x03
#define LED2LEDENDC   0x04
#define ALED2STC      0x05
#define ALED2ENDC     0x06
#define LED1STC       0x07
#define LED1ENDC      0x08
#define LED1LEDSTC    0x09
#define LED1LEDENDC   0x0a
#define ALED1STC      0x0b
#define ALED1ENDC     0x0c
#define LED2CONVST    0x0d
#define LED2CONVEND   0x0e
#define ALED2CONVST   0x0f
#define ALED2CONVEND  0x10
#define LED1CONVST    0x11
#define LED1CONVEND   0x12
#define ALED1CONVST   0x13
#define ALED1CONVEND  0x14
#define ADCRSTCNT0    0x15
#define ADCRSTENDCT0  0x16
#define ADCRSTCNT1    0x17
#define ADCRSTENDCT1  0x18
#define ADCRSTCNT2    0x19
#define ADCRSTENDCT2  0x1a
#define ADCRSTCNT3    0x1b
#define ADCRSTENDCT3  0x1c
#define PRPCOUNT      0x1d
#define CONTROL1      0x1e
#define SPARE1        0x1f
#define TIAGAIN       0x20
#define TIA_AMB_GAIN  0x21
#define LEDCNTRL      0x22
#define CONTROL2      0x23
#define SPARE2        0x24
#define SPARE3        0x25
#define SPARE4        0x26
#define SPARE4        0x26
#define RESERVED1     0x27
#define RESERVED2     0x28
#define ALARM         0x29
#define LED2VAL       0x2a
#define ALED2VAL      0x2b
#define LED1VAL       0x2c
#define ALED1VAL      0x2d
#define LED2ABSVAL    0x2e
#define LED1ABSVAL    0x2f
#define DIAG          0x30

#endif

Here is protocentral_afe44xx.cpp

//////////////////////////////////////////////////////////////////////////////////////////
//
//    Arduino library for the AFE44XX Pulse Oxiometer Shield
//
//    This software is licensed under the MIT License(http://opensource.org/licenses/MIT).
//
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
//   NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
//   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//   For information on how to use, visit https://github.com/Protocentral/AFE44XX_Oximeter
/////////////////////////////////////////////////////////////////////////////////////////



#include "protocentral_afe44xx.h"
#include "Protocentral_spo2_algorithm.h"
#include "protocentral_hr_algorithm.h"

#define AFE44XX_SPI_SPEED 2000000
SPISettings SPI_SETTINGS(AFE44XX_SPI_SPEED, MSBFIRST, SPI_MODE0); 

volatile boolean afe44xx_data_ready = false;

unsigned long IRtemp,REDtemp;

int32_t n_spo2;  //SPO2 value
int32_t n_heart_rate; //heart rate value

int8_t ch_spo2_valid;  //indicator to show if the SPO2 calculation is valid
int8_t  ch_hr_valid;  //indicator to show if the heart rate calculation is valid

const uint8_t uch_spo2_table[184]={ 95, 95, 95, 96, 96, 96, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 99, 99, 99, 99,
                                    99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
                                   100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 97, 97,
                                    97, 97, 96, 96, 96, 96, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91,
                                    90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 81,
                                    80, 80, 79, 78, 78, 77, 76, 76, 75, 74, 74, 73, 72, 72, 71, 70, 69, 69, 68, 67,
                                    66, 66, 65, 64, 63, 62, 62, 61, 60, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50,
                                    49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 30, 29,
                                    28, 27, 26, 25, 23, 22, 21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5,
                                    3,   2,  1  } ;

spo2_algorithm Spo2;
hr_algo hral;

AFE44XX::AFE44XX(int cs_pin, int pwdn_pin, afe44xx_data *afe44xx_raw_data)
{
    afe44xx_raw_data->cs_pin=cs_pin;
    
    afe44xx_raw_data->pwdn_pin=pwdn_pin;

    pinMode(afe44xx_raw_data->cs_pin, OUTPUT);
    digitalWrite(afe44xx_raw_data->cs_pin,HIGH);

    pinMode (afe44xx_raw_data->pwdn_pin,OUTPUT);

    hral.initStatHRM();
}

boolean AFE44XX::get_AFE44XX_Data(afe44xx_data *afe44xx_raw_data)
{
  afe44xxWrite(CONTROL0, 0x000001,afe44xx_raw_data->cs_pin);
  IRtemp = afe44xxRead(LED1VAL,afe44xx_raw_data->cs_pin);
  afe44xxWrite(CONTROL0, 0x000001,afe44xx_raw_data->cs_pin);
  REDtemp = afe44xxRead(LED2VAL,afe44xx_raw_data->cs_pin);
  afe44xx_data_ready = true;
  IRtemp = (unsigned long) (IRtemp << 10);
  afe44xx_raw_data->IR_data = (signed long) (IRtemp);
  afe44xx_raw_data->IR_data = (signed long) ((afe44xx_raw_data->IR_data) >> 10);
  REDtemp = (unsigned long) (REDtemp << 10);
  afe44xx_raw_data->RED_data = (signed long) (REDtemp);
  afe44xx_raw_data->RED_data = (signed long) ((afe44xx_raw_data->RED_data) >> 10);

  if (afe44xx_raw_data->dec == 20)
  {
    afe44xx_raw_data->aun_ir_buffer[afe44xx_raw_data->n_buffer_count] = (uint16_t) ((afe44xx_raw_data->IR_data) >> 4);
    afe44xx_raw_data->aun_red_buffer[afe44xx_raw_data->n_buffer_count] = (uint16_t) ((afe44xx_raw_data->RED_data) >> 4);
    afe44xx_raw_data->n_buffer_count++;
    afe44xx_raw_data->dec = 0;
  }

  afe44xx_raw_data->dec++;

  if (afe44xx_raw_data->n_buffer_count > 99)
  {
    Spo2.estimate_spo2(afe44xx_raw_data->aun_ir_buffer, 100, afe44xx_raw_data->aun_red_buffer, &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
    afe44xx_raw_data->spo2 = n_spo2;
    //afe44xx_raw_data->heart_rate = n_heart_rate;
    afe44xx_raw_data->n_buffer_count = 0;
    afe44xx_raw_data->buffer_count_overflow = true;
  }

  hral.statHRMAlgo(afe44xx_raw_data->RED_data);
  afe44xx_raw_data->heart_rate = hral.HeartRate;

  afe44xx_data_ready = false;
  return true;
}

void AFE44XX::afe44xx_init(afe44xx_data *afe44xx_raw_data)
{
  digitalWrite(afe44xx_raw_data->pwdn_pin, LOW);
  delay(500);
  digitalWrite(afe44xx_raw_data->pwdn_pin, HIGH);
  delay(500);

  afe44xxWrite(CONTROL0, 0x000000,afe44xx_raw_data->cs_pin);
  afe44xxWrite(CONTROL0, 0x000008,afe44xx_raw_data->cs_pin);
  afe44xxWrite(TIAGAIN, 0x000000,afe44xx_raw_data->cs_pin); // CF = 5pF, RF = 500kR
  afe44xxWrite(TIA_AMB_GAIN, 0x000001,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LEDCNTRL, 0x001414,afe44xx_raw_data->cs_pin);
  afe44xxWrite(CONTROL2, 0x000000,afe44xx_raw_data->cs_pin); // LED_RANGE=100mA, LED=50mA
  afe44xxWrite(CONTROL1, 0x010707,afe44xx_raw_data->cs_pin); // Timers ON, average 3 samples
  afe44xxWrite(PRPCOUNT, 0X001F3F,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED2STC, 0X001770,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED2ENDC, 0X001F3E,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED2LEDSTC, 0X001770,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED2LEDENDC, 0X001F3F,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ALED2STC, 0X000000,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ALED2ENDC, 0X0007CE,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED2CONVST, 0X000002,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED2CONVEND, 0X0007CF,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ALED2CONVST, 0X0007D2,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ALED2CONVEND, 0X000F9F,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED1STC, 0X0007D0,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED1ENDC, 0X000F9E,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED1LEDSTC, 0X0007D0,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED1LEDENDC, 0X000F9F,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ALED1STC, 0X000FA0,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ALED1ENDC, 0X00176E,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED1CONVST, 0X000FA2,afe44xx_raw_data->cs_pin);
  afe44xxWrite(LED1CONVEND, 0X00176F,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ALED1CONVST, 0X001772,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ALED1CONVEND, 0X001F3F,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ADCRSTCNT0, 0X000000,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ADCRSTENDCT0, 0X000000,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ADCRSTCNT1, 0X0007D0,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ADCRSTENDCT1, 0X0007D0,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ADCRSTCNT2, 0X000FA0,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ADCRSTENDCT2, 0X000FA0,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ADCRSTCNT3, 0X001770,afe44xx_raw_data->cs_pin);
  afe44xxWrite(ADCRSTENDCT3, 0X001770,afe44xx_raw_data->cs_pin);
  delay(1000);
}

void AFE44XX :: afe44xxWrite (uint8_t address, uint32_t data, int cs)
{
  digitalWrite (cs, LOW); // enable device
  SPI.beginTransaction(SPI_SETTINGS);
  SPI.transfer (address); // send address to device
  SPI.transfer ((data >> 16) & 0xFF); // write top 8 bits
  SPI.transfer ((data >> 8) & 0xFF); // write middle 8 bits
  SPI.transfer (data & 0xFF); // write bottom 8 bits
  digitalWrite (cs, HIGH); // disable device
  SPI.endTransaction();
}

unsigned long AFE44XX :: afe44xxRead (uint8_t address, int cs)
{
  unsigned long data = 0;

  digitalWrite (cs, LOW); // enable device
  SPI.beginTransaction(SPI_SETTINGS);
  SPI.transfer (address); // send address to device
  data |= ((unsigned long)SPI.transfer (0) << 16); // read top 8 bits data
  data |= ((unsigned long)SPI.transfer (0) << 8); // read middle 8 bits  data
  data |= SPI.transfer (0); // read bottom 8 bits data
  digitalWrite (cs, HIGH); // disable device
  SPI.endTransaction();

  return data; // return with 24 bits of read data
}

Here is the new ino code.

#include <SPI.h>
#include "protocentral_afe44xx.h"

afe44xx_data data_modul1;
afe44xx_data data_modul2;

// Konfigurasi pin untuk modul 1
#define AFE44XX_CS_PIN_1   9
#define AFE44XX_PWDN_PIN_1 4
AFE44XX afe44xx_modul1(AFE44XX_CS_PIN_1, AFE44XX_PWDN_PIN_1,&data_modul1);

// Konfigurasi pin untuk modul 2
#define AFE44XX_CS_PIN_2   10
#define AFE44XX_PWDN_PIN_2 5
AFE44XX afe44xx_modul2(AFE44XX_CS_PIN_2, AFE44XX_PWDN_PIN_2,&data_modul2);


int32_t heart_rate_prev1 = 0;
int32_t spo2_prev1 = 0;
int32_t heart_rate_prev2 = 0;
int32_t spo2_prev2 = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println("Initializing AFE44xx Modules..");
  
  SPI.begin();

  pinMode(AFE44XX_CS_PIN_1, OUTPUT);
  pinMode(AFE44XX_CS_PIN_2, OUTPUT);

  digitalWrite(AFE44XX_CS_PIN_1, HIGH);   // Aktifkan CS modul 1
  digitalWrite(AFE44XX_CS_PIN_2, HIGH);  // Nonaktifkan CS modul 2

  // Inisialisasi modul 1
  afe44xx_modul1.afe44xx_init(&data_modul1);
  
  // Inisialisasi modul 2
  afe44xx_modul2.afe44xx_init(&data_modul2);
  
  Serial.println("Modules Initialized...");
}

void loop()
{
    // read modul 1

    afe44xx_modul1.get_AFE44XX_Data(&data_modul1);
    
    if (data_modul1.buffer_count_overflow)
    {
      if (data_modul1.spo2 == -999)
      {
        Serial.println("Modul 1 - Probe error!!!!");
      }
      else if ((heart_rate_prev1 != data_modul1.heart_rate) || (spo2_prev1 != data_modul1.spo2))
      {
        heart_rate_prev1 = data_modul1.heart_rate;
        spo2_prev1 = data_modul1.spo2;

        Serial.print("Modul 1 - SpO2 : ");
        Serial.print(data_modul1.spo2);
        Serial.print("%, Pulse rate : ");
        Serial.print(data_modul1.heart_rate);
        Serial.println(" bpm");
      }
    }

    // read modul 2
    afe44xx_modul2.get_AFE44XX_Data(&data_modul2);

    if (data_modul2.buffer_count_overflow)
    {
      if (data_modul2.spo2 == -999)
      {
        Serial.println("Modul 2 - Probe error!!!!");
      }
      else if ((heart_rate_prev2 != data_modul2.heart_rate) || (spo2_prev2 != data_modul2.spo2))
      {
        heart_rate_prev2 = data_modul2.heart_rate;
        spo2_prev2 = data_modul2.spo2;

        Serial.print("Modul 2 - SpO2 : ");
        Serial.print(data_modul2.spo2);
        Serial.print("%, Pulse rate : ");
        Serial.print(data_modul2.heart_rate);
        Serial.println(" bpm");
      }
  }
}

Edit: The CS pins need not be changed in loop. The library takes care of the CS pins after the init calls.

Are you replying to me here? It is not clear. Please learn to use the forum's mention (like @tesmontes), reply and quote features so that there is no confusion.

If you are replying to me, I am aware of the purpose of CS pins on SPI bus. Did you understand my explanation of why your code should not write to them? (EDIT: Except in setup() as @SurferTim mentioned).

The CS pins should be set HIGH in setup before the init calls. This applies only when multiple devices share the SPI bus.
After that, the library with my mods takes care of the CS pins.

1 Like

A good point, @SurferTim and thanks for fixing the library code. Will you be able to raise a pull request on the git repo, do you think?