16F877@4Mhz calculate Pulsin to RPM
OK, first things first I'm new to programming PIC's (although have been prgramming PC's etc for over 10 years now) and this is my first time out with PBP.
For reference I am using a 16F877 MCU running with a 4Mhz crystal and porting my information out via serial as I don't have an LCD or similar at present.
I've been trying for the past day or so to make a basic readout of
RPM based on an incoming square wave to pin B0.
I've got a 4500rpm signal coming in based on my cars crank angle sensor readout (4 pulses per rotation) and using the count function I can relate that back no problem (300 rps/4 * 60=4500rpm).
What I need to do though is count the pulses WITHOUT holding the MCU in a state of flux while the reading is being taken.
I've tried doing this with the pulsin command but I'm not sure I'm getting the right things back from it.
The pulse (in theory) should run high for 1/8 of a revolution and low for 1/8 of a revolution which signifies a quarter turn on the crank.
Currently if I count the pulse width using the pulsin command I get a result of 165 high and 168 low (using two pulsin commands, one for high one for low).
The area where I am getting stuck is how to convert this into a useable RPS value and therefore convert to RPM.
This has to be done fairly rapidly as the circuit I am designing will use this value to retard the timing on my car based on RPM and Airflow (Airflow is an easy 0-5v reference and can be read via an A/D input so no problems there). Obviously there will only be around 12-14 revs per second at idle raising to 125 at the engines redline of 7500RPM so it has to fit with a sample time of around 250ms I think (correct me if I'm wrong though!).
Can anyone offer any suggestions or code snippets for how I should go about the calculation - or even if there is a much simpler/more efficient wat of doing it.
One possibility I did think of is measuring the time between the pulses leading edges so I could get a time between the first pulse and the next and base the rps on that after multiplying by 4.
Thanks in advance.
Leigh Windridge
Re: 16F877@4Mhz calculate Pulsin to RPM
Hi Darrel Taylor
You said the ccp should work from 500 - 10,000 rpm. Please kindly advice how to measure rpm 0-10,000 rpm by use ccp module on [email protected] you have source code please show me. Thank you.
Re: 16F877@4Mhz calculate Pulsin to RPM
You'll need to count the timer overflows and use them as the high word of the period after a capture.
Then change all the math, because the values will be larger than 16-bits.
Since you are using an 877A, you won't have the luxury of using LONG variables.
Re: 16F877@4Mhz calculate Pulsin to RPM
Thank you for your advice but i still not clear please kindly show example about your advice above. For my program show as below
PIC16F877A
DEFINE OSC 4
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 2
Define LCD_EREG PORTD
Define LCD_EBIT 1
Low PORTE.2
PIE1.2=1
Symbol Capture = PIR1.2 ' CCP1 capture flag
T1 VAR WORD ' 1st capture value
PW VAR WORD ' 2nd capture value & ultimately final pulse width
intermediate VAR WORD
Dummyvar VAR WORD
rpm VAR WORD
TRISC.2 = 1 ' CCP1 input pin (Capture input)
INTCON = 0 ' Interrupts off
ReLoad:
CCP1CON = %00000101 ' Capture mode, 4capture on rising edge
T1CON = 0 ' TMR1 prescale=1, clock=Fosc/4, TMR1=off (200nS per count @20MHz)
TMR1H = 0 ' Clear high byte of TMR1 counter
TMR1L = 0 ' Clear low byte
T1CON.0 = 1 ' Turn TMR1 on here
Capture = 0 ' Clear capture int flag bit
While (!Capture) ' Wait here until capture on rising edge
Wend
' Rising edge detected / stuff Timer1 value in T1
T1.HighByte = CCPR1H
T1.LowByte = CCPR1L
CCP1CON = %00000100 ' Configure capture for falling edge now
Capture = 0 ' Clear capture interrupt flag bit
While !Capture ' While here until capture on falling edge
Wend
' Falling edge detected / stuff Timer1 value in PW
PW.HighByte = CCPR1H
PW.LowByte = CCPR1L
PW = PW-T1 ' High pulse width = PW-T1
intermediate = 60 * 1000 / 4 ' Compulsory !!!
' ( no "intermediate CON xxx" allowed )
' Disable interrupts ... if some used !!!
Dummyvar = 1000 * intermediate
rpm = DIV32 PW
' re-enable interrupts allowed
lcdout $fe,1,"TCH",$fe,$84,DEC RPM
GOTO ReLoad
END