Multiple PWM-Fan controller (interrupt problem)

Hey guys and girls,

I want to use multiple PWM-Fans, a PWM watercooling pump and a hall-effect flow-sensor with an Arduino Mega which also has a 3,2" touchdisplay-shield and drives a couple of WS2812b-LEDs. (That's the plan anyway.)

The control part of this project is clear, I just have problems with all the different tachometer-signals.

To begin with, I don't have enough free interrupt-pins free on my Arduino (the display-shield blocks 2 of the 6 pins and I would need at least 6 preferably up to 8 pins for the different applications). Secondly, I worry that this many interrupts will not only interfere with each other, but with the main program as well.

So ideally I am looking for a way to collect the individual pulses, convert them to RPM and transfer them to my arduino. (Maybe individual attinys via i2c/usi?) Hopefully my idea isn't to far fetched and what I wrote makes any sense to you.

Looking forward to hear your ideas and criticisms! :wink: Regards, Jan

p.S.: I know I could just appoximate the RPM with the duty cycle, but where is the fun in that :D

Pin change interrupts can be used with every port (up to 8 inputs each). When the interrupt rate becomes too high, use additional controllers (Pro Mini...) for rpm measurement. It's always a good idea to separate time critical tasks from visualization and command processing.

Just one timer interrupt could be used. The timer ISR could read a port at defined intervals. For example, if the maximum RPM for your inputs are 30,000 (500Hz) then the timer interrupt could be fired every 2ms and a port read and micros() could be recorded.

Overall, there'll be much fewer interrupts with this method and they'll occur at known intervals. A 16MHz MCU would have about 32,000 cycles in between interrupts to process calculations and other code.

Your RPM calculations would be based on pulse period measurements with ±2ms error which is only 0.2% error for 1 second measurements. Of course, the timer interval could be decreased for higher accuracy if needed.

Why use a timer interrupt to check the port for changes, when the PCINT will occur only if something has definitely changed?

With using PCINT ... 8 inputs pulsing asynchronously at 500Hz would produce up to 8x as many interrupts as replacing PCINT with just one timer interrupt that samples the port(s) or pins at regular 2ms intervals.

The sampled readings would all use the same time stamp which is simpler and more efficient than using independent timing data. Debouncing (if required) would also be simpler because the timing interval allows some time for the inputs to settle.

Not much different really than using a shift register or input (I/O) expander to latch the status of 8 (or more) inputs, then shift in the data. Could alternatively use SPI or shiftIn() with a 74HC165, MCP23S08, MCP23S18 (or other) to reduce required inputs and interrupts required on the MCU.

The polling frequency depends on the duration of the rpm pulses, not on their frequency. The timer interrupt interval must be shorter than the pulse duration, else pulses may be missed.

Yes, I agree. The polling frequency will depend on the pulse width and should probably be adjusted so that the interval is <= 1/2 of the minimum expected pulse width. The polling rate would only be proportional to input frequency if the inputs are square wave.

My example was very general … just to show how a different method could reduce interrupts and processing time.