I2C sensor + Other sensors that use Interrupt

Hello there,

I'm doing my undergraduate thesis and I'm using arduino to do so. I'm using a bunch of sensors to get measures of me experiment. These sensores are:

  • 1x Water flow sensor (uses interrupt to count pulses).
  • 3x vibration sensors.
  • 1x Water flow with TDS sensor embedded (uses interrupt to count pulses as well).
  • 1x Differential pressure sensor.
  • 1x MPU 6050 GY 521 sensor measures accel and gyro (I2C protocol).

I didn't use any library to handle the MPU sensor, instead I've done everything by my self using only Wire and sensor's datasheet. However, when I open the serial monitor to check my values the monitor freezes when it reaches the time to read MPU values for accel and gyro. I've seen that this might have something to do with the other interrupts and this kind of stuff, but since I'm new to Arduino and don't know that much about the matter I'd appreacite some help on this one.

Here is all my code:

// Arduino Nano
// SDA - A4; SCL - A5
// Digital Pins for Interrupt: 2;3

#include <Wire.h>

int HzPerLiterInlet = 98;
int HzPerLiterOutlet = 24;
int interval = 5000;

// Sensors' pins
const byte pinInletFlow = 2;                                        // Pin to Interrupt first flow meter (pure water) YF-s401.
const byte pinOutletFlow = 3;                                       // Pin to Interrupt second flow meter (Air-Water mixture) DWS-MH-01.
int pinPiezo1 = A0;                                                 // Piezoeletric Ceramic Vibration sensor pin.
int pinPiezo2 = A1;                                                 // Piezoeltric Vibration sensor pin.
int pin801s = A2;                                                   // 801s Vibration sensor pin.
int pinPressure = A3;                                               // Differencial Pressure sensor pin.
int pinCond = A6;                                                   // Condutance Sensor pin (embedded in DWS-MH-01).

// Pulse variables
volatile double InletPulses;                                        // Inlet flow pulses to count - volatile because it's inside ISR (Interrupt Service Routines).
volatile double OutletPulses;                                       // Outlet flow pulses to count - volatile because it's inside ISR (Interrupt Service Routines).

// Storing Variables
double valueInletFlow;                                              // Inlet water flow - L/min.
double valueOutletFlow;                                             // Outlet Air-Water flow - L/min.
float valuePressure;                                                // Differencial Pressure - kPa.
int valueCond;                                                      // Condutance value.
int valuePiezo1;                                                    // Vibration value from piezo 1.
int valuePiezo2;                                                    // Vibration value from piezo2.
int value801s;                                                      // Vibration value from 801s.

// I2C Adress for MPU-6050 sensor
const int MPU = 0x68;

// Variables for MPU
float AccX, AccY, AccZ, Temp, GyrX, GyrY, GyrZ;

void setup() {
  // Begin Serial Transmission.
  Serial.begin(9600);  //baudrate
  // Setting MPU 6050 up.
  setMPU();
  // Attaching functions to interrupt pins for flow meters
  attachInterrupt(digitalPinToInterrupt(pinInletFlow),CountInletPulses, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pinOutletFlow),CountOutletPulses, CHANGE);
  // Printing headers.
  Serial.print("Piezo1");Serial.print(",");
  Serial.print("Piezo2");Serial.print(",");
  Serial.print("801s");Serial.print(",");
  Serial.print("Condutance");Serial.print(",");
  Serial.print("dP");Serial.print(",");
  Serial.print("InletFlow");Serial.print(",");
  Serial.print("OutletFlow");Serial.print(",");
  Serial.print("AccX");Serial.print(",");
  Serial.print("AccY");Serial.print(",");
  Serial.println("AccZ");
}

void loop() {
  // Dealing with interrupt
  InletPulses = 0;                                                  // Resets pulse counter for inlet flow.
  OutletPulses = 0;                                                 // Resets pulse counter for outlet flow.
  interrupts();                                                     // Enables interrupts.
  delay(interval);
  noInterrupts();
  // Reading sensors' values.
  valuePiezo1 = analogRead(pinPiezo1);                              // Piezo 1 value.
  valuePiezo2 = analogRead(pinPiezo2);                              // Piezo 2 value.
  value801s = analogRead(pin801s);                                  // 801s value.      
  valueCond = analogRead(pinCond);                                  // Condutance value.
  valuePressure = readDeltaPressure();                              // Pressure value.
  valueInletFlow = Flow(HzPerLiterInlet,InletPulses);      // Inlet flow value.
  valueOutletFlow = Flow(HzPerLiterOutlet,OutletPulses);   // Outlet flow value.
  // Reading MPU 6050 measures
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 14, true); // Solicita os dados ao sensor
  AccX = Wire.read() << 8 | Wire.read(); //0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AccY = Wire.read() << 8 | Wire.read(); //0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AccZ = Wire.read() << 8 | Wire.read(); //0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Temp = Wire.read() << 8 | Wire.read(); //0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyrX = Wire.read() << 8 | Wire.read(); //0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyrY = Wire.read() << 8 | Wire.read(); //0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyrZ = Wire.read() << 8 | Wire.read(); //0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  // Scaling factor MPU 6050
  /* Accel
      +/-2g = 16384
      +/-4g = 8192
      +/-8g = 4096
      +/-16g = 2048

      Gyro
      +/-250°/s = 131
      +/-500°/s = 65.6
      +/-1000°/s = 32.8
      +/-2000°/s = 16.4
  */
  // Accel
  AccX = AccX/16384;
  AccY = AccY/16384;
  AccZ = AccZ/16384;
  // Gyro
  GyrX = GyrX/131;
  GyrY = GyrY/131;
  GyrZ = GyrZ/131;
  // Printing values
  Serial.print(valuePiezo1);Serial.print(",");
  Serial.print(valuePiezo2);Serial.print(",");
  Serial.print(value801s);Serial.print(",");
  Serial.print(valueCond);Serial.print(",");
  Serial.print(valuePressure);Serial.print(",");
  Serial.print(valueInletFlow);Serial.print(",");
  Serial.print(valueOutletFlow);Serial.print(",");
  Serial.print(AccX);Serial.print(",");
  Serial.print(AccY);Serial.print(",");
  Serial.println(AccZ);
}

