Pages: [1]   Go Down
Author Topic: Beginners first program, port addressing and button input  (Read 419 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 1
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's 2:30AM and I've had entirely too much coffee.  smiley-eek

I got an Uno and I'm having a blast with it. It works on Linux... with Emacs + make. Hallalujah!

I have a (guitar pedal related) project I'd like to implement, but I have to learn how microcontrollers work first. It's loosely described here: http://www.diystompboxes.com/smfforum/index.php?topic=101045.0

My project will require 16 push buttons. So I've been reading all I can find on the topic (shift registers, debouncing, etc.).

Here is some code I came up with. A 7 segment display is incremented once, when -- and only when -- the button transitions from released to pressed. I don't really have a specific question. I'd just like know if I'm headed in the right direction.

Code:
/*                                                                             
  Increment a 7 segment display once per button press.                         
                                                                               
  Written for Arduino Uno Rev 3.                                               
                                                                               
  Uno pins 0-6 are segments a-g respectively.                                   
  Pin 8 is the button input.                                                   
                                                                               
  7 segment display is common cathode.                                         
  Button down is 0v, up is 5v;                                                 
 */

/******************************************                                     
  NOTE: Unhook pin 0 and 1 before uploading                                     
*********************************************/

const int but = 8;

const byte segMap[] = {
    0x3F,       /* 0 */
    0x06,       /* 1 */
    0x5B,       /* 2 */
    0x4F,       /* 3 */
    0x66,       /* 4 */
    0x6D,       /* 5 */
    0x7D,       /* 6 */
    0x07,       /* 7 */
    0x7F,       /* 8 */
    0x6F,       /* 9 */
    0x77,       /* A */
    0x7C,       /* B */
    0x39,       /* C */
    0x5E,       /* D */
    0x79,       /* E */
    0x71,       /* F */
};

int butPressed();
void increment();

void setup() {
    DDRD = 0x7f;                /* set pin 0-6 output */
    pinMode(but, INPUT);
    PORTD = segMap[0];          /* initialize display to 0 */
}

void loop() {
    if (butPressed())
        increment();
}

/*                                                                             
  Increment the display once per call.                                         
  Start at 0 (initialized in setup()). After F is displayed, start over.       
*/
void increment() {
    static int n = 1;
    PORTD = segMap[n];
    n = ++n % 16;
}

/*                                                                             
  Return 1 only if the button has transitioned from released to pressed.       
  Return 0 otherwise.                                                           
 */
int butPressed() {
    static int oldVal = 1;
    int val = 0, ret = 0;
    for (int i=0; i!=3; ++i) {
        val = digitalRead(but);
        delay(10);
    }
    ret = (oldVal && !val);
    oldVal = val;
    return ret;
}
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 654
Posts: 50931
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
    for (int i=0; i!=3; ++i) {
The middle part of a for statement is a while clause. Using == and != works, but <, <=, >, and >= are more intuitive and obvious, in my opinion.

The final part is the increment clause. While ++i or i++ work there, i++ is far more common.

However, the far more important issue is why are you reading digital switches more than once? Only the last reading matters, so you might as well simply have a delay() 30 before you read the switch once, and a delay(10) afterwards.

Anding and notting are typically done with boolean values.

That code does not debounce the switch, and is a rather complicated method of detecting the state change.
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
However, the far more important issue is why are you reading digital switches more than once?

Yeah, that was pretty convoluted. I have no idea what I was thinking there.

I found this article on debouncing: http://www.ganssle.com/debouncing.htm

In the software debouncing section (part 2) I like the way the samples are shifted into a value then masked to test for the edge of the transition. That's really what I'm after. The edge transition.

I adapted the code using an 8 bit sample instead of 12.

Code:
int butPressed() {
    static unsigned int state = 0;
    state = (state << 1) | digitalRead(but) | 0xfe00;
    delay(4);
    return (state == 0xff00);
}

/*
          +-------- eight 'button down' samples in a row
          v       v
1111 1111 0000 0000
        ^
        +------- and the previous sample was 'button up'
*/

I actually understand how this works. What is giving me fits is the delay. How much, and do I delay in butPressed() or loop(). Ultimately the program will be doing much more than checking a single button.

The reason I'm using a 7 seg is so I can actually see if there are multiple state changes per button press. (Instead of trying to say, catch the flicker of a single LED). That's why I assumed the first version was working okay: one button press == exactly one state change in the display.
« Last Edit: January 31, 2013, 05:31:16 pm by stirfoo » Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 654
Posts: 50931
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What kind of switches are you reading? How long do they typically bounce? Typically, switches bounce for less than 10 milliseconds.

A delay(10) in the butPressed() function is probably the best value/place for it.

Quote
I adapted the code using an 8 bit sample instead of 12.
A digital switch is either pressed or not. That's one bit. Food for thought.
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 118
Posts: 4405
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How much, and do I delay in butPressed() or loop()
Answers - none and don't
Have a look at the debounce example in the IDE to see how to do non blocking debouncing.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Offline Offline
Newbie
*
Karma: 1
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What kind of switches are you reading?

Using a tactile momentary switch.



Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Have a look at the debounce example in the IDE to see how to do non blocking debouncing.

I'll take a look. I haven't been using the IDE at all. For good or bad, I'm thoroughly dependent on emacs keystrokes. smiley-red
Logged

Temple, Texas
Offline Offline
Sr. Member
****
Karma: 14
Posts: 361
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For good or bad, I'm thoroughly dependent on emacs keystrokes. smiley-red

(alone
  (forthat
     (+ karma 1)))
Logged

Pages: [1]   Go Up
Jump to: