PDA

View Full Version : Some sort of state monitoring?



Oldbitcollector (Jeff)
10-11-2011, 04:05 AM
I've got a programming challenge that I haven't been able to get my head around..

I'm reading a switch that is either on all the time or off all the time, however I need to activate a command only once when the state of the switch changes.

Anyone have an elegant method for this?

Thanks
OBC

Ariba
10-11-2011, 04:25 AM
Is this elegant enough?

PUB Main | oldstate, newstate
oldstate := ina[pin] 'init old state
repeat
newstate := ina[pin] 'read new state
if newstate <> oldstate 'detect change
if newstate==1
... 'changed Low to High
else
... 'changed High to Low
oldstate := newstate
'add a delay here if you need debouncing (~15ms)


Andy

Mike Green
10-11-2011, 04:25 AM
In hardware, you can do this with a capacitor to differentiate the switch output. You get a positive going pulse when the switch goes from low to high and a negative going pulse when the switch goes from high to low. You can use a dual optoisolator with the LEDs connected back to back and the outputs in parallel to produce a single positive going pulse when the switch changes either from low to high or from high to low.

In software, you can do the same sort of thing using a single memory bit to save the most recent state of the switch. Each time through the loop, you compare the bit to the state of the switch. If they're different, you execute your command. In all cases, you copy the state of the switch as it was when you tested it to the bit, wash, rinse, and repeat.

shimniok
10-11-2011, 04:31 AM
Not that I've done this specific thing on Propeller just yet, but I'd probably try code that, based on current state, issues either waitpne or waitpeq followed by the command, then loop through the code again. Assuming some sort of debouncing in hardware is present. There are programmatic ways to do it but I would think waitpne or waitpeq would be more elegant. That's what I used to sync to rising/falling clock edges on one of my projects.

frank freedman
10-11-2011, 05:01 AM
Not that I've done this specific thing on Propeller just yet, but I'd probably try code that, based on current state, issues either waitpne or waitpeq followed by the command, then loop through the code again. Assuming some sort of debouncing in hardware is present. There are programmatic ways to do it but I would think waitpne or waitpeq would be more elegant. That's what I used to sync to rising/falling clock edges on one of my projects.

I have used the waitpeq/pne for syncing to the ADC sample clock to the csel in the ADC/DAC fun objects. The one unknown in this equation is by state change does Jeff anticipate always one way or the other with brief excursions to the opposite state, or once switched does it stay permanently there (mostly). If it is not a permanent transition, all three of the solutions presented here have a good probability of failure if the transition is narrow enough to be missed by a cog watching for this transition not being in a tight enough loop time-wise.

If it is a short transition then consider using the counter feature of the prop cog wherein the init routine looks at the state of the monitored pin and uses a movi to set the counter for pos or neg edge transition detection to capture the transient depending on the initial state recorded.

Otherwise, you are not looking for a transition, rather a level change. In that case, I would probably use the waitpeq/pne and again at init, see what the initial state is and set the peq/pne instruction looking for one or zero using the movi as done for the transition detect above.

Frank

Oldbitcollector (Jeff)
10-11-2011, 02:18 PM
Ah!

if newstate <> oldstate

That's what I wasn't thinking of!

Thanks Ariba!

OBC


Is this elegant enough?

PUB Main | oldstate, newstate
oldstate := ina[pin] 'init old state
repeat
newstate := ina[pin] 'read new state
if newstate <> oldstate 'detect change
if newstate==1
... 'changed Low to High
else
... 'changed High to Low
oldstate := newstate
'add a delay here if you need debouncing (~15ms)


Andy

MagIO2
10-11-2011, 05:29 PM
I'd not call waitpne or waitpeq more elegand for the given problem! Oldbitcollector stated that the state is either 0 or 1 ALL the time. I'm sure he meant something like it's only changing very seldom. So, with waitpne and waitpeq you would block a COG for the most time.
Aribas code can easily be added to a loop which is doing some real work.

frank freedman
10-11-2011, 06:15 PM
I'd not call waitpne or waitpeq more elegand for the given problem! Oldbitcollector stated that the state is either 0 or 1 ALL the time. I'm sure he meant something like it's only changing very seldom. So, with waitpne and waitpeq you would block a COG for the most time.
Aribas code can easily be added to a loop which is doing some real work.

If he is looking to create a safety ckt or a watch dog function, then he may want a dedicated cog. Hate to waste a cog unless you have to, but cheaper than external circuitry if you have a cog to spare.

Frank

Oldbitcollector (Jeff)
10-11-2011, 07:56 PM
I've got a master loop which Andy's code fit into nicely. The loop was so fast that I actually had to create a 50 bounce loop when the change was detected so that the device I'm communicating with catches the change. :)

OBC