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
}