Beginner in need of help !!


Closed Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 72
  1. #1
    Join Date
    Jan 2015
    Posts
    45

    Question Beginner in need of help !!

    Hi everyone, I am completely new to both these forums & pic programming. I am working with the 12f683 which I have managed to flash led 's read potentiometers etc, very basic stuff.

    Now to my question. I want to turn an LED on/off with a single tap of a tactile button. So press & release button: led turns on, then repeat to turn led off.

    I knio how to turn an LED on/off by holding the button for on & releasing for off, but I can't work out how to do the above.

    Any help would be greatly appreciated, I intend to over come any hiccups, not give up.

    Thanks,
    Rob

  2. #2
    Join Date
    Apr 2011
    Location
    Welches, Oregon
    Posts
    198


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Not sure how much help you need. I'm assuming you know input/ output, high/ low...

    Google "Pull down switch" and see how the level goes from high to low when the button is pressed (there is a pull up as well); use standard input technique to read the level change when the switch is pressed. To control the LED output, I think an if/ then will work well:

    If Button press = 0 and LED = off then [turn on LED]
    If Button press = 0 and LED = on then [turn off LED]

    You should also look at "debounce" as there is some issue to mechanical switches.

    Also, without some programming to limit the speed, the switch will turn the LED on/ off very quickly. A pause will work (to give the user time to release the button) or, you can look for a "1" on the switch (released) before allowing another button press to register.

    HTH,
    Last edited by Amoque; - 15th January 2015 at 13:35.

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Rob,
    Welcome to the forum! As you can imaging there are several ways to do this (and most other things). Amoque shows you one, here's another (which also tries to take care of the debounce):
    Code:
    LED VAR GPIO.0
    Switch VAR GPIO.1
    
    ANSEL = 0                     ' No analog inputs
    CMCON = 7                     ' Comparators disabled
    TRISIO = %11111110            ' GPIO.0 as output
    
    Main:
      IF Switch = 1 THEN          ' If the button is pressed...
        TOGGLE LED                ' ...we toggle the LED.
        Pause 20                  ' Then we wait for contact bounce on make to die, may need tweaking
        WHILE Switch = 1 : WEND   ' Then we wait for the user to actually release the button
        Pause 20                  ' Finally we wait for contact bounce on release to die, may need tweaking
      ENDIF
    Goto Main
    /Henrik.

  4. #4
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Guys, thanks for the help. I will go away & have a play with your examples

    Thanks again,
    Rob

  5. #5
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Quote Originally Posted by HenrikOlsson View Post
    Hi Rob,
    Welcome to the forum! As you can imaging there are several ways to do this (and most other things). Amoque shows you one, here's another (which also tries to take care of the debounce):
    Code:
    LED VAR GPIO.0
    Switch VAR GPIO.1
    
    ANSEL = 0                     ' No analog inputs
    CMCON = 7                     ' Comparators disabled
    TRISIO = %11111110            ' GPIO.0 as output
    
    Main:
      IF Switch = 1 THEN          ' If the button is pressed...
        TOGGLE LED                ' ...we toggle the LED.
        Pause 20                  ' Then we wait for contact bounce on make to die, may need tweaking
        WHILE Switch = 1 : WEND   ' Then we wait for the user to actually release the button
        Pause 20                  ' Finally we wait for contact bounce on release to die, may need tweaking
      ENDIF
    Goto Main
    /Henrik.
    Thanks for this Henrik, I found this the best way. Another question, what if I wanted to run a different command to just turning on the LED, what about if I wanted to start the LED flashing upon button tap? Could I do this with the same method?

    Thanks,
    Rob

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi,

    > what if I wanted to run a different command to just turning on the LED
    Don't understand this one, sorry...

    > what about if I wanted to start the LED flashing upon button tap?
    Well, yes. But as soon as you mention blinking it starts to get a Little bit more complicated. Why?
    Because then you need delays in there, during which (if using PAUSE) the button won't be polled so it'll feel unresponsive. Of course there are ways around this but the correct one depends on what you want to do after we get that LED to blink....

    Try this (I haven't, hope it works....):
    Code:
    LEDState VAR BYTE
    Time VAR WORD
    
    LED_OFF CON 0
    LED_ON CON 1
    LED_FLASH CON 2
    
    Rate CON 250		      ' Time between LED toggles when blinking
    
    Main:
      IF Switch = 1 THEN          ' If the button is pressed...
        LEDState = LEDState + 1
        IF LEDState = 3 THEN LEDState = 0
        Pause 20                  ' Then we wait for contact bounce on make to die, may need tweaking
        WHILE Switch = 1 : WEND   ' Then we wait for the user to actually release the button
        Pause 20                  ' Finally we wait for contact bounce on release to die, may need tweaking
      ENDIF
    
      IF (LEDState = LED_OFF) or (LEDState = LED_ON) THEN
        LED = LEDState            ' Turn LED on or off, solid.
      ENDIF
    
      IF LEDState = LED_FLASH THEN
        Time = Time + 1
        IF Time = Rate THEN
          TOGGLE LED
          Time = 0
        ENDIF
        PAUSEUS 1000
      ENDIF  
      
    Goto Main
    /Henrik.

  7. #7
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Question Re: Beginner in need of help !!

    Hi again, I have been trying to play around with interrupts, both instant asm (which barely makes any sense to me) & basic 'on interrupt'.

    I have wrote a very basic code, however what I cant get my head around is how to incorporate the button method we discussed before into an interrupt? So how can one push & release of the button enter an interrupt loop & wait there, until I push & release the button again which would exit back to the main loop? Here is the small code I have written.

    Thanks again,
    Rob



    Code:
    ANSEL = 0 'digital I/O
    CMCON0 = 7 'comparator off
    INTCON = %00010000 'enable pin 4 interrupt
    TRISIO = %00010000 'pin 4 input
     
    LED VAR GPIO.0 'pin 7 led
    Switch VAR GPIO.4 'pin 3 button
    
    ON INTERRUPT GOTO int1 
    
    main:
    HIGH LED
    PAUSE 500
    LOW LED
    PAUSE 500
    GOTO main
    
    DISABLE
    int1:
    TOGGLE LED
    INTCON.1 = 0
    RESUME
    ENABLE

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Rob,
    If you want the button to enable/disable the blining LED then you can't toggle the LED itself in the interrupt and then just continue to blink it in the main program loop. What you need is flag or semaphore telling the main loop if the LED is supposed to blink or not.
    Code:
    BLINK VAR BIT
    
    ON INTERRUPT GOTO int1 
    
    main:
    If Blink = 1 THEN
      HIGH LED
      PAUSE 500
      LOW LED
      PAUSE 500
    ENDIF
    GOTO main
    
    DISABLE
    int1:
    Blink = !Blink   ' Invert the state of the semapore
    RESUME
    ENABLE
    Please note that the PAUSE statement is basically delaying the Int1 routine from executing until the PAUSE statement finishes (that's the drawback of ON INTERRUPT). So if you push the button just as the PAUSE 500 start to exectute the ISR won't execute until 500ms later. This won't matter in this case but please keep that in mind when you start doing more complicated stuff.

    Also, the above does not incorporate any debounce, you may want to add that.

    /Henrik.

  9. #9
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Henrik, thanks for explaing that to me it will help me a lot I am learning more & more as I go on

    Rob

    Quote Originally Posted by HenrikOlsson View Post
    Hi Rob,
    If you want the button to enable/disable the blining LED then you can't toggle the LED itself in the interrupt and then just continue to blink it in the main program loop. What you need is flag or semaphore telling the main loop if the LED is supposed to blink or not.
    Code:
    BLINK VAR BIT
    
    ON INTERRUPT GOTO int1 
    
    main:
    If Blink = 1 THEN
      HIGH LED
      PAUSE 500
      LOW LED
      PAUSE 500
    ENDIF
    GOTO main
    
    DISABLE
    int1:
    Blink = !Blink   ' Invert the state of the semapore
    RESUME
    ENABLE
    Please note that the PAUSE statement is basically delaying the Int1 routine from executing until the PAUSE statement finishes (that's the drawback of ON INTERRUPT). So if you push the button just as the PAUSE 500 start to exectute the ISR won't execute until 500ms later. This won't matter in this case but please keep that in mind when you start doing more complicated stuff.

    Also, the above does not incorporate any debounce, you may want to add that.

    /Henrik.

  10. #10
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi, please can someone tell me how I disable MCLR on gp3 (my pic is 12f683). Ive been researching for the past 2 hours & I have got no closer to disabling it, I just want GP3 as a normal input pin, not this MCLR crap!

    If anyone knows could you please help?

    Rob

  11. #11
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi,
    MCLR is disabled by clearing the correct "fuse" in the CONFIG word. With PBP3 you set the CONFIG word(s) with the #CONFIG/#ENDCONFIG compiler directives (more on that in the manual). Your PBP3 installation folder has a subfolder named DEVICE_REFERENCES in which you'll find a file for each and every device the compiler supports. The file contains information about the various CONFIG options and also what defaults PBP uses if you don't include any in your code.

    For a 12F683 the defaults are:
    Code:
    #CONFIG
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _CP_OFF
    #ENDCONFIG
    If you want to disable MCLR and keep everything else then copy/paste this into your program:
    Code:
    #CONFIG
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    /Henrik.

  12. #12
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    MCLR is disabled by clearing the correct "fuse" in the CONFIG word. With PBP3 you set the CONFIG word(s) with the #CONFIG/#ENDCONFIG compiler directives (more on that in the manual). Your PBP3 installation folder has a subfolder named DEVICE_REFERENCES in which you'll find a file for each and every device the compiler supports. The file contains information about the various CONFIG options and also what defaults PBP uses if you don't include any in your code.

    For a 12F683 the defaults are:
    Code:
    #CONFIG
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _CP_OFF
    #ENDCONFIG
    If you want to disable MCLR and keep everything else then copy/paste this into your program:
    Code:
    #CONFIG
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    /Henrik.
    Your a life saver mate. I knew I had to write to the config but I just could not find out which way to do it, I was nearly there I was putting @config instead though!

    Thanks again,
    Rob

  13. #13
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    MCLR is disabled by clearing the correct "fuse" in the CONFIG word. With PBP3 you set the CONFIG word(s) with the #CONFIG/#ENDCONFIG compiler directives (more on that in the manual). Your PBP3 installation folder has a subfolder named DEVICE_REFERENCES in which you'll find a file for each and every device the compiler supports. The file contains information about the various CONFIG options and also what defaults PBP uses if you don't include any in your code.

    For a 12F683 the defaults are:
    Code:
    #CONFIG
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _CP_OFF
    #ENDCONFIG
    If you want to disable MCLR and keep everything else then copy/paste this into your program:
    Code:
    #CONFIG
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    /Henrik.
    Hi Henrik, I am going to start my first project which will hopefully teach me new things along the way. I have question for you before I start though, I am hoping you can give a short answer to this.

    Basically I want different modes (say 10) which are each cycled through via a tap of a tactile button (so mode 1, tap button, mode 2, tap, mode 3, etc) & each mode has its own led flashing at a different speed.

    My question is, which way is the best to do this? With interrupts or something else? I would also like the chip to watch for other button presses as well not just this one sequence of modes, so its not going to be just a simple sequnce of button tap to next mode etc.

    So I need a way of watching for multiple input changes all the time, I am expecting interrupts to be the answer after reading about, but just want to be sure

    Hope you can help,
    Rob
    Last edited by robbo78; - 21st January 2015 at 08:48.

  14. #14
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Rob,
    There are several ways - as is the case most of the time.
    Interrupts are probably the way to go but there may be other ways.

    Do you have a particular chip in mind, is it still the 12F683? I think not since you mention 10 modes, each with its own LED.....
    How many switches do you need to monitor?

    /Henrik.

  15. #15
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Henrik, I will still be using the pic12f683. This is just a starter project which I am hoping to take to something bigger, but I will be flashing 1 led, the 10 modes are all outputting to the one led. I would like to sense 2 inputs, 1 tactile button & 1 using adc to mintor coltage change.

    Thanks,
    Rob

  16. #16
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    My last post messed up a bit at the end, it was supposed to be monitor voltage lol. Anyway given the things I would like, do you think interrupts are the best route? I would end up adding more outputs to this (in the end 4 outputs, 2 inputs).

    Thanks again,
    Rob

  17. #17
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Unhappy Re: Beginner in need of help !!

    Ive decided to go the interrupt route... I am stuck already. Here is my simple code, why isnt my interrupt working?

    Code:
    #CONFIG 
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    
    DEFINE OCS 4 '4mhz ocsillator
    ANSEL = 0 'all I/O digital
    CMCON0 = 7 'comparator off
    LED VAR GPIO.0 'LED pin 7
    LED2 VAR GPIO.1 'LED2 pin 6
    
    ON INTERRUPT GOTO mode1 'interrupt handler is mode1
    INTCON = %10001000 'enable gp3 interrupt
    
    main:
    ENABLE
    HIGH LED 'led on
    PAUSE 500 'delay 0.5 second
    LOW LED 'led off
    PAUSE 500 'delay 0.5 second
    GOTO main 'repeat
    
    DISABLE 'disable interrupts in handler
    mode1:
    HIGH LED2 'led2 on
    PAUSE 50
    LOW led2 'led2 off
    PAUSE 50
    RESUME 'return to where left off
    ENABLE 'enable interrupts

  18. #18
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Normally in the interrupt routine this is needed.
    INTCON.1 = 0
    But the data sheet for this chip reads like this is needed.
    INTCON.0 = 0

    Then at the beginning of your code below
    INTCON = %10001000
    add
    IOC.3=1

    I think...
    Dave
    Always wear safety glasses while programming.

  19. #19
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Quote Originally Posted by mackrackit View Post
    Normally in the interrupt routine this is needed.
    INTCON.1 = 0
    But the data sheet for this chip reads like this is needed.
    INTCON.0 = 0

    Then at the beginning of your code below
    INTCON = %10001000
    add
    IOC.3=1

    I think...
    Brilliant, that got it working. I take it IOC.3 = 1 tells the chip when to interrupt & on what pin?

    So INTCON = %10001000 tells it to enable interrupts on pin 3 & IOC.3 = 1 tells it to interrupt on pin 3 change ?

    Thanks for your help,
    Rob

  20. #20
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    This should work for you. It works in my simulator.

    Also, since PBP's ON INTERRUPT only checks to see if an interrupt has occurred between PBP commands, you may want to use a loop counter in your main routine and use short pauses. This is how I revised your code.

    Comments are added to the code below.

    Good Luck.

    Code:
    'PIC 12F683
    #CONFIG 
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    
    'DEFINE OCS 4 '4mhz ocsillator
    DEFINE OSC 4 '4mhz ocsillator
    ANSEL = 0 'all I/O digital
    CMCON0 = 7 'comparator off
    LED VAR GPIO.0 'LED pin 7
    LED2 VAR GPIO.1 'LED2 pin 6
    
    loop1 var byte  ' Loop 1 Counter
    
    ON INTERRUPT GOTO mode1 'interrupt handler is mode1
    INTCON = %10001000 'enable GIE and GPIE; clear GPIF
    IOC = %00001000 ' enable IOC3 (GPIO3 Interrupt on change)
    
    ENABLE 
    main:
    do
        for loop1 = 1 to 50
            HIGH LED 'led on
            'PAUSE 500 'delay 0.5 second
            pause 10    '10 ms
        next loop1
        
        for loop1 = 1 to 50
            LOW LED 'led off
            'PAUSE 500 'delay 0.5 second
            pause 10    '10 ms
        next loop1
    
    'GOTO main 'repeat
    loop
    
    DISABLE 'disable interrupts in handler
    mode1:
    if INTCON.0 = 1 then    'one of the GPIO<5:0> pins changed state (must be cleared in software)
    
        HIGH LED2 'led2 on
        PAUSE 50
        LOW led2 'led2 off
        PAUSE 50
    
    endif
    INTCON = %10001000  'enable GIE and GPIE; clear GPIF
    
    RESUME 'return to where left off
    ENABLE 'enable interrupts
    
    end 'got here by mistake
    Regards,
    TABSoft

  21. #21
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Quote Originally Posted by Tabsoft View Post
    This should work for you. It works in my simulator.

    Also, since PBP's ON INTERRUPT only checks to see if an interrupt has occurred between PBP commands, you may want to use a loop counter in your main routine and use short pauses. This is how I revised your code.

    Comments are added to the code below.

    Good Luck.

    Code:
    'PIC 12F683
    #CONFIG 
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    
    'DEFINE OCS 4 '4mhz ocsillator
    DEFINE OSC 4 '4mhz ocsillator
    ANSEL = 0 'all I/O digital
    CMCON0 = 7 'comparator off
    LED VAR GPIO.0 'LED pin 7
    LED2 VAR GPIO.1 'LED2 pin 6
    
    loop1 var byte  ' Loop 1 Counter
    
    ON INTERRUPT GOTO mode1 'interrupt handler is mode1
    INTCON = %10001000 'enable GIE and GPIE; clear GPIF
    IOC = %00001000 ' enable IOC3 (GPIO3 Interrupt on change)
    
    ENABLE 
    main:
    do
        for loop1 = 1 to 50
            HIGH LED 'led on
            'PAUSE 500 'delay 0.5 second
            pause 10    '10 ms
        next loop1
        
        for loop1 = 1 to 50
            LOW LED 'led off
            'PAUSE 500 'delay 0.5 second
            pause 10    '10 ms
        next loop1
    
    'GOTO main 'repeat
    loop
    
    DISABLE 'disable interrupts in handler
    mode1:
    if INTCON.0 = 1 then    'one of the GPIO<5:0> pins changed state (must be cleared in software)
    
        HIGH LED2 'led2 on
        PAUSE 50
        LOW led2 'led2 off
        PAUSE 50
    
    endif
    INTCON = %10001000  'enable GIE and GPIE; clear GPIF
    
    RESUME 'return to where left off
    ENABLE 'enable interrupts
    
    end 'got here by mistake
    Hi Tabsoft, that worked perfectly. I can see what you mean by using loops instead of pauses, the interrupt is much more reactive.

    Now I just need to know how to stay in that interrupt routine until I tap the button again.

    Thanks,
    Rob

  22. #22
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Rob,
    Now I just need to know how to stay in that interrupt routine until I tap the button again.
    Even though that would work for this particular application that's generally not what you want to do (ie stay in the interrupt routine). Instead you do as I showed earlier, use a flag/semaphore in the interrupt service routine which the main code reads and determines what to do.

    The same thing applies to your scenario with ten states. You have a variable which you increment in the interrupt (ie once very time you press the button), once it gets to 10 you reset it to zero. Then, in the main program loop you simply check the value of this variable and act accordingly. With a bit of thought and some math you might even USE the variables value directly as the delay in your loop to blink the LED.

    As for the analog input it's important to understand that there is no mechanism to automatically run the ADC and detect (ie interrupt) when the voltage at the input changes. You need to write code to sample the input once every minute, second, millisecond or whatever the requirement may be.

    Finally, please don't quote the full message just posted. There's really no need to have the very latest post quoted in full.

    /Henrik.

  23. #23
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Rob,

    Glad it worked for you.

    I'm not sure if you want/need to stay in the ISR as I don't know your final objective.

    I would suggest using a flag to determine the state of the IOC.3 interrupt coming from your button.
    Then in the ISR change the state of the flag each time the interrupt occurs and then get out of the ISR.
    You can then setup a subroutine for what you wanted to accomplish in the ISR.
    Finally in your main loop check the state of the flag and gosub to the new subroutine.

    Here is a working example. Expanded on what I posted last time.

    Code:
    'PIC 12F683
    #CONFIG 
       __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    
    'DEFINE OCS 4 '4mhz ocsillator
    DEFINE OSC 4 '4mhz ocsillator
    ANSEL = 0 'all I/O digital
    CMCON0 = 7 'comparator off
    LED VAR GPIO.0 'LED pin 7
    LED2 VAR GPIO.1 'LED2 pin 6
    
    loop1 var word  ' Loop 1 Counter (word for 0 to 65535 increments)
    loop2 var byte  ' Loop 2 Counter (byte used for 0 to 255 increments)
    ModeFlag var bit   ' Bit to determine what state of IOC.3 is
    
    '*****Initlaze Vars*****
       loop1 = 0
       loop2 = 0
    ModeFlag = 0
    '***********************
    
    ON INTERRUPT GOTO mode1 'interrupt handler is mode1
    INTCON = %10001000 'enable GIE and GPIE; clear GPIF
    IOC = %00001000 ' enable IOC3 (GPIO3 Interrupt on change)
    
    ENABLE 
    main:
    do
        for loop1 = 1 to 500
            HIGH LED 'led on
            'PAUSE 500 'delay 0.5 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            gosub moderoutine
        endif
        
        next loop1
        
        for loop1 = 1 to 500
            LOW LED 'led off
            'PAUSE 500 'delay 0.5 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            gosub moderoutine
        endif
        
        next loop1
    
    'GOTO main 'repeat
    loop
    
    moderoutine:
        do while ModeFlag = 1
            high LED2   'LED2 On
            for loop2 = 0 to 50
                pause 1 '1ms
            next loop2
            
            low LED2    'LED2 Off
            for loop2 = 0 to 50
                pause 1 '1ms
            next loop2 
        loop    
    
        return
    
    DISABLE 'disable interrupts in handler
    mode1:
    if INTCON.0 = 1 then    'one of the GPIO<5:0> pins changed state (must be cleared in software)
    
        'HIGH LED2 'led2 on
        'PAUSE 50
        'LOW led2 'led2 off
        'PAUSE 50
    
        'Set the ModeFlag
        ModeFlag = ~ ModeFlag
    endif
    INTCON = %10001000  'enable GIE and GPIE; clear GPIF
    
    RESUME 'return to where left off
    ENABLE 'enable interrupts
    
    end 'got here by mistake
    Regards,
    TABSoft

  24. #24
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Thanks a lot for the help guys, I appreciate it I understand now how isr's work now.

    Thanks,
    Rob

  25. #25
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi,
    Another aproach is to use the interrupt mechanism as a way to "latch" the buttonpress but then not actually enable the interrupt itself but instead poll the interrupt flag to determine if the button was pressed.
    Code:
    State VAR BYTE
    
    Main:
    
        If INTCON.1 = 1 THEN    ' GP2 input interrupt
          INTCON.1 = 0   ' Clear flag
          State = State + 1
          If State = 3 THEN State = 0
        ENDIF
    
       SELECT CASE State
    
          Case 0
            HIGH LED
            PAUSE 50
            LOW LED
            PAUSE 50
      
          CASE 1
            HIGH LED
            PAUSE 100
            LOW LED
            PAUSE 100
    
          CASE 2
            HIGH LED
            PAUSE 150
            LOW LED
            PAUSE 150
    GOTO MAIN

  26. #26
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi, I like that way as well. Although at some point I need to add a nap command with wdt off so it wakes when a voltage is higher than 0.60v & naps when voltage is less then, so I would have to use an interupt anyway at some point?

    Thanks,
    Rob

  27. #27
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Question Re: Beginner in need of help !!

    Right I have changed the code from what Tabsoft last posted, so now there are 3 modes each blinking led at a different rate depending on the mode. Every tap of the button is supposed to goto the next mode.

    Something weird is happening though, each tap of the button is reversing the mode lol. So instead of going forwards to the next mode, its going backwards (should go mode 1 > mode 2, but is going Mode 1 > mode 3 > mode 2).

    Any ideas? here is the code -

    Code:
     
    'PIC 12F683
    
    #CONFIG 
       __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    
    'DEFINE OCS 4 '4mhz ocsillator
    DEFINE OSC 4 '4mhz ocsillator
    ANSEL = 0 'all I/O digital
    CMCON0 = 7 'comparator off
    LED VAR GPIO.0 'LED pin 7
    
    loop1 var word  ' Loop 1 Counter (word for 0 to 65535 increments)
    ModeFlag var bit   ' Bit to determine what state of IOC.3 is
    
    '*****Initlaze Vars*****
       loop1 = 0
    ModeFlag = 0
    '***********************
    
    ON INTERRUPT GOTO modeselect 'interrupt handler is modeselect
    INTCON = %10001000 'enable GIE and GPIE; clear GPIF
    IOC = %00001000 ' enable IOC3 (GPIO3 Interrupt on change)
    
    ENABLE 
    mode1:
    do
        for loop1 = 1 to 1000
            HIGH LED 'led on
            'PAUSE 1000 'delay 1 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            gosub mode2
        endif
        
        next loop1
        
        for loop1 = 1 to 1000
            LOW LED 'led off
            'PAUSE 1000 'delay 1 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            gosub mode2
        endif
        
        next loop1
    
    'GOTO mode1 'repeat
    loop
    
    ENABLE 
    mode2:
    do
        for loop1 = 1 to 500
            HIGH LED 'led on
            'PAUSE 500 'delay 0.5 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            gosub mode3
        endif
        
        next loop1
        
        for loop1 = 1 to 500
            LOW LED 'led off
            'PAUSE 500 'delay 0.5 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            gosub mode3
        endif
        
        next loop1
    
    'GOTO mode2 'repeat
    loop
    
    ENABLE
    mode3:
    DO
        for loop1 = 1 to 50
            HIGH LED 'led on
            'PAUSE 50 'delay 0.05 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            gosub mode1
        endif
        
        next loop1
        
        for loop1 = 1 to 50
            LOW LED 'led off
            'PAUSE 50 'delay 0.05 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            gosub mode1
        endif
        
        next loop1
    
    'GOTO mode3 'repeat
    loop
        
    DISABLE 'disable interrupts in handler
    modeselect:
    if INTCON.0 = 1 then    'one of the GPIO<5:0> pins changed state (must be cleared in software)    
        
        'next mode
    
        'Set the ModeFlag
        ModeFlag = ~ ModeFlag
    endif
    INTCON = %10001000  'enable GIE and GPIE; clear GPIF
    
    RESUME 'return to where left off
    ENABLE 'enable interrupts
    
    end 'got here by mistake

  28. #28
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    UPDATE: I've just worked it out I think, its because I haven't got any debounce in there so every 'tap' could be jumping a couple of modes instead of seeing it as 1 button tap & jumping 1 mode.

    Where do I actually add the debounce though? I couldn't add it into the sub modes as it would wreck the routine timing wouldn't it?

  29. #29
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi,
    No debounce may very well be part of the problem but in THIS case I think the contact bounce is what actually makes it sort of "work".
    The real issue, I believe, is that your "loops" looks for ModeFlag being equal to 1 and switches mode. But the flag is not being cleared. So, if you push the button once, the ISR sets the flag. If there are no bounce the flag will be set all the time and the program will keep cycling between the different modes since the flag is never cleared. That's a problem with the implementation.

    What's more severe is that you're using GOSUB without a matching RETURN. What you want in this case is GOTO.

    Make the ISR set (and only set) the ModeFlag, implement some debounce in the ISR.
    In the main loop you check the ModeFlag and IF it's set you first clear it and then act accordingly (ie. jump to the next mode).

    Also, there's no need to set the LED high or low 1000 times (ie do it inside the FOR_NEXT loop), one time is enough, I'd rewrite the loop like:
    Code:
    DO
        HIGH LED
        for loop1 = 1 to 1000
            pause 1    '1 ms
            IF ModeFlag = 1 THEN
              ModeFlag = 0
              GOTO Mode 2
            ENDIF    
         next loop1
        
        LOW LED 'led off
        for loop1 = 1 to 1000
            pause 1    '1 ms
            IF ModeFlag = 1 THEN
              ModeFlag = 0
              GOTO Mode 2
            ENDIF
        next loop1
    LOOP
    /Henrik.

  30. #30
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Henrik, thanks for helping. I have changed to the code to do as you said: goto's instead of gosub's & made the ISR set flag only (i think).

    It all seems to work better now, however I still have a problem with the debounce as I think it is actually 'the problem' now instead of actually making the code work as you stated. The isr sees the release of the button as an interrupt & sets a flag again which skips modes. So how do I go about adding the debounce without slowing things down?

    Isnt there a way to only interrupt or tell the ISR to flag only if the button is depressed & not when released? Here is the updated code -

    Code:
    'PIC 12F683
    
    #CONFIG 
       __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
    #ENDCONFIG
    
    'DEFINE OCS 4 '4mhz ocsillator
    DEFINE OSC 4 '4mhz ocsillator
    ANSEL = 0 'all I/O digital
    CMCON0 = 7 'comparator off
    LED VAR GPIO.0 'LED pin 7
    
    loop1 var word  ' Loop 1 Counter (word for 0 to 65535 increments)
    ModeFlag var bit   ' Bit to determine what state of IOC.3 is
    
    '*****Initlaze Vars*****
       loop1 = 0
    ModeFlag = 0
    '***********************
    
    ON INTERRUPT GOTO modeselect 'interrupt handler is modeselect
    INTCON = %10001000 'enable GIE and GPIE; clear GPIF
    IOC = %00001000 ' enable IOC3 (GPIO3 Interrupt on change)
    
    ENABLE 
    mode1:
    do
        for loop1 = 1 to 1000
            HIGH LED 'led on
            'PAUSE 1000 'delay 1 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            ModeFlag = 0
            goTO mode2
        ENDIF
        
        next loop1
        
        for loop1 = 1 to 1000
            LOW LED 'led off
            'PAUSE 1000 'delay 1 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            Modeflag = 0
            goTO mode2
        endif
        
        next loop1
    
    'GOTO mode1 'repeat
    loop
    
    ENABLE 
    mode2:
    do
        for loop1 = 1 to 500
            HIGH LED 'led on
            'PAUSE 500 'delay 0.5 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            modeflag = 0
            goTO mode3
        endif
        
        next loop1
        
        for loop1 = 1 to 500
            LOW LED 'led off
            'PAUSE 500 'delay 0.5 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            modeflag = 0
            goTO mode3
        endif
        
        next loop1
    
    'GOTO mode2 'repeat
    loop
    
    ENABLE
    mode3:
    DO
        for loop1 = 1 to 50
            HIGH LED 'led on
            'PAUSE 50 'delay 0.05 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            modeflag = 0
            goTO mode1
        endif
        
        next loop1
        
        for loop1 = 1 to 50
            LOW LED 'led off
            'PAUSE 50 'delay 0.05 second
            pause 1    '1 ms
            if ModeFlag = 1 then
            modeflag = 0
            goTO mode1
        endif
        
        next loop1
    
    'GOTO mode3 'repeat
    loop
        
    DISABLE 'disable interrupts in handler
    modeselect:
    if INTCON.0 = 1 then    'one of the GPIO<5:0> pins changed state (must be cleared in software)    
        'next mode
    
        'Set the ModeFlag
        ModeFlag = 1
        ENDIF
        
    INTCON = %10001000  'enable GIE and GPIE; clear GPIF
    RESUME 'return to where left off
    ENABLE 'enable interrupts
    
    end 'got here by mistake

  31. #31
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi,
    You're quite right, it's because you're using the IOC (Interrupt On Change), it'll trip the interrupt both when you push the button and when you release the button. (As well as on all the edges of the contact bounce). Also, when you're using IOC you need to remember to read the port (even if you're not using the value) in order to clear the mismatch condition.

    I'd wire the button to GP2 and use the "normal" INT instead of IOC.

    /Henrik.

  32. #32
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    So if I want to use IOC, I would need to read the button or any other type of input such as the adc?

    I'm only asking as I need to be able to use interrupt on like 5 inputs, not just 1. Although gp2 will use adc not any others if that would be easier.

    Thanks,
    Rob

  33. #33
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Rob,
    The IOC trips the interrupt on any change of the state on a digital pin. An interrupt will trip when the pin goes low and again when the pin goes high - provided you read the state of the pin in between. So in the ISR you need to read the state of switch and determine if it was pushed or released (and don't forget about the contact bounce). If it's determined that the interrupt tripped because the button was released you don't set the MODEFLAG.

    And, once again, the ADC can NOT generate an interrupt when the analog voltage on the input changes. It won't work with IOC. Any pin configured as analog input will always read '1' and will never trip the IOC or INT interrupts.
    Depending on what you want to do you might be able to use the comparator, they can be setup to trip an interrupt when their respective output changes state.

    /Henrik.

  34. #34
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Hi Henrik, thanks for explaining that it makes things a lot clearer as to how I'm going to run the code. What I would like to do is have one of the inputs (gp2), taking a reading from ADC every say 0.5 - 1 seconds.

    Basically I want the chip to enter low power mode along with the device. When the device is off, one of the component pins goes to 0.00v, then when it is turned on it goes to 0.70v & stays at that. So I would like the ADC to monitor this, then when the voltage drops below 0.60v the chip is in low power mode, then when the voltage is higher than 0.60v I want it to come out of low power mode.

    I hope this can be done in some way,
    Rob
    Last edited by robbo78; - 22nd January 2015 at 20:23.

  35. #35
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Rob,

    I don't think the ADC module will accomplish what you are attempting as Henrik stated in his last reply.
    You should look into the Comparator of the PIC, again as Henrik suggested.
    Regards,
    TABSoft

  36. #36
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    You can use the ADC to sample the voltage but the PIC needs to be awake for the ADC to operate and, again, the ADC doesn't run continously and can not automatically generate an interrupt when a given voltage or threshold is detected. You'd need to wake the PIC up every now and then, sample thevoltage at the pin and based on that determine if you should stay awake or go back to sleep. No problems doing that but to me it looks like you'll be better served by using comparator module. Using that you can put the PIC to sleep and it will automatically wake up when the comparator output flips.

    /Henrik.

  37. #37
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Oh I see, yes it sounds like the comparator will be the best then. Anyway thanks for your help guys, I have learned a lot.

    I will be back lol

    Rob

  38. #38
    Join Date
    Jan 2015
    Posts
    45


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Back again already, Comparators are mind boggling !!

    Firstly I have no idea how to even set the mode of the comparator, let alone working out & setting the VRC. I have been researching all day, the only info that looks helpful is in C so it is all gobbledygook to me as I have only just started learning basic.

    I am not looking for someone to spoon feed me a code, I just want to be able to understand it for myself. What does this mean from the data sheet CM<2:0> = 011? How do you get CMCON0 = 2 from that? If I could understand the data sheet enough to put it into basic then it would help me a lot.

    Just being able to turn on an LED when the voltage goes under 1.00v using a pot would be a massive accomplishment for me at the moment, as I could understand how it all works.

    Any help on this would be great.

    Thanks,
    Rob

  39. #39
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    What does this mean from the data sheet CM<2:0> = 011?
    It means bits 2 , 1, 0 are set 011
    very common nomenclature to use the colon to be inclusive of all the bits in between 2:0
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  40. #40
    Join Date
    Jan 2013
    Location
    Texas USA
    Posts
    229


    Did you find this post helpful? Yes | No

    Default Re: Beginner in need of help !!

    Rob,

    Yes Comparators can be confusing the 1st time using them on the PIC MCU.

    First, have a read through this link.
    http://www.cuteminds.com/index.php/e...23-comparators

    It explains simply how the comparator
    on the PIC12F683 can be used. Ignore the C language stuff, but pay attention
    to the setup of the Comparator, especially the Second Case.
    This case describes what you will probably implement.

    This will give you the info on how the Comparator will work by polling the
    Comparator output, NOT USING INTERRUPTS.

    Once you have this digested, then you can move on to the Interrupt portion.

    Use the equation for VRR=1 (Low Range): (VR3:VR0/24) x Vdd to set the "Threshold Voltage"

    E.g.
    Vdd = +5Vdc
    VR3:VR0 = 5 (%1001)

    Putting this into the equation above gives this CVref "Threshold voltage"

    (5/24) x 5 = 1.042 Vdc

    This will be the reference voltage that will be used to compare the input voltage to.

    General Rules when using the Comparator:
    1. Set the appropriate pins to analog for the Comparator with ANSEL
    2. Set the direction of the pins appropriately with TRISIO
    3. Configure the Compare Module using CMCON0
    4. Configure the reference voltage using VRCON
    To use the comparator, poll the value of the status bit in CMCON0.

    See if this gets you started.

    Regards,
    Last edited by Tabsoft; - 23rd January 2015 at 19:10. Reason: Forget a general rule
    Regards,
    TABSoft

Similar Threads

  1. Beginner help!
    By Recognize in forum General
    Replies: 14
    Last Post: - 26th April 2012, 14:55
  2. pic24 beginner
    By robertpeach in forum General
    Replies: 23
    Last Post: - 13th August 2009, 11:57
  3. need help! to beginner
    By emilhs in forum mel PIC BASIC Pro
    Replies: 27
    Last Post: - 6th May 2009, 18:44
  4. Beginner at PB
    By alphahr in forum Off Topic
    Replies: 1
    Last Post: - 21st April 2008, 17:43
  5. Can anyone help a beginner in a struggle?
    By douglasjam in forum mel PIC BASIC
    Replies: 1
    Last Post: - 5th May 2005, 23:29

Members who have read this thread : 2

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