PDA

View Full Version : COUNT is not counting again



jellis00
- 5th May 2009, 02:13
My excerpted code as listed below all works until it gets to the point where it is suppose to count the input pulses to pin RA1 during each loop of a REPEAT...UNTIL epoch and write the count valuable to a variable Cin. Then the accumulated count for all epochs is incremented for each epoch by adding Cin to i. The accumulated count is then suppose to be written to EEPROM after the accumulated count reaches its limit and exits the loop.
I know the loop is working because I see the LED blinking on each loop and because the WRITE statement is actually writing over the FF value in EEPROM. However, the Cin value that is written is always zero (0), indicating that COUNT is actually not counting. Therefore, the loop is never exiting, because i=i+Cin is always zero and the WRITE 7,i statement is therefore never executed. For the life of me I can't figure out why this is happening.
I had a similar problem when I first wrote this code and solved the problem by adding the missing ANSEL =0 and ANSELH = 0 statements, which are in this code now, so that can't be the problem. I checked my register settings and I can see no reason why COUNT is not counting. Can anyone see what is wrong?


' -----[ Title ]-----------------------------------------------------------*
' *
' File...... Toilet_Meter.BAS *
' Compiler.. PICBASIC PRO Compiler from microEngineering Labs *
' Purpose... PIC16F690 microcontroller for Toilet Meter Project *
' Author.... John R. Ellis, *
' Started... 2/20/2009 *
' *
' Updated... Version 1.0.6 on 5/2/2009 *
' Program Size: 255 Words * *
' -----[ Program Description ]---------------------------------------------*
' This Program is for a PIC16F690 installed in a PICkit2 Starter Kit *
' Purpose:
' 1) Monitor an input for an external Interrupt from flush *
' 2) On Interrupt, command latching solenoid to open valve *
' 3) Measure flow meter output to determine when 1.6 *
' gallons have passed *
' 4) On 1.6 gallons, command latching solenoid to close *
' 5) Put Microcontroller back in Sleep State to await next *
' Flush Interrupt *
'
' This Program uses the PIC16F690 to control a solenoid operated water valve
' and to measure the volume of water flowing through a flow meter.
' This program places the MCU in sleep mode most of the time until it receives
' an interrupt from the activation of the toilet flush handle that closes a
' contact limit switch that grounds an input pin of the microcontroller as an
' interrupt. I/O pin connections to the PIC16F690 are as follows:
'
' RA1...is connected as an input from the meter to count pulse inputs, which
' are simulated by multiple manual depressions of a switch on the PICKIT2
' demo board during program testing.
' RA3...is connected as an interrupt input from the FLUSH contact limit Switch.
' RC0...is connected as an output to an LED and is slowly flashed when the valve
' is open. It is also flashed even more slowly when the battery is low.
' RC3...is connected as an output to the latching solenoid that opens or
' closes the valve. During program testing with the PICkit2 demo
' board it is connected to an LED to show when the pulse is sent.

' -----[ Device Declaration ]----------------------------------------------
'
'@device pic16F690, intrc_osc_noclkout, BOD_OFF, PWRT_OFF, wdt_off,mclr_off,
' protect_off

' -----[ Revision History ]------------------------------------------------
'
' -----[ Variables Initialization ]----------------------------------------
'
k CON 15 ' Calibration factor for flow meter...# pulses per gal
i VAR Byte ' Index used in Gallon counter Repeat...Until loop
Cin VAR Byte ' Storage variable for count from COUNTER

' -----[ Initialization ]--------------------------------------------------
'

'Registers Settings
Init:
ADCON1 = %01110000 ' Set PORTA to digital I/O & FRC (clock derived from a
' dedicated internal oscillator)
TRISA = %00000010 ' Set all PORTA pins except RA1 to outputs
TRISB = %00000000 ' Set all PORTB and PORTC pins to outputs
TRISC = %00000000
PORTC = %00000000 ' Pre-set PORTB pins low, turning LEDs off
ANSEL = 0 ' Set PortA to digital I/O; Unselect any of the A/D channels
ANSELH = 0
TRISA.1 = 1 ' Set RA1 as input port for meter pulse inputs
PortA.1 = 0 ' Pre-set RA1 at Low value
INTCON = %10010000 ' Set INTCON register to enable interrupts

' -----[ Main Code ]-------------------------------------------------------
MAIN:
'Send PWM pulse to latching solenoid to open valve
'Generates 10 millisec pulse on RC3 output pin
LOW PORTC.3 ' Initialize output pulse polarity
PULSOUT PORTC.3,1000 ' Generate 10 msec pulse to RC3

' Valve should be open at this point and water flowing

' Start measuring output of flow meter at RA1 input pin
Cin = 0 ' Initialize pulse count variable to zero
i = 0 ' Initialize total pulse count index to zero
REPEAT ' Assume it takes k accumulated pulses for required gallons
' Count the number of pulses from Hall Effect Magnetic Sensor in 5 sec
' epochs and add count from each epoch to total accumulation and then
' shutoff the valve when count meets i>k criteria.
Count PORTA.1,5000,Cin
WRITE 5,Cin ' Write count into EEPROM location 5 during
' pre-production testing
'Slowly blink LED during water flow
HIGH PORTC.0 ' If we get here, Blink the LED once
PAUSE 100
LOW PORTC.0
i = i + Cin ' Add count to total pulse accumulation indexer
'When i >= k, required gallons have flowed by the meter
UNTIL i = k
WRITE 7,i 'Store result as test of code..not in production
'Write 8,i.LowByte
GoTo ShutValve

ShutValve: 'Send PWM pulse to latching solenoid to close valve
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3

' Valve should be closed at this point and no water flowing
END

Darrel Taylor
- 5th May 2009, 05:45
John,

You've Enabled Interrupts, but there aren't any handlers defined.
That usually causes everything to Lock-Up from "Continuous Interruptus".

Interrupts have nothing to do with the COUNT statement.
If it was to exit sleep mode? Don't enable the GIE bit.

But the way you're doing it, you're going to miss a lot of pulses.
It really should use interrupts to count the pulses.
<br>

