Need 4 modes with just 3 switches - need all modes to be selectable QUICKLY!


Closed Thread
Results 1 to 40 of 68

Hybrid View

  1. #1
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    What's the purpose of diodes D2-D4 and their connection to RA2, please?

  2. #2
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Mike, K8LH View Post
    What's the purpose of diodes D2-D4 and their connection to RA2, please?
    RA2 (pin 17) on a 16F690 is the external interupt pin. So when a switch is pressed, RA2 is grounded & an interupt occurs - I then check in the interupt subroutine to see which of the three 'switch' connected pins was actually pressed (ie which one of the three switch pin also went low) - the diodes isolate the 'switched' ground from the other two pins not pressed.

    It essentially allows you to implement three physical pins (or more) to be 'psuedo'-interupt pins (vs just the one ext interupt that the 16f690 has)

    All credit to forum members on this thread for filling me in on how to do it....

    http://www.picbasic.co.uk/forum/show...9900#post89900

    Quote Originally Posted by Kamikaze47 View Post
    Ahh, right. I was assuming you were setting that pin high. Makes sense now.
    RA2 (pin 17) is set high...but high via an internal weak pullup (at the risk of teaching grannie to suck eggs, note the lack of the word 'resistor' on the end of that phrase - apparently not a resistor, but some silicon junction internal to the PIC providing the resistance here)

    Just for the record, any similar noobs like me, who may find this thread via a search, here are the 16F690 register settings needed to bring the weak pullups into play (obviously change the 1 & 0s of wht WPUA & WPUB registers to suit your own external connections)

    Code:
    OPTION_REG.7 = 0         'enable weak pullups.
    WPUA         = %00000110  'activate weak pullups on RA1 & RA2.
    WPUB         = %01100000  'activate weak pullups on RB5 & RB6.
    Last edited by HankMcSpank; - 6th August 2010 at 18:41.

  3. #3
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    The schematic I drew in the thread you linked to above used a PIC without all the extra interrupt inputs, so it has switches ORed to 2 interrupt pins.

    The 16F690 you're using has IOC for all 3 of your switch inputs. So you could get rid of the diodes if you want to save parts & realestate on your board.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  4. #4
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    That's what I thought you might be doin' (OR'ing active lo switch signals to trigger INT). As Bruce mentioned, using IOC might be a better option.

    Is there some compelling reason you're using interrupts for the switches instead of just polling them at regular intervals?

    Also, I re-read your original post and see where you said you don't have physical space for four switches so I apologize for not paying attention...
    Last edited by Mike, K8LH; - 6th August 2010 at 19:41.

  5. #5
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Hi Bruce,

    I'd not investigated IOC, cos I wasn't sure how to implement! (like I say - n00b alert!) I like the idea of saving 3 x diodes worth of pcb space!

    So, would it go something like thus....

    Code:
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
        INT_Handler    IOC_INT,  _Switch_Interupt,   PBP,  yes  
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    @   INT_ENABLE   IOC_INT     ; Enable 'Int On Change' interrupts
    ********************************************************************
    
    (main body of code)
    
    '********************************************************************
    Switch_Interupt:
    
    if portB.4 = 0 then  mode = 1
    if portB.5 = 0 then  mode = 2
    
    blah blah...
    
    @ INT_RETURN
    Quote Originally Posted by Mike, K8LH View Post
    That's what I thought you might be doin' (OR'ing active lo switch signals to trigger INT).

    Is there some compelling reason you're using interrupts for the switches instead of just polling them at regular intervals?
    Nothing other than wanting my unit's 'mode' to change the instant a switch is pressed. (what originated this thread, was I'd noticed that even holding a button down for a mere 200ms - to determine say mode 3 or mode 4 from one switch - seemed like a lifetime when playing a guitar, so polling three switches is just not gonna cut it - my code uses a whole heap of pauses in the main body of the program, this would hinder such polling)
    Last edited by HankMcSpank; - 6th August 2010 at 19:30.

  6. #6
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    Hank',

    Thanks. I think I understand your concerns and constraints. Best of luck on your project Sir.

    Cheerful regards, Mike

  7. #7
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    I think what you want here is RABC_INT. So:
    Code:
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
        INT_Handler    RABC_INT,  _Switch_Interupt,   PBP,  yes  
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
     
    @   INT_ENABLE   RABC_INT     ; Enable 'Int On Change' interrupts
    Note: Your schematic is wrong with pins 11 & 12 shown as RB2 & RB3. These should be RB6 & RB5 respectively. So;
    Code:
    Switch_Interupt:
     
    if portB.4 = 0 then  mode = 1
    if portB.5 = 0 then  mode = 2
    Should be;
    Code:
    Switch_Interupt:
     
    if portB.6 = 0 then  mode = 1
    if portB.5 = 0 then  mode = 2
    if porta.2 = 0 then ? whatever ' this is the interrupt pin on RA.2
    Or, of course, you can use RA.1 as shown in your schematic for this interrupt pin. Either will work the same since they both have IOC (interrupt-on-change) functionality, and internal pull-ups.

    Note I have not used DT_INTs on this PIC type with interrupt-on-change, but that should get you going. I'm sure Darell will jump in here, and correct me if I'm wrong, but I think that's what you're looking for.

    But, I HAVE used his DT_INTs for our 4-digit & 6-digit serial LED displays, and I most certainly can vouch for them working spot-on, and making life a lot easier for us mere mortals...

    I've also used DT_INTs in several commercial applications, and had ZERO problems - so a huge thanks to DT for all the hard work, and sharing his routines with us.
    Last edited by Bruce; - 6th August 2010 at 21:34. Reason: BIG thanks to DT
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  8. #8
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Bruce ....you're good, like *really* good!

    You spotted my Eagle Part mistake - I failed to declare it, because it's been there for a while & I get used to it....my actual code does reference the right port names! (I need to go back into my Eagle part I created and change the text for those pins....not sure if you've ever had to make your own device/parts in Eagle - fit's not pretty!)

    Quick question - if IOC stands for interupt on change(?), then the 'change' in this scenario will be the pin going from 1 to 0...this will generate an interupt - but what happens when the switch is released (since it's another 'change', then in theory another interupt?!) now I'm sure this is catered for with a rising/falling edge setting in some register but I thought I'd ask!

    Even though the term gets a little over used nowadays ...guys like yourself, DT (& others who've helped me here - a list too long to mention), really do make a difference

    Already, after your recent input - the 3 diodes have already been whipped out on my schematic & I've now just that little bit more pcb real estate to arrange the board layout more to my liking....so a a genuine thanks.
    Last edited by HankMcSpank; - 6th August 2010 at 22:12.

  9. #9
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Thanks Hank. But you're good too. You spotted this. Good catch. Interrupt-on-change is exactly what it means, but you have to know how it works to really take advantage of it.

    So here's a quick tutorial.

    Sample the port/ports first, then enable interrupt-on-change, but only after all port pins with this interrupt enabled are in the non pressed state.

    This takes a snap-shot of pins, which is used later on to determin the change-of-state when a switch is pressed. I.E. a transition from logic 1 to 0, assuming a switch grounds the pin, and it has internal pull-ups enabled.

    What you'll normally want to do is use a WHILE WEND statement to WAIT until all switches are in the un-pressed state. I.E. just wait until all port pins that have interrupt-on-change enabled return a value indicating the switch is NOT pressed. Then enable int-on-change.

    The last read of the port is saved & used to determine the transition from un-pressed to pressed - or the transition from logic 1 to 0.

    And - yes - I know Mike will yell at me for suggestiing this, but I normally wait for the pin to return to the un-pressed state in my interrupt handler, then exit & clear the interrupt flag bit. It's just so much easier than sampling pins for a switch-press in a timer-based interrupt. But - Mike does have some cool stuff to do this if you're interested.

    Interrupt-on-change requires you to read the port first to end the miss-match condition before it will allow you to clear the interrupt flag bit, so it just makes sense to wait until the switch is released before clearing the flag bit & exiting the int handler.

    If you don't (like you just mentioned), then you end up having an interrupt generated by switch press & switch release - because both events = a change after you have read the port, and cleared the int-on-change flag bit, and exit the int handler.

    Assuming the user isn't going to press & hold a switch down for any length of time, this is for sure the way to go, and it can be incredibly fast if the user just taps & releases the switch.

    If the user does hold a switch down, it will simply wait for them to release the switch before exiting the interrupt handler, which also works fine, but it does delay exit from your inerrupt handler until switch release.

    This is really simple with just a few extra lines of code in your interrupt handler like this:

    Code:
    IF PORTB.6 = 0 THEN
       WHILE PORTB.6 = 0
       WEND
    ENDIF
    And you can do this for any port pin with int-on-change enabled.

    Hope this helps!
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

Members who have read this thread : 0

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

Posting Permissions

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