1

I am currently trying to connect 3 I2C Devices to an Arduino Mega, as detailed in the fritzing sketch. The Sensors are: Max86150 PPG Sensor on a breakout board (5v), MLX90614 IR Temperature Sensor (3.3V) and a SM9336 Pressure Sensor(3.3V). Essentially I can connect all devices and read off the sensors using individual sketches, but when I combine the sketches the values are not consistent and then the sketch crashes after only a few seconds.

Weirdly enough, when I combine a sketch with either the Temperature sensor and the Pressure sensor or the Temperature Sensor and PPG Sensor, it will work. But Pressure and PPG do not work together.

Does anyone have any idea what could be happening? I did have it working for a small while with some different wires, could this have anything to do with it? But even still some results I was reading from the sensor were the error values (e.g. the value you get when there is nothing connected, but it wasn't crashing). For reference I am using 30 AWG wires and strip board instead of the breadboard in the Fritzing. Fritzing Sketch

//PPG
#include "max86150.h"
MAX86150 max86150Sensor;
uint16_t ppgunsigned16;
uint16_t irdata;


// Pressure Sensor
#include <Wire.h>

#define PressureSensor_Data 0x30 // Pressure Register address
#define TemperatureSensor_Data 0x2E // Pressure Temp Sensor Address  


int P0,T0,P1,T1;
int SMD993Address = 0x6C; // Device Address 

//Timing 
#define INTERVAL 10 //10 milliseconds per sample for 100 Hz, change this for different sampling rates.
uint32_t lastMicros = 0;

// Temp
#include <Adafruit_MLX90614.h>
Adafruit_MLX90614 mlx = Adafruit_MLX90614();



void ppgsetup()
{
  max86150Sensor.setup();
}

void PPG() {
   
while (1){
 if(max86150Sensor.check()>0)
    {
        ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);

        Serial.println(ppgunsigned16);
  //ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);
  //Serial.println(ppgunsigned16);

  if (ppgunsigned16 > 7000){ 
  

     for (int z = 0; z <= 500; z++){//This takes a reading every 10 milliseconds for 5000 milli seconds which is 5 seconds, 500 readings 
       digitalWrite(ledPin,HIGH);//turning LED on
        //if (micros() - lastMicros > INTERVAL) { //This takes a reading every 100th of a second
            //lastMicros = micros(); // do this first or your interval is too long!
            
            if(max86150Sensor.check()>0)
    {
        ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);
        irdata = (uint16_t) (max86150Sensor.getFIFOIR()>>2);
            
        Serial.print(ppgunsigned16);
        Serial.print(",");       
        Serial.println(irdata);
            //Serial.print("Check PPG");Serial.println(y);
            //mySerial.write(84);mySerial.print(ppgunsigned16);mySerial.print("/");
            //mySerial.write(83);mySerial.print(irdata);mySerial.print("/");
    }
    } 
    digitalWrite(ledPin,LOW);//turning LED off
    break;
    
}
}
}
}




void spirometry() {
    

    for (int x = 0; x <= 500; x++){
    Wire.beginTransmission(SMD993Address);
    Wire.write(PressureSensor_Data);
    Wire.write(TemperatureSensor_Data);
    Wire.endTransmission();
    Wire.requestFrom(SMD993Address,2);//This takes a reading every 100 milliseconds for 10000 milli seconds which is 10 seconds
 
    //if (micros() - lastMicros > INTERVAL) { //This takes a reading every 1000th of a second
      //lastMicros = micros(); // do this first or your interval is too long!

    if(Wire.available()<= 2) { 
    P0 = Wire.read();
    P1 = Wire.read();
      }
  
    int Ptotal = P0 + (P1<<8); //The high byte is transmitted second so that 
    
    Serial.println(Ptotal); // Print Ptotal to the serial monitor
    //mySerial.write(81);mySerial.print(Ptotal);mySerial.print("/");// Send PTotal over BLE with flag 81, this will change as sending via bytes is more efficient
    
    }
    
    
  }


void temperature() {
  for (int y = 0; y <= 10; y++){
      mlx.begin();
      Serial.println(mlx.readObjectTempC());  
      mySerial.write(82);mySerial.print(mlx.readObjectTempC());mySerial.print("/");
      delay(10);
}
}

void setup() {
  
  
  // BT
  mySerial.begin(9600);
  Serial.begin(9600);//Sets BT Serial Comms to 115200, ensure that BT is allowing for this 
  //LED
  pinMode(ledPin, OUTPUT);
  // PPG
    // Initialize sensor
    if (max86150Sensor.begin(Wire, I2C_SPEED_FAST) == false)
    {
        Serial.println("MAX86150 was not found. Please check wiring/power. ");
        while (1);
    }
    Serial.println(max86150Sensor.readPartID());
    ppgsetup();

    
  //Pressure Sensor

  //Temp 
  

  //Sleep 
  sleep();
  

}

void loop()
{
  // put your main code here, to run repeatedly
  
   PPG();
   delay(10000);
   spirometry();
   delay(1000);
   temperature();

  
   
}
8
  • 1
    Have you tried adding pullup resistors to the lines? As you put more devices on the bus, the capacitance is rising. Pullups (maybe 4.7kOhm, which I mostly use for I2C) may help with that. Also: How long are your wires? I2C is made for rather short connections in the single digit cm region. Long wires can make it unreliable.
    – chrisl
    Feb 21 at 20:17
  • 1
    It might not be a good idea to totally spam the bus with your messages (for example you take readings very rapidly in spirometry(). Please try to introduce a small delay or similar there. And why do you call mlx.begin() 11 times for reading the temperature? Wouldn't one begin in setup be enough?
    – chrisl
    Feb 21 at 20:21
  • @chrisl I've been running I2C devices over 10m cable, with only occassional read errors, so that's unlikely the problem here. Are the device addresses unique?
    – PMF
    Feb 21 at 20:34
  • @chrisl AFAIK there are internal pullup resistors within the Arduino, but I will give them a try and see if it works any better. The cables are probably 10 cm max, most would be in the single cm range. I have tried playing around with the delays but it doesn't seem to change anything, I am trying to achieve a 100 hz sample rate, which I have read should be achievable on the Arduino Mega. The Mlx.begin() is in the wrong location, good spot I will move that. Feb 21 at 21:56
  • @PMF Yes all addresses are unique, what wire gauge are you using for 10m? Feb 21 at 21:59
2

I had a similar problem sometime ago, where I attached 2 servo driver boards and a battery hat (that used I2C for reading power levels) to a Raspberry Pi. The battery board worked alone and the servo boards worked alone, but when all three were present, the battery board stopped working. And all had unique addresses. After a few hours of going nuts, I realised that there were pullup resistors on the pi and all three boards attached. The total resistance of all 4 parallel pullup resistors were out of spec for I2C. I removed the resistors from the servo boards and everything started working together. So maybe you could disable the pullups on all baords except the Arduino and see if that is the problem.

2
  • Thanks for the response, it seems to be that I had unknowingly set the I2C Wire Interface to High Speed and that it was essentially crashing the pressure sensor and the sketch, as far as I can tell anyway. Feb 22 at 15:00
  • 1
    @TeeGallagher, I voted this up because it was a good answer anyway. If you have some confidence that your high-speed rate was the problem, you should make a separate answer and later accept it.
    – timemage
    Feb 22 at 15:02
2

As pointed out by @peterpaulkeifer; Here

// Initialize sensor
    if (max86150Sensor.begin(Wire, I2C_SPEED_FAST) == false)
    {
        Serial.println("MAX86150 was not found. Please check wiring/power. ");
        while (1);
    }

I was setting the I2C Speed of the I2C Interface bus to fast and it seems that the pressure sensor was not able to handle this and would therefore give error answers and then crash.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.