12F683 interrupt on change improvement?


+ Reply to Thread
Results 1 to 7 of 7
  1. #1
    Join Date
    Jan 2009
    Location
    Huntsville, AL
    Posts
    41

    Default 12F683 interrupt on change improvement?

    I have a project using three 12F683s controlled by a 16F883 master. The goal of the project is to track the RPM of 4 independant propellers on a quadcopter using an IR photodiode and emitter (i.e. a beam breaker). When the propeller blade crosses between the IR photodiode and emitter, the voltage at the interrupt pin drops to ~0.7V (a 3.3k resistor to GND). When the blade moves out of the way, the voltage at the interrupt pin increases to ~4.8V. The IR setups for the 16F883 and the 12F683s are effectively identical (same wire lengths, same IR components, resistors, etc). The 16F883 drives an 8Mhz xtal osc with the osc2 pin tied to the osc1 pins of the 12F683s (short distance). The 16F883 starts the process and takes a pin high that tells the 12F683s to start logging data. The 16F883 also begins logging data. I opted to use 4 PICs as the props can spin around 9000RPM, which is ~300 interrupts per second (2 blades per prop) and I'm not sure how I'd get it to work with interrupts occuring that frequently and occasionally falling on top of each other.

    My problem is that the 12F683s are not that reliable and the data is poor, however the 16F883 seems to be logging the blade interrupts great. Below are 2 examples of a 25 second run:

    Name:  883.jpg
Views: 7
Size:  37.5 KB
    Name:  683.jpg
