Hello everyone,
my problem is as simple and as confusing as the title. I have two MAX30105 V10. I use them with an ESP32 (“Feather”). I have a test program that reads all available samples when an interrupt occured. It works when I use the DATA_RDY interrupt but it does nothing when I change the one bit in the setup that changes the DATA_RDY interrupt to the A_FULL interrupt.
My wiring is as simple as the sensor requires; i have all five wires connected to the appropriate pins of the ESP32 (SDL => SDL, SDC => SDC, 5V => USB, GND => GND, INT => A2), I have an additional 4.7k resistor on the INT and additional 1k resistors on the I2C connectors to improve the I2C signal. I only use one MAX30105 at a time but both have the same problem.
My program is attached. I used the Arduino IDE. I documented all the configs in the code, it should be pretty obvious what I did. (It starts in the setup() routine from the “max30105 config” comment.)
What am I missing? Are there any requirements to use the A_FULL interrupt? Is this a hardware problem?
Thank you in advance.
Christian
#include <Wire.h> // I2C library
#define max30105 0x57 // I2C Address MAX30101
#define bufferlength 200 // length of buffer to be filled by the interrupt routine
const byte interruptPin = 36;
volatile int interruptCounter = 0;
int nrofirqs = 0;
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; // a mechanisms to prevent clossions during interrupt handling
//Set array for real measured values and imaginary. NOTE: LED1 = RED LED
double redLEDbuffer[bufferlength];
double irLEDbuffer[bufferlength];
volatile unsigned int fifo_wr_pt; // FIFO pointers
volatile unsigned int ovf_counter;
volatile unsigned int fifo_rd_pt;
volatile int availablesamples;
volatile unsigned int redvalue;
volatile unsigned int irvalue;
int i;
int error, nbytes;
// interrupt handling routine
void IRAM_ATTR handleInterrupt() {
portENTER_CRITICAL_ISR(&mux); // do not allow other interrupts to happen while this is being worked on (causes crashes when timing fails)
interruptCounter++;
portEXIT_CRITICAL_ISR(&mux);
}
void setup() {
Wire.begin();
Wire.setClock(100000); //set Frequency for SCLK clock at 100kHz
Serial.begin(115200); // USB Baud Rate
// max30105 reset
Wire.beginTransmission(max30105);
Wire.write(0x09);
Wire.write(0b01000000); //reset MAX30105 device(data to register)
error = Wire.endTransmission();
if (error == 0) Serial.println("MAX30101 communication o.k.");
delay(200); //maybe unneccessary or too long (give MAX30105 some time for internal reset)
// max30105 config
Wire.beginTransmission(max30105);
Wire.write(0x08);
Wire.write(0b00011111); // Mode Configuration register: 000 = 1 samples average, 1 = enable FIFO rollover, 1111 = FIFO_A_FULL on 15 samples left (was: 0111)
Wire.write(0b00000011); // set mode to 2-LED particle sensing mode using IR and red LEDs (last 3 Bits = 011)
Wire.write(0b01100011); // 0 = reserved, 11 = 16384 nA full scale, 000 = 50 samples/second; 11 = 18 bit ADC resolution
error = Wire.endTransmission(); // skip reserved register
if (error == 0) Serial.println("MAX30101 registers 8 through A initialized");
Wire.beginTransmission(max30105);
Wire.write(0x0C);
Wire.write(0x7F); // red LED set current to 25.4 mA
Wire.write(0x7F); //IR LED set current to 25.4 mA
error = Wire.endTransmission(); // skip green LED register, reserved and proximity settings
if (error == 0) Serial.println("MAX30101 registers C through D initialized");
Wire.beginTransmission(max30105);
Wire.write(0x11);
Wire.write(0b00100001); // 0 = reserved, 010 = IR LED in slot 2, 0 = reserved, 001 = red LED in slot 1,
Wire.write(0b00000000); // nothing in slot 4, nothing in slot 3
error = Wire.endTransmission();
if (error == 0) Serial.println("MAX30101 registers initialized");
// temp and proximity have been skipped
// max30105 Interrupt enable Register setzen
Wire.beginTransmission(max30105);
Wire.write(0x02);
Wire.write(0b10000000); // 0 = A_FULL off, 1 = DATA_RDY on, all others off
Wire.write(0b00000000);
error = Wire.endTransmission();
if (error == 0) Serial.println("MAX30101 interrupt enable registers initialized");
// reset FIFO
Wire.beginTransmission(max30105);
Wire.write(0x04); // clear FIFO pointers
Wire.write(0x00); // see page 15
Wire.write(0x00);
Wire.write(0x00);
error = Wire.endTransmission();
if (error == 0) Serial.println("MAX30101 FIFO reset");
Wire.beginTransmission(max30105);
Wire.write(0x00);
error = Wire.endTransmission();
nbytes = Wire.requestFrom(max30105, 2, true); // read and clear both interrupt registers
if (error == 0 && nbytes == 2) Serial.println("MAX30101 interrupt registers cleared");
// interrupt setup on microcontroller
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
Serial.println("End of setup ... entering loop.");
}
void loop() {
if (interruptCounter > 0)
{
portENTER_CRITICAL(&mux);
nrofirqs = interruptCounter;
interruptCounter = 0;
portEXIT_CRITICAL(&mux);
// read FIFO pointers
Wire.beginTransmission(max30105);
Wire.write(0x04);
error = Wire.endTransmission();
nbytes = Wire.requestFrom(max30105, 3, true); //read 3 bytes for the two FIFO pointers and overflow counter
if (error != 0 || nbytes != 3) Serial.println("Could not read FIFO pointers");
fifo_wr_pt = Wire.read();
ovf_counter = Wire.read();
fifo_rd_pt = Wire.read();
availablesamples = (fifo_wr_pt - fifo_rd_pt) & 0b00011111; // no of avail samples calculated from pointers
if (availablesamples > 0) {
//Reading from FIFO
Wire.beginTransmission(max30105);
Wire.write(0x07); // FIFO register
error = Wire.endTransmission();
nbytes = Wire.requestFrom(max30105, 6 * availablesamples, true); // request 6*nsamples Bytes (3 * 2 - Red & IR)
if (error != 0 || nbytes != 6 * availablesamples) Serial.println("Could not read FIFO data");
for (int i = 0; i < availablesamples; i++) {
// Clear first 6 bits because they are defined as "unused" which does not necessarily mean zero
// Shift the others to combine the three bytes
redvalue = (Wire.read() & 0b00000011) * 65536 + Wire.read() * 256 + Wire.read();
irvalue = (Wire.read() & 0b00000011) * 65536 + Wire.read() * 256 + Wire.read();
Serial.print("Rot: ");
Serial.print(redvalue);
Serial.print(" Infrarot: ");
Serial.println(irvalue);
}
}
// read interrupt register to reset interrupt
// commented out because it is unnecessary according to documentation
//Wire.beginTransmission(max30105);
//Wire.write(0x00);
//Wire.endTransmission();
//Wire.requestFrom(max30105, 1, true);
Serial.print("Interrupt triggered...");
Serial.println(nrofirqs);
Serial.print("Pointer & samples: ");
Serial.print(fifo_wr_pt);
Serial.print(" ");
Serial.print(ovf_counter); // should always be 0 but is not
Serial.print(" ");
Serial.print(fifo_rd_pt);
Serial.print(" ");
Serial.println(availablesamples);
}
}