Interrupt Conflict between water flow sensor and wind speed sensor

Hello everyone,

I'm hoping you can help me with a problem I'm having with my Arduino project. I'm trying to log data from different sensors, like thermocouples, Ds18B20, DHT22, flow meters, and wind speed meters..... etc. I'm using an Arduino Mega as the controller. The issue is that I can't get the flow meter and the wind speed meter to work together with interrupts. When I use both interrupts, only the wind speed sensor gives me readings, the flow sensor doesn't. But when I test each sensor separately, they both work fine. I don't know what's causing this problem. I've looked online for some answers, but nothing seems to work. Do you have any suggestions on how to fix this code?
Thanks in advance.

//Wind Sensor Code in meter per second(m/s). (Connect VCC to brown wire and GND to black wire)
#define READ_TIME 1000                      //ms
#define WIND_SENSOR_PIN 3                   //wind sensor pin (BLUE WIRE)
#define WIND_SPEED_20_PULSE_SECOND 1.75     //in m/s this value depend on the sensor type
#define ONE_ROTATION_SENSOR 20.0
volatile unsigned long Rotations;           //Cup rotation counter used in interrupt routine
float WindSpeed;                            //Speed meter per second
float WindSpeedKh;                          //Speed kilometer per hour
unsigned long gulStart_Read_Timer = 0;

//liquid/water flow meter in litre per minute(L/m). (Connect VCC to red wire and GND to black wire)
byte sensorInterrupt = 0;         // 0 = digital pin 2
byte sensorPin       = 2;         //signal line(yellow) to arduino digital pin 2.
float calibrationFactor = 7.5;    // The hall-effect flow sensor outputs approximately 7.5 pulses per second per litre/minute of flow.
volatile byte pulseCount;  
float flowRate;
unsigned long oldTime;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;



void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  // Wind sensor
  pinMode(WIND_SENSOR_PIN,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(WIND_SENSOR_PIN),isr_rotation, CHANGE); //Set up the interrupt
  sei(); //Enables interrupts
  gulStart_Read_Timer - millis();

  // flow metre
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);
  pulseCount        = 0;
  flowRate          = 0.0;
  oldTime           = 0;
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);




  Serial.println("L/m ,m/s , K/h");
}

void loop() {
  

  // wind sensor
  if((millis() - gulStart_Read_Timer) >= READ_TIME)
  {
    cli(); //Disable interrupts
   
    //convert rotation to wind speed in m/s
    WindSpeed = WIND_SPEED_20_PULSE_SECOND/ONE_ROTATION_SENSOR*(float)Rotations;
    WindSpeedKh=WindSpeed*3.6;
   
    sei(); //Enables interrupts

    Rotations = 0; //Set Rotations count to 0 ready for calculations
    gulStart_Read_Timer = millis();
  }



  // flow sensor
  if((millis() - oldTime) > 1000)         // Only process counters once per second
  { 
    detachInterrupt(sensorInterrupt);  // Disable the interrupt while calculating flow rate and sending the value to the host
        
    /*
    Because this loop may not complete in exactly 1 second intervals we calculate the number of milliseconds
    that have passed since the last execution and use that to scale the output. We also apply the calibrationFactor
    to scale the output based on the number of pulses per second per units of measure (litres/minute in this case) coming from the sensor.
    */
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    /*
    Note the time this processing pass was executed. Note that because we've disabled interrupts the millis() function won't 
    actually be incrementing right at this point, but it will still return the value it was set to just before interrupts went away.
    */
    oldTime = millis();
    /*
    Divide the flow rate in litres/minute by 60 to determine how many litres have passed through the sensor 
    in this 1 second interval, then multiply by 1000 to convert to millilitres.
    */
    flowMilliLitres = (flowRate / 60) * 1000;
    totalMilliLitres += flowMilliLitres;        // Add the millilitres passed in this second to the cumulative total
    unsigned int frac;
    
  
    Serial.print(flowRate);
    Serial.print(",");
    Serial.print(WindSpeed);
    Serial.print(",");
    Serial.println(WindSpeedKh);
    delay(1000);
  }
}



// Increment the pulse counter
void pulseCounter()
{
  
  pulseCount++;
}
// This is the function that the interrupt calls to increment the rotation count
void isr_rotation()
{
    Rotations++;
}

I am surprised it is printing in the interrupt for you.

1 Like

Thanks for your replay. I changed the line, but still, the issue is not solved.

attachInterrupt(digitalPinToInterrupt(WIND_SENSOR_PIN),isr_rotation, CHANGE);

attachInterrupt(digitalPinToInterrupt(sensorInterrupt), pulseCounter, FALLING);