jellis00
- 5th May 2009, 07:12
Darrell,
Thanks for the reply. I commented out the INTCOM statement and the program still runs as I was describing above, but still doesn't count input pulses.
As far as missing pulses, the rate at which the incoming pulses occur is much, much slower than the loop rate, so I don't think it will miss that many pulses.
At any rate, I will look into how to do this with interrupts, but I still would like to figure out why the COUNT statement is not counting. Any ideas??

Archangel
- 5th May 2009, 08:04
Hello jellis00,
Have you verified the presence and level of the pulses you are counting?
What happens if i = i + cin >15 then will it not overshoot the until and never make the statement true ? Maybe UNTIL i >= k would be better ?
Looked at the data sheet, no schmitt triggers to worry about, porta on change interrupts are available. I notice your code does not loop, one shot as is. I really did not write any code <font color=red>AND I DID NOT TEST THIS,</font color> but here is what I was thinking you might do differently. I would actually make the int handler a bit smaller and tidier but you get the jist.


' -----[ Title ]---------------------------------------------------------- -*
' *
' File...... Toilet_Meter.BAS *
' Compiler.. PICBASIC PRO Compiler from microEngineering Labs *
' Purpose... PIC16F690 microcontroller for Toilet Meter Project *
' Author.... John R. Ellis, *
' Started... 2/20/2009 *
' *
' Updated... Version 1.0.6 on 5/2/2009 *
' Program Size: 255 Words * *
' -----[ Program Description ]---------------------------------------------*
' This Program is for a PIC16F690 installed in a PICkit2 Starter Kit *
' Purpose:
' 1) Monitor an input for an external Interrupt from flush *
' 2) On Interrupt, command latching solenoid to open valve *
' 3) Measure flow meter output to determine when 1.6 *
' gallons have passed *
' 4) On 1.6 gallons, command latching solenoid to close *
' 5) Put Microcontroller back in Sleep State to await next *
' Flush Interrupt *
'
' This Program uses the PIC16F690 to control a solenoid operated water valve
' and to measure the volume of water flowing through a flow meter.
' This program places the MCU in sleep mode most of the time until it receives
' an interrupt from the activation of the toilet flush handle that closes a
' contact limit switch that grounds an input pin of the microcontroller as an
' interrupt. I/O pin connections to the PIC16F690 are as follows:
'
' RA1...is connected as an input from the meter to count pulse inputs, which
' are simulated by multiple manual depressions of a switch on the PICKIT2
' demo board during program testing.
' RA3...is connected as an interrupt input from the FLUSH contact limit Switch.
' RC0...is connected as an output to an LED and is slowly flashed when the valve
' is open. It is also flashed even more slowly when the battery is low.
' RC3...is connected as an output to the latching solenoid that opens or
' closes the valve. During program testing with the PICkit2 demo
' board it is connected to an LED to show when the pulse is sent.

' -----[ Device Declaration ]----------------------------------------------
'
'@device pic16F690, intrc_osc_noclkout, BOD_OFF, PWRT_OFF, wdt_off,mclr_off,
' protect_off

' -----[ Revision History ]------------------------------------------------
@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
' -----[ Variables Initialization ]----------------------------------------
'
k CON 15 ' Calibration factor for flow meter...# pulses per gal
i VAR Byte ' Index used in Gallon counter Repeat...Until loop
Cin VAR Byte ' Storage variable for count from COUNTER

' -----[ Initialization ]--------------------------------------------------
'

'Registers Settings
Init:
ADCON1 = %01110000 ' Set PORTA to digital I/O & FRC (clock derived from a dedicated internal oscillator)
'
TRISA = %00000010 ' Set all PORTA pins except RA1 to outputs
TRISB = %00000000 ' Set all PORTB and PORTC pins to outputs
TRISC = %00000000
PORTC = %00000000 ' Pre-set PORTB pins low, turning LEDs off
ANSEL = 0 ' Set PortA to digital I/O; Unselect any of the A/D channels
ANSELH = 0
TRISA.1 = 1 ' Set RA1 as input port for meter pulse inputs
PortA.1 = 0 ' Pre-set RA1 at Low value
INTCON = %10011000 ' Set INTCON register to enable interrupts

' -----[ Main Code ]-------------------------------------------------------
on interrupt goto Int_Handler

MAIN:
'Send PWM pulse to latching solenoid to open valve
'Generates 10 millisec pulse on RC3 output pin
LOW PORTC.3 ' Initialize output pulse polarity
PULSOUT PORTC.3,1000 ' Generate 10 msec pulse to RC3

' Valve should be open at this point and water flowing

Log:
WRITE 7,i 'Store result as test of code..not in production
'Write 8,i.LowByte
GoTo ShutValve

ShutValve: ' Send PWM pulse to latching solenoid to close valve
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
@ sleep
Disable ' Valve should be closed at this point and no water flowing
Int_Handler:
' Start measuring output of flow meter at RA1 input pin
Cin = 0 ' Initialize pulse count variable to zero
i = 0 ' Initialize total pulse count index to zero
REPEAT ' Assume it takes k accumulated pulses for required gallons
' Count the number of pulses from Hall Effect Magnetic Sensor in 5 sec
' epochs and add count from each epoch to total accumulation and then
' shutoff the valve when count meets i>k criteria.
Count PORTA.1,5000,Cin
WRITE 5,Cin ' Write count into EEPROM location 5 during
' pre-production testing
' Slowly blink LED during water flow
HIGH PORTC.0 ' If we get here, Blink the LED once
PAUSE 100
LOW PORTC.0
i = i + Cin ' Add count to total pulse accumulation indexer
'When i >= k, required gallons have flowed by the meter
UNTIL i >= k
goto Log
return
enable
END

Bruce
- 5th May 2009, 16:38
This could be really easy with Timer0 configured to count external pulses.

Here's one version;


@ device pic16F690, intrc_osc_noclkout, wdt_off, mclr_off, protect_off

T0_CLK VAR PORTA.0 ' for testing, RA0 provides external clock input to RA2
Time CON 100 ' pause delay time

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0
PORTA = 0
TRISC = %11110000 ' lower 4 pins output TMR0 count to LEDs
TRISA = %11111110 ' RA0 = pulse output to RA2 TMR0 clock input

Main:
TMR0 = 0 ' clear TMR0 count
REPEAT
HIGH T0_CLK ' rising edge on T0CKI
PAUSE Time
LOW T0_CLK ' trigger TMR0 counter on falling edge on T0CKI
PAUSE Time
PORTC = TMR0 ' show Timer0 external clock count on LEDs
UNTIL TMR0 = 15
PAUSE 1000
GOTO Main
If you prefer interrupts, just preload Timer0 to over-flow after 15 pulses, and do whatever
you need in the interrupt.

You don't need to worry about missing any pulses, and you can do lots of other stuff while
waiting for the counter to trigger.

jellis00
- 7th May 2009, 05:02
Joe and Bruce, thanks for the excellent inputs! I didn't totally grasp Joe's suggested use of the TMR0 as a counter, mainly because the wiring on microcontroller board doesn't enable me to use RA0 to generate a clock input to RA2 as Bruce's approach suggests.
However, I have gone back to the drawing board to try to count the input pulses from the external sensor by counting them as interrupts. I am enclosing my new code below for reference. I tried to set up the Int-Handler to test for either a RA2/INT or a RA1 on change interrupt by means of two IF_Then blocks. Unfortunately it doesn't appear to recognize any interrupts. I know this because I inserted a LED blink at the very start of the Int_handler to tell me when an interrupt has been recognized and it never blinks for either a RA2/INT or a RA1 on change interrupt. If the RA1 interrupt is received it would increment an index counter, i, for each pulse. I also put the write statement in the If_Then block for RA1 on change interrupt so I could use the PICkit2 to read the EEPROM memory address for the value and it never changes from the FF value. These two tests tell me that my interrupt handler isn't working. Can anyone tell me what I have done wrong from this code??


' -----[ Device Declaration ]--------------------------------------------------*
'
@device pic16F690, intrc_osc_noclkout, wdt_off, mclr_off, protect_off

' -----[ Variables Initialization ]--------------------------------------------*
'
k CON 15 ' Calibration factor for flow meter = # pulses per gal
i VAR Byte ' Index used in Gallon counter Repeat...Until loop

' -----[ Initialization of Registers ]-----------------------------------------*
'

'Register Settings
TRISA = %00001010 ' Set PORTA pins RA1 and RA3 to inputs, others as outputs
TRISB = %00000000 ' Set PORTB pins as outputs
TRISC = %01000000 ' Set PORTC pin RC6 to input, all others as outputs
PORTC = %0000000 ' Pre-set PORTC LED pins low, turning LEDs off
'A/D & Comparators disabled
ADCON1 = %01110000 ' Set PORTA to digital I/O & FRC (clock derived from a
' dedicated internal oscillator)
ANSEL=0 ' Set PortA to digital I/O
ANSELH=0 ' Analog module disabled
CM1CON0=0
CM2CON0=0
TRISA.1 = 1 ' Set RA1 as input port for simulated meter pulse inputs
TRISA.3 = 1 ' Set RA3 as Master Reset input port
PORTA.1 = 1 ' Pre-set RA1 at High value

' Setup Interrupts
INTCON = %10011000 ' Enable RA2/Int external interrupt and PORTA interrupts on
' change
IOCA = %00000010 ' Enable RA1 for interrupt on change for pulses received
' from momentary switch, activation which simulates external HS1 sensor pulses
on interrupt goto Int_Handler
i=0 ' Initialize counter index to zero

' -----[ Main Code ]-----------------------------------------------------------*
MAIN:
INTCON = %10011000 ' Clear interrupt flags
IF i < k Then 'k is 15 pulse threshold
' Keep the valve open...do nothing..let water flow
Else
'i >= 15....1.6 gallons reached...Close the valve
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
ENDIF
GOTO Main 'Main program loops while waiting for RA1 on change interrupt to count pulses

Int_Handler:
Disable ' No interrupts past this point
'Blink LED on receipt of this interrupt
HIGH PORTC.0 ' Blink the LED once
PAUSE 100
LOW PORTC.0
If INTCON = %10011010 Then 'RA2/INT external interrupt received
PULSOUT PORTC.3,1000 ' Generate 10 msec pulse to RC3 to open valve
Endif
If INTCON = %10011001 Then ' Flow meter interrupt pulse received on PORTA
i = i + 1 'Increment pulse count value
WRITE 7,i 'Store updated count result
ENDIF
Resume ' Return to main program
Enable
END

Archangel
- 7th May 2009, 09:02
Hello, here is some spaghetti, you can remove the extra junk but it counts.


'************************************************* ******************************
'
'jellis00
' File...... Toilet_Meter.BAS *
' Compiler.. PICBASIC PRO Compiler from microEngineering Labs *
' Purpose... PIC16F690 microcontroller for Toilet Meter Project *
' Author.... John R. Ellis, *
' Started... 2/20/2009 *
' *
' Updated... Version 1.0.6 on 5/2/2009 *
'************************************************* ******************************
'
'
'
' -----[ Device Declaration ]--------------------------------------------------*
' __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _CP_OFF
@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF &_CP_OFF
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
' -----[ Variables Initialization ]--------------------------------------------*
'
k CON 15 ' Calibration factor for flow meter = # pulses per gal
i VAR Byte ' Index used in Gallon counter Repeat...Until loop

' -----[ Initialization of Registers ]-----------------------------------------*
'

'Register Settings
TRISA = %00001010 ' Set PORTA pins RA1 and RA3 to inputs, others as outputs
TRISB = %00000000 ' Set PORTB pins as outputs
TRISC = %01000000 ' Set PORTC pin RC6 to input, all others as outputs
PORTC = %0000000 ' Pre-set PORTC LED pins low, turning LEDs off
'A/D & Comparators disabled
ADCON1 = %01110000 ' Set PORTA to digital I/O & FRC (clock derived from a
' dedicated internal oscillator)
ANSEL=0 ' Set PortA to digital I/O
ANSELH=0 ' Analog module disabled
CM1CON0=0
CM2CON0=0
TRISA.1 = 1 ' Set RA1 as input port for simulated meter pulse inputs
TRISA.3 = 1 ' Set RA3 as Master Reset input port
PORTA.1 = 1 ' Pre-set RA1 at High value
GIE VAR INTCON.1
OPTION_REG = %01110000 ' CLOCK ON RISING EDGE 'enable timer 0 count mode on RA.2

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _Interrupt_Handler, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_ENABLE TMR0_INT ; enable Timer 0 interrupts
INT_ENABLE INT_INT ; enable external (INT) interrupts
ENDASM
' Setup Interrupts
INTCON = %10011000 ' Enable RA2/Int external interrupt and PORTA interrupts on
' change
'IOCA = %00000010 ' Enable RA1 for interrupt on change for pulses received
' from momentary switch, activation which simulates external HS1 sensor pulses
'on interrupt goto Int_Handler
i=0 ' Initialize counter index to zero
GIE = 0 ' Clear interrupt flags
' -----[ Main Code ]-----------------------------------------------------------*

flush:if portA.1 = 1 then

goto main
else
endif
goto flush
MAIN:
IF i < k Then
goto main 'k is 15 pulse threshold
Else
if i >= k then
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
WRITE 7,i 'Store updated count result
I=0 ' CLEAR COUNTER FOR NEXT FLUSH
ENDIF
endif
GOTO flush 'Main program loops while waiting for RA1 on change interrupt to count pulses
Disable
Interrupt_Handler: ' only get here if interrupt occured

PULSOUT PORTC.0,500 ' Blink the LED once
i = i + 1 'Increment pulse count value
GIE = 0
@ INT_RETURN ; Resume ' Return to main program


Enable

END

Bruce
- 7th May 2009, 17:10
Non interrupt version;


@ device pic16F690, intrc_osc_noclkout, wdt_off, mclr_off, protect_off
K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
PORTA = 0
TRISC = %11110000 ' lower 4 pins outputs
TRISA = %11111111 ' RA2 = TMR0 clock input for simulated meter pulse inputs
TMR0 = 0 ' clear TMR0 count

Main:
IF TMR0 < K THEN
' Keep the valve open...do nothing..let water flow
ELSE
TMR0 = 0 ' clear TMR0 count
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
' WRITE 7, TMR0 ' write count if you need to?
HIGH PORTC.0 ' LED toggle stuff
PAUSE 500
LOW PORTC.0
ENDIF
GOTO Main

END
With DT interrupts; Note that now you need to use the MPASM
assembler & config settings for MPASM.


@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts

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

K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
PORTA = 0
TRISC = %11110000 ' lower 4 pins outputs
TRISA = %11111111 ' RA2 = TMR0 clock input for simulated meter pulse inputs
TMR0 = 241 ' preload TMR0 to overflow after 15 counts

@ INT_ENABLE TMR0_INT ; enable TMR0 counter interrupt

Main:
PAUSE 1
GOTO Main

FlusO_Matic:
TMR0 = 241 ' reload TMR0 to overflow after 15 counts
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
' WRITE 7, TMR0 ' write count if you need to?
@ INT_RETURN

END
Then of course, you can do pretty much the same by just watching the Timer0
interrupt flag;


@ device pic16F690, intrc_osc_noclkout, wdt_off, mclr_off, protect_off

K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
PORTA = 0
TRISC = %11110000 ' lower 4 pins outputs
TRISA = %11111111 ' RA2 = TMR0 clock input for simulated meter pulse inputs
TMR0 = 241 ' preload TMR0 to overflow after 15 counts

TMRO_INT_FLAG VAR INTCON.2 ' Timer0 overflow flag bit
INTCON = 0 ' not using interrupts + clear Timer0 int flag

Main:
WHILE TMRO_INT_FLAG = 0
WEND
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
' WRITE 7, TMR0 ' write count if you need to?
TMRO_INT_FLAG = 0 ' clear overflow flag
TMR0 = 241 ' reload TMR0 to overflow after 15 counts
GOTO Main

END
And, last, but not least, there's the old stand-by ON INTERRUPT;


@ device pic16F690, intrc_osc_noclkout, wdt_off, mclr_off, protect_off

K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
PORTA = 0
TRISC = %11110000 ' lower 4 pins outputs
TRISA = %11111111 ' RA2 = TMR0 clock input for simulated meter pulse inputs
TMR0 = 241 ' preload TMR0 to overflow after 15 counts

TMRO_INT_FLAG VAR INTCON.2 ' Timer0 overflow flag bit
INTCON = %10100000 ' enable global & Timer0 interrupt

ON INTERRUPT GOTO FlushOMatic

Main:
PAUSE 1
GOTO Main

DISABLE
FlushOMatic:
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
' WRITE 7, TMR0 ' write count if you need to?
TMRO_INT_FLAG = 0 ' clear overflow flag
TMR0 = 241 ' reload TMR0 to overflow after 15 counts
RESUME
ENABLE

END
All kept really simple & fairly easy to follow/modify...;o}

jellis00
- 8th May 2009, 00:26
Bruce, I really liked the code you posted for a Non-interrupt version to do my counting. I prefer it over the other options you posted, since I won't get into the problems I have seen in trying to handle interrupts in noisy signal envoirnments. It is concise with minimal executable statements, low memory requirement and should execute efficiently.
It looked to me like it should run with my PIC16F690 almost as is. So I set up a pinout so that my momentary push button switch that I have been using to simulate the external sensor pusles will connect the RA2 pin to ground each time I depress the switch. I presumed this would be enough of a "clock" transition to increment the TMR0 counter. However, I haven't yet been able to see it run since I am having a compile problem with assembler errors that I can't understand or trace. I am attaching a screen snapshot (.jpg image) that shows the errors in lower left. Can you clarify what these errors are telling me?

Bruce
- 8th May 2009, 00:40
Make sure you're using the PM assembler, and not MPASM. Or change to the MPASM
config line I've already shown in the DT interrupts version.

jellis00
- 8th May 2009, 01:14
Bruce,
OK, I am using PBP compiler via MicroStudio that uses MSPM assembler. So I made the config change. Now I get a different, but single assembler error: " Error[118]: Overwriting previous address contents[2007]" When I click on it, it points to the @__config statement.
Again I don't know what this is telling me...can you advise.
BTW, is there anywhere that you can get error listings for the MSPM assembler so you know what they mean?

mister_e
- 8th May 2009, 01:43
http://www.picbasic.co.uk/forum/showthread.php?t=11116

jellis00
- 8th May 2009, 01:57
Thanks, Mister e, for the link. The article by Melanie on how to set configuration fuses answered my error question and also a lot of others I have had about the subject. I edited my .incl file per her instructions to eliminate overwrite by the @__config statement and it now compiles without errors.
Now that it finally runs, I have another question for Bruce. The Non-interrupt code runs fine, but I am not seening any pulse counts show up in TMR0 value when I write it during execute and then use READ in PICKkit2 to read the memory address....it is continuously zero. I thought maybe it was because my simulation mode for pulses wasn't working so I put a voltmeter on the RA2 pin while running the program and depressing the switch button to simulate pulses. What I saw was that RA2 was at 1.8 volts when the switch was open and of course it went to ground when I depress it. Isn't the 1.8 volt transition enough to trigger the TMR0 to count the pulses?

jellis00
- 8th May 2009, 02:59
Bruce, I see now in 16F690 data sheet that for TTL the minimum Vih threshold is 2.0 volts and for Schmidt trigger it is 0.8 volts. Would my switch grounding interface appear to RA2 as TTL or Schmidt trigger? Since the RA2 input is 1.8 v when open and I am grounding it to create a simulated pulse, I don't know whether this is enough downward transition or not. If not, what can I do about it. I thought the open circuit voltage level of RA2 would be over 2.0 volts.

Bruce
- 8th May 2009, 03:49
Do you see where it states TMR0 = 0 ' clear TMR0 count

This clears the timer0 count. If you need to write the timer0 count value to EEPROM first,
then simply move the TMR0 = 0 below where you have WRITE 7, TMR0. Then you will clear
the TMR0 count after you write it to EEPROM.

It's not rocket science...;o}

A TTL input requires 2V to VDD. As long as power is 4.5V ≤ VDD ≤ 5.5V, which just means
VDD is greater than or equal to 4.5V and less than or equal to 5.5V. Then it meets the Vih
logic 1 threshold.

A Schmitt Trigger tytpe input requires 0.8V * VDD to VDD.

If you were operating from a 5V supply, then 0.8 * 5V = 4V, which is what you'll need to
apply as a minimum to the input for it to recognize a logic 1.

Ground is ground. Your switch is for sure taking the input to ground.

With 4.5V ≤ VDD ≤ 5.5V, Vil is met when the input is at Vss, up to 0.8V. But check the
column under Conditions to be sure. It varies a bit with different VDD levels.

Look at PINOUT DESCRIPTION – PIC16F690. Now look at RA2 for what type of input T0CKI
is under the Input Type column.

Now look at RA5. When you use RA5 as a general purpose I/O-pin, it only needs TTL level
voltages. When you flip the switch to make it the Timer1 clock input, now it's a Schmitt
Trigger input.

Check out the BLOCK DIAGRAM OF RA5 to find out why.

It's all right there. Just takes time to learn how to find & decipher it all...;o}

And, when that doesn't work, download the latest Errata sheet for the PIC you're using.
Microchip screws up once in a while, and makes changes to datasheets....;o}

jellis00
- 8th May 2009, 05:19
Bruce, I moved the TMR0 = 0 clear statement after the WRITE statement. However, that is not the problem. I can see while running the code that the TMR0 value is never exceeding the value of K so it never enters the ELSE block and therefore never gets to the WRITE statement which leaves the EEPROM address at inital value of FF continuously.
All this is telling me that my approach to simulating the input pulses by momentarily grounding the RA2 port with my switch closure is not triggering the TMR0 count, but not quite sure what to do about that...I don't yet have access to the meter so I can use real pulse inputs from the sensor.
I understand what you are saying about the threshold value for Vih. However, my 16F690 is running off 5.0 volts, so I would have expected the voltage at RA2 to be near 5.0 volts when the switch is open (not grounded). Yet what I see is 1.8 volts, which is obviously not enough for Vih. This doesn't make sense to me, but explains why the TMR0 value is not incrementing. Any ideas why the RA2 port voltage would be at 1.8 vdc rather than 5.0 vdc when it is unloaded?
I also didn't quite understnd your comments about RA5. My code is a close modification of the Non-interrupt version code you posted above and doesn't even mention RA5 (see current code posting below). Are you saying I have to use RA5 somehow in generating the "clock" input to RA2??


@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
PORTA = 0
TRISC = %11110000 ' lower 4 pins outputs
TRISA = %11111111 ' RA2 = 2TMR0 clock input for simulated meter pulse inputs
TMR0 = 0 ' clear TMR0 count

Main:
IF TMR0 < K THEN
' Keep the valve open...do nothing..let water flow
HIGH PORTC.0 ' Light LED continuously while water is flowing
ELSE
WRITE 7, TMR0 ' write before TMR0 cleared
TMR0 = 0 ' clear TMR0 count
Low PORTC.0 ' Blink LED on each clear after TMR0 >= K
PAUSE 500
HIGH PORTC.0
PAUSE 500
LOW PORTC.0
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
ENDIF
GOTO Main
END

jellis00
- 8th May 2009, 06:39
Bruce, I may have stumbled onto part of my problem. I checked the switch interface more closely and discovered that the wire I was inserting into a female header that was connected to RA2 from the switch was not making good contact. Now when I check the voltage on RA2 pin when it is open output it reads 3.2 vdc. Still a long ways from VDD or Vih, but yet when I now depress the switch I am getting TMR0 count values. However, I notice that only 3-4 depressions of the switch causes TMR0 to obviously exceed the K value and trigger the ELSE block where it is written to memory and then cleared. I presume that this means there is a lot of switch bounce on the momentary switch depressions, each bounce being counted as a pulse by TMR0. Yet I can't figure out why it even works when the RA2 voltage transitions are only from 3.2 volts to ground. Any ideas?
Maybe Interrupts would still be the better approach to do the counting, where the interrupt would trigger on the first switch closure and should ignore the switch bounces while further interrupts are disabled during the Int-handler. What do you think?

Archangel
- 8th May 2009, 06:47
However, my 16F690 is running off 5.0 volts, so I would have expected the voltage at RA2 to be near 5.0 volts when the switch is open (not grounded). Yet what I see is 1.8 volts, which is obviously not enough for Vih. This doesn't make sense to me, but explains why the TMR0 value is not incrementing. Any ideas why the RA2 port voltage would be at 1.8 vdc rather than 5.0 vdc when it is unloaded?
RA2 is set as an input by the tris register, so the impeadence is relativly high, your meter MAY be enough load to reduce the voltage read, install a pull up resistor from RA2 to VDD to bring it up to the 5v level or enable WPUA (sect 4.3) data sheet.

jellis00
- 8th May 2009, 07:42
Joe, I enabled a WPUA.2 = 1 on RA2. However, with this change the voltage on RA2 when open circuit output is still at 3.2 vdc rather than Vih or close to Vdd. My code now looks like below. Interestingly the WRITE 7, TMR0 in the IF block never shows a value other than zero. However, just a couple of momentary switch activations will enter into the ELSE block where the WRITE 9, TRM0 statement shows a value of greater than K each time. So it looks like a lot of switch bounce going on, but the thing I don't understand is why the WRITE 7, TMR0 statement isn't showing any TMR0 values< K.
I also notice that if I comment out the LED blink statements in the IF block, the WRITE 7 statement doesn't write anything because the memory address shows a continuous FF value. Strange things that I don't understand. But at least it looks like the TMR0 is counting whether the value shows up correctly or not.
Tomorrow I am going to try to generate another method of simulating the external sensor input pulses to eliminate the switch bounce problem. I thought this might be possible by using one of the I/O pin outputs in a similar blink sequence loop as I am using for the LED, and then route that output into RA2. Do you think this would work? I will try to use one of the I/O pins that has a CMOS output.

jellis00
- 8th May 2009, 07:44
This time with the code:


@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
PORTA = 0
TRISC = %11110000 ' lower 4 pins outputs
TRISA = %11111111 ' RA2 = 2TMR0 clock input for simulated meter pulse inputs
TMR0 = 0 ' clear TMR0 count
WPUA.2 = 1 ' enable weak pull-up on RA2

Main:
IF TMR0 < K THEN
WRITE 7, TMR0 ' write count during testing
' Keep the valve open...do nothing..let water flow
HIGH PORTC.0 ' Blink Light LED while water is flowing
Pause 500
LOW PORTC.0
PAUSE 500
ELSE
WRITE 9, TMR0 ' write count during testing before clearing
TMR0 = 0 ' clear TMR0 count
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
ENDIF
GOTO Main
END

Archangel
- 8th May 2009, 09:15
This time with the code:


@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
PORTA = 0
TRISC = %11110000 ' lower 4 pins outputs
TRISA = %11111111 ' RA2 = 2TMR0 clock input for simulated meter pulse inputs
TMR0 = 0 ' clear TMR0 count
WPUA.2 = 1 ' enable weak pull-up on RA2

Main:
IF TMR0 < K THEN
WRITE 7, TMR0 ' write count during testing
' Keep the valve open...do nothing..let water flow
HIGH PORTC.0 ' Blink Light LED while water is flowing
Pause 500
LOW PORTC.0
PAUSE 500
ELSE
WRITE 9, TMR0 ' write count during testing before clearing
TMR0 = 0 ' clear TMR0 count
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
ENDIF
GOTO Main
END

try masking the interrupt just before write and reenable right after.


eecon1 = 6 ' enables eeprom write
intcon.7 = 1
write address, data
intcon.7 =0

mister_e
- 8th May 2009, 10:25
FYI, there's a new DEFINE for that

DEFINE WRITE_INT 1

Bruce
- 8th May 2009, 15:41
This code;


@ device pic16F690, intrc_osc_noclkout, wdt_off, mclr_off, protect_off
K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0

' Port setup
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
PORTA = 0
TRISC = %11110000 ' lower 4 pins outputs
TRISA = %11111111 ' RA2 = TMR0 clock input for simulated meter pulse inputs
TMR0 = 0 ' clear TMR0 count

Main:
IF TMR0 < K THEN
' Keep the valve open...do nothing..let water flow
ELSE
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3
WRITE 7, TMR0 ' write count if you need to?
TMR0 = 0 ' clear TMR0 count
HIGH PORTC.0 ' LED toggle stuff
PAUSE 500
LOW PORTC.0
ENDIF
GOTO Main

END
With the schematic attached - works. It writes 15 to EEPROM after precisely
15 press/release actions on the switch.

Tested on the PICkit 2 low pin count demo board.

The cap on RA3 is 0.01uF, which helps eliminate contact bounce from the switch.

The switch on the PICkit 2 demo board connects to RA3, so a wire runs directly from
RA3 to RA2. Remove the cap, and switch bounce causes problems. It's a really simple
fix.

If your circuit is powered from 5V, and you measure 5V between the PIC VDD/VSS pins,
and you only see 3.2V on RA2 with a pull-up to VDD, then check your circuit. There's a
problem somewhere with your wiring or connections.

jellis00
- 8th May 2009, 17:03
FYI, there's a new DEFINE for that

DEFINE WRITE_INT 1
I don't see this DEFINE listed in Appendix B of the PICBASIC PRO manual, which supposedly lists all DEFINEs.
Can you explain how you would use this to replace the code statements Joe lists to mask interrupts while writing? Do you just precede the WRITE statement with DEFINE WRITE_INT1? After the WRITE, do you still have to re-enable the interrupt? I guess if you have to do all this, I don't see how it is any more efficient than using Joe's 4 statements.