void CountInletPulses(){
  InletPulses++;
}

void CountOutletPulses(){
  OutletPulses++;
}

float readDeltaPressure(){
  float sinal = analogRead(pinPressure);
  float dP;
  if(sinal<102){
    dP = -2.0;
    }else{
      if(sinal>921){
        dP = 2.0;
        } else{
          dP = (sinal/1023-0.5)/0.2;
          }
      }
  return dP;
}

double Flow(int CalibrationFactor,volatile double pulse_counts){
  double Measure;
  Measure = pulse_counts/CalibrationFactor/interval*1000;
  return Measure;
}

void setMPU(){
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  // Configuring Gyro Range
  /*
    Wire.write(0b00000000); //  +/-250°/s
    Wire.write(0b00001000); //  +/-500°/s
    Wire.write(0b00010000); //  +/-1000°/s
    Wire.write(0b00011000); //  +/-2000°/s
  */
  Wire.beginTransmission(MPU);
  Wire.write(0x1B); // Gyro register
  Wire.write(0x00000000);  // Set Gyro range
  Wire.endTransmission();

  // Configuring Accel Range
  /*
      Wire.write(0b00000000); //  +/-2g
      Wire.write(0b00001000); //  +/-4g
      Wire.write(0b00010000); //  +/-8g
      Wire.write(0b00011000); //  +/-16g
  */
  Wire.beginTransmission(MPU);
  Wire.write(0x1C); // Accel register
  Wire.write(0b00000000);  // Set Accel range
  Wire.endTransmission();
}

Can you write a loop() that does not turn off the interrupts ?

Serial() and Wire both require interrupts to operate, yet you have them turned off so they don't function.

You should only turn them off to obtain a copy of your volatile variables and then turn them back on. Also, pulse counts don't need to be floats, ints will work better. Are you really just trying to measure your pulses for 5 seconds? There are better ways to do that...

Thanks!! My experiments are very short (3 minutes), but I need a good amount of data so I can't use an excessively large interval, but could you tell me more about these other ways?

Here is an example that reports out every 'interval' amount of time

// Arduino Nano
// SDA - A4; SCL - A5
// Digital Pins for Interrupt: 2;3

#include <Wire.h>

int HzPerLiterInlet = 98;
int HzPerLiterOutlet = 24;
const unsigned long interval = 5000;

// Sensors' pins
const byte pinInletFlow = 2;                                        // Pin to Interrupt first flow meter (pure water) YF-s401.
const byte pinOutletFlow = 3;                                       // Pin to Interrupt second flow meter (Air-Water mixture) DWS-MH-01.
const int pinPiezo1 = A0;                                                 // Piezoeletric Ceramic Vibration sensor pin.
const int pinPiezo2 = A1;                                                 // Piezoeltric Vibration sensor pin.
const int pin801s = A2;                                                   // 801s Vibration sensor pin.
const int pinPressure = A3;                                               // Differencial Pressure sensor pin.
const int pinCond = A6;                                                   // Condutance Sensor pin (embedded in DWS-MH-01).

// Pulse variables
volatile unsigned long InletPulses;                                        // Inlet flow pulses to count - volatile because it's inside ISR (Interrupt Service Routines).
volatile unsigned long OutletPulses;                                       // Outlet flow pulses to count - volatile because it's inside ISR (Interrupt Service Routines).

// Storing Variables
double valueInletFlow;                                              // Inlet water flow - L/min.
double valueOutletFlow;                                             // Outlet Air-Water flow - L/min.
float valuePressure;                                                // Differencial Pressure - kPa.
int valueCond;                                                      // Condutance value.
int valuePiezo1;                                                    // Vibration value from piezo 1.
int valuePiezo2;                                                    // Vibration value from piezo2.
int value801s;                                                      // Vibration value from 801s.

// I2C Adress for MPU-6050 sensor
const int MPU = 0x68;

// Variables for MPU
float AccX, AccY, AccZ, Temp, GyrX, GyrY, GyrZ;

unsigned long startTime;

void setup() {
  // Begin Serial Transmission.
  Serial.begin(9600);  //baudrate
  // Setting MPU 6050 up.
  setMPU();
  // Attaching functions to interrupt pins for flow meters
  attachInterrupt(digitalPinToInterrupt(pinInletFlow), CountInletPulses, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pinOutletFlow), CountOutletPulses, CHANGE);
  startTime = millis(); // start of interval
  // Printing headers.
  Serial.print("Piezo1"); Serial.print(",");
  Serial.print("Piezo2"); Serial.print(",");
  Serial.print("801s"); Serial.print(",");
  Serial.print("Condutance"); Serial.print(",");
  Serial.print("dP"); Serial.print(",");
  Serial.print("InletFlow"); Serial.print(",");
  Serial.print("OutletFlow"); Serial.print(",");
  Serial.print("AccX"); Serial.print(",");
  Serial.print("AccY"); Serial.print(",");
  Serial.println("AccZ");
}

void loop() {
  if ( millis() - startTime >= interval ) {
    // time to deal with inertval data
    // grab a copy of the counters
    noInterrupts();
    unsigned long inPulses = InletPulses;
    unsigned long outPulses = OutletPulses;
    InletPulses = 0;                                                  // Resets pulse counter for inlet flow.
    OutletPulses = 0;                                                 // Resets pulse counter for outlet flow.
    interrupts();
    startTime = millis();

    // Reading sensors' values.
    valuePiezo1 = analogRead(pinPiezo1);                              // Piezo 1 value.
    valuePiezo2 = analogRead(pinPiezo2);                              // Piezo 2 value.
    value801s = analogRead(pin801s);                                  // 801s value.
    valueCond = analogRead(pinCond);                                  // Condutance value.
    valuePressure = readDeltaPressure();                              // Pressure value.
    // Reading MPU 6050 measures
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 14, true); // Solicita os dados ao sensor
    AccX = Wire.read() << 8 | Wire.read(); //0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AccY = Wire.read() << 8 | Wire.read(); //0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AccZ = Wire.read() << 8 | Wire.read(); //0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Temp = Wire.read() << 8 | Wire.read(); //0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyrX = Wire.read() << 8 | Wire.read(); //0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyrY = Wire.read() << 8 | Wire.read(); //0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyrZ = Wire.read() << 8 | Wire.read(); //0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
    // Scaling factor MPU 6050
    /* Accel
        +/-2g = 16384
        +/-4g = 8192
        +/-8g = 4096
        +/-16g = 2048

        Gyro
        +/-250°/s = 131
        +/-500°/s = 65.6
        +/-1000°/s = 32.8
        +/-2000°/s = 16.4
    */
    // Accel
    AccX = AccX / 16384;
    AccY = AccY / 16384;
    AccZ = AccZ / 16384;
    // Gyro
    GyrX = GyrX / 131;
    GyrY = GyrY / 131;
    GyrZ = GyrZ / 131;
    // Printing values
    Serial.print(valuePiezo1); Serial.print(",");
    Serial.print(valuePiezo2); Serial.print(",");
    Serial.print(value801s); Serial.print(",");
    Serial.print(valueCond); Serial.print(",");
    Serial.print(valuePressure); Serial.print(",");
    Serial.print(valueInletFlow); Serial.print(",");
    Serial.print(valueOutletFlow); Serial.print(",");
    Serial.print(AccX); Serial.print(",");
    Serial.print(AccY); Serial.print(",");
    Serial.println(AccZ);
  }
}

void CountInletPulses() {
  InletPulses++;
}

void CountOutletPulses() {
  OutletPulses++;
}

float readDeltaPressure() {
  int sinal = analogRead(pinPressure);
  float dP;
  if (sinal < 102) {
    dP = -2.0;
  }
  else if (sinal > 921) {
    dP = 2.0;
  }
  else {
    dP = (sinal / 1023.0 - 0.5) / 0.2;
  }
}
return dP;
}

float Flow(int CalibrationFactor, unsigned long pulse_counts) {
  float Measure = pulse_counts * 1.0 / CalibrationFactor / interval * 1000.0;
  return Measure;
}

void setMPU() {
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  // Configuring Gyro Range
  /*
    Wire.write(0b00000000); //  +/-250°/s
    Wire.write(0b00001000); //  +/-500°/s
    Wire.write(0b00010000); //  +/-1000°/s
    Wire.write(0b00011000); //  +/-2000°/s
  */
  Wire.beginTransmission(MPU);
  Wire.write(0x1B); // Gyro register
  Wire.write(0x00000000);  // Set Gyro range
  Wire.endTransmission();

  // Configuring Accel Range
  /*
      Wire.write(0b00000000); //  +/-2g
      Wire.write(0b00001000); //  +/-4g
      Wire.write(0b00010000); //  +/-8g
      Wire.write(0b00011000); //  +/-16g
  */
  Wire.beginTransmission(MPU);
  Wire.write(0x1C); // Accel register
  Wire.write(0b00000000);  // Set Accel range
  Wire.endTransmission();
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.