This months Smiley's article

Electronics Computer Programming Q&A
User avatar
Chupa
Posts: 41
Joined: Thu Nov 06, 2008 2:22 pm
Contact:

This months Smiley's article

Post by Chupa » Fri Jan 02, 2009 8:07 am

Smiley's article in this months is about makeing a Nav menu in C. He joked in the article saying that some users would probably laugh at his method of using a state machine and a ton of switch statements which made me wonder if theirs a better way to do it, even if it is more complex.

psycho
Posts: 388
Joined: Thu Jan 10, 2008 8:13 pm
Location: Northwest Indiana
Contact:

Post by psycho » Fri Jan 02, 2009 8:37 am

I would use switch statements, too. You would obviously have to use some sort of decision making statements and a switch statement fits best in this case.

That is, unless you are using a language that doesn't support anything like that. I don't think basic does???

He mentioned about break statements. When I start a case statement, I ALWAYS type:

case somecase:

break;

first. Then I fill in the "meat" of the code. That way I will never forget the break statement.

User avatar
Chupa
Posts: 41
Joined: Thu Nov 06, 2008 2:22 pm
Contact:

Post by Chupa » Fri Jan 02, 2009 1:07 pm

how would one go about writing a menu system without locking the code up.

IE you need to continue to monitor something that cannot cause an INT while also allowing someone to nav though a menu.

psycho
Posts: 388
Joined: Thu Jan 10, 2008 8:13 pm
Location: Northwest Indiana
Contact:

Post by psycho » Fri Jan 02, 2009 1:34 pm

I am not sure I understand your question...

If you use polling, i.e.:

Code: Select all

void main(void) {
  while(1) {
    processmenu();
    do_your_other_stuff();
  }
}
each time processmenu is called, it will process the current state of the buttons and return (i.e. left, right, up ...). If it has to stall, then you would have to either a) accept that the "other stuff" will not be taken care of or b) use an ISR for either the "other stuff" or the menu itself.

I did not download the code for the article so I can't say how Mr. Smiley <?> did it.

You could use and ISR for a change on the port pins (PIC, I am talking about here) and set the state that way. Then, as long as you know the state has changed, update the menu accordingly.

User avatar
Chupa
Posts: 41
Joined: Thu Nov 06, 2008 2:22 pm
Contact:

Post by Chupa » Fri Jan 02, 2009 6:28 pm

you know i cant seem to find any place to download what the article is referencing. It says workshop6 but there's only 1-5 on his site and there's no link in the downloads for this issue section on the N&V site.

But i think i understand what your saying. Sometimes i forget that code is executed so fast on a µC that it wont be an issue to do what your saying.

What i mean is it might be possible for someone to press and release the button for only say... 10ms (highly unlikely) at the exact time the code is off doing something else, so the button polling will miss the press. But also that can be avoided by using the ISR, which you also mentioned.

Good times.

jwax, is this not a N&V forum? :razz:

User avatar
Chupa
Posts: 41
Joined: Thu Nov 06, 2008 2:22 pm
Contact:

Post by Chupa » Fri Jan 02, 2009 6:38 pm

i would have put it in the other section if there hadn't been an article in this months issue.

psycho
Posts: 388
Joined: Thu Jan 10, 2008 8:13 pm
Location: Northwest Indiana
Contact:

Post by psycho » Fri Jan 02, 2009 6:46 pm

Maybe one of the moderators can move it.

It is quite possible that a "keystroke" could be missed. For instance, you were saving the "configuration" of your device to an I2C EEPROM. Say that configuration is 100 bytes. In this case you would make the user wait (and show a message on the display). If I remember right, the normal write time for a byte is ~5ms. that would mean a half a second at minumum.

But, under normal conditions, you could use polling.

If I were going to do it, I would use interrupt on change and enable the device to wake from sleep on a button press. This way you can put the uC to sleep and not show anything on the display (big power savings). When the user presses a button, the uC wakes up and, if you saved the previous state, you can continue there.

A bit long winded, but....

User avatar
Chupa
Posts: 41
Joined: Thu Nov 06, 2008 2:22 pm
Contact:

Post by Chupa » Fri Jan 02, 2009 7:44 pm

yea using a pin INT on the nav buttons would make a lot of scene. good information for project im working on. Thanks!

thank god it was moved. it was causing so much trouble being the general section.

psycho
Posts: 388
Joined: Thu Jan 10, 2008 8:13 pm
Location: Northwest Indiana
Contact:

Post by psycho » Fri Jan 02, 2009 7:52 pm

On the menu system, I ordered some rotory encoders a while back to do a module for user interface control. Never did get around to doing anything with them (yet).

