Hello Henrik,
Is this mean that I can use similar approach like in this link? (http://www.picbasic.co.uk/forum/show...519#post117519)
Regards,
tacbanon
Hello Henrik,
Is this mean that I can use similar approach like in this link? (http://www.picbasic.co.uk/forum/show...519#post117519)
Regards,
tacbanon
Not sure.
In that thread it looks like you're using the external interrupts (INT0-INT2) but the 877A only has one "normal" external interrupt (INT0). However it does have four Interrupt on change pins (PortB.4-7) which you could use.
Or, like I said, you might get away with simply polling the inputs in a loop. As long as you read the inputs atleast ~120 times per second you shouldn't miss any pulses.
/Henrik.
Thank you Henrik, I will try to work on it and post here in case I have some inquiries.
Regards,
tacbanon
Hi I'm back...My first attempt for 1 flow sensor is I tried to count the pulse similar to a switch button....but still not really sure if I'm doing it right. If its fine how do I get flow rate?...kindly check the code I'm using.
I also attached some pics about my hardware setup..Code:INCLUDE "MODEDEFS.BAS" ' Include Shiftin/out modes INCLUDE "DT_INTS-14.bas" ' Base Interrupt System INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts ;-- Define LCD connections -- (change these to match your hardware) ------------ DEFINE LCD_DREG PORTB DEFINE LCD_DBIT 0 DEFINE LCD_EREG PORTB DEFINE LCD_EBIT 5 DEFINE LCD_RSREG PORTB DEFINE LCD_RSBIT 4 DEFINE LCD_BITS 4 DEFINE LCD_LINES 2 DEFINE LCD_COMMANDUS 2000 DEFINE LCD_DATAUS 50 PAUSE 100 TRISA = %00000000 ; set PORTA to output pins PortA = %00000000 ; set to PORTA low TRISB = %10000000 ; set PORTB to B7 input pin rest output pins PortB = %00000000 ; set to PORTB low TRISC = %10000000 ; set PORTD to output pins PORTC = %00000000 TRISD = %10000000 ; set PORTD to output pins PORTD = %00000000 ; set to PORTD low LCDOUT $FE,1 ; Initialize the LCD pause 200 ; pause 2 milisec OPTION_REG = $7f 'enable pull offs '--variables init flag1 var bit flag1 = 0 c var byte c = 0 cnt1 var word cnt1 = 0 StatLed var PORTA.0 StatLed = 0 But0 var PortB.7 But0 = 0 '--LCD line ln1 con $80 ln2 con $C0 CS con 1 SerialInput var byte[50] Serialdata var byte ; setup serial port line for transmition DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 1 DEFINE HSER_BAUD 9600 DEFINE HSER_CLROERR 1 ' Clear overflow automatically RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty) TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full) '------------------------------------------------------Transmition------------- ; create the transmition interrupt '((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))) ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler TMR1_INT, _ToggleLED1, PBP, yes INT_Handler RX_INT, _Getbytes, PBP, no endm INT_CREATE ; Creates the interrupt processor ENDASM ; T1CON = $31 ; Prescaler = 8, TMR1ON @ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts @ INT_ENABLE RX_INT '((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))) ;------------------------------------------------------------------------ Hserout ["Flow Sensor Test",13] pause 1000 Main: PortB.7 = 0 LCDOUT $FE,ln1,"Flow Sensor Test" LCDOUT $FE,ln2 ,"Cnt: ",dec3 cnt1 Pause 25 IF But0 = 0 then cnt1 = cnt1+1 While But0 = 0:Wend If flag1 = 0 then HSEROUT ["Counter:",Dec3 cnt1,13] flag1 = 1 else flag1 = 0 Endif else endif Goto main '(((((((((((((((((((((((((This is a preparation for PC interface)))))))))))))))) Getbytes: While RCIF = 1 ' clear the buffer c = c + 1 Hserin [Serialdata] select case Serialdata ' What to do with that data??? case "A" ' User selection HSEROUT ["Option A",13] ' take it out case "B" HSEROUT ["Option B",13] ' take it out case "C" HSEROUT ["Option C",13] ' take it out case "*" 'HSEROUT ["This is it! > ",13] ' take it out SerialInput[c] =" " case else SerialInput[c] = Serialdata End select Wend @ INT_RETURN '******************************************************************************* ToggleLED1: 'Toggle statLed @ INT_RETURN
Appreciate any input and time...
Regards,
tacbanon
If it counts the pulses properly then I guess you're doing it right. However, doing it this way is probably not the best when you're trying to get more sensors in but more on that later.
If you look at the product page for the sensor there's a diagram showing the output frequency as a function of the flowrate. The output seems pretty linear (as you'd expect) with 4.5Hz/l/min.
So if you count pulses for on second and divide the result by 4.5 you have your flowrate in litres/minute.
For multiple sensors I'd set up a timer interrupt and poll all inputs in one go. Compare this state to the previous one to see if any input changed. Since the dutycycle of sensor output is 50% you can get twice the resolution (if needed) by counting both the positive and negativ going edges of the signal but then you'd need to poll the inputs twice as fast to guarantee not missing any pulses. It's going to be kind of like reading incremental encoders (lots of examples floating around here) but without the need to determine direction.
Nice hardware setup!
/Henrik.
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
WOW Henrik...Thank You! I know it would take for me another week(s) to get this application running and probably thinking of another path to make it easier for me...but this is just so great (save me lot of precious time)...I will work on it, and feed back you later.
Kind regards,
tacbanon
Bookmarks