Tachometer

General discussion on mikroPascal.
Author
Message
Charlie
Posts: 2744
Joined: 01 Dec 2004 22:29

#16 Post by Charlie » 14 Sep 2005 01:00

Hi Bob,

that did the trick.Thanks a lot.
Regards Charlie M.

Storic
Posts: 393
Joined: 01 Oct 2004 00:20
Location: Australia (S.A.)

#17 Post by Storic » 14 Sep 2005 01:01

I tried it and gote it to work(compile OK) :)

1st-ly I decided to create a directory for this as in the pass, I found that I had another director somewhere on my HDD the same as the one I was working on and saved files to this (i did it again when I first tried this file)

2nd-ly On the Procedure Initialize_LCD; LCD8_Config(PORTC,PORTD,6,4,5,7,6,5,4,3,2,1,0);got an error Expected 'end' but found ')', I replaced the line with Lcd8_Init(PORTB, PORTC); and All compiled OK

Andrew

Charlie
Posts: 2744
Joined: 01 Dec 2004 22:29

#18 Post by Charlie » 14 Sep 2005 01:11

Hi Storic,

Are you using Easypic3?
Regards Charlie M.

Storic
Posts: 393
Joined: 01 Oct 2004 00:20
Location: Australia (S.A.)

#19 Post by Storic » 14 Sep 2005 01:49

Yes I AM

wwwhelp
Posts: 33
Joined: 17 Jan 2005 13:11

#20 Post by wwwhelp » 14 Sep 2005 07:31

Thanks! I will try this code.

Charlie
Posts: 2744
Joined: 01 Dec 2004 22:29

#21 Post by Charlie » 14 Sep 2005 10:40

Hi storic,

The reason I ask Is I am having trouble getting the 8 bit Lcd configuration to work. I will try your Lcd init . Thanks
Regards Charlie M.

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Tach

#22 Post by Rotary_Ed » 14 Sep 2005 17:29

Charlie,

Its unlikely that my LCD initialization would work for you, unless you just happened to have your hardware wired exactly like mine. Since mine was developed for my own project board, it is not like on the EASYPIC board. Hopefully, someone will change the LCD initialization to be compatible with the Mikro boards.

Sorry 'bout that.

Apparently someone showed you how to create units, so I won't bother with that.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Bob Lawrence
Posts: 300
Joined: 18 Aug 2004 11:55
Location: Lwr Sackville, Nova Scotia, Canada

Use Lcd-Init

#23 Post by Bob Lawrence » 14 Sep 2005 18:14

Charlie,

You have the right idea. Configure port b for output and try the following

Procedure Initialize_LCD; //This must be tailored for your particular LCD set up
begin

//LCD8_Config(PORTC,PORTD,6,4,5,7,6,5,4,3,2,1,0); //RS,EN,RW Data Use in Real Fuel board Initialze LCD through PORTs

/// LCD8_Cmd(Lcd_Clear);//Clear LCD display

/// LCD8_Cmd(Lcd_Cursor_Off);//Turn visible cursor off

Lcd_Init(PortB);

end;
=======================================

Then change all the Lcd8 statements to Lcd such as:

LCD_OUT(1,1,TxtStr);

Anyway, it works for me. 8)

Charlie
Posts: 2744
Joined: 01 Dec 2004 22:29

#24 Post by Charlie » 14 Sep 2005 21:10

Rotery_Ed: write:
Its unlikely that my LCD initialization would work for you, unless you just happened to have your hardware wired exactly like mine. Since mine was developed for my own project board, it is not like on the EASYPIC board. Hopefully, someone will change the LCD initialization to be compatible with the Mikro boards.
Hello Ed,

I figured that your LCd configuration would'nt work so I tried the configuration as its printed on the Easypic3,but No luck. Thanks for the reply.

Hi Bob,

Thanks for the help.I will try your example and see what happens.
Regards Charlie M.

Charlie
Posts: 2744
Joined: 01 Dec 2004 22:29

#25 Post by Charlie » 14 Sep 2005 21:27

Hi Ed,

I finally got the code to work. Great Job.I had a question.Would it be possible to use timer1 and start and stop the timer at every rev. and use a lookup table to figure RPM? I guess one would have to predetermain the values for the lookup table.

Thanks again for the Great Code.:)
Regards Charlie M.

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Tach

#26 Post by Rotary_Ed » 15 Sep 2005 00:29