Views: 7
Size:  70.0 KB

    As is apparent, the 883 is doing great, but the 12F683s are not (data from all 12F683s is similar). The IR max and min voltages are meeting the high/low logic requirements (0.7V low, 4.8V high) and the IR setups are effectively the same for all 4 PICs, so I'm wondering if there's some register or code modification I can do to improve the 12F683 interrupts? Or is this more of a hardware issue between the 16F883 and 12F683?

    Below is the code for the 12F683 PICs. The code and interrupt for the 16F883 is similar (identical interrupt routine in fact). Thanks in advance for any help or suggestions!
    Dave

    Code:
    'PIC-12F683
    #CONFIG
    __config _FOSC_EC & _WDT_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _CPD_OFF &_FCMEN_OFF &_IESO_OFF 
    #ENDCONFIG 
    
    DEFINE OSC 8
    
    'Initialize Regsters:
    TRISIO =%101111 'I or O; MCLR is pin3
    CMCON0 = 7 'Analog comparators off
    ADCON0 = 0
    ANSEL = 0 'all inputs digital, the adcin command automatically converts it to analog
    CCP1CON=%00000000 'disable PWM mode
    IOC=%00000100
    OPTION_REG=%11000000 ' Interrupt on rising edge INTEDG bit, disable internal pullups
    
    'pins and variables
    EE_DAT     var GPIO.1
    EE_CLK     var GPIO.0                                              
    INT_PIN    VAR GPIO.2
    MODEPIN    VAR GPIO.3  'MCLR
    OUTPIN     VAR GPIO.4  'OUTPIN also hooked up to an LED
    
    wsave       var    byte $20 SYSTEM
    wsave1      var    byte $A0 SYSTEM
    pausetime1  var    word
    pausetime2  var    word
    hbfix       var    byte
    ibit        var    bit
    n           var    byte
    wconfig     var    byte
    address     var    word
    wbit        var    bit
    
    INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
    INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
    
    ASM
    INT_LIST macro ; IntSource, Label, Type, ResetFlag?
    INT_Handler GPC_INT, _PULSE_WIDTH, PBP, yes
    endm
    INT_CREATE ; Creates the interrupt processor
    ENDASM
    
    @ INT_DISABLE GPC_INT ; disable external (INT) interrupts      
    
    wconfig=%10100000
    
    'At 8Mhz with 1:1 prescaler 
    T1CON = %00000000 ' Prescaler = 1:1, timer off
    
    low OUTPIN
    pause 500
    
    waitforstart:
    OUTPIN=INT_PIN  'toggles LED on OUTPIN to make sure IR sensor is reading high (clear) or low (blade in the way)
    if MODEPIN=1 then waitforstart
    
    high OUTPIN
    wbit=0 'initial write bit setting to make sure eeprom is written every other interrup
    TMR1H = 0
    TMR1L = 0
    ibit=0
    address=0
    @ bsf     T1CON, TMR1ON   ' Start timer
    @ INT_ENABLE GPC_INT ; enable external (INT) interrupts
    
    main:
    if MODEPIN=1 then waitforstart
    if ibit=0 then main
    @ INT_DISABLE GPC_INT ; disable external (INT) interrupts
    if pausetime2.lowbyte=0 then pausetime2.highbyte=hbfix
    if wbit=1 then                   
    I2CWRITE EE_DAT,EE_CLK,wconfig,address,[pausetime1,pausetime2]
    endif
    pausetime1=pausetime2  
    address=address+2 'effectively adding 4 to address between eeprom writes
    if address=0 then done  'if 0 at this point, rollover of address has occured and eeprom is full
    wbit=~wbit
    ibit=0
    @ INT_ENABLE GPC_INT ; enable external (INT) interrupts
    goto main
    
    done:
    input EE_CLK
    input EE_DAT
    low OUTPIN
    pause 10
    if MODEPIN=0 then done
    
    goto waitforstart
    
    '---[INT - interrupt handler]---------------------------------------------------
    PULSE_WIDTH:     
    pausetime2.highbyte = TMR1H
    pausetime2.lowbyte  = TMR1L
    hbfix = TMR1H
    ibit=1
    @ INT_RETURN
    
    end

  2. #2
    Join Date
    Jan 2009
    Location
    Huntsville, AL
    Posts
    41


    Did you find this post helpful? Yes | No

    Default Re: 12F683 interrupt on change improvement?

    I had thought - should I be using "INT_INT" instead of "GPC_INT"? It is set up using GPIO.2 as the interrupt pin, which is the dedicated INT pin per the datasheet. Can you set up an interrupt on GPIO.2 as you would any of the other viable GPIOs OR as the dedicated external interrupt? Looking at the INTCON register, seems like you can set bit 3 (GPIE) for any GPIO interrupt or bit 4 (INTE) specific to GP2/INT? Seems to compile OK with "INT_INT"...? I'm trying to understand the differences if they are both viable methods to set it up?

  3. #3
    Join Date
    May 2013
    Location
    australia
    Posts
    2,702


    Did you find this post helpful? Yes | No

    Default Re: 12F683 interrupt on change improvement?

    should I be using "INT_INT" instead of "GPC_INT"?
    i would



    you are not using IOC correctly since the gpio is never read in the isr to clear the change condition


    4.2.3 INTERRUPT-ON-CHANGE
    Each of the GPIO pins is individually configurable as an
    interrupt-on-change pin. Control bits IOCx enable or
    disable the interrupt function for each pin. Refer to
    Register 4-5. The interrupt-on-change is disabled on a
    Power-on Reset.
    For enabled interrupt-on-change pins, the values are
    compared with the old value latched on the last read of
    GPIO. The ‘mismatch’ outputs of the last read are OR’d
    together to set the GPIO Change Interrupt Flag bit
    (GPIF) in the INTCON register (Register 2-3).
    This interrupt can wake the device from Sleep. The
    user, in the Interrupt Service Routine, clears the
    interrupt by:
    a) Any read or write of GPIO. This will end the
    mismatch condition, then,
    b) Clear the flag bit GPIF.
    A mismatch condition will continue to set flag bit GPIF.
    Reading GPIO will end the mismatch condition and
    allow flag bit GPIF to be cleared. The latch holding the
    last read value is not affected by a MCLR nor
    Brown-out Reset. After these resets, the GPIF flag will
    continue to be set if a mismatch is present.
    Warning I'm not a teacher

  4. #4
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    173


    Did you find this post helpful? Yes | No

    Default Re: 12F683 interrupt on change improvement?

    Hi Dave,

    How clean is the output from your photodiode?
    I have been working on a similar setup recently using an encoder wheel and photointerrupter.
    I had greater success feeding the MCU's input pin via a schmitt-trigger buffer (SN74LVC1G17 or similar).

    I hope this helps.

    Cheers
    Barry

  5. #5
    Join Date
    Jan 2009
    Location
    Huntsville, AL
    Posts
    41


    Did you find this post helpful? Yes | No

    Default Re: 12F683 interrupt on change improvement?

    Yep, that did it! The output is now as smooth as the 16F883's output. The 16F883 used the INT_INT interrupt from the start. The GPC_INT requires the particulars you noted, and additionally it interrupts on rising or falling edges (new to me). I had only use INT_INT before prior to this application, but encountered problems when I tried it on a 12F629 switching to the GPC_INT, which I later switched to the 12F683 but kept the GPC_INT in error.

    Thanks for the comment!
    Dave

  6. #6
    Join Date
    May 2013
    Location
    australia
    Posts
    2,702


    Did you find this post helpful? Yes | No

    Default Re: 12F683 interrupt on change improvement?

    There are less complicated ways i think


    Code:
    'PIC-12F683#CONFIG
      __config _FOSC_EC & _WDT_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _CPD_OFF &_FCMEN_OFF &_IESO_OFF 
    #ENDCONFIG 
    
    
    DEFINE OSC 8
        DEFINE DEBUG_REG GPIO
        DEFINE DEBUG_BIT 0      
        DEFINE DEBUG_BAUD 9600
        DEFINE DEBUG_MODE 0 
    
    
    'Initialize Regsters:
    TRISIO =% 101110 'I or O; MCLR is pin3
    CMCON0 = 7 'Analog comparators off
    
    
    ANSEL = 0 'all inputs digital, the adcin command automatically converts it to analog
    
    
    
    
    OPTION_REG=% 11000000 ' Interrupt on rising edge INTEDG bit, disable internal pullups
    
    
    'pins and variables
                                                 
    INT_PIN    VAR GPIO.2
    OUTPIN     VAR GPIO.4  'OUTPIN also hooked up to an LED
    
    
    wsave       var    byte $20 SYSTEM
    wsave1      var    byte $A0 SYSTEM
    time1       var    word  
    time2       var    word  
    bvars       var    byte  
    ibit        VAR    bvars.0     ; TIME BEGIN
    wbit        VAR    bvars.1     ; TIME DONE
    
    
    INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
    INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
    
    
    ASM
    INT_LIST macro ; IntSource, Label, Type, ResetFlag?
     INT_Handler INT_INT, _PULSE_WIDTH, PBP, yes
     endm
     INT_CREATE ; Creates the interrupt processor
    ENDASM
    
    
       
    
    
    
    
    GPIO.0  = 1    ;DEBUG
    
    
    
    
    T1CON = $10 ' Prescaler = 2:1, off
    
    
    low OUTPIN
    pause 200
    debug "ready",13 
    high OUTPIN
    INTCON=$80   ; CLEAR INTF
    @ bsf     T1CON, TMR1ON   ' Start timer
    @ INT_ENABLE INT_INT ; enable external (INT) interrupts
    
    
    main:
        if wbit then 
            @ INT_DISABLE INT_INT ; disable external (INT) interrupts
            time1 = time2 - time1
            DEBUG #TIME1,13          ;  prints out cycle count
             ;time1 = time2  
            ibit=0
            wbit=0
            OUTPIN = !OUTPIN
            @ INT_ENABLE INT_INT ; enable external (INT) interrupts
        endif
    goto main
    
    
    
    
    
    
    '---[INT - interrupt handler]---------------------------------------------------
    PULSE_WIDTH: 
        if  ibit=1   then  
            time2.highbyte = TMR1H
            time2.lowbyte  = TMR1L
            wbit=1
        else
            time1.highbyte = TMR1H
            time1.lowbyte  = TMR1L
            ibit=1
        endif
    @ INT_RETURN
    end
    Last edited by richard; Today at 03:53.
    Warning I'm not a teacher

  7. #7
    Join Date
    Jan 2009
    Location
    Huntsville, AL
    Posts
    41


    Did you find this post helpful? Yes | No

    Default Re: 12F683 interrupt on change improvement?

    The output is pretty clean in my experience. I use my photodiode in photoconductive mode (reverse bias), which makes it faster and supposedly noisier but I haven't noticed any noise except in some applications (I note below). The response time seems to be plenty fast in the applications I've used it.

    If I were to give a couple suggestions for a similar beambreaker using a photodiode, here's what I would suggest:
    • Use it in photoconductive mode for speed
    • You want a good IR source that's not a constraint on your design, so make sure you're getting a strong output from the IR emitter. I typically use something like 500 ohm resistors for mine, which means I'm pushing about 8mA from 5V (~1.2V fwd voltage for the diode). You can go higher, but 500 ohms seems to work for me. Fun fact: you can make sure they're working (or not burned out) by using your cell phone camera, which is filtered for human vision but some near IR gets through and shows up as a hazy purple aura around the LEDs.
    • I'd recommend using a potentiometer to ground on the output of the photodiode unless you've already played around with it and know what resistance you need. Getting the voltage low enough to trigger low when it's not exposed, and then high enough to trigger high when it is exposed can take some tweaking. A resistance range on the order of 2k-10k seems to work for me most of the time.
    • Distance between the photodiode and emitter is a big factor. In my applications, they are typically 1" to 6" apart. So take my suggestions with a grain of salt depending on how far your photodiode is from your emitter.
    • If you're photodiode is anywhere near a motor, then shield the wires, make them twisted pairs, put a faraday cage around the motor, and/or verbally threaten the motor. A powered motor will create a lot of EMI that the wires from the photodiode can pick up and will generate a LOT of noise and false high/low triggers. I made an inertial dynamometer to test some motors for drones, and data from some of the larger motors were initially unusable. Making the wires as short as possible, twisting them, wrapping the wires in foil, adding distance between the motor and photodiode wires, and changing the orientation of the motor with respect to the wires fixed it for me.

    Hope that helps!
    Dave

Similar Threads

  1. Help with PORTB Interrupt On Change Please
    By Aussie Barry in forum PBP3
    Replies: 2
    Last Post: - 11th September 2017, 11:57
  2. ADC and Interrupt on Change
    By RossWaddell in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 26th June 2016, 01:37
  3. Code Improvement
    By gadelhas in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 2nd December 2010, 02:38
  4. RB Change Interrupt understanding
    By PickyBiker in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 13th April 2010, 15:48
  5. Interrupt On Change - question
    By kevj in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 13th July 2008, 00:20

Members who have read this thread : 3

You do not have permission to view the list of names.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts