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.
Bookmarks