PDA

View Full Version : Incoming Pulse Monitoring code - comments and suggestions welcome



jamie_s
- 4th March 2007, 02:22
Hi,

I've been working on a project that looks at an incoming pulse which is a 50% duty cycle and varying between 0 to 400hz.

This project is using the instant interrupts routines to do all its work.

The pic basically needs to invert the incoming pulse and put it back out of a port, however, If theres no incoming pulse for around 1.5 or more seconds, then the pic needs to generate approx 15 Hz on the same output port, until the incoming pulse is restored, then it will output the inverted incoming pulse back on the output.

On the scope it seems to work upto about 2kHz which is more than enough speed for my purpose.

Anyway here is my code, any comments or suggestions are welcome (sorry about the formatting, it did look ok in MPLAB)



'------------------------------------------------
' Pulse Monitor
' PIC16F628A @ 4mhz
'
'
' Input Signal Port B.3
' Output Signal Port B.5
'------------------------------------------------


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


CMCON = 7 ' set portA to digital
TRISA = %00100000 ' Port A all output but MCLR
TRISB = %00001000 ' Port B all output but 3 (CCP)
T1CON = %00110000 ' Set Timer 1, Off and 1/8 prescale (fire every 520ms)
T2CON = %00000011 ' Set Timer 2, Off and 1/16 prescae (fire every 4ms)
Symbol Capture = PIR1.2 ' CCP1 capture flag
T1count VAR BYTE ' Timer 1 count (1 count = 0.52 sec)
i VAR BYTE ' i is the incrementer for the pulse generator

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler CCP1_INT, _gotpulse, PBP, yes
INT_Handler TMR1_INT, _nospeed, PBP, yes
INT_Handler TMR2_INT, _generate, PBP, yes

endm
INT_CREATE ; Creates the interrupt processor

INT_ENABLE TMR1_INT ; enable timer1 interrupts (CCP timer)
INT_ENABLE CCP1_INT ; enable CCP port change interrupt
INT_DISABLE TMR2_INT ; enable timer2 interrupts (pulse generator)
ENDASM



Low portb.5 ' start with Portb.5 low
T1count = 0 ' set variable
i = 0 ' set variable

CCP1CON = %00000100 ' Capture mode, capture on falling
T1CON.0 = 1 ' Turn TMR1 on here


MainLoop:

pauseus 20
GOTO MainLoop

END


'================================================= ======================================

'---[CCP1 - interrupt handler - We got an input Pulse] ---------------------------------

gotpulse:

If CCP1CON.0 = 0 then ' if we captured a falling edge, switch to rising edge
CCP1CON.0 = 1
else
if CCP1CON.0 = 1 then ' if we captured a rising edge, switch to a falling edge
CCP1CON.0 = 0
endif
endif

Portb.5 = Portb.3 ^ $0F ' Output PortB.5 = inverted state of Portb.3

TMR1H = 0 ' Clear high byte of TMR1 counter
TMR1L = 0 ' Clear low byte
@ INT_DISABLE TMR2_INT ' disable timer0 interrupts (pulse generator)
T2CON = %00000011 ' Set Timer 2 Off prescale 1/16

@ INT_RETURN



'================================================= ======================================

'---[TMR1 - interrupt handler - Called when CCP Timer Overflows @ 520ms] ---------------
nospeed:

T1count = T1count + 1 ' increment every 520ms

If T1count >= 3 then ' no pulses for 1560ms, start generating them
T2CON = %00000111 ' Set Timer 2 prescale 1/16 and on
Low portb.5 ' start with portb.5 low
@ INT_ENABLE TMR2_INT ' enables timer0 interrupts (TMR0 fires on Overflow)
T1count = 0 ' reset the TMR1 count
endif

TMR1H = 0 ' Clear high byte of TMR1 counter
TMR1L = 0 ' Clear low byte


@ INT_RETURN


'================================================= =========================================

'---[TMR2 - interrupt handler - This will fire every 4ms]----------------------------------
' send a 20ms pulse every (12 *4ms) 48ms, gives a frequency of ~ 15hz
generate:

i = i + 1 ' increment tmr2 count

if i => 12 then ' equal to or more than 12, send a pulse
pulsout portb.5,2000 ' 20ms pulse out
i = 0 ' wait another 12+ cycles
endif


@ INT_RETURN

Darrel Taylor
- 4th March 2007, 06:14
Hi jamie,

It's nice to see more examples with Instant Interrupts popping up. :)

I think using the CCP to generate an interrupt on every transition of the Input is slowing things down.

If you handle the "Input to Inverted Output" in the main loop, It should go alot faster than 2khz.
Then the interrupts can just handle the timer overflows.

Here's a possibility ...
'------------------------------------------------
' Pulse Monitor
' PIC16F628A @ 4mhz
'
'
' Input Signal Port B.3
' Output Signal Port B.5
'------------------------------------------------


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


CMCON = 7 ' set portA to digital
TRISA = %00100000 ' Port A all output but MCLR
TRISB = %00001000 ' Port B all output but 3 (CCP)
T1CON = %00110000 ' Set Timer 1, Off and 1/8 prescale (fire every 520ms)
T2CON = %00000011 ' Set Timer 2, Off and 1/16 prescae (fire every 4ms)
T1count VAR BYTE ' Timer 1 count (1 count = 0.52 sec)
i VAR BYTE ' i is the incrementer for the pulse generator

InPIN VAR PORTB.3 ' Input Pin
OutPIN VAR PORTB.5 ' Output Pin
TMR1ON VAR T1CON.0
TMR2ON VAR T2CON.2
LastState VAR BIT

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

INT_ENABLE TMR1_INT ; enable timer1 interrupts (CCP timer)
INT_ENABLE TMR2_INT ; enable timer2 interrupts (pulse generator)
ENDASM


Low OutPIN ' start with Output LOW
T1count = 0 ' set variable
TMR1H = 0 ' Clear high byte of TMR1 counter
TMR1L = 0 ' Clear low byte
i = 0 ' set variable
TMR1ON = 1 ' Turn TMR1 on here


'================================================= ======================================
'---[MainLoop handles the Inverted transfer From InPIN to OutPIN] ----------------------
MainLoop:
if InPIN <> LastState then ' If Input State Changed
LastState = InPIN
TMR2ON = 0 ' Stop Timer 2
OutPIN = LastState ^ 1 ' Output = inverted state of Input
TMR1H = 0 ' Clear high byte of TMR1 counter
TMR1L = 0 ' Clear low byte
T1count = 0
endif
GOTO MainLoop

'================================================= ======================================
'---[TMR1 - interrupt handler - Called when Timer1 Overflows @ 520ms] ------------------
nospeed:
T1count = T1count + 1 ' increment every 520ms

If T1count >= 3 then ' no pulses for 1560ms, start generating them
TMR2ON = 1 ' Set Timer 2 on
T1count = 0 ' reset the TMR1 count
endif
@ INT_RETURN

'================================================= =========================================
'---[TMR2 - interrupt handler - This will fire every 4.103ms]------------------------------
' send a 20ms pulse every (12 * 4ms) 48ms, gives a frequency of ~ 15hz
generate:
i = i + 1 ' increment tmr2 count

if i < 12 then ' Pin is low for 1-11
OUTPIN = 0
else
OutPin = 1 ' Pin is high for 5 ints (20ms)
endif
If i = 17 then i = 0 ' restart cycle, total = 69.751ms = 14.3hz
@ INT_RETURN

mystified
- 13th September 2008, 17:38
capture
ansel0=%00000000 'all digital
trisa=%11111111 'set all port a pins to input cap1,cap2,cap3
trisb=%00000000 'set all port b pins as output

t1 var word
t2 var word
t3 var word

Capture1 var pir3.1 ' tmr5 value was capture by the active edga on capl input
Capture2 var pir3.2 'interrupt flag for pin cap2
Capture3 var pir3.3 'interrupt flag for pin cap3

' auto time base reset, capture on rising to falling edge
RiseToFall CON %01000111
' auto time base reset, capture on falling to rising edge
FallToRise CON %01000110
false con 0
true con 1

'capture mode
intcon =0 'interrupts off
tmr5h = 0 'clean high byte of tm5 counter
tmr5l = 0 'clean low byte
t5con = %00000001 ' prescale 1:1, int clock, tmr5 =on


cap1con=%01000111 ' enable caputure,pulse width measurement mode,
'every rising o falling edge
cap2con=%01000101
cap3con=%01000101

Capture1 = false 'rest caputer flag
Capture2 = false
Capture3 = false
main :
if (Capture1=true)and(capture2=true)and(capture3 = true) then
high portb.7
endif


end
if (Capture1=true)and(capture2=false)and(capture3 = true) then
high portb.6
endif
goto main

mystified
- 13th September 2008, 17:40
need help with 3-input caputer transtion detector