CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Keeping track of button states for

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

Keeping track of button states for
PostPosted: Mon Mar 10, 2008 10:47 pm     Reply with quote

I have 5 buttons, two pots (roughly two turns from center either direction), and a couple of multiposition switches all on a machine that my pic is hooked up to. I'm using the inputs already on the machine to act as the inputs for my controller (debouncing is not a problem). What I would like to do is use certain button combinations as triggers for the pic's functionality.

What I'm having a problem with is how to keep track of what combinations are valid for which buttons pressed. I would think there is an easy way to do this but I'm just not seeing it.


For instance, I want to trigger an event when button A is pressed for two seconds and the pot is turned at least 50% left then at least 50% right, then button A is released all within 4 seconds, but if button B is pressed at any time in there, a timeout has occurred, or some of the multiposition switches are press or in the wrong state then I don't want the event triggered.

The problem is that this is not the only thing the pic is doing. So I need some way of keeping track of whats going on and what a good way (most efficient or easiest to implement) to do that is in the compiler. So, flag, polling, or interrupts have to be kept in mind

The two ideas I have are:

1. Poll all of the buttons every 100ms. Keep track of the state changes for every 500ms block (if button A was pressed once in the 500ms then the entire 500ms block is recorded as ON. Keep a log depth of 32 or 64 instances (16 or 32 seconds). Then at every 500ms when I add a new state to the 'log' I search back through and see if any events (based on priority and exclusivity) have been correctly punched in.

2. Keep track of all buttons on and off state times. So that if button A is pressed for 1 second the button_A_on = 10 and button_A_off = 0. This way I can have a series of IFs and Flags to determine the 'next step' in the routine's series of button presses.

I have an idea of how I would do this in objective programming. But not so much in CCS C.

Anyone have an idea of how this is most often done ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 10, 2008 11:35 pm     Reply with quote

See this thread on multi-tasking:
http://www.ccsinfo.com/forum/viewtopic.php?t=17189
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

Re: Keeping track of button states for
PostPosted: Tue Mar 11, 2008 8:03 am     Reply with quote

iso9001 wrote:
Anyone have an idea of how this is most often done ?


If there is a 'standard' method for dealing with this, I'm not aware of it (and I'm no expert either). But I'd probably use a state machine-like implementation. I'm also a fan of 'racing' events against a timer (do that all the time). I use the race approach for things like button presses & holds, and especially for quadrature encoders (user interface knobs) to detect when the user is spinning it really fast, so that the processor can skip numbers when incrementing/decrementing user-controlled values.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Tue Mar 11, 2008 8:54 am     Reply with quote

Try debouncing the keys in a timer. Say the timer interrupts 30 times per sec
then any state of a key can be determined within the timer. Bounces can be rejected due to the much shorter duration of a bounce relative to a real key
state. Within the timer set a state machine for the key state. Human key actions are on a very slow timescale compared to the cycle time of a PIC. The timer isr can break the rule that isr be short and crisp since it will not be called again for over 1/30 so all the code to determine the state of the keys can be placed within it with a small risk that it is so bloated it takes more than 1/30 to complete. A key press for example that lasts for say 1/5th of a second gives the timer 6 views of the pin state wired to the button. A longer key press can be considered as a true press and the new state is captured in the state machine.
bwhiten



Joined: 26 Nov 2003
Posts: 151
Location: Grayson, GA

View user's profile Send private message

RTOS?
PostPosted: Tue Mar 11, 2008 10:32 am     Reply with quote

No one has mentioned using the built in RTOS function for handling the multiple tasks here. I am using it now with decent success for several RT tasks. Read USB, Write USB, Read I2C slave, Write I2C slave, Scan touch sensitive buttons, Update LCD, Write XBEE via RS-232 and Read XBEE via RS-232.
I've noticed this function is not talked about much by the more experienced users on the board and would like to know what the reason might be. Bad experiences, not enough control, no past experience?
I did have trouble with the function when using a PIC33 component but there were so many other bugs with the compiler and that part that I chalked it up to the newness of the part and CCS.
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

PostPosted: Tue Mar 11, 2008 12:20 pm     Reply with quote

I don't think I explained it very well, in my head, both of my examples were already state machines.

I'm going to avoid RTOS for right now, I don't have the time to think about calling and killing tasks.

There is no debouncing for me to do since I'll have no access to direct buttons, just a data stream of what buttons are currently pressed and what position the pots are at.



I'm thinking of going with the log approach and then every 500ms or whenever check back through the 'history' and see if anything qualified for an event. For instance,

The sequence is Button A, Button B, Pot set to far left, Button A. All within 6 seconds. Button states count as either Press or Press and Release. If any other buttons went active in the sequence the whole thing is discounted.

So, I would have 2 bytes for each button (bitmapped for every 500ms), and 16 bytes for the pot values. See, excel grab attached. I think this should be relatively easy to search through. I'm not sure its efficient on memory, but all added up with the other proposed method I bet its close.





Problem with keeping a counter per value is I need an ON and OFF byte for each. For instance, some values will need to be ON for certain time while checking for OFF on some other buttons. So I would think the code would look something like

Check_Routine() {
if button_A_on > 2 (pressed for 1s)
event_sequence_1 = TRUE
... go do something else

... on next pass
if (event_sequence_1 && Button_B_on > 2 (2nd button pressed for 1s)
event_sequence_2 = TRUE


etc... while at every stage checking the vars that will make the sequence invalid


The only thing I can relate this to is like programming in easter eggs that would require a button sequence related to time. Aside from complexity I see a problem with the button history log that events would have upto a 1/2 second of latency before triggering, I think thats acceptable.

Maybe I'm missing something way easier ?
barryg



Joined: 04 Dec 2006
Posts: 41

View user's profile Send private message

PostPosted: Tue Mar 11, 2008 2:37 pm     Reply with quote

This is tempting, since I do this all the time. In fact, I'm working state driven operations right now. I don't have time to do a full explanation, but here are a few thoughts.

iso9001 wrote:

event_sequence_1 = TRUE

You can do stuff like this, but it's easier to think about, if you just have one state variable and use numbers. So as you progress though the puzzle or code inputs, you count up. 1 means they pressed button A. 2 means they then pressed button B. Anything done out of order and they go back to 0.

Once you have that in hand, you can use "enum" to number the states for you:
Code:
enum { START_OVER, PRESSED_A, PRESSED_B, POT_LEFT, ... } ;


Now, you can also have state machines within state machines. If you want button B pressed for 1 second, then make another state variable that just counts up to some number. If you test the button every 10 ms, then you'd count to 100 and there's your one second. Set it back to zero if they let go too soon.

You don't always have to check everything, just the next thing that's supposed to happen. With a single state variable, you can switch() on it. Well, I guess you'd have to check for "wrong" inputs, to send them back to zero.
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

PostPosted: Tue Mar 11, 2008 3:47 pm     Reply with quote

Yea, thats what I'm saying. I need to keep track of pressed cycles and not pressed cycles. They're complex operations Smile

the event_1 thing was just a long hand way of explaining it. You're right, one byte for the seq is a good idea and enum works well with that. I'll just need to do a progess switch statement and a fail switch statement for every sequence

But, the problem is I would have a maze of ifs to check through. And while 99% of the time they won't make it past the first if its quiet a bit of rom to use. My search idea is tempting but I'm hesitant to write a function that accepts a sequence and determines if it was pressed - IF there is a better way to do this.

I guess for now I'll try a generic state enum deal. But, unless I get a better idea I'll also code the search routine and see which works better.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group