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