PDA

View Full Version : Switch Sequence



Tissy
- 8th February 2005, 20:27
I am very new to PICs, so any help is greatly appriciated. I have scowled the NET and this seems the friendliest place for help.
I would like to develop using a 16F876 a small application that had 1 switch as input, say on RB0. Then each time the switch is pressed a different LED routine is actioned.
So for example:

1st switch push, LED on RC0 stays on
2nd switch push, LED on RC1 blinks
3rd switch push, LEDs on RC2 and RC3 'wink'

etc etc.

Once the, say 3 routines are completed, it goes back to the first again.

Can anyone help with this or point me in the right directionto get me going. I'm keen to learn about PICs as they have so many uses.

Many thanks for any anticipate help.

Steve

mister_e
- 8th February 2005, 21:55
.... that had 1 switch as input, say on RB0. Then each time the switch is pressed a different LED routine is actioned.
So for example:

1st switch push, LED on RC0 stays on
2nd switch push, LED on RC1 blinks
3rd switch push, LEDs on RC2 and RC3 'wink'


As i don't know what 'wink' mean... this is something to help you to start...

There's so many different way but... Never tested but should work.


ADCON1=7 'disable analog to digital converter
OPTION_REG.7=0 'enable pull-up resistor on PORTb

PushButton var PORTB.0 ' pushButton connected between RB0
' and ground

Led1 VAR PORTC.0 ' All LEDs
Led2 VAR PORTC.1 ' Connected between
Led3 VAR PORTC.2 ' RC pins and ground
Led4 VAR PORTC.3 ' via resistor

PushHowManyTimes var byte
Delay VAR BYTE

Delay=0
PushHowManyTimes=0

start:
While pushbutton ' do the specific task untill pushbutton
' is pressed
branch PushHowManyTimes , [Start,StayOn,Blink]
wend

PushHowManytimes=PushHowManytimes+1 ' Changing task
if PushHowManytimes=3 then PushHowManytimes=1
while pushbutton=0 ' waiting untill pushbutton is release
wend
pause 50 ' debounce time
goto start


StayOn:
High PORTC.0
goto start

Blink:
Low PORTC.0
If delay<50 then
High PORTC.1
else
If delay<100 then
low PORTC.1
else
delay=0
endif
endif
pause 10
Delay=delay+1
goto start

Tissy
- 10th February 2005, 02:34
Thanks very much for your help Steve, this is exactly what i wanted and it is a good platform to expand from.

One question, is it possible to permantly monitor the switch input.

For example, when the switch is pressed, the program BRANCHes to a preset routine. However, if this preset routine is a long one , ie multiple LED flashes etc, it will only look at the switch input at the end of this preset routine (when it 'goto START') and not during the routine.

ie.

Blink:
Low PORTC.0
If delay<50 then
High PORTC.1
else
If delay<100 then
low PORTC.1
else
delay=0
endif
endif
pause 10
Delay=delay+1
goto start *** ONLY LOOKS AT SWITCH INPUT HERE AND NOT DURING ROUTINE ***

Does this make sense, i need to permantly monitor the switch input no matter what else the code is doing elsewhere.

Many thanks again,

Steve

mister_e
- 10th February 2005, 03:49
hi,

In the above section, it monitor the switches every 10ms. Close to be constant monitoring.

BTW, i case you have more complex routines, the most interesting stuff to do it is to use interrupts (rb0 or else other interrupt source that your PIC can provide).

In this case, it will monitor in background your push button and jump to the "interrupt handler" when he is pressed. In the interrupt handler, set a flag or variable that will say to your previous task that you have to change to another task.

Tissy
- 11th February 2005, 01:52
I have read some notes on inturrupts and have come up with the following, however, it doesn't do anything !! Of course with what i know about PICs, im not surprised. I am learning quickly though !!

This is what i have so far. Can you correct me if i've gone wrong on the interrupt side please?

ADCON1=7 'disable analog to digital converter
OPTION_REG.7=0 'enable pull-up resistor on PORTb

Led1 VAR PORTC.0 ' All LEDs
Led2 VAR PORTC.1 ' Connected between
Led3 VAR PORTC.2 ' RC pins and ground
Led4 VAR PORTC.3 ' via resistor
Led5 Var PORTC.4 '

ON INTERRUPT GOTO start ' Interrupt handler is start
INTCON = %10010000 ' Enable RB0 interrupt

Bright var byte

PushHowManyTimes var byte
Delay VAR BYTE

Delay=0
PushHowManyTimes=0

start:
DISABLE ' Disable interrupts in handler

branch PushHowManyTimes , [Start,StayOn,Blink,Fade,Wink]

PushHowManytimes=PushHowManytimes+1 ' Changing task
If PushHowManytimes=5 then PushHowManytimes=1


RESUME ' Return to main program
ENABLE ' Enable interrupts after handler
GOTO START

StayOn **** Routine *****
etc etc etc etc

Blink **** Routine *****
etc etc etc etc

