Hi,
I spent some time on this and here's what I came up with. It counts four sensors on PortC.0-3 using a timer based interrupt, polling the inputs at 250Hz. It counts both rising and falling edges effectively doubling the resolution and calculates the flowrate. Hope it's of some use.
Code:
'****************************************************************
'*  Name    : Flowrate.PBP                                      *
'*  Author  : Henrik Olsson                                     *
'*  Notice  : Copyright (c) 2011 Henrik Olsson 2010             *
'*          : No Rights Reserved                                *
'*  Date    : 2013-03-10                                        *
'*  Version : 1.0                                               *
'*  Notes   : Written for tacbanon.                             *
'*          : Counts pulses from four flow sensors connected    *
'*          : to the lower four bits of PortC and calculates    *
'*          : the flowrate based on 4.5Hz/l/min.                *
'*          : Program requires TMR1 interrupt to exectute at    *
'*          : 250Hz. Set TmrReload constant to correct value:   *
'*          : 61543 for 4MHz                                    *
'*          : 57543 for 8MHz                                    *
'*          : 45543 for 20MHz                                   *
'*          :  1543 for 64MHz                                   *
'*          : Tweak if neccesary                                *
'*          :                                                   *
'*          : Development board used: AMICUS18 platform @64MHz  *
'*          : Change hardware setup to match acutal hardware!   *
'****************************************************************
DEFINE OSC 64
DEFINE LOADER_USED 1                    ' We're using a bootloader.
DEFINE HSER_RCSTA 90h                   ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h                   ' Enable transmit, BRGH = 1
DEFINE HSER_CLROERR 1                   ' Clear overflow automatically
DEFINE HSER_SPBRG 138                   ' 115200 Baud @ 64MHz, -0,08%

INCLUDE "DT_INTS-18.bas"                ' Include Darrel Taylors interrupt processing routines
INCLUDE "ReEnterPBP-18.bas"

ASM
INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
        INT_Handler   TMR1_INT,  _PollInputs,   PBP,  yes
    endm
    INT_CREATE              ; Creates the interrupt processor
ENDASM


' Create an alias to the TIMER1 register so we can access it as a word.
' Make sure RD16 is disabled.
@Timer1 = TMR1L
Timer1  VAR  WORD EXT

TMR1_ON VAR T1CON.0                     ' Alias to the TMR1ON bit

SensorCount Var BYTE[4]                 ' Count 4 sensors
FlowRate VAR BYTE[4]                    ' Flow rate for 4 sensors
SensorState VAR BYTE                    ' Stores current state of inputs.
PreviousState VAR BYTE                  ' Used to determine if inouts has changed state.
ISRCount VAR WORD                       ' Used to keep time based on number of interrupts
i VAR byte                              ' General purpose index variable
j VAR BYTE                              ' General purpose index variable
DataReady VAR BIT

TmrReload CON 1543                      ' 250Hz, 1:1 @64MHz

CLEAR

SPBRGH = 0
BAUDCON.3 = 1                           ' Enable 16 bit baudrate generator
TRISB = %00000000                       ' PortB.0 are all outputs
TRISC = %10001111                       ' Sensor inputs on PortC.0-3, RX/TX on PortC.7/PortC.6

Timer1 = TmrReload                      ' Preload the timer for 250Hz interrupt
TMR1_ON = 1                             ' Start the timer and....

@ INT_ENABLE TMR1_INT                   ; ....enable the interrupt

HSEROUT["Program start",13]

Main:
    If DataReady = 1 THEN               ' ISR sets this flag when data new data is avialble
        DataReady = 0                   ' Clear the flag
        HSEROUT["Flowrate: "]
        For j = 0 to 3

            ' The ISR calculate the flow rate in units of 0.1 litres per minute.
            HSEROUT[DEC FlowRate[j] / 10, ".", DEC FlowRate[j] // 10, "l/min."]
            
            If j = 3 THEN
                HSEROUT[13]
            ELSE
                HSEROUT[" - "]
            ENDIF
        
        NEXT
    ENDIF
Goto Main


' ------------- [Interrupt service routine for Timer1 interrupt] ---------------
' Designed to be executed at 250Hz. Make sure to change the TmrReload constant
' to match the actual clock frequency of the PIC.
 
PollInputs:
    TMR1_ON = 0                         ' Stop timer
    Timer1 = Timer1 + TmrReload         ' Reload timer, account for latency
    TMR1_ON = 1                         ' Restart timer  
    'Toggle PortB.0                      ' Used to verify interrupt frequency
    
    SensorState = PortC & %00001111     ' Get state of inputs.
  

  ' Iterate thru the four sensor inputs and determine if anyone has changed
  ' state since last interrupt. If so, increment the count for that sensor.
    For i = 0 to 3
        If SensorState.0[i] XOR PreviousState.0[i] = 1 THEN
            SensorCount[i] = SensorCount[i] + 1
        ENDIF
    NEXT

  
    PreviousState = SensorState         ' Store current state so we have something to compare with.

  
    ' To get some resolution we update the flowrate and volume at a rate of
    ' 0.5Hz based on the 250Hz interrupt frequency. The output frequency of
    ' the sensor is 4.5Hz/l/min, we're counting both rising and falling edges
    ' so we're getting 9 counts/l/min per second. We're counting for 2 seconds
    ' so we're going to divide by 1.8 to get the flow in units of 0.1 l/min
    
    ISRCount = ISRCount + 1
    If ISRCount = 499 THEN               ' 500 interrupts = 2 seconds.
        ISRCount = 0
        DataReady = 1
        For i = 0 to 3
            FlowRate[i] = SensorCount[i] ** 36409
            SensorCount[i] = 0
        NEXT
    ENDIF
@ INT_RETURN
/Henrik.