Actually, Charlie, what you propose using a Timer, is what the Tach_Acq unit does. If you go back and look and the procedure Initialize_Timer_CCP in the main module (Tach.ppas), you will find that I have do two things with timers. I set T3CON so that Timer 1 is the source clock for the CCP module. I then set T1CON (Timer 1 Control Register) so that it provides the time in 8 bits, set the prescaler to 1 and turn on timer 1.

Procedure Initialize_Timer_CCP;
begin

INTCON := $00; //Disable all Interrupts for initialization of other registers
T3CON := $00; //0000 0000 was $C0 Sets Timer1 as source clock for CCP1 and CCP2 leaves timer3 off
CCP2CON:= $06; //set for 4th rising edge, $07 Initially Set CCP2 for 16th Rising Edge Capture
T1CON := $01; //set for 8 bit time read, prescaler of 1 and turn timer 1 on
TMR1L := $00; //zero timer registers
TMR1H := $00;

end;


In the Tach_Acq unit, I have 4 varibles to capture the timer1 times. In the section of code where CASE = $06, two variables Pulse_HSL and Pulse_HSH captures the start time of the revolution period by capturing the time (provided by timer1) the CCP2 module detects the rising edge of a pulse (this time is provided by Timer 1 because that is the timer I selected - you could have selected timer 3 instead).

Pulse_HSL := CCPR2L; //Get captured pulse high start time low byte
Pulse_HSH := CCPR2H; //Get captured time high byte

so we have the start time

Then in CASE = $05 I have two varibles

Pulse_EL := CCPR2L; //Get time of second Rising Edge
Pulse_EH := CCPR2H;

These two variables captures the time of the second Rising edge of a pulse
which means the rotation period (rising pulse to rising pulse) has been completed.

Then using the Start time with Pulse_HL/HL and End time with Pulse_EH/EL, I simply subtract the start time from the end time which gives be the period of rotation. Then back in the main module I take this time (which in clock cycles/microcseconds) and convert it to Revolutions per Minute.

So, you see we are timing the pulse using the timer as you suggested. The timer is providing the event time in registers CCPR2L (low byte) and CCPR2H (high byte). You must save the time in your own varibles (as I did) because Timer1 will overwrite what ever was in CCPR2L/H from last event when the new event occurs.

Once you have the rotation period (time) it is much easier to do the simple calculation for RPM rather than have a Look up table, in my opinion.

However, you could probably use the ADC (analog Digital Conversion modules along with a timer to write code to do the same thing or even the Port B interrupts - so many ways is what makes it fun.

Hope this helps.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Charlie
Posts: 2744
Joined: 01 Dec 2004 22:29

#27 Post by Charlie » 15 Sep 2005 00:44

Hi Ed,

Thanks for putting it all together for me.The code works Great.:)
Regards Charlie M.

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

tach

#28 Post by Rotary_Ed » 15 Sep 2005 02:11

You're welcome, Charlie.

Playing/working with the PIC is a learning experience (as they say). They great thing about the PIC is its tremendous flexibility - the bad thing about the PIC is its tremendous flexibility (= complexity).