:pensive: :sleepy: :woozy_face: :sob:

Hello Kamranrauf87

you like to use the interrupt pin number 2 for flow sensor
So better do:

#define FLOW_SENSOR_PIN 2
attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_PIN ),pulseCounter, FALLING); 

Inside the flow sensor calculation you detach the Interrupt but never activate again. So interrupt will work only one time.
To block the interrupts use the

cli() and sei() 

you already used for wind sensor block.

Best regards Mascho11

1 Like

I'm so grateful for your assistance @Delta_G and @mascho11 . You guys are awesome! I followed your advice and I finally fixed the problem. Here is my final code that works perfectly.

/*****************************************************************
 * Project: Wind and Flow Sensor Test Code
 * Name   : Kameran Raoof Ali
 * Date   : 23 November 2023
*****************************************************************/

#define READ_TIME 1000 //ms
#define WIND_SENSOR_PIN 2 //wind sensor pin
#define WIND_SPEED_20_PULSE_SECOND 1.75  //in m/s this value depend on the sensor type
#define ONE_ROTATION_SENSOR 20.0
volatile unsigned long Rotations; //Cup rotation counter used in interrupt routine
float WindSpeed; //Speed meter per second
unsigned long gulStart_Read_Timer = 0;

#define FLOW_SENSOR_PIN 3
float calibrationFactor = 7.5;
volatile int pulseCount;  
float flowRate;
unsigned long oldTime=0;


void setup(){
  Serial.begin(9600);
  //Wind sensor
  pinMode(WIND_SENSOR_PIN,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(WIND_SENSOR_PIN),isr_rotation, CHANGE); //Set up the interrupt
  sei(); //Enables interrupts
  gulStart_Read_Timer = millis();
  //flow sensor
  pinMode(FLOW_SENSOR_PIN, INPUT);
  digitalWrite(FLOW_SENSOR_PIN, HIGH);
  attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_PIN ),pulseCounter, FALLING);

}

void loop()
{
  //wind sensor
  if((millis() - gulStart_Read_Timer) >= READ_TIME)
  {
    cli(); //Disable interrupts
    WindSpeed = WIND_SPEED_20_PULSE_SECOND/ONE_ROTATION_SENSOR*(float)Rotations;  //convert rotation to wind speed in m/s
    sei(); //Enables interrupts

    Serial.print("Wind speed :"); 
    Serial.print(WindSpeed); 
    Serial.print(" m/s  "); 

    Rotations = 0; //Set Rotations count to 0 ready for calculations
    gulStart_Read_Timer = millis();
  }
  //flow sensor
  if((millis() - oldTime) > 1000)    // Only process counters once per second
    { 
    cli(); // Disable the interrupt while calculating flow rate and sending the value to the host
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    sei(); //Enables interrupts

    Serial.print("Flow rate: ");
    Serial.print(float(flowRate));  // Print the integer part of the variable
    Serial.println(" L/min");

    pulseCount = 0; // Reset the pulse counter so we can start incrementing again
    oldTime = millis();
  }
 

}

// This is the function that the interrupt calls to increment the rotation count
void isr_rotation()
{
    Rotations++;
}
// Increment the pulse counter
void pulseCounter()
{
   pulseCount++;
}

I want to use Serial.print to display the measurment on the serial monitor, but the output is too fast and hard to read. So I put the Serial.print statement inside the loop function, but I wonder if adding a delay(1000) at the end of serial. prints outside the loop would give me similar result.

void loop()
{
  //wind sensor
  if((millis() - gulStart_Read_Timer) >= READ_TIME)
  {
    cli(); //Disable interrupts
    WindSpeed = WIND_SPEED_20_PULSE_SECOND/ONE_ROTATION_SENSOR*(float)Rotations;  //convert rotation to wind speed in m/s
    sei(); //Enables interrupts
    Rotations = 0; //Set Rotations count to 0 ready for calculations
    gulStart_Read_Timer = millis();
  }
  //flow sensor
  if((millis() - oldTime) > 1000)    // Only process counters once per second
    { 
    cli(); // Disable the interrupt while calculating flow rate and sending the value to the host
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    sei(); //Enables interrupts

    pulseCount = 0; // Reset the pulse counter so we can start incrementing again
    oldTime = millis();
  }
 
    Serial.print("Wind speed :"); 
    Serial.print(WindSpeed); 
    Serial.print(" m/s  "); 
    Serial.print("Flow rate: ");
    Serial.print(float(flowRate));  // Print the integer part of the variable
    Serial.println(" L/min");
    delay(1000);
}

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