1

I want to refactor this code

/*
YF‐ S201 Water Flow Sensor
Water Flow Sensor output processed to read in litres/hour
Adaptation Courtesy: www.hobbytronics.co.uk
*/
volatile int flow_frequency; // Measures flow sensor pulses
unsigned int l_hour; // Calculated litres/hour
unsigned char flowsensor = 2; // Sensor Input
unsigned long currentTime;
unsigned long cloopTime;
void flow () // Interrupt function
{
   flow_frequency++;
}
void setup()
{
   pinMode(flowsensor, INPUT);
   digitalWrite(flowsensor, HIGH); // Optional Internal Pull-Up
   Serial.begin(9600);
   attachInterrupt(0, flow, RISING); // Setup Interrupt
   sei(); // Enable interrupts
   currentTime = millis();
   cloopTime = currentTime;
}
void loop ()
{
   currentTime = millis();
   // Every second, calculate and print litres/hour
   if(currentTime >= (cloopTime + 1000))
   {
      cloopTime = currentTime; // Updates cloopTime
      // Pulse frequency (Hz) = 7.5Q, Q is flow rate in L/min.
      l_hour = (flow_frequency * 60 / 7.5); // (Pulse frequency x 60 min) / 7.5Q = flowrate in L/hour
      flow_frequency = 0; // Reset Counter
      Serial.print(l_hour, DEC); // Print litres/hour
      Serial.println(" L/hour");
   }
}

Originally found here: source

to an Class based solution:

/*
YF‐ S201 Water Flow Sensor
Water Flow Sensor output processed to read in litres/hour
Adaptation Courtesy: www.hobbytronics.co.uk
*/
class FlowSensor {
  volatile int flow_frequency;
  unsigned int l_hour;
  unsigned char pin;
  unsigned long currentTime;
  unsigned long cloopTime;
  public:
    void flow () {
      flow_frequency++;
    };
    void setup() {
      pinMode(pin, INPUT);
      digitalWrite(pin, HIGH); // Optional Internal Pull-Up
      Serial.begin(9600);
      attachInterrupt(digitalPinToInterrupt(pin), flow, RISING); // Setup Interrupt
      sei(); // Enable interrupts
      currentTime = millis();
      cloopTime = currentTime;
    }
    void loop() {
      currentTime = millis();
      // Every second, calculate and print litres/hour
      if(currentTime >= (cloopTime + 1000))
      {
        cloopTime = currentTime; // Updates cloopTime
        // Pulse frequency (Hz) = 7.5Q, Q is flow rate in L/min.
        l_hour = (flow_frequency * 60 / 7.5); // (Pulse frequency x 60 min) / 7.5Q = flowrate in L/hour
        flow_frequency = 0; // Reset Counter
        Serial.print(l_hour, DEC); // Print litres/hour
        Serial.println(" L/hour");
      }
    }
    FlowSensor() {
      setup();
    };
};
FlowSensor flowsensor_intake;
void setup()
{
   flowsensor_intake = FlowSensor();
}
void loop ()
{
   flowsensor_intake.loop();
}

But i get the following error in the Arduino IDE:

/tmp/087639235/water_flow/water_flow.ino: In static member function 'static void FlowSensor::flow()':

/tmp/087639235/water_flow/water_flow.ino:17:19: error: cannot call member function 'void FlowSensor::update_flow()' without object

update_flow()

^

exit status 1

I understand that flow is not a static function and that i cannot make it static because it is midifying a non static member.

But i cannot think of an alternate solution to this Problem. My goal is to monitor multiple flow sensors by creating an object in the setup() function, and updating them with every loop() call.

1 Answer 1

1

You've run into a classic trap. There are a couple of things to think about. First off, if this is a singleton class (as in there will only ever be one instance) then you can just have a non-member function that you use with attachInterrupt and have that function just call the member function you want. Normally what I would do would be to create the instance in the .cpp and put an extern declaration for it in the header so that it can just be used without creating it. Look at how Serial works for an example. Then put all the configuration type stuff into a begin or init method to call from setup. That way the non-member function for the interrupt can be part of the header and the user never has to see or mess with it and it feels like it's part of the class.

If this is not a singleton class and you might one day have several instances of this in one program then you have to start asking yourself how will the interrupt know which instance to act upon.

3
  • Yes i want to have multiple instances. Thinking of a struct approach now.
    – Valanthor
    Apr 2, 2020 at 21:23
  • Ok then you've got a problem. How will each instance know which interrupt to attach itself to? How will the interrupt know which instance goes with which interrupt? That turns out to be a can of worms, and it's the reason it's not allowed.
    – Delta_G
    Apr 2, 2020 at 23:42
  • I agree. Singlton or static member functions won't work. My current work around is a member function which is called by a specific function for each attachInterrupt.
    – Valanthor
    Apr 4, 2020 at 10:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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