Using a 16F877A to measure engine rpm. I have a rpm simulator that connects to a racing ignition system and fires a test plug. The simulator has two outputs, one will fire the ignition system and the other is just a simple square wave. When I use the following Pulsin code I get good data using the square wave and also when making sparks.
When I use the interrupt code I get data that matches the simulator but I get some problems when I create a spark. Once in a while on my LCD I see the correct value however most of the time I get data that is extremely high. What can I do to fix this deal? Initially I was thinking it was purely hardware so I put a 0.1uf cap on the output of the opto-isolator that connects to the RPM pin. It really didn't solve the problem. I have the standard caps on the VDD of the PIC. I am pulling the RPM pin high with a 10k resistor and using the opto to ground the pin. Any ideas?Code:DEFINE OSC 20 RPM var word period var Word HRPM var word LRPM var word RPM_Total VAR Word LCD VAR PortC.6 'LCD output RPMInput var PortC.2 Prefix con $FE ' needed before each command LcdCls CON $51 ' clear LCD (use PAUSE 5 after) CursorPS con $45 'Cursor Position loop: Pulsin RPMInput, 0, LRPM PULSIN RPMInput, 1, HRPM RPM_Total = HRPM + LRPM RPM = 1000 RPM = RPM * RPM RPM = DIV32 RPM_Total ' 1,000,000 / Pulse_Total RPM = RPM * 60 ' Per minute RPM = Div32 8 ' 4 pulses per rev pause 100 SEROUT2 LCD,84, [Prefix,CursorPS,0,"RPM ",dec5 RPM] goto loop
Code:DEFINE OSC 20 Prefix con $FE ' needed before each command LcdCls CON $51 ' clear LCD (use PAUSE 5 after) CursorPS con $45 'Cursor Position Capture VAR PIR1.2 ' CCP1 capture flag Overflow VAR PIR1.0 ' Timer1 overflow flag RPM var word period var Word LCD VAR PortC.6 'LCD output CCP1CON = %00000110 ' Enable the CCP1 capture, every 4th rising edge pause 50 SEROUT2 LCD,84, [Prefix, LcdCls] pause 50 SEROUT2 LCD,84, [Prefix,CursorPS,0,"**** ",#RPM, " ", #Period] pause 200 loop: T1CON = %00100000 ' TMR1 prescale=1:2 Timer OFF '11 = 1:8 prescale value '10 = 1:4 prescale value '01 = 1:2 prescale value '00 = 1:1 prescale value TMR1H = 0 ' Zero the Timer TMR1L = 0 capture = 0 Start: IF capture = 0 Then goto Start ' Wait here for the first capture endif T1CON.0 = 1 ' Start the Timer capture = 0 ' Reset the capture flag CaptureLoop: IF capture = 0 Then goto CaptureLoop ' Wait here until captured endif period.lowbyte = CCPR1L ' Store the captured value in period.highbyte = CCPR1H ' period variable period = period / 2 RPM = 10000 RPM = RPM * RPM ' 100,000,000 RPM = DIV32 period ' 100,000,000 / RevCount RPM = RPM * 60 ' Per minute RPM = DIV32 400 RPM = (RPM /10)*25'+25 pause 100 SEROUT2 LCD,84, [Prefix,CursorPS,0,"RPM ",dec5 RPM, " ", #Period] gosub cleartimer1 GoTo loop ' Do it forever ClearTimer1: IF (capture = 0) Then goto cleartimer1 ' Wait for beginning of next period endif TMR1L = 0 ' Clear Timer1 low register TMR1H = 0 ' Clear Timer1 high register capture = 0 ' Clear capture flag overflow = 0 ' Clear overflow flagReturn return




Bookmarks