Pages: [1]   Go Down
Author Topic: Pushbotton Counter  (Read 607 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am working on some software where I have three different cases.  I want it so when the push button is pushed the first time, the first routine occurs.  Then when pushed again, the second routine and then the third.  After the third routine I want the counter to reset to 0. And then start over again.

I conceptually understand how I want to do it, but I can't think of how to program it correctly.  I am an EE lol software is not my expertise. 

Thanks in advance.
Logged

Des Moines, WA - USA
Offline Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
// <http://arduino.cc/forum/index.php/topic,142400.0.html>

class push_button_t
{
    const uint8_t   _pin;
    const uint8_t   _transition_level;
    const uint8_t   _number_of_states;

    uint8_t         _press_counter;
    uint8_t         _state_then;

public:
    push_button_t(uint8_t pin, uint8_t transition_level = LOW, uint8_t number_of_states = 2)
        : _pin(pin)
        , _transition_level(transition_level)
        , _number_of_states(number_of_states)
       
        , _press_counter(0)
        , _state_then(0)
    {}

    void begin()
    {
        pinMode(_pin, INPUT);
    }

    operator uint8_t()
    {
        uint8_t state_now = digitalRead(_pin);
        if ( state_now != _state_then )
        {
            if ( state_now == _transition_level )
            {
                _press_counter++;
                _press_counter %= _number_of_states;
            }
        }
       
       _state_then = state_now;

       return _press_counter;
    }
};

class led_t
{
    const uint8_t     _pin;

public:   
    led_t(uint8_t pin) : _pin(pin)      {}

    void begin()                        { pinMode(_pin, OUTPUT); }
   
    uint8_t operator = (uint8_t rhs)    { digitalWrite(_pin, rhs); return rhs; }
    operator uint8_t ()                 { return ((LOW == digitalRead(_pin)) ? LOW : HIGH); }
};


const uint8_t   pinLED      = 33;   // chipKIT Basic I/O Shield LD1
const uint8_t   pinBUTTON   =  4;   // chipKIT Basic I/O Shield BN1

led_t           led(pinLED);
push_button_t   button(pinBUTTON, LOW, 4);

void loop()
{
    switch ( button )
    {
        case 0: led = 0;                    break;
        case 1: led = !led;  delay(125UL);  break;
        case 2: led = !led;  delay(250UL);  break;
        case 3: led = !led;  delay(500UL);  break;
    }
}

void setup()
{
    led.begin();
    button.begin();
}
« Last Edit: February 01, 2013, 10:49:25 pm by lloyddean » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
push_button_t   button(pinBUTTON, LOW, 4);

void loop()
{
    switch ( button )
    {
The variable button is an instance of a class. It can't be used as in a switch statement.
Logged

Des Moines, WA - USA
Offline Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You might think so but due to the use of the conversion operator 'operator uint8_t()' it can, and does, work just fine.

Try it!
Logged

Des Moines, WA - USA
Offline Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A version for you to test with below, just adjust 'pinBUTTON' as required.

Code:
//#define NDEBUG

#include <Arduino.h>


#if !defined(NDEBUG)

#define DebugStr(STR)           Serial.print(STR)
#define DebugStrln(STR)         Serial.println(STR)
#define DebugDelay(MILLIS)      delay(MILLIS)

#else

#define DebugStr(STR)
#define DebugStrln(STR)
#define DebugDelay(MILLIS)

#endif


class push_button_t
{
    const uint8_t   _pin;
    const uint8_t   _transition_level;
    const uint8_t   _number_of_states;

    uint8_t         _press_counter;
    uint8_t         _state_then;

public:
    push_button_t(uint8_t pin, uint8_t transition_level = LOW, uint8_t number_of_states = 2)
        : _pin(pin)
        , _transition_level(transition_level)
        , _number_of_states(number_of_states)
        
        , _press_counter(0)
        , _state_then(0)
    {}

    void begin()
    {
        DebugStrln(__PRETTY_FUNCTION__);
    
        pinMode(_pin, INPUT);
    }

    operator uint8_t()
    {
        DebugStrln(__PRETTY_FUNCTION__);
    
        uint8_t state_now = digitalRead(_pin);
        if ( state_now != _state_then )
        {
            if ( state_now == _transition_level )
            {
                _press_counter++;
                _press_counter %= _number_of_states;
            }
        }
        
       _state_then = state_now;

       return _press_counter;
    }
};


const uint8_t   pinBUTTON = 4;


push_button_t   button(pinBUTTON, HIGH, 4);


void funct4()   { DebugStrln(__PRETTY_FUNCTION__); }
void funct3()   { DebugStrln(__PRETTY_FUNCTION__); }
void funct2()   { DebugStrln(__PRETTY_FUNCTION__); }
void funct1()   { DebugStrln(__PRETTY_FUNCTION__); }

void loop()
{
    switch ( button )
    {
        case 0: funct1(); break;
        case 1: funct2(); break;
        case 2: funct3(); break;
        case 3: funct4(); break;
    }
}

void setup()
{
#if !defined(NDEBUG)
    Serial.begin(9600);
#endif

    button.begin();
}
« Last Edit: February 01, 2013, 11:14:31 pm by lloyddean » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
You might think so but due to the use of the conversion operator 'operator uint8_t()' it can, and does, work just fine.
In most cases, operators are defined to make a class behave in a manner that the users expect. For instance, one would, in a string class, overload the + operator, or, for a list class, one would overload the {} operator.

I don't see a reasonable use for the () operator in a button class. One does not expect an instance name by itself to be equivalent to a function call. Adding a method to the class, with a meaningful name to get that value returned by the () operator is a MUCH better idea, in my opinion.
Logged

Des Moines, WA - USA
Offline Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

And yet this is exactly what conversion operators are for.  They are a type of 'getter' function.
Logged

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

If you are going to have a conversion operator, is there any reason not to provide conversion to bool instead of to uint8_t?

Or is this just me still having mental problems with digitalWrite( int,int) vs  digitalWrite( int, bool)
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Or is this just me still having mental problems with digitalWrite( int,int) vs  digitalWrite( int, bool)
For that matter, are there really plans to create an Arduino with more than 255 pins? Does digitalWrite() need to use an int as the pin number?
Logged

Des Moines, WA - USA
Offline Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

'digitalWrite' uses 'uint8_t' for both parameters.  And yes other conversion operator can be defined.
Logged

Pages: [1]   Go Up
Jump to: