Using timer.setTimer() function vs. timer.setInterval()

If meaning use a BlynkTimer to refresh the LCD, every x amount of time, or put the LCD writes in other already timed functions… then yes, same general logic

As a general rule interrupts have to be as short as possible like changing some variable, or making some quick calculations. Anything that could take more than couple of uS is not recommended.

Regarding second thing it’s just a matter of preference. Won’t really change anything

I think we are coming back to the same question that began this topic.

I think I understand that you are recommending using an interrupt so that the change in pin state can be captured, especially at high speed or at a random condition that may not fall in the specific time period of the timer.setTimer( ) interval. As I am learning more about interrupts, I also agree that an interrupt should be a very short process because you do not want to interfere with other timer events.

If I understand your logic … by using "timer.setInterval(1000L, pulseCounter), you would call the interrupt every second, count the pulses in that period of time using a volatile variable, multiply by 60 for rpm’s then pass the variable to Blynk before exiting the timer function.

Question: Does the interrupt “RUN” for the full second, or is it necessary to use millis( ) within some sort of a loop to keep track of time and then start and stop the interrupt?

If I could have the interrupt RUN for 10 seconds, then I would be able to count enough pulses to make a reasonable calculation of water flow.

That is what I have accomplished using two timer events. One of the timers uses “timer.setInterval(60000L, flowSensorData)” and within the function “flowSensorData” I call another timer using
"timer.setTimer(100, waterFlowPinStatus, 100) which does the actual counting based on change of pin state from HIGH to LOW. It repeats 100 times, every 100 milliseconds. I don’t have to worry about code for how long to “stay” in the function or how often to repeat the checking of the pin state. Before exiting the function I pass the global counter variable to Blynk and reset the counter to “0”.

Maybe not very elegant, but it seems to work. I am sure if I understood how to make an interrupt continue counting for 10 seconds or any fixed time, I may consider that a more elegant way of writing the code.

Comments from all are VERY appreciated.

Hey I know theres been loads of discussion in here but gonna try and add my 2 cents.

This mechanical function is almost exactly the same as a water flow sensor. It uses a timed moment to calculate pulses from a hall effect sesnor and output it according to your sensor datasheet.

Here is snippet of code I use in my garden watering system which monitors water use within 97% accuracy.
I uses interupts and a timer in combonation.

void setup(){
    // ... insert the timer and interrupt in to your setup
    attachInterrupt(FLOW_SENSOR, pulseCounter, FALLING);
    timer.setInterval(1000, flowSensor);
    // .... 
}
/**************************************************************

                     Flow Sensor

 **************************************************************/
/*
   pulseCounter() -
      - attached to an interrupt counting the pulses from the sensor then used to calculate the rate
*/
void pulseCounter() {
  pulseCount++;
}
/*
   flowSensor() -
      - uses interrupt on the sensor pin
      - calculates the flowRate in mL/s then converts to L/s
      - allow global use of the data
*/
void flowSensor() {
  // every 1000ms detach the flow sensor interrupt
  detachInterrupt(FLOW_SENSOR);
  // save the data
  flowRate = pulseCount / FLOW_CALIBRATION;
   // reset pulseCount to 0
  pulseCount = 0;
  // start over again
  attachInterrupt(FLOW_SENSOR, pulseCounter, FALLING);
  // while here, save or calc totals from sensor datasheet info
  flowMilliLitres = (flowRate / 60) * 1000;
  totalMilliLitres += flowMilliLitres;
  totalMilliLitres_month += flowMilliLitres;
}

You could easily remove my “flow” data and replace it with your own expected data.

1 Like

ohh just saw this… look at my code above ^^

See how I use pulseCount++ ? Its constantly counting up, until the timer is reached and compiles hte data somewhere before resetting the pulseCount.

There is absolutely no reason to disable interrupt at all you simply execute a function that will process your pulse count. Interrupt once enabled will work until it’s disabled but what’s the point to disable it… As long as you process pulse count before it overflows its fine.

Yes, you need to use millis in between to keep track of time because your function might not execute perfectly after 1000ms or whatever you set. It all depends on the quality of your code.

Timer library is an extremly primitive form of a scheduler, which should enable sort of parallel processing. Which is mainly why you need some variables in place to check time intervals. And yes in contrary to what you think you need to worry about time execution (how long it stays in the function) becuase there is no preemption which means things that should be processed straight away won’t be.

BTW even 1ms is ages in terms of microcontrollers, think about it. You can’t design something like

What @Jamin posted above is what you should look into. If you wanna go Low Level read about Timer in Capture mode which is hardware peripheral used in such cases.

1 Like

Ok -

The comments are helpful and I am not ignoring the advice. I just need to process this logic, and write some code to get past my lack of experience using interrupts.

The logic I will follow looks something like this:

Create global variables for passing data to Blynk.
Create volatile variables for the “counter” within the interrupt.
Create a timer that is set for some interval time ( 1 or 10, or 60 seconds).
That timer calls an interrupt.

The interrupt uses a “while” loop and millis( ) to count state changes of a pin for a specific time period that is based on millis( ) and some “endtime” variable. The time period is less than the interval time of the timer.

The “state” changes relate to the revolutions of the water wheel.
I calculate whatever I wish with the revolution counter.
I pass that global variable to Blynk.
The interrupt is closed (just for good housekeeping)
The timer interval waits until it is called again, and the process repeats.

Does that sound reasonable?

Incorrect, As you will see in my code above, it pauses the interrupt then restarts it every 1000ms.

Let’s visualise it

Soooo -

The interrupt is declared in the setup( ).
When the timer calls the flowSensor( ) function the first thing it does is detach (stop) the interrupt, update the global flowRate variable, reset the volatile pluseCount variable, then attach (start) the interrupt which uses the pulseCounter( ) function to increment the global pluseCount variable. That function runs for the remainder of the 1000 milliseconds until the timer is called again. That process repeats every 1000 milliseconds.

Final question: If I wanted to count the SLOW revolutions for 10 seconds, I would simply set the timer interval to 10000 and the interrupt would occupy the same amount of time.

Correct?

Nice visual BTW :grinning:

Just to put a final note on this discussion … Is there ever a concern about interrupts running constantly? I guess not. They are in some ways a form of a timer? I had thought at first that counting and recounting would be a waste of resources, but the more I consider it, the same takes place in the CPU as it keeps track of millis( ).

Thanks for all the suggestions and help from all. Hope to return the favor someday.

Spot on. Just be sure to do all the proper calculations right after starting the interrupt again. Whether is is some sort of simple math or whatever… but do something with it before its lost when the next timer comes round.

Haha thanks… it was my 3rd drawing before i got it right :smile:

No concern about them running. Interrupts are a background task, not affected, only controlled by the sketch.
Also the ESP8266 (albeit old) is still extremely fast and can handle a number of interrupts.