There are so many control registers and their individual bits (not always in obivious registers) to set or clear that I found it a pretty steep learning curve for my old brain. But, the more you work with it and learn it ( read, read, that data sheet on your chip {:>), the more you find you can do with it.

And of course, haveing Mikro Pascal is what made it possible for me. I was struggling with assembly and while I can sort-of write it - its hard and painful for me. Mikro Pascal is what made it possible for me to start building projects that I can use in my other hobbies.

Stick in there - its worth the effort.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

ghspirit
Posts: 22
Joined: 07 Oct 2004 10:25

Adaptation in MB but I've always 5585 like RPM???

#29 Post by ghspirit » 03 Oct 2005 14:52

Hello,
i've adapt the code to MB Can someone check it or say why i have always 5585 rpm??? I send info not by LCD but by USART(9600) and i use Pic 16F876 4 mhz:

program Tach

'Program measures the rotation period based on a pulse input and calculates RPM
'NOTE: Interrupt Procedure is NOT used as the CCP2 interrupt flag is set regardless
'of whether interrupt is enabled. Since the CCP2IF is checked in the Main repeat loop, there is no
'need for the MP3 Interrup Procedure.
'include "Tach_Acq" 'Determines rotation period time based on Timer TMR1
'Note this works for an 18F452 with a 4 Mhz crystal
'MP3 Default Configuration for 19F452 chip was used for chip configuration
'Note: 18F452 Chip is configured so that CCP2 is on pin RC1
'rather than RB3 __CONFIG _CONFIG3H_OFF
'Pulse train must be +5V (Pluse logic High) and 0 volts (Pulse Logic Low)

'Sub Procedure Initialize_LCD 'This must be tailored for your particular LCD set up
'
' LCD8_Config(PORTC,PORTD,6,4,5,7,6,5,4,3,2,1,0) 'RS,EN,RW Data Use in Real Fuel board Initialze LCD through PORTs
' LCD8_Cmd(Lcd_Clear) 'Clear LCD display
' LCD8_Cmd(Lcd_Cursor_Off) 'Turn visible cursor off
'
'End Sub

Sub Procedure Initialize_RS_232
USART_init(9600) ' Initialise RS232 communication
End Sub

Sub Procedure Initialize_Ports


'TRISD = $00 'Set all PORTD for output
'PORTD = $00
TRISC = 00000010 'TRISC = $02 ' 0000 0010 Set bit RC1 for CCP2 input, RC6,4,5(Rs/En/RW) LCD control Output
'Note: this may need to be changed to match your board wiring
End Sub

Sub Procedure Initialize_Timer_CCP

INTCON = $00 'Disable all Interrupts for initialization of other registers
'T3CON = $00 '0000 0000 was $C0 Sets Timer1 as source clock for CCP1 and CCP2 leaves timer3 off
CCP2CON = $06 'set for 4th rising edge, $07 Initially Set CCP2 for 16th Rising Edge Capture
T1CON = $01 'set for 8 bit time read, prescaler of 1 and turn timer 1 on
TMR1L = $00 'zero timer registers
TMR1H = $00

End Sub

'Sub Procedure Display_Title
' Dim Txtstr as char[16]
'
' TxtStr = " RPM READING " 'Displayed even when Tach pulse train is not ON
' LCD8_OUT(1,1,TxtStr)
'End Sub

Sub Procedure Display_RPM(Dim RPM as word)
Dim Txt as char[6]
Dim k as Byte
'Dim Txtstr as char[8]

Txt= "" 'Intialize Txt
'TxtStr= " RPM = " 'Displayed when Pulse train to CCP2 is active
'LCD8_OUT(2,1,Txtstr)
'LCD8_OUT(2,9,Txt)

Wordtostr(RPM,Txt)
USART_write(Txt)



End Sub

Sub Procedure ccp2_RPM(Dim Rot_P_H as byte,Dim Rot_P_L as byte)'CCP2_Fuel;

'This procedure is to measure the period of a pulse train to pin RC2.
' The rotation period of the engine is determined by the duration of pulse Low Logic + Pulse High Logic.

' Note: The procedure is set up to interrupt on the 16th rising edge of a pulse CCPXCON := 07

'**************************** Start of timing sequence *********************************************************
' <----------------------- 4th or 16th RE -----------_->
' '''''''''''| |'''''''''''| |''''''''''' '''''''| |'''''''
' |.......| |.......| |.......|
' 16thRE FE RE 16thRE Repeating
' start Time Stop Time

'****************************************************************************************************************



'*********************************************************************
'Note: 18F452 Chip is configured so that CCP2 is on pin RC1 rather than RB3 __CONFIG _CONFIG3H_OFF
'*********************************************************************

'The rising edge CCP2 capture may be set as either CCP2Con := $06 (every 4th rising edge) or
' CCP2Con := $07 (every 16th rising pules). Must also reset value in main pgrom in CCP2 Initialization procedure
'and CCP2_Call Procedure (where If statement signifies end of timeing sequence)
Dim Pulse_HSL as byte 'Hold Rise Edge time for start of timing sequence
Dim Pulse_HSH as byte
Dim Pulse_EL as byte 'Next Rising Edge for End of Time Sequence
Dim Pulse_EH as byte


'Start measurement with pulse going low (falling), end measurement with pulse going high (rising)
ClearBit(INTCON,GIE) 'clear GIE to prevent further interupts while handling this one

if TestBit(PIR2,CCP2IF) = 1 then 'Is it CCP2 Interrupt?
'Yes, it is CCP2 Interrup.
' The CASE section determines which code section processes the request, Start_Time, Fall_Edge or 2nd Rise_Edge

select case CCP2CON 'Note: CCP2CON := $06 (4th Rising edge) could also use $07 (16th rising edge)
case $06 'This STARTS TIMING SEQUENCE, get start time of every 4th rising edge - Leave and wait for next falling ($04) Edge of pulse train
'******* Captures Start time of pulse sequence (Rising edge *****************************************************=


Pulse_HSL = CCPR2L 'Get captured pulse high start time low byte *******Change back to CCPR1L *****
Pulse_HSH = CCPR2H 'Get captured time high byte

CCP2CON = $04 'Set to capture next Falling edge
ClearBit(PIR2,CCP2IF) 'Reset to preclude False Interrupt


case $04'This detects the falling edge simply to know to reset CCP2 module to intercept next Rising edge ($05)
'This is next falling edge of pulse, so reset for next rising edge($05 - which will end period measurement)
'All this does, on detection of the falling edge, is to reset the CCP2 module for next Rising Edge


CCP2CON = $05 'ReSet for Rising Edge Capture on next entry into this CCP2_RPM Routine
ClearBit(PIR2,CCP2IF) 'Clear in case of false interrupt when changin mode


case $05'This ENDS TIMING SEQUENCE
' 2nd Rising edge (1st after Fallin edge) so timing sequence is complete - calculate time internvals
'Find Rotation Period - Rot_P_X


Pulse_EL = CCPR2L 'Get time of second Rising Edge
Pulse_EH = CCPR2H


Rot_P_L = Pulse_EL - Pulse_HSL 'Calculate Rotation Time = Time Pulse HI + Time Pulse Lo
If TestBit(STATUS,C) = 0 then

Pulse_EH = Pulse_EH - 1
Rot_P_H = Pulse_EH - Pulse_HSH

CCP2CON = $06 'Set to start next timing cycle on 4th rising edge was $07 Set for 16th Rising edge Interrupt
ClearBit(PIR2,CCP2IF) 'Clear possible supurious Interrupt caused by changing CCP interrupt mode
end if

end select'case

end if ' end of IF Statement CCP2_Inj

end sub

Sub Procedure CCP2_Call 'Calls CCP2_RPM to get pulse interval of rotation period then calculates and displays RPM
Dim Rot_P_L as byte 'Bytes to hold rotation period time from CCP2_RPM
Dim Rot_P_H as byte
Dim R_Period as Word 'Holds rotation period time calculated
Dim RPM as word 'Holds RPM value calculated


Rot_P_L = 0'Variables for Rotation Period Time
Rot_P_H = 0
If testbit(PIR2,CCP2IF) = 1 then 'If CCP2 flag is set then pulse has triggered CCP2 module


ccp2_RPM( Rot_P_H,Rot_P_L) 'Calls to Data_Acq unit for pulse measurements
if (CCP2CON = $06) AND (CCP2IF = 0) then 'update viariable values after finished with entire time sequence

R_Period = 00
R_period = Word(Rot_P_H << 8) OR Rot_P_L 'combined hi and low byte of rotation period into word
RPM = 60000000 div R_Period 'Calculate RPM (period is in clock cycles this turns it into revs/min)
'Conversion value valid for a 4 Mhz oscillator frequency ONLY
Display_RPM(RPM) 'Displays RPM Data

end if 'If (CCP2CON =7 .....


ClearBit(PIR2,CCP2IF)'Clear ccp2 Flag for next cycle
end if

End Sub

Main: 'Main part of program
Initialize_Ports
'Initialize_LCD
Initialize_RS_232
Initialize_Timer_CCP
'Display_Title 'Display title of program on LCD

while TRUE 'Loop forever calling CCP2_Call to determine rotation period and calculate RPM

CCP2_call 'Call for Data and display RPM based on CCP2 module response to a pulse train

wend
end.

I have put all procedure and ccp2_RPM TOO in One Project!

Best Regards

Rotary_Ed
Posts: 756
Joined: 26 Dec 2004 23:10
Location: Matthews, NC, USA
Contact:

Tach Problem

#30 Post by Rotary_Ed » 03 Oct 2005 15:37

It appears there may be an error in this section of your code

R_Period = 00
R_period = Word(Rot_P_H << OR Rot_P_L combined hi and low byte of rotation period into word
RPM = 60000000 div R_Period 'Calculate RPM (period is in clock cycles this turns it into revs/min)
'Conversion value valid for a 4 Mhz oscillator frequency ONLY
Display_RPM(RPM) 'Displays RPM Data

end if 'If (CCP2CON =7 .....

Notice that the line R_Period = Word(Rot_P_H << OR Rot_P_L is not complete. The line should read
R_Period = Word(Rot_P_H << 8) OR Rot_P_L or its equivalent in MB. You line appears to be missing the "8" and parents ")" closing the shift statement. You may have the 8 in the code but it comes through the post as a smilie face, so I am not certain if the "8) is missing or not. But when I copy your code into my compiler the 8) does not show up. So check it out.
Rotary_Ed
Matthews, NC USA
Rv-6A N494BW Rotary Powered

Post Reply

Return to “mikroPascal General”