User avatar
philba
Posts: 2050
Joined: Tue Nov 30, 2004 1:01 am
Location: Seattle
Contact:

Post by philba » Sat Jan 03, 2009 8:46 am

Presuming you are using a microcontroller. If you have a timer available, you can always use the timer interrupt to do the device polling. In general, I try to poll switches/buttons this way rather than use interrupts or main loop polling. There are several reasons for this:
- interrupt pins are often scarce
- bounce causes problems with interrupt driven switches (multiple interrupts per event)
- debouncing is easy with polling, harder with interrupt driven switches

Polling the switches in the main loop of your code is a bad idea in general. Not only do you potentially lose switch events but debouncing wastes time (or is much more complex).

User avatar
Chupa
Posts: 41
Joined: Thu Nov 06, 2008 2:22 pm
Contact:

Post by Chupa » Sat Jan 03, 2009 2:56 pm

philba wrote:Presuming you are using a microcontroller. If you have a timer available, you can always use the timer interrupt to do the device polling. In general, I try to poll switches/buttons this way rather than use interrupts or main loop polling. There are several reasons for this:
- interrupt pins are often scarce
- bounce causes problems with interrupt driven switches (multiple interrupts per event)
- debouncing is easy with polling, harder with interrupt driven switches

Polling the switches in the main loop of your code is a bad idea in general. Not only do you potentially lose switch events but debouncing wastes time (or is much more complex).
Your saying to poll the button registers every X amount of time using a timer? How often do you suggest doing this?

User avatar
philba
Posts: 2050
Joined: Tue Nov 30, 2004 1:01 am
Location: Seattle
Contact:

Post by philba » Mon Jan 05, 2009 12:44 pm

I typically use a 5 mS timer. This is so I can debounce the switch. Here's the general idea:

Code: Select all

#define SWMAX = 3
unsigned char sw1;

switch_poll_ISR() {
    if( SWITCH_PIN_1 ) 
        if(sw1 < SWMAX) sw1 += 1;       // increment sw1
    else
        if(sw1 > 0) sw1 -= 1;           // decrement sw1
}

// in main line code
if(sw1 == SWMAX)    // switch is on?
if(sw1 != SWMAX)     // switch is off?

With a 5 mS sample period, you get 15 mS debounce time. Most switches bounce for less than 15 mS so that works pretty well. Depending on your processor, this will take on the order of a few percent CPU overhead. You could reduce the overhead by increasing the period and decreasing the number of samples.

If you have lots of switches, you can save space by packing the SW counters into a single byte (4 per byte) but the increment and test operations are more complex.

Another approach is to use a 2 sample scheme. This is effective for lots of switches. Set your sample frequency to the max debounce latency - say 20 mS. On first sample, read the pin (or a port of pins) and save the results. Next sample, read the pin and compare against the saved sample, if there are both on (or off for pulled high), then the switch is closed. If either is off, then the switch is open. (then save the latest sample) You can use simple logic operations for the test so it is fast.

User avatar
philba
Posts: 2050
Joined: Tue Nov 30, 2004 1:01 am
Location: Seattle
Contact:

Post by philba » Mon Jan 05, 2009 12:47 pm

I seem to have lost the ability to edit my posts. There's a slight error. its should be
#define SWMAX 3

User avatar
Chupa
Posts: 41
Joined: Thu Nov 06, 2008 2:22 pm
Contact:

Post by Chupa » Mon Jan 05, 2009 12:49 pm

philba wrote:I typically use a 5 mS timer. This is so I can debounce the switch. Here's the general idea:

Code: Select all

#define SWMAX = 3
unsigned char sw1;

switch_poll_ISR() {
    if( SWITCH_PIN_1 ) 
        if(sw1 <SWMAX> 0) sw1 -= 1;           // decrement sw1
}

// in main line code
if(sw1 == SWMAX)    // switch is on?
if(sw1 != SWMAX)     // switch is off?

With a 5 mS sample period, you get 15 mS debounce time. Most switches bounce for less than 15 mS so that works pretty well. Depending on your processor, this will take on the order of a few percent CPU overhead. You could reduce the overhead by increasing the period and decreasing the number of samples.

Ooo I like that a lot. Im going to start doing that. Thanks a lot!

User avatar
Michael Kaudze
Site Admin
Posts: 16300
Joined: Fri Nov 22, 2002 1:01 am
Location: at work
Contact:

Post by Michael Kaudze » Tue Jan 06, 2009 8:58 am

http://www.nutsvolts.com/index.php?/mag ... ue/2009/01

Click on the Smiley Micros column to get the download file. All downloads can now be found on the issue they were mentioned in.

Post Reply

Who is online

Users browsing this forum: No registered users and 10 guests