View Full Version : Tachometer with Interrupts
serkanc
- 25th August 2009, 10:41
I tried to make a tachometer using RB0 and Timer1 interrupt. I simulated on ISIS with a Pulse generator... I choose 200mS from pulse generator, but on LCD it shows always different values. I cannot find the reason. Pls help...
DEFINE LCD_DREG PORTB' LCD Data Port
DEFINE LCD_DBIT 4 ' LCD Data Bit
DEFINE LCD_RSREG PORTA ' LCD RS Port
DEFINE LCD_RSBIT 0 ' LCD RS Bit
DEFINE LCD_EREG PORTA ' LCD Enable Port
DEFINE LCD_EBIT 1 'LCD Enable Bit
DEFINE LCD_BITS 4 ' LCD Data Bit Sayisi
DEFINE LCD_LINES 2 ' LCD Satir Sayisi
SONUC1 VAR WORD
SONUC2 VAR WORD
X VAR WORD ' 1mS
EK VAR WORD
PIE1.0=1 ' 1 = Enables the TMR1 overflow interrupt
TRISB.0=1
T1CON=%00000001 ' bit 7-6 Unimplemented - bit 5-4=00 1:1 Prescale value - bit 0= 1=Disables Timer1
OPTION_REG.7=1 ' 1 = PORTB pull-ups are disabled
OPTION_REG.6=1 ' 1 = Interrupt on rising edge of RB0/INT pin
INTCON.4=1 ' 1 = Enables the RB0/INT external interrupt
INTCON.6=1 ' 1 = Enables all unmasked peripheral interrupts
INTCON.7=1 ' 1 = Enables all unmasked interrupts
CMCON=7 ' Turn comparators off and enable pins for I/O functions
ON INTERRUPT GOTO KESME ' Kesme Durumunda Gidecegi Alt Yordam
x=0
Basla:
@NOP
goto basla
DISABLE
KESME:
IF PIR1.0 THEN
IF X<1000 THEN X=X+1
PIR1.0=0
endif
IF INTCON.1 THEN
SONUC2=TMR1H*256+TMR1L
SONUC2=SONUC2/1000
SONUC1=X**65535
X=DIV32 1000
sonuc2=SONUC2+X
LCDOUT $FE,1,DEC SONUC2," mS Passed"
INTCON.1=0
X=0
endif
RESUME
ENABLE
Acetronics2
- 25th August 2009, 11:26
Hi,
Use ASM interrupts ...
NOT PBP Interrupts
Alain
aratti
- 25th August 2009, 11:48
If you oscillator is wired as per your diagram it will not work!
Al.
serkanc
- 25th August 2009, 11:58
If you oscillator is wired as per your diagram it will not work!
Al.
I don't understand what you mean? Should I remove crystal on ISIS?
serkanc
- 25th August 2009, 12:13
Hi,
Use ASM interrupts ...
NOT PBP Interrupts
Alain
how to use ASM interrupts in PBP ?
fratello
- 25th August 2009, 12:15
Check this picture.
serkanc
- 25th August 2009, 12:23
Check this picture.
I see, but Crystal has no effect on Simulation. I wired it now correctly, but it gives again different values.
serkanc
- 25th August 2009, 12:27
I tried also with the command count
Count PortB.0,1000,Value, and it gives the correct value
Acetronics2
- 25th August 2009, 12:39
Hi,
Some " real world " ideas ...
http://www.usinages.com/compte-tours-t26.html
Alain
serkanc
- 25th August 2009, 12:58
I want to use this for my wind turbine...
Archangel
- 25th August 2009, 21:21
how to use ASM interrupts in PBP ?
Easiest way is use Darrel's Instant Interrupts
Charles Linquis
- 26th August 2009, 02:57
Tach input on any pin
Uses Darrel Taylor's Instant Interrupts
Fast, since is in ASM
This routine uses TMR0, but will work with any other unused timer.
To use -
Set interrupt period so that there will ALWAYS be an interrupt in the shortest
"high" or "low" period you want to measure. For example, if highest tach freq
is 100Hz and is a square wave, the period will be 10msec and the "high" part
of the square wave will be 5msec and the "low" period will be 5msec. In this case
the interrupt period should be 5msec minimum - choose 4 msec or less (must be a
little less than 5msec to cover interrupt latency). If the tach frequency is higher
or the input is not a square wave, you will have to increase the interrupt rate
accordingly.
In your main PBP routine - Clear TachCounter,ShaftCounter1,ShaftCounter2,Shaftcount erX.
Then clear PeriodDone. The routine will count for 1000 interrupts. When you want to
read the tachs, check if PeriodDone bit 0 is set - if it is, then the count is finished.
Move the ShaftCounters into PBP variables, Clear the shaftcounters and clear PeriodDone.
The cycle repeats and runs totally in the background.
You will have to mutliply the ShaftCounter variables by a value determined by
the tachometer and interrupt rate to get actual RPM.
The code can probably be improved, but it works for me.
Asm
ReadTachs
movlw 0xEC ; Reload TMR0 with your own value - sets INT rate - see explanation above
movwf TMR0H ; Load the high byte first
movlw 0x7E ; Load the low byte
movwf TMR0L
btfss PeriodDone,0 ; Check to see if counting period is over
bra CheckTach
bra DoneForNow
infsnz TachCounter ; 16 bit counter
incf TachCounter + 1
movlw 0x03 - 1 ; 1000 = 0x3E8, but must have one less
cpfsgt TachCounter + 1 ; to compare with greater than (choose a different number if you like)
bra FanRoutine
movlw 0xE8 - 1 ; Again, subtract one
cpfsgt FanCounter
bra MainRoutine
bsf PeriodDone,0 ; Set the PERIOD Done lsbit
clrf TachCounter ; Clear the counter
clrf TachCounter+ 1
bra DoneForNow
MainRoutine
movf PORTB,0,0 ; Load all of Port B
movwf Temp,0 ; Copy it into TEMP for safety
xorwf OldPortB,0,0 ; XOR it with previous read
movwf changedB,0 ; Move the XORed byte into variable
movff Temp,OldPortB ; Move Temp to OldPortB
movf PORTC,0,0 ; Do the same for PORTC (or any port with a tach input)
movwf Temp,0
xorwf OldPortC,0,0
movwf changedC,0
movff Temp,OldPortC
movf PORTD,0,0
movwf Temp,0
xorwf OldPortD,0,0
movwf changedD,0
movff Temp,OldPortD
Shaft1
btfss changedB,0 ; Read in the bit - if it changed from last read it will be a "1"
bra Shaft2 ; It hasn't changed, so go to next
infsnz Shaft1Counter ; Increment the counter lowbyte
incf Shaft1Counter+1 ; If necessary, increment the high byte
Shaft2
btfss changedC,1 ; This shaft tach is fed into PORTC.1
bra Shaft3
infsnz Shaft2Counter
incf Shaft2Counter+1
; Put more shaftcounters here if you need them.
DoneForNow
bcf INTCON,2 ; Clear the TIMER0 interrupt flag
INT_RETURN
ENDASM
serkanc
- 26th August 2009, 14:54
Thanks for help.. I tried to write codes with CCS C, it's very simple.. Asm codes are difficult for me.. So it works without any problem. If someone needs I can paste the codes..
naga
- 27th August 2009, 09:59
Thanks for help.. I tried to write codes with CCS C, it's very simple.. Asm codes are difficult for me.. So it works without any problem. If someone needs I can paste the codes..
Please paste the code,would love to see.. Regards.
serkanc
- 28th August 2009, 08:10
#include <16F628A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) #FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES MCLR //Master Clear pin enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or
#FUSES NOCPD //No EE protection
#use delay(clock=4000000)
#define LCD_DATA_PORT getenv("SFR:PORTB")
#define LCD_ENABLE_PIN PIN_A1
#define LCD_RS_PIN PIN_A0
#define LCD_RW_PIN PIN_A2
#define LCD_DATA0 PIN_B4
#define LCD_DATA1 PIN_B5
#define LCD_DATA2 PIN_B6
#define LCD_DATA3 PIN_B7
#define LCD_TYPE 2
#include <lcd.c>
long suretmp;
long sure;
#int_EXT
void EXT_isr(void)
{
suretmp=sure;
sure=0;
set_timer0(0);
}
#int_TIMER2
void TIMER2_isr(void)
{
sure++;
}
void main()
{
long devir;
int i;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_1,99,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator( OSC_4MHZ );
lcd_init();
enable_interrupts(INT_EXT);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
while(1)
{
for(i=0;i<250;i++)
{
delay_us(2);
}
lcd_gotoxy(1,1);
devir=600000/suretmp;
if((600000%suretmp)>(suretmp/2))
devir++;
printf(lcd_putc,"%Lu mS Passed",suretmp);
printf(lcd_putc,"\n%Lu RPM",devir);
}
}
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.