Many thanks for any help received.

mister_e
- 11th February 2005, 05:47
not too far. You didn't define the RB0 interrupt type (falling edge)

and i do my own version. Hope this work and help you.




' I/O definition
'
TRISC=0 ' Set PORTC as OUTPUT
TRISB.0=1 ' Set PORTB.1 as input

Led1 VAR PORTC.0 ' All LEDs
Led2 VAR PORTC.1 ' Connected between
Led3 VAR PORTC.2 ' RC pins and ground
Led4 VAR PORTC.3 ' via resistor
Led5 Var PORTC.4 '


' register and interrupt definition
'
ADCON1=7 'disable analog to digital converter


OPTION_REG=0 ' enable pull-up resistor on PORTb
' Interrupt on falling edge of RB0

INTCON = %10010000 ' Enable RB0 interrupt
ON INTERRUPT GOTO ProcedureSwitcher

' Variable definition
'
PushHowManyTimes var byte
Bright var byte
Delay VAR WORD
DelayLoop var Word

' Variable initialisation
'
PORTC=0 ' Reset all outputs on PORTC
PushHowManyTimes=0

start:
Select Case PushHowManyTimes
case 1
gosub StayOn
Case 2
gosub Blink
'
' Place your other procedure here
'
end select

goto start


StayOn:
PORTC.0 = 1
return

Blink:
Toggle PORTC.1
Delay = 500
Gosub DoDelay
return


' I do a Delay Loop to be sure getting all interrupt withou latency
'
DoDelay:
For DelayLoop=0 to Delay
pause 1
Next

' Interrupt handler stuff here
'
DISABLE ' Disable interrupts in handler
ProcedureSwitcher:

PORTC=0 ' reset output to PORTC
PushHowManytimes=PushHowManytimes+1 ' Changing task
If PushHowManytimes=5 then PushHowManytimes=1

DelayLoop=Delay ' to exit the delay loop

While PORTB.0 = 0 ' waiting for push-button release
wend
pause 50 ' debounce time

RESUME ' Return to main program
ENABLE ' Enable interrupts after handler

Tissy
- 11th February 2005, 22:26
Thanks Steve. I've tried but failed !! The code was copied exactly as you have posted it, but didn't seem to work. I've tried to see what the problem is but can't figure it out.

Just to confirm

RC0 is Outputs
RB0 is Switch Input.

Can you help please.

Thanks again.

Steve

mister_e
- 12th February 2005, 11:58
Damn, the next time i'll test it before sending here.. many apologize. Change to this tested one ;o[




' I/O definition
'
TRISC=0 ' Set PORTC as OUTPUT
TRISB.0=1 ' Set PORTB.1 as input

Led1 VAR PORTC.0 ' All LEDs
Led2 VAR PORTC.1 ' Connected between
Led3 VAR PORTC.2 ' RC pins and ground
Led4 VAR PORTC.3 ' via resistor
Led5 Var PORTC.4 '


' register and interrupt definition
'
ADCON1=7 'disable analog to digital converter


OPTION_REG=0 ' enable pull-up resistor on PORTb
' Interrupt on falling edge of RB0

INTCON = %10010000 ' Enable RB0 interrupt
ON INTERRUPT GOTO ProcedureSwitcher

' Variable definition
'
PushHowManyTimes var byte
HexLed var byte
Delay VAR WORD
DelayLoop var Word

' Variable initialisation
'
PORTC=0 ' Reset all outputs on PORTC
PushHowManyTimes=0
HexLed=0

start:
Select Case PushHowManyTimes
case 1
gosub StayOn
Case 2
gosub Blink
case 3
gosub HEXonPORTC0_1
end select

goto start


StayOn:
led1 = 1
return

Blink:
Toggle led2
Delay = 500
Gosub DoDelay
return

HEXonPORTC0_1:
PORTC=HexLed
delay=500
gosub dodelay
HexLed=HexLed+1
if HexLed=4 then HexLed=0
return


' I do a Delay Loop to be sure getting all interrupt withou latency
'
DoDelay:
For DelayLoop=0 to Delay
pause 1
Next
RETURN

' Interrupt handler stuff here
'
DISABLE ' Disable interrupts in handler
ProcedureSwitcher:
INTCON.7 = 1 'disable all interrputs

PORTC=0 ' reset output to PORTC
HexLed=0
DelayLoop=Delay ' to exit the delay loop

PushHowManytimes=PushHowManytimes+1 ' Changing task
If PushHowManytimes=4 then PushHowManytimes=1

While PORTB.0 = 0 ' waiting untill
wend ' push-button is release

pause 100 ' debounce time

INTCON = %10010000 ' Enable RB0 interrupt
' reset RB0 interrupt flag

RESUME ' Return to main program
ENABLE ' Enable interrupts after handler

Tissy
- 12th February 2005, 14:15
Thanks very much, that works great. I'm almost there with the main code now. The one thing i can't figure out though, is that with an Interrupt, should that stop what ever is being processed and then move onto the next procedural call? As part of the sequence i have set up at the moment is some PWM. If this procedure is being processed, and you push the button, it does remember the push, but doesn't move on until the full PWM part of the code has finished its cycle.

Heres an extract of working code which hopefully demonstartes what i mean. Its a piece of code which makes the LEDs look as if the are fading on and off. I would like to step to the next LED immediately the button is pushed, no matter at what position the fading is at. Can this be done?

Here it is:

' I/O definition
'
TRISC=0 ' Set PORTC as OUTPUT
TRISB.0=1 ' Set PORTB.1 as input

Red VAR PORTC.0 ' All LEDs
Green VAR PORTC.1 ' Connected between

Bright var byte

' register and interrupt definition
'
ADCON1=7 'disable analog to digital converter


OPTION_REG=0 ' enable pull-up resistor on PORTb
' Interrupt on falling edge of RB0

INTCON = %10010000 ' Enable RB0 interrupt
ON INTERRUPT GOTO ProcedureSwitcher

' Variable definition
'
PushHowManyTimes VAR byte
Delay VAR WORD
DelayLoop VAR Word

' Variable initialisation
'
PORTC=0 ' Reset all outputs on PORTC
PushHowManyTimes=0

start:
Select Case PushHowManyTimes
case 1
gosub FadeRed
Case 2
gosub FadeGreen
end select
goto start

FadeRed:
low Red
for bright = 0 to 255
PWM Red,Bright,1
next
for bright = 255 to 0 step -1
PWM Red,Bright,1
next
return

FadeGreen:
low red
for bright = 0 to 255
PWM Green,Bright,1
next
for bright = 255 to 0 step -1
PWM Green,Bright,1
next
return

' I do a Delay Loop to be sure getting all interrupt withou latency
'
DoDelay:
For DelayLoop=0 to Delay
pause 1
Next
RETURN

' Interrupt handler stuff here
'
DISABLE ' Disable interrupts in handler
ProcedureSwitcher:
INTCON.7 = 1 'disable all interrputs

PORTC=0 ' reset output to PORTC
' HexLed=0
DelayLoop=Delay ' to exit the delay loop

PushHowManytimes=PushHowManytimes+1 ' Changing task
If PushHowManytimes=3 then PushHowManytimes=1

While PORTB.0 = 0 ' waiting untill
wend ' push-button is release

pause 100 ' debounce time

INTCON = %10010000 ' Enable RB0 interrupt
' reset RB0 interrupt flag

RESUME ' Return to main program
ENABLE ' Enable interrupts after handler

Thank you again.

mister_e
- 12th February 2005, 14:36
Heres an extract of working code which hopefully demonstartes what i mean. Its a piece of code which makes the LEDs look as if the are fading on and off. I would like to step to the next LED immediately the button is pushed, no matter at what position the fading is at. Can this be done?


sure it can be done.


start:


Select Case PushHowManyTimes
case 1
GetOut = 0
gosub FadeRed
Case 2
GetOut = 0
gosub FadeGreen
end select
goto start

FadeRed:
bright = 0
while (Bright !=255) and (GetOut=0)
PWM Red,Bright,1
bright = bright + 1
wend

while (bright !=0) and (getout = 0)
PWM Red,Bright,1
bright=bright - 1
wend
return

FadeGreen:
bright = 0
while (Bright !=255) and (GetOut=0)
PWM Green,Bright,1
bright = bright + 1
wend

while (bright !=0) and (getout = 0)
PWM Green,Bright,1
bright=bright - 1
wend
return

' Interrupt handler stuff here
'
DISABLE ' Disable interrupts in handler
ProcedureSwitcher:

INTCON.7 = 1 'disable all interrputs

PORTC=0 ' reset output to PORTC
DelayLoop=Delay ' to exit the delay loop

GetOut = 1 ' to get out of the entire PWM loops
PushHowManytimes=PushHowManytimes+1 ' Changing task
If PushHowManytimes=3 then PushHowManytimes=1

While PORTB.0 = 0 ' waiting untill
wend ' push-button is release

pause 100 ' debounce time

INTCON = %10010000 ' Enable RB0 interrupt

' reset RB0 interrupt flag

RESUME ' Return to main program
ENABLE ' Enable interrupts after handler

Tissy
- 13th February 2005, 19:38
Thanks ever so much for your help Steve. I now have the main body of the code working very well.

As it is evident that you know your stuff when it comes to Pic Basic, can you recommend any books for learning. I value your opinion.

Thanks again.

Steve

mister_e
- 13th February 2005, 20:36
Sorry to disapointed you but, i can't recommmend any book since i use only the PBP manual and datasheets.

BUT if you do a search in this forum, on Melabs, on Crownhill and on Reynolds Electronic website, you'll find few books related to PBP.

Be friend with PBP manual and datasheet will lead you success. I know datasheet are sometime hard to understand but... what is the worst result you'll have ??? compile error, nothing is working... that's food for brain cells ;)

Have fun!