Bruce
- 8th May 2009, 17:44
If DEFINE WRITE_INT isn't in your manual, then you probably have an older version of PBP
or an old manual before this new define option was added.

Newer versions of PBP include a check for this in the WRITE library. If you have DEFINE
WRITE_INT 1 declared, it automatically disables interrupts before the write, and re-enables
interrupts immediately after the write is complete.

It just saves you from having to remember to do it yourself.

jellis00
- 8th May 2009, 18:15
PROBLEM SOLVED ON THIS THREAD.

Thanks, Bruce, for clarification on DEFINE. I will use this in all future programs where I have write statements.

Joe S., the 0.01 uF capacitor definitely solved my switch bounce problem. The code now works perfectly and always counts exactly 15 pulses when it activates the external pulse to the valve solenoid.

Your guys are stupendous! I learned more in the interchanges during this thread about programming PIC MCUs than I have learned in weeks reading different sources.

Thanks again and keep up the good work!

Archangel
- 8th May 2009, 19:00
FYI, there's a new DEFINE for that

DEFINE WRITE_INT 1That should save someone some brain damage. Where did you learn that? Das Book ?

Joe S., the 0.01 uF capacitor definitely solved my switch bounce problem. The code now works perfectly and always counts exactly 15 pulses when it activates the external pulse to the valve solenoid.Credit to where credit is due . . . BRUCE . . . always on target.
After the WRITE, do you still have to re-enable the interrupt? I guess if you have to do all this, I don't see how it is any more efficient than using Joe's 4 statements. Maybe not more efficient, but way easier.

jellis00
- 17th May 2009, 01:22
I thought I had this problem licked. Then I purchased PCB PRO and tried to run the same code that ran in PCB. I get all an "Overwriting prrevious address contents" assembly error and many "Symbol not previously defined erros" as related to the ANSEL, ANSELH, CM1CON and CM2CON statements as shown in the attached image. These errors sort of sound like a problem with the CONFIG statement not being commented out in the .inc file. I did make sure I commented out the @ __device statement in the 16F690.incl file that came with PCB PRO so it isn't overwritten by the !__config statement in the code.
Can't figure thwhy this code now won't assemble. Can any of you advise me why my code would run in PCB and won't assemble in PCB PRO??

Here is the current code as adapted from Bruce's "Non-Interrupt version" in his above post.


@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
i var Byte ' Indexer for use in For..Next loop
K CON 15 ' Calibration factor for flow meter = # pulses per gal

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

' A/D & Comparators disabled
ANSEL=0 ' all digital
ANSELH=0 ' analog module disabled
CM1CON0=0
CM2CON0=0
' Port setup
PORTA = 0 ' Clear the port register latches
PORTB = 0
PORTC = 0 ' LEDs off, PULSOUT RC3 provides a high-going pulse
' Set or clear the data direction registers
TRISA = %11111111 ' RA2 = TMR0 clock input for simulated meter pulse inputs
TRISB = %11111111
TRISC = %11110000 ' lower 4 pins outputs

'VRCON = %00000000 ' turns the Vref Module OFF by clearing bit 7, 6, 4
TMR0 = 0 ' clear TMR0 count

Main:
IF TMR0 < K THEN
' Keep the valve open...do nothing..let water flow
ELSE
PULSOUT PORTC.3,1000 ' Generate required 10 msec pulse to RC3..close valve
DEFINE WRITE_INT 1
WRITE 7, TMR0 ' write count if you need to during testing
TMR0 = 0 ' Clear timer count
For i = 1 to 3 ' Blink LED 3x to indicate valve turned off
HIGH PORTC.0
PAUSE 500
LOW PORTC.0
Next
ENDIF
GOTO Main ' Loop to Main to wait for next meter flow input

Bruce
- 17th May 2009, 18:02
The first error indicates you have not commented out the __config line if the 16F690.INC
file that's used with the MPASM assembler. Make sure you do before compiling if you insert
the MPASM @ __config directive in your code.

The remaining errors indicate it's not finding the Microchip P16F690.INC file, which defines
register locations/names.

Make sure your path statement includes information on where you have MPLAB installed, or
modify the 16F690.INC file to point directly to it.

INCLUDE "C:\Program Files\Microchip\MPASM Suite\P16F690.INC"

jellis00
- 18th May 2009, 00:15
"Make sure your path statement includes information on where you have MPLAB installed, or modify the 16F690.INC file to point directly to it."
I guess when I upgraded to PB Pro and installed it, MPLAB must have ended up in a different place. Thanks for catching this...I could have spent a long time looking and not thinking of this.
Now I have a different problem. Although I was going to try to do the counting with a NonInterrupt version of using the TMR0 overflow counter as you described above, I discovered as I progressed on my app design that I really need to do the counting with an interrupt and also another interrupt for checking on an external switch closure. I therefore am trying to use the below code where I have the interrupt handler doing two IF..THEN checks of the flag bits to handle either the TMR0 overflow while using RA2 input to TMR0 as switch for counting, or the RABIE on-change-interrupt for the RA3 input from a switch closure to ground. The TMR0 interrupt works in this code, however, the RABIE on-change-interrupt does not. I can't figure out why. Can you see whay the RABIE isn't working??


' -----[ Device Declaration ]----------------------------------------------
'
@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF

' -----[ Variables & Aliases Intitialization ]-----------------------------
'
led1 VAR PORTC.0 ' Set RC0 as LED indicator of valve open..water flowing
led2 VAR PORTC.1 ' Set RC1 as LED indicator of low battery
valve VAR PORTC.3 ' Set RC3 as valve solenoid open/close command
low_bat VAR PortA.0 ' Set RA0 as battery low power monitor
meter VAR PORTA.2 ' Set RA2 as input for Hall Sensor meter pulse Interrupt
flush VAR PORTA.3 ' Set RA3 as input for sensing flush switch closure Int
bat_mon VAR Byte ' bat_mon value when Vtrh multiplied by low_bat


