Go Down

Topic: Beginners first program, port addressing and button input (Read 430 times) previous topic - next topic

stirfoo

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: [Select]

/*                                                                             
  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;
}

PaulS

Code: [Select]
    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.

stirfoo

#2
Jan 31, 2013, 11:24 pm Last Edit: Jan 31, 2013, 11:31 pm by stirfoo Reason: 1
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: [Select]

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.

PaulS

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.

UKHeliBob


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.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

stirfoo

Quote
What kind of switches are you reading?


Using a tactile momentary switch.




stirfoo

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:

johncc


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


(alone
  (forthat
     (+ karma 1)))

Go Up