PDA

View Full Version : Use a switch by change not on/off status.



courtec
- 14th October 2014, 12:44
Dear all,

I have a problem with a toggle switch where the output must change on a status on a switch going from 1 to 0 or vice versa.
To read a 0 or 1 from a switch is no problem. I need to read the flank, like a flipflop does. Is the right way an interrupt?
The output must remain 0 on startup, regardless the on or off status of the switch.
Any help appreciated.

Thanks,
Koert

Ioannis
- 14th October 2014, 13:26
Interrupt sure is one way. Maybe PulsIn is another, to read the edge of the pulse.

Ioannis

rsocor01
- 15th October 2014, 04:43
The output must remain 0 on startup, regardless the on or off status of the switch.


What exactly do you mean by that? Do you mean a logical 0 in the program algorithm or 0 volts at the switch? There are a few ways to do it depending on what you want.

Demon
- 15th October 2014, 05:09
Off the top of my head in pseudo-code:


SwitchIn VAR PortB.0
OldState VAR BIT
SwitchState VAR BIT

OldState = SwitchIn
SwitchState = 0

Main:
IF SwitchIn not = OldState THEN
SwitchState = SwitchState ^ %1 ' Switch has been toggled
OldState = SwitchIn
ENF-IF
GOTO Main

Robert

Archangel
- 15th October 2014, 20:43
I would use interrupt on change. ISR just changes output port status. Set port status in start up code to " your safe off status" set interrupts off until pic is stable then enable interrupts. Whatever status toggle switch is in initally is irrelevant as changing it triggers the interrupt.

Demon
- 15th October 2014, 22:42
Interrupt on change is more efficient. But this is Koert's first post and he just joined, he hasn't given any indication to his level of PBP expertise..

Assuming he is a beginner, he's better off trying logic instead of interrupts to get the ball started, then switch to interrupts later as a challenge.

Koert, search for Darrel Taylor's Instant Interrupts in FAQ section. Unless you only do super simple programming, they help A LOT when using USB, timers, interrupts, and many more features.

Robert

richard
- 16th October 2014, 03:35
I agree with Robert contact bounce and such can really confuse an interrupt based solution ,unless you have some experience behind you. slow changing inputs can easily be read (and debounced) by using polling style solutions

Archangel
- 16th October 2014, 08:09
contact bounce can be marginalized with a short pause. IOC would trigger going to either logic state and his output would always start out at what it is initialized to. If he is not too worried about latency then even ON INTERRUPT would work, though I prefer Darrel's asm interrupts.

courtec
- 17th October 2014, 09:37
Thank you all for the input so far. And indeed, I am new with pic programming. Knowledge of basic language and electronics for many years. This kind of switching solution was done by a 4027 JK flipflop. But it's time to move on and use a micro controller. And more of a challenge then i expected!
Anyway, to be more precise about the question asked:
a micro switch in a machine is standard closed by a magnet.
When the switch opens, so goes from 0 to 1 (logical) a relais must be activated. When the magnet returns and the switch goes back to 0, doe nothing
Again when the switch opens again toggle the relais. All with sufficient code to avoid bouncing.
'
Quite simpel i think but several programs i tried don't work as good as a 4027. "Probably" due to the fact that i am a new-be....

I'l look into the two solutions mentioned and let you know. Thanks again.

Koert.

Ioannis
- 17th October 2014, 13:17
Try this. I have not tested though, but is based on Roberts idea to work as you requested. Roberts idea will toggle the output everytime the switch will change state. Not on 0->1 only.



SwitchIn VAR PortB.0
OldState VAR BIT
SwitchState VAR BIT

OldState = SwitchIn
SwitchState = 0

Main:
IF SwitchIn not = OldState THEN
IF SwitchIn THEN
SwitchState = SwitchState ^ %1 ' Switch has been toggled
ENDIF
ENDIF
OldState = SwitchIn
GOTO Main


Ioannis

Demon
- 17th October 2014, 14:22
You can tweak a PAUSE 50 before GOTO as simple debounce.

Robert

Ioannis
- 17th October 2014, 15:13
I think debounce is not necessary since he wants to see the edge from 0->1 and toggle the output. Then do nothing with 1->0 until a new 0->1 edge comes.

Ioannis

Demon
- 18th October 2014, 00:16
I know, I was just suggesting minimal debounce as he requested.

All with sufficient code to avoid bouncing.

Robert

killdill045
- 17th November 2014, 09:26
Set port status in start up code to " your safe off status" set interrupts off until pic is stable then enable interrupts. Whatever status toggle switch is in initally is irrelevant as changing it triggers the interrupt.

peterdeco1
- 20th November 2014, 19:14
Just a thought. I did something like this for a LDR to act as a motion detector. It should work for a switch.

checkswitch var bit
compare var bit
clear 'bits are 0
low portb.0 'output pin off

start:
let checkswitch = porta.0 'toggle switch
pause 50
let compare = porta.0
if compare <> checkswitch then toggle portb.0 : clear: goto start
goto start

muddy0409
- 22nd November 2014, 13:07
I have used the following on a few occasions quite successfully:

Lets say the switch is on portc.3

SW VAR PORTC.3




WHILE SW = 0 : WEND 'THIS WILL CONTINUALLY LOOP AS LONG AS THE INPUT IS LOW, MAKE IT SW = 1 TO DETECT
'GOING LOW.
' ASSUMES THAT ALL YOU ARE DOING IS WAITING FOR A SWITCH CHANGE
'ACCORDING TO THE MANUAL THIS LOOP CHECKS ABOUT 50 TIMES A SECOND
'SO IT SHOULD SEE THE CHANGE WITHIN 1/50 OF A SECOND.

DO SOMETHING HERE 'THIS IS WHAT YOU WANT TO DO AT THE SWITCH CHANGE

Archangel
- 23rd November 2014, 12:07
Ok, a JK FlipFlop is a 2 input one output device.
I am guessing you are using a latching relay which
changes states every time it is energised, is
this correct?

If so you need to read 2 pins to check switch state.


@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
DEFINE OSC 4
TrisA = %00000011

TRISC = %00000000
PortC = %00000000

ANSEL=0
ANSELH=0
ADCON0 = 0
ADCON1 = 0
Option_Reg = %00000000 ; enable RABPU
WPUA = %00000011 ;Set RABPU
Main:
If PortA.0 = 0 then
portc.2 = 1
pause 500 ; 1/2 seconds of power out
portc.2 = 0
else
goto main
endif
goto Impatient ; wait for microswitch to zero

Impatient:
while PortA.1 = 1
portc.3 = 1
pause 100
portc.3 = 0
pause 100
wend
if PortA.1 = 0 then goto main

end


Tested with 16F690 demo board. Weak pullups did not work, had to use real resistors, likely because the PICKit2 was still connected. LEDs were enabled to verify operation