+ Reply to Thread
Page 1 of 2
1 2 Last
Results 1 to 15 of 18

Thread: Pic Micro RPM Counter using both Interrupt TM1 and On Interrupt (RB0)

  1. #1
    mesamune80 Newbie
    Join Date
    Oct 2004
    Location
    Malaysia
    Posts
    117

    Default Pic Micro RPM Counter using both Interrupt TM1 and On Interrupt (RB0)

    Hi All,

    Recently i am doing a fast speed (1000~4000) RPM counter using a motor's shaft with a plate and 12 slot evenly distributed on the plate.The plate is placed between a OMRON photomicrosensor EE-SX 671 .so that i can get a ON OFF signal (rising edge) when a slot is slice through the sensor.
    but this idea don know really can work or not because when test with low speed (500) this work fine .but when the speed is as fast as 3000 RPM then my system can't detect the speed anymore.Does Anyone has any idea?
    Thanks.


  2. #2
    kchriste Excellent kchriste Excellent kchriste Excellent kchriste Excellent kchriste Excellent kchriste Excellent kchriste Excellent kchriste Excellent kchriste Excellent
    Join Date
    Jul 2006
    Location
    Victoria BC, Canada
    Posts
    3,681

    Default

    when test with low speed (500) this work fine .but when the speed is as fast as 3000 RPM then my system can't detect the speed anymore.Does Anyone has any idea?
    You need to do one (or more) of the following in order of probability:
    1: Optimize/debug your code.
    2: Use a timer/counter in the PIC for counting pulses/measuring period.
    (OOppps Just looked at the subject line! )
    3: Increase the PICs clock speed.
    Your pulse rate at 3000 RPM with a 12 slot wheel should only be around 600Hz which the PIC should have no problem counting even in polled mode. Why are you using two interrupts? You should be able to do it with just one. Are you multiplexing a display at the same time or some other task? Maybe post a schematic of your circuit and the code.
    Last edited by kchriste; 19th December 2006 at 04:23 AM.
    Inside every little problem, is a big problem trying to get out.

  3. #3
    mesamune80 Newbie
    Join Date
    Oct 2004
    Location
    Malaysia
    Posts
    117

    Wink

    For your information i am using timer one interrupt to act as a counter(measuring period) and On interrupt external interrupt ,rising edge detection for RB0 to count the slotted wheel while slicing through the sensor.
    Microcontroller i am using:PIC16F877 4MHZ

    This is the picbasic compiler i am using:
    http://oshonsoft.com/pic.html

    This is the sensor i am using :
    http://oeiwcsnts1.omron.com/pdfcatal.nsf/0/3D4B80C095EC4F4886256C5600712077/$File/D21EESX4700902.pdf?OpenElement

    this is the code:
    Dim interrupt_count As Byte
    Dim timeroffset As Word
    Dim tmroffset As Word
    Dim count1 As Word 'RB0 interrupt count

    EEPROM 21, 0, 0, 0, 0,

    TRISA = %0000000
    TRISC = 0
    OPTION_REG.6 = 1 'RB0/INT edge triggered (Rising)
    OPTION_REG.7 = 0 ' PORTB pull up enabled by individual port latch value
    INTCON.INTE = 0 'External interrupt for RB0 disable!
    INTCON.7 = 1 'Global interrupt enabled!

    Symbol t1ck0 = T1CON.4 ' Timer1 Input Clock Prescale Select bits
    Symbol t1ck1 = T1CON.5 ' Timer1 Input Clock Prescale Select bits
    Symbol sensor = PORTD.0 'sensor
    'WaitMs 3000
    Define LCD_LINES = 2
    Define LCD_CHARS = 8
    Define LCD_BITS = 4 'allowed values are 4 and 8 - the number of data interface lines
    Define LCD_DREG = PORTB
    Define LCD_DBIT = 4 '0 or 4 for 4-bit interface, ignored for 8-bit interface
    Define LCD_RSREG = PORTB
    Define LCD_RSBIT = 1
    Define LCD_EREG = PORTB
    Define LCD_EBIT = 3
    Define LCD_RWREG = PORTB 'set to 0 if not used, 0 is default
    Define LCD_RWBIT = 2 'set to 0 if not used, 0 is default

    Lcdinit
    WaitMs 2 'wait For lcd To start
    Lcdcmdout 0x0e 'Underline cursor on
    Lcdcmdout LcdClear
    Lcdcmdout LcdLine1Home
    Lcdout "RPM" 'Clear LCD display
    Lcdcmdout LcdLine2Home
    Lcdout "Ver1.0"

    timeroffset = 15535 ' interrput occurs every 50 ms(0.05sec)
    t1ck0 = 0 'prescaler 1:1 selected
    t1ck1 = 0

    PIE1.0 = 1 'enable TMR1 interupts
    INTCON.6 = 1 'enable all unmasked interrupts
    INTCON.7 = 1 'enable Global interrupts
    PIR1.0 = 0 'reset interupt flag
    T1CON.0 = 0 'stop the timer
    TMR1H = timeroffset.HB 'timersethigh 'load a start up value into the timer
    TMR1L = timeroffset.LB 'timersetlow
    T1CON.0 = 1 'start the timer
    INTCON.INTE = 1 'External interrupt for RB0 enable!

    main:

    end

    On Interrupt

    If INTCON.1 = 1 Then 'RB0 External interrupt count!
    count1 = count1 + 1
    Write 21, count1.LB
    Write 22, count1.HB
    INTCON.INTF = 0 'RB0 External Interrupt flag bit cleared!
    Endif

    If PIR1.0 = 1 Then 'TMR1F - Timer 1 overflow interrupt flag bit ;1=overflow
    INTCON.INTE = 0 'External interrupt for RB0 disable!

    T1CON.0 = 0 'stop the timer

    TMR1H = timeroffset.HB 'timersethigh 'load a start up value into the timer
    TMR1L = timeroffset.LB 'timersetlow
    PIR1.0 = 0 'reset TMR1 interupt flag

    interrupt_count = interrupt_count + 1 'timer 1 interrupt count
    If interrupt_count = 20 Then '1 sec elapsed!

    interrupt_count = 0
    Gosub menu1
    count1 = 0
    Write 21, count1.LB
    Write 22, count1.HB
    T1CON.0 = 1 'start the timer
    INTCON.INTE = 1 'External interrupt for RB0 enable!
    Endif
    Endif

    T1CON.0 = 1 'start the timer
    INTCON.INTE = 1 'External interrupt for RB0 enable!

    Resume 'return back to where set timer was called
    Enable 're enable interrupts

    menu1:
    Lcdcmdout LcdClear
    Lcdout "RPM"
    Lcdcmdout 0xc0
    Lcdout "RPM:" 'count

    Gosub update1

    Return

    update1:
    Read 21, count1.LB
    Read 22, count1.HB

    Lcdcmdout LcdLine2Pos(5)
    count1 = count1 * 5 '12 slot used (1 minute Total count)
    Lcdout #count1 ' RPM
    Return


    what my program going to do is at 1st it will start the 0.05 sec timer,and RB0 will start generating pulse while the wheel is rotating ,so after 2 times timer overflow which is 1 sec the total number of slot passing through the sensor since the timer was started is now being stored and display to the LCD.the LCD will refresh almost every sec i can said.This process is repeated........
    Anyone has any idea can share with me and the others ,after study my code above.So fell free to share anything ok! Enjoy ur Day!

  4. #4
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,792

    Default

    You appear to be writing the values to EEPROM. This is very slow.

    Set up a new variable such as CountCopy and replace
    Write 21, count1.LB
    Write 22, count1.HB

    With
    CountCopy = count1

    and then just use CountCopy in your update routine.

    Whoops, I just noticed you read from the EEPROM back into count1. Don't copy CountCopy into count1, just use CountCopy instead of count1 in the update routine.

    HTH

    Mike.
    Edit, I just noticed that you do everything on interrupt. You need to change your code so that the interrupt just counts pulses and your main code updates the LCD etc.
    Last edited by Pommie; 19th December 2006 at 06:14 AM.

  5. #5
    mesamune80 Newbie
    Join Date
    Oct 2004
    Location
    Malaysia
    Posts
    117

    Default

    I see ,now i try and modify the code and test it .Thanks for sharing.
    GoodDay!

  6. #6
    mesamune80 Newbie
    Join Date
    Oct 2004
    Location
    Malaysia
    Posts
    117

    Default

    i just tested the new modified code with my hardware ,but i found out that when i start the wheel in a differnt position then the result will be different,for instance when i start up the wheel with a slot is in between the sensor which will give high to my uC then when i start the wheel at about 3000 RPM it looks just like the sensor is keeping ON,then my LCD shown 500 for my RPM +_+.And another case is when i start up with no slot between the sensor when i start the wheel the sensor seem to be not ON at all!!!and of course my LCD shown RPM:0 while the whell is rotating in 3000+ RPM =_=
    What is the reason behind this ?
    And Pommie ,how do i manage to change my code so that only waiting for interrup,and i though my routine for updating the LCD is out of the interrupt routine?Please help me!!! >_< Thanks.

  7. #7
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,792

    Default

    I don't know the compiler that you are using but your code should do something like this pseudo code,

    Code:
    On Interrupt
        if RB0int
            CountCopy=Count
            Count=0
        if Timer1int
            Count=Count+1
    end interrupt
    
    Main
        if CountCopy=0 then goto Main
        Display CountCopy
        CountCopy=0
        goto Main
    
    HTH

    Mike.

  8. #8
    William At MyBlueRoom Newbie
    Join Date
    Feb 2006
    Location
    Toronto, Canada
    Posts
    721

    Default

    Maybe the BASIC is too slow. Might need to learn a little C or assembler.
    Bill
    Home of the
    Firefly PIC Tutor
    Inchworm ICD2

    http://www.blueroomelectronics.com

  9. #9
    mramos1 Excellent mramos1 Excellent mramos1 Excellent mramos1 Excellent
    Join Date
    Sep 2005
    Location
    Boynton Beach, Florida USA
    Posts
    2,254

    Default

    I use BASIC.. If I can not do the task in BASIC, I use assembler. There is no C for me, it is the same as basic when you are using microcontrollers.

    There is easy code and real code. Basic/C or assmbler. Just my thought.
    Last edited by mramos1; 21st December 2006 at 10:42 AM.

  10. #10
    mesamune80 Newbie
    Join Date
    Oct 2004
    Location
    Malaysia
    Posts
    117

    Default

    how about if i use a faster crystal oscillator? Can the speed be improve?
    Let say i use 20MHZ instead of 4MHZ (which i am using now) a instruction cycle will take 200ns to accomplish instead of 1us.This definately will help right?

  11. #11
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,792

    Default

    Using a faster crystal may help but your biggest problems are,

    You are writing (and reading back) to EEPROM and writing to the LCD in your interrupt service routine. Both these things have a long wait before they finish. I'm assuming your interrupt start with the "on interrupt" instruction and ends at the resume instruction.

    If I had to guess what your code would be, it would be something like,

    Code:
    Dim interrupt_count As Byte
    Dim timeroffset As Word
    Dim tmroffset As Word
    Dim count1 As Word 'RB0 interrupt count
    Dim countcopy As Word
    
    TRISA = %0000000
    TRISC = 0
    OPTION_REG.6 = 1 'RB0/INT edge triggered (Rising)
    OPTION_REG.7 = 0 ' PORTB pull up enabled by individual port latch value
    INTCON.INTE = 0 'External interrupt for RB0 disable!
    INTCON.7 = 1 'Global interrupt enabled!
    
    Symbol t1ck0 = T1CON.4 ' Timer1 Input Clock Prescale Select bits
    Symbol t1ck1 = T1CON.5 ' Timer1 Input Clock Prescale Select bits
    Symbol sensor = PORTD.0 'sensor
    'WaitMs 3000
    Define LCD_LINES = 2
    Define LCD_CHARS = 8
    Define LCD_BITS = 4 'allowed values are 4 and 8 - the number of data interface lines
    Define LCD_DREG = PORTB
    Define LCD_DBIT = 4 '0 or 4 for 4-bit interface, ignored for 8-bit interface
    Define LCD_RSREG = PORTB
    Define LCD_RSBIT = 1
    Define LCD_EREG = PORTB
    Define LCD_EBIT = 3
    Define LCD_RWREG = PORTB 'set to 0 if not used, 0 is default
    Define LCD_RWBIT = 2 'set to 0 if not used, 0 is default
    
    	Lcdinit
    	WaitMs 2 'wait For lcd To start
    	Lcdcmdout 0x0e 'Underline cursor on
    	Lcdcmdout LcdClear
    	Lcdcmdout LcdLine1Home
    	Lcdout "RPM" 'Clear LCD display
    	Lcdcmdout LcdLine2Home
    	Lcdout "Ver1.0"
    
    	timeroffset = 15535 ' interrput occurs every 50 ms(0.05sec)
    	t1ck0 = 0 'prescaler 1:1 selected
    	t1ck1 = 0
    
    	PIE1.0 = 1 'enable TMR1 interupts
    	INTCON.6 = 1 'enable all unmasked interrupts
    	INTCON.7 = 1 'enable Global interrupts
    	PIR1.0 = 0 'reset interupt flag
    	T1CON.0 = 0 'stop the timer
    	TMR1H = timeroffset.HB 'timersethigh 'load a start up value into the timer
    	TMR1L = timeroffset.LB 'timersetlow
    	T1CON.0 = 1 'start the timer
    	INTCON.INTE = 1 'External interrupt for RB0 enable!
    
    main:
    	If countcopy=0 then goto main
    	gosub menu1
    	countcopy=0
    	goto main
    
    On Interrupt
    	If INTCON.1 = 1 Then 'RB0 External interrupt count!
    		count1 = count1 + 1
    		INTCON.INTF = 0 'RB0 External Interrupt flag bit cleared!
    	Endif
    	
    	If PIR1.0 = 1 Then 'TMR1F - Timer 1 overflow interrupt flag bit ;1=overflow
    		T1CON.0 = 0 'stop the timer	
    		TMR1H = timeroffset.HB 'timersethigh 'load a start up value into the timer
    		TMR1L = timeroffset.LB 'timersetlow
    		PIR1.0 = 0 'reset TMR1 interupt flag
    	
    		interrupt_count = interrupt_count + 1 'timer 1 interrupt count
    		If interrupt_count = 20 Then '1 sec elapsed!	
    			interrupt_count = 0
    			Gosub menu1
    			countcopy=count1
    			count1 = 0
    			T1CON.0 = 1 'start the timer 
    		Endif
    	Endif
    	
    Resume 'return back to where set timer was called
    	
    
    menu1:
    	Lcdcmdout LcdClear
    	Lcdout "RPM"
    	Lcdcmdout 0xc0
    	Lcdout "RPM:" 'count
    
    	Gosub update1
    
    	Return 
    
    update1:
    	Lcdcmdout LcdLine2Pos(5)
    	countcopy = countcopy * 5 '12 slot used (1 minute Total count)
    	Lcdout #countcopy ' RPM
    	Return
    
    Mike.

  12. #12
    mesamune80 Newbie
    Join Date
    Oct 2004
    Location
    Malaysia
    Posts
    117

    Default

    No i try to not use EEPROM and i use countcopy to count the interrupt

    like this:
    Dim interrupt_count As Byte
    Dim countcopy As Word
    Dim count_10_interrupts As Byte
    Dim timeroffset As Word
    Dim tmroffset As Word
    Dim count1 As Word 'RB0 interrupt count

    TRISA = %0000000
    TRISC = 0
    OPTION_REG.6 = 1 'RB0/INT edge triggered (Rising)
    OPTION_REG.7 = 0 ' PORTB pull up enabled by individual port latch value
    INTCON.INTE = 0 'External interrupt for RB0 disable!
    INTCON.7 = 1 'Global interrupt enabled!

    Symbol t1ck0 = T1CON.4 ' Timer1 Input Clock Prescale Select bits
    Symbol t1ck1 = T1CON.5 ' Timer1 Input Clock Prescale Select bits
    Symbol sensor = PORTD.0 'sensor

    'WaitMs 3000
    Define LCD_LINES = 2
    Define LCD_CHARS = 8
    Define LCD_BITS = 4 'allowed values are 4 and 8 - the number of data interface lines
    Define LCD_DREG = PORTB
    Define LCD_DBIT = 4 '0 or 4 for 4-bit interface, ignored for 8-bit interface
    Define LCD_RSREG = PORTB
    Define LCD_RSBIT = 1
    Define LCD_EREG = PORTB
    Define LCD_EBIT = 3
    Define LCD_RWREG = PORTB 'set to 0 if not used, 0 is default
    Define LCD_RWBIT = 2 'set to 0 if not used, 0 is default

    Lcdinit
    WaitMs 2 'wait For lcd To start
    Lcdcmdout 0x0e 'Underline cursor on
    Lcdcmdout LcdClear
    Lcdcmdout LcdLine1Home
    Lcdout "RPM" 'Clear LCD display
    Lcdcmdout LcdLine2Home
    Lcdout "Ver1.0"

    PORTC.1 = 1 'dir of movement
    PORTC.0 = 1 'output Enable for stepper driver
    timeroffset = 15535 ' interrput occurs every 50 ms(0.05sec)
    t1ck0 = 0 'prescaler 1:1 selected
    t1ck1 = 0


    PIE1.0 = 1 'enable TMR1 interupts
    INTCON.6 = 1 'enable all unmasked interrupts
    INTCON.7 = 1 'enable Global interrupts
    PIR1.0 = 0 'reset interupt flag
    T1CON.0 = 0 'stop the timer
    TMR1H = timeroffset.HB 'timersethigh 'load a start up value into the timer
    TMR1L = timeroffset.LB 'timersetlow
    T1CON.0 = 1 'start the timer
    INTCON.INTE = 1 'External interrupt for RB0 enable!

    main:

    End

    On Interrupt

    If INTCON.1 = 1 Then 'RB0 External interrupt count!
    count1 = count1 + 1
    countcopy = count1
    'Write 21, count1.LB
    'Write 22, count1.HB
    INTCON.INTF = 0 'RB0 External Interrupt flag bit cleared!
    Endif

    If PIR1.0 = 1 Then 'TMR1F - Timer 1 overflow interrupt flag bit ;1=overflow
    INTCON.INTE = 0 'External interrupt for RB0 disable!

    T1CON.0 = 0 'stop the timer

    TMR1H = timeroffset.HB 'timersethigh 'load a start up value into the timer
    TMR1L = timeroffset.LB 'timersetlow
    PIR1.0 = 0 'reset TMR1 interupt flag

    interrupt_count = interrupt_count + 1 'timer 1 interrupt count
    If interrupt_count = 20 Then

    interrupt_count = 0
    Gosub menu1
    count1 = 0
    countcopy = count1
    T1CON.0 = 1 'start the timer
    INTCON.INTE = 1 'External interrupt for RB0 enable!
    Endif
    Endif
    T1CON.0 = 1 'start the timer
    INTCON.INTE = 1 'External interrupt for RB0 enable!

    Resume 'return back to where set timer was called
    Enable 're enable interrupts


    menu1:
    Lcdcmdout LcdClear
    Lcdout "RPM"
    Lcdcmdout 0xc0
    Lcdout "RPM:" 'count
    Gosub update1

    Return

    update1:

    Lcdcmdout LcdLine2Pos(5)
    countcopy = countcopy * 5 '12 slot used (1 minute Total count)
    Lcdout #countcopy ' RPM

    Return

  13. #13
    Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent Oznog Excellent
    Join Date
    Apr 2004
    Location
    Austin, Tx
    Posts
    2,766

    Default

    Yeah I can't follow BASIC exactly but if you use the EEPROM, not only is it far too slow but it's also got a limited rewrite endurance. If you write it a lot (like millions, check your spec sheet) the memory location will be permanently damaged and unusable. That won't happen in the life of the product if you only use it for something like configuration data or even backing up the timeclock every couple of minutes. Writing many times a sec can realistically exceed the write endurance specification long before the product's expected life is met.
    I thought what I'd do was I'd pretend I was one of those deaf-mutes.

  14. #14
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,792

    Default

    I give up. You need to work your way through some tutorials.

    Merry Xmas,

    Mike.

  15. #15
    mesamune80 Newbie
    Join Date
    Oct 2004
    Location
    Malaysia
    Posts
    117

    Default

    i already try out the code but it seem high speed "cannot be detect" may be i should try to use different crystal.at low speed i connect a motor to +5VDC and i get the correct RPM displayed 571 ,but after i connect the motor to +12VDC the motor spin even faster than before,and i got a false displayed at my LCD.which is 505 .

+ Reply to Thread
Page 1 of 2
1 2 Last

Tags for this Thread