PDA

View Full Version : CCP and timers to capture frequency



boroko
- 1st October 2020, 08:54
Related to , but different aspect, of "PPS understanding on 16F15313"http://www.picbasic.co.uk/forum/showthread.php?t=24129. Figured a new thread naming the issue would be better.

This system receives pulses between 0 and 250Hz. I need to distinguish when it crosses above 45Hz and derive a count that I can use to generate a PWM based on the measured frequency. I don't need to measure below that frequency, just set a flag, so that the Main can still pulse when it has a capture. Basically, it monitors ECU tach pulses and each pulse generates a pulse out, no matter the frequency. Above 45Hz, it synthesizes an output that is related to pulse speed, but is not linear, so it must be generated.

Still not understanding of why I'm getting quite an unstable timer capture.

The thought is to let TMR1 roll over and check those (Overflow) and grab the remainder. If the preload is set so that it overflows below 45Hz, I can just ignore anything that overflows, and if no overflow, use the remainder to determine frequency in. I have not applied the preload of 22063 yet to TMR1 (1:1) as I can't even get it to read with any stability yet. Getting 0-2 overflows @45Hz and remainder all over the place. If this is this fragile in the striped down form, there's no way I'm going to be able to add needed code for the rest of it.

If you eagle-eyed members can see my error, or have a different way of doing this, I'd love to hear it.
Thank you
bo



'************************************************* ***************
'* Name : 324_CCP1_Test.pbp *
'* Date : 09/30/20 *
'* Notes : TEST using PPS and CCP1 *
'************************************************* ***************
'*THIS REV: timing erratic

INCLUDE "DT_INTS-16F18xx.bas" ; v1.20 Modified for 16F183xx: IOC INTs added for each pin.
INCLUDE "ReEnterPBP.pbp" ; Include for DT_INTS. ver 3.4

DEFINE OSC 8
PulseIn var PORTC.5 ' Monitor ECM tachometer signal
PulseFlag var byte ' register if CAPTURE Int was entered
Overflows VAR word ' count the times TMR1 overflows
Remainder VAR word ' remaining TMR1 ticks after last overflow
ANSELA = 0 ' Set all digital
ANSELC = 0
CCP1CON = %10000101 ' On, Capture every + edge
CCP1PPS = 00010101 ' set CCP1 input to RC5
'CCPTMRS = %01010101 ' ALL CCPS using TMR1 (already default)
'INTCON = %11000001
OSCEN = %01000000 ' HFINTOSC ENABLED
OSCFRQ = %00000100 ' 100:8mhZ, 101:12MHz, 110:16MHz
PORTA = %00000000 ' Outputs
PORTC = %00100000 ' Outputs except RC5 for Tach In input
TRISA = %00000000 ' Pins output
TRISC = %00100000 ' Outputs except RC5 for Tach In input
T1CON = %00000001 ' 1:1 prescale, clock=Fosc/4, TMR1=on
T2CON = %00000100 ' 1:1 PRE and POST, ON
'********* USART ************************************************** **
DEFINE HSER_RCSTA 90h ' Set receive register to receiver enabled
DEFINE HSER_TXSTA 20h ' Set transmit register to transmitter enabled
DEFINE HSER_BAUD 9600 ' Set baud rate
DEFINE HSER_SPBRG 25 ' Set SPBRG directly
HSEROUT ["324_CCP1_test",10,13]
pause 2000
;----[Interrupts]----------------------------------------
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler CCP1_INT, _Capture, PBP, yes ; WORKS
INT_Handler TMR1_INT, _Timer1, PBP, yes
endm
INT_CREATE ; Creates the High Priority interrupt processor
ENDASM
@ INT_ENABLE CCP1_INT ; enable Capture interrupts
@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts
Main:
IF PulseFlag = 1 THEN
' PULSOUT tachdrv, 50 '
HSEROUT ["OF= ",DEC Overflows," ,Ticks= ",DEC Remainder, 13,10]
PulseFlag = 0
Overflows = 0
PIR1.0 = 0 ' clear TMR1IF
ELSE
HSEROUT ["NoFlag", 13,10]
ENDIF
GOTO Main
'---[CCP1 - interrupt handler]------------------------------------------
Capture: ' Enter here with input Pulse (CCP1)
Remainder = TMR1
PulseFlag = 1 ' set flag to pulse out @ each +capture
PIR4.0 = 0 ' clear CCP1IF
@ INT_RETURN
''**** TMR *********
Timer1:
Overflows = Overflows + 1
@ INT_RETURN
END

boroko
- 1st October 2020, 10:26
I'm trying to base this on Tip #1 from http://ww1.microchip.com/downloads/en/DeviceDoc/41214a.pdf, but evidently I'm not turning the suggested steps into code very well.

richard
- 1st October 2020, 11:44
my old proteus can't sim that chip but a 16f1825 is ok

done like this the "remainder" is time between pulses in uS provided overflow is < 2








'************************************************* ***************
'* Name : 324_CCP1_Test.pbp *
'* Date : 09/30/20 *
'* Notes : TEST using 16F1825 *
'************************************************* ***************
'*THIS REV: timing perfect
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
__config _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG

INCLUDE "DT_INTS-14.bas" ;
INCLUDE "ReEnterPBP.bas" ; Include for DT_INTS. ver 3.4

DEFINE OSC 8
PulseIn var PORTC.5 ' Monitor ECM tachometer signal
PulseFlag var byte ' register if CAPTURE Int was entered
Overflows VAR word ' count the times TMR1 overflows
Remainder VAR word ' remaining TMR1 ticks after last overflow
lastcount VAR word
ANSELA = 0 ' Set all digital
ANSELC = 0
CCP1CON = %00000101 ' On, Capture every + edge

'CCPTMRS = %01010101 ' ALL CCPS using TMR1 (already default)
'INTCON = %11000001

OSCCON=$70


T1CON = %00010001 ' 1:1 prescale, clock=Fosc/4, TMR1=on
T2CON = %00000100 ' 1:1 PRE and POST, ON
'********* USART ************************************************** **
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 51 ' 9600 Baud @ 8MHz, 0.16%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator

HSEROUT ["324_CCP1_test",10,13]
pause 2000
;----[Interrupts]----------------------------------------
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler CCP1_INT, _Capture, PBP, yes ; WORKS
INT_Handler TMR1_INT, _Timer1, PBP, yes
endm
INT_CREATE ; Creates the High Priority interrupt processor
ENDASM
@ INT_ENABLE CCP1_INT ; enable Capture interrupts
@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts


Main:
IF PulseFlag = 1 THEN
' PULSOUT tachdrv, 50 '
HSEROUT ["OF= ",DEC Overflows," ,Ticks= ",DEC Remainder, 13,10]
PulseFlag = 0
Overflows = 0
PIR1.0 = 0 ' clear TMR1IF
ELSE
HSEROUT ["NoFlag", 13,10]
ENDIF
GOTO Main
'---[CCP1 - interrupt handler]------------------------------------------
Capture: ' Enter here with input Pulse (CCP1)
Remainder= TMR1 - lastcount
lastcount = TMR1
PulseFlag = 1 ' set flag to pulse out @ each +capture
@ INT_RETURN
''**** TMR *********
Timer1:
Overflows = Overflows + 1
@ INT_RETURN
END

boroko
- 1st October 2020, 12:26
Richard,

I had to change CCP1CON = %00000101 to CCP1CON = %10000101 to turn on the CCP, but it looks like it works a lot better than what I was trying.
I'll play with it a bit and see.

Sorry to keep asking questions, I feel like a dolt sometimes... :-)

Thanks
bo