' -----[ Constants Initialization ]----------------------------------------
'
k CON 10 ' Calibration factor for flow meter...# pulses per gal
i VAR Byte ' Index used in Gallon counter loop
Vthr CON 4 ' Low Battery Monitor threshold

' -----[ Initialization ]--------------------------------------------------
'
'EEPROM PRESETS
'DATA @0,0

'OSC DEFINE
'DEFINE OSC 4

' Setup Timer0 as an 8-bit counter with the clock input on RA2.
' 1:1 TMR0 prescaler
' TMR0 counts on high-to-low transitions
OPTION_REG = %00111000

'Register Settings
Init:
TRISA = %11111111 ' Set all PORTA pins to inputs...RA0, RA2 & RA3 are used
TRISB = %00000000 ' Set all PORTB and PORTC pins to outputs
TRISC = %00000000
PORTC = %00000000 ' Pre-set PORTC pins low, turning LEDs off
TMR0 = 256-K ' Preload TMR0 to overflow after k counts

'A/D & Comparators disabled
ADCON0 = %01110000 ' Set PORTA to digital I/O & FRC (clock derived from a
ADCON1 = %00000000 ' dedicated internal oscillator)
ANSEL=0 ' Set PortA to digital I/O
ANSELH=0 ' Analog module disabled
CM1CON0=0
CM2CON0=0
TRISC.3 = 0 ' Set RC3 as output port for valve latching solenoid control
Low Valve ' Initialize RC3 (valve) at Low value
TRISA.2 = 1 ' Set RA2 as input port for clock to TMR0
TRISA.3 = 1 ' Set RA3 as input port for sensing METER switch closure
High meter ' Initialize RA2 (meter) at High value for METER pulse inputs
' RA2 = TMR0 clock input for simulated meter pulse inputs
High flush ' Initialize RA3 (flush) at High value for flush interrupt

'Interrupts Settings
FLUSH_INT_FLAG VAR INTCON.0 ' RA3 (FLUSH) On-change-interrupt flag bit
TMRO_INT_FLAG VAR INTCON.2 ' Timer0 overflow flag bit
INTCON = %10101000 ' Enable global, TMR0 & RABIE (RA3 on-change-INT)
IOCA = %00000000 ' Enable RA3 as on-change-INT

' -----[ Main Code ]-------------------------------------------------------
'Set INT Handler
ON INTERRUPT GOTO Int_handler

'Start...normal code here
MAIN:
PORTC = %00000000 ' Turn all LEDs off
PAUSE 1
'SLEEP = 65,535 ' Put MC in Sleep state at power up
' Microcontroller is in Sleep State waiting for external FLUSH Interrupt
GOTO Main ' Loop to Main to wait for next Flush interrupt

DISABLE
Int_handler:
IF FLUSH_INT_FLAG = 1 Then ' Interrupt was from RA3 on change
DEFINE WRITE_INT 1
write 9, flush ' Write RA3 (FLUSH) value during testing
PULSOUT valve,1000 ' Generate required 10 msec pulse to RC3 to open valve
High led1 ' Light indicator that valve is open & water flowing
Low low_bat ' Simulate battery monitor input is low
'Put code here to Wakeup the Microcontroller

' Put code here to start a timer to run for 50 secs as a fail safe
' to prevent overflow of toilet tank in case of sensor failure.
'Goto Shutvalve
High flush ' Clear the interrupt
FLUSH_INT_FLAG = 0 ' Clear interrupt flag
Endif
IF TMRO_INT_FLAG = 1 then ' Interrupt was a TMR0 overflow..volume reached
PULSOUT valve,6000 ' Generate required 20 msec pulse to RC3..close valve
WRITE 5, TMR0 ' Write TMR0 value..remove comment for test only
bat_mon = low_bat * Vthr
Write 7, bat_mon ' Remove comment for test only
If bat_mon < Vthr Then
'Light the low battery monitor light
HIGH led2
ENDIF
TMR0 = 256-k ' Reload TMR0 to overflow after k counts
TMRO_INT_FLAG = 0 ' Clear overflow flag
ENDIF
LOW led1
Low led2
RESUME
ENABLE

' If the user program ends by getting to the last statement of the program
' at an END instruction, the MCU will SLEEP and await a wakeup.
END

jellis00
- 18th May 2009, 02:08
I discovered one of DT's posts that explained part of my problem was that I wasn't properly clearing the mismatch. When I did that the On-interrupt for RA3 worked. However, I noticed in the same DT post his statement "Keep in mind that you will get an interrupt on both the Press and Release of the button. You will eventually need to change the interrupt handler to determine which Edge occurred." I am using a momentary switch button that grounds RA3 for this On-interrupt and now I see happening what he was warning about...I get an intterupt on press AND release. However, I don't quite grasp how to modify my interrupt handler "to determine which Edge occurred." Obviously I want the interrupt to respond only to the press and not the release. Is there a way to filter out the release action to prevent the 2nd interrupt?

Archangel
- 22nd May 2009, 19:28
I discovered one of DT's posts that explained part of my problem was that I wasn't properly clearing the mismatch. When I did that the On-interrupt for RA3 worked. However, I noticed in the same DT post his statement "Keep in mind that you will get an interrupt on both the Press and Release of the button. You will eventually need to change the interrupt handler to determine which Edge occurred." I am using a momentary switch button that grounds RA3 for this On-interrupt and now I see happening what he was warning about...I get an intterupt on press AND release. However, I don't quite grasp how to modify my interrupt handler "to determine which Edge occurred." Obviously I want the interrupt to respond only to the press and not the release. Is there a way to filter out the release action to prevent the 2nd interrupt?
Page 37 of the data sheet, Option Reg allows you to control rising or falling edge on RA2, you might have to move your ports around a bit . . .

Bruce
- 22nd May 2009, 19:57
If your switch grounds the input pin to generate the interrupt, and it returns high when the
switch is released, just wait for the pin to return high before exiting the interrupt.

jellis00
- 19th June 2009, 04:52
By following your suggestion for basically debouncing it works. Thanks for advice!;)