Pages: [1]   Go Down
Author Topic: AnalogButtons repeat?  (Read 1008 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there any way to get the AnalogButtons library to repeat a key when held down? I tried a few different ways to no avail.

Code:
void handleButtons(int id, boolean held)

  if (held) {
    Serial.print("button id="); Serial.print(id); Serial.println(" was pressed and held");
    int num = 0;
    do
{
    num = num++;
    Serial.println(num);
    delay(50);
    analogButtons.checkButtons();
} while (held);
   
  } else{
    Serial.print("button id="); Serial.print(id); Serial.println(" was pressed only");
  }
}

don't work...

Still learning. smiley I want this to work like a PC keyboard when the button is held down. Thanks for any help in advance!
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 597
Posts: 33292
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Stop using the baby AnalogButtons library and just write the functions yourself. Then you have control over what is happening and you can make it do what you want.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What's wrong with AnalogButtons ? It even has an overridable held() method, which should solve the OP's problem.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tuxduino, can you elaborate on the "overridable held() method" ? Very new to programming and trying to learn. Thanks
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hmm... if you're very new to programming it might be difficult to explain... Do words like class, object, method, base and derived class make sense to you ?

I'm trying held() right now, think I'll post an example soon.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No need to derive AnalogButtons and override held(), it seems. Here's an example sketch:

Code:
#include <AnalogButtons.h>

const byte ANALOG_PIN = 0;


void handleButtons(int id, boolean held) {
    if (held) {
        Serial.print("button id=");
        Serial.print(id);
        Serial.println(" was pressed and held");
    }
    else {
        Serial.print("button id=");
        Serial.print(id);
        Serial.println(" was pressed only");
    }
}


AnalogButtons analogButtons(ANALOG_PIN, 30, &handleButtons);
/*
nokey = 801..1023
ok = 601..800
left = 401..600
down = 201..400
up = 101..200
right = 0..100
*/
Button btnOk    = Button(1, 601, 800);
Button btnLeft  = Button(2, 401, 600);
Button btnDown  = Button(3, 201, 400);
Button btnUp    = Button(4, 101, 200);
Button btnRight = Button(5,   0, 100);


void setup() {
    Serial.begin(115200);
    analogButtons.addButton(btnOk);
    analogButtons.addButton(btnLeft);
    analogButtons.addButton(btnDown);
    analogButtons.addButton(btnUp);
    analogButtons.addButton(btnRight);
}


void loop() {
    /*
    Serial.println(analogRead(ANALOG_PIN));
    delay(1000);
    */
   
    analogButtons.checkButtons();
}

No repeat support, it seems, at least out-of-the-box.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No need to derive AnalogButtons and override held(), it seems. Here's an example sketch:

Code:
#include <AnalogButtons.h>

const byte ANALOG_PIN = 0;


void handleButtons(int id, boolean held) {
    if (held) {
        Serial.print("button id=");
        Serial.print(id);
        Serial.println(" was pressed and held");
    }
    else {
        Serial.print("button id=");
        Serial.print(id);
        Serial.println(" was pressed only");
    }
}


AnalogButtons analogButtons(ANALOG_PIN, 30, &handleButtons);
/*
nokey = 801..1023
ok = 601..800
left = 401..600
down = 201..400
up = 101..200
right = 0..100
*/
Button btnOk    = Button(1, 601, 800);
Button btnLeft  = Button(2, 401, 600);
Button btnDown  = Button(3, 201, 400);
Button btnUp    = Button(4, 101, 200);
Button btnRight = Button(5,   0, 100);


void setup() {
    Serial.begin(115200);
    analogButtons.addButton(btnOk);
    analogButtons.addButton(btnLeft);
    analogButtons.addButton(btnDown);
    analogButtons.addButton(btnUp);
    analogButtons.addButton(btnRight);
}


void loop() {
    /*
    Serial.println(analogRead(ANALOG_PIN));
    delay(1000);
    */
    
    analogButtons.checkButtons();
}

No repeat support, it seems, at least out-of-the-box.

Instead of writing to serial, you could toggle a boolean flag and have a function in loop that just checks for the flag and use the blink without delay trick ( http://arduino.cc/en/Tutorial/BlinkWithoutDelay ) to write the key to serial every X seconds as long as the flag is up.  (or whatever else the OP had in mind)
« Last Edit: December 31, 2012, 01:35:42 pm by madchaz » Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mmh... Maybe Mike's suggestion was right after all...  smiley-roll-sweat
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tuxduino, yes I have a basic understanding of most of it. this biggest issue I am having is trying to get it to know when you let go of the button. Everything works just I would like to increment a value when the button is held until the button is released just like a PC keyboard would. Maybe someone could help me on this?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I figured it out but thinking for a few min... simple as reading the analog pin (don't even worry about the library) to see if is pressed out not. Man kinda a duh moment huh? Thanks guys for your help. Here is my code in case someone else runs into this.

Code:
    do
{
    num = num++;
    Serial.println(num);
    delay(50);
    analogButtons.checkButtons();
} while (analogRead(A0) < 900);

Here is the working example...

Code:
/*
  AnalogButtons,
 
  created 02 Jan 2009 V 0.1
 
 Connect more than one button to a single analog pin,
 register a call-back function.which gets called when a button
 is pressed or held down for the defined number of seconds. Includes
 software key debouncing which may need to be adjusted, the the second
 argument to AnalogButtons class. Define the ANALOG_PIN in the constructor
 of AnalogButtons.
 
 The circuit:

 * 5 buttons, 1 side of all buttons connected together to +5V.
   The other side of each button is connected via a different value
   resister (tested with) 1k, 2k5, 5k8, 10k, 18k to one side of a
   100k resister which is in turn connected to GND. At the point
   where all the different resisters are joined you make a connection
   to your analog input. Basicly a different voltage divider is setup
   depending upon which button is pressed. You have to configure the
   Buttons Hi/Low values, see the comments in example code below and the
   AnalogButtons::configure(ANALOG_PIN) function.
   
   More or less than 5 buttons could be added, just pick different values
   of the resister sot hat all buttons have different values which arn't too
   close in size.
   
   I'm not sure what happens when Arduino is powered from batteries and Power V
   drops below V5.
 
 by Neil DUdman and everyone who's ever used Arduino
 
 */
#include "AnalogButtons.h"

#define ANALOG_PIN 0

// A call back function that you pass into the constructor of AnalogButtons, see example
// below. Alternitivly you could extend the Button class and re-define the methods pressed()
// or held() which are called


AnalogButtons analogButtons(ANALOG_PIN, 30, &handleButtons);
Button b1 = Button(1, 802,812);
Button b2 = Button(2, 635, 645);
Button b3 = Button(3, 412, 422);
Button b4 = Button(4, 242, 252);
Button b5 = Button(5, 93, 103);
Button b6 = Button(6, 0, 10);

void setup()
{
  Serial.begin(9600);
  Serial.println("Testing your Analog buttons");
 
  analogButtons.addButton(b1);
  analogButtons.addButton(b2);
  analogButtons.addButton(b3);
  analogButtons.addButton(b4);
  analogButtons.addButton(b5); 
  analogButtons.addButton(b6);
 }
 
void loop()

  // To check values when button are pressed
  analogButtons.checkButtons();
 
  // To configure the MAX/Min values for each
  // Button, uncomment this line, make sure you've called Serial.begin(9600);
  // Then in turn hold town each botton, noting the max/min values
  //AnalogButtons::configure(ANALOG_PIN); //delay(1000);
}

void handleButtons(int id, boolean held)

  if (held) {
    Serial.print("button id="); Serial.print(id); Serial.println(" was pressed and held");
    int num = 0;
//Repeat code start
    do
{
    num = num++;
    Serial.println(num);
    delay(50);
    analogButtons.checkButtons();
} while (analogRead(A0) < 900);
//Repeat code end
   
  } else{
    Serial.print("button id="); Serial.print(id); Serial.println(" was pressed only");
  }
}
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

delay() must be avoided at all costs smiley
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The following code has still some rough edges, but works.

I've developed it on a nuelectronics lcd+analog keypad shield, so you might have to adjust the key adc values.

Analog keyboard class:
Code:
#ifndef _ANALOG_KEYBOARD2_H
#define _ANALOG_KEYBOARD2_H


#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif


typedef void (*keyEventHandler)(byte keyId);


class AnalogKeyboard2 {
public:
    AnalogKeyboard2(byte analogPin, byte numKeys) {
        _analogPin = analogPin;
        _numKeys = numKeys;
       
        _lowest = 0;
        _highest = 1023;
        _readIntervalMs = 30;
       
        _prevKey = NO_KEY;
       
        _keyPress = NULL;
        _keyRelease = NULL;
        _keyRepeat = NULL;
       
        _repeatCountMax = 7;
       
        _ranges = (int*)NULL;
    };
   
   
    void run() {
        if (millis() - _prevMillis >= _readIntervalMs) {
            _prevMillis = millis();
           
            byte currKey = getKey();
           
            if ((currKey != NO_KEY) && (_prevKey == currKey)) {
                _repeatCount++;
                if (_repeatCount >= _repeatCountMax) {
                    _repeatCount = 0;
                    if (_keyRepeat != NULL) {
                        (*_keyRepeat)(currKey);
                    }
                }
            }
            else if ((_prevKey == NO_KEY) && (currKey != NO_KEY)) {
                _repeatCount = 0;
                if (_keyPress != NULL) {
                    (*_keyPress)(currKey);
                }
            }
            else if ((_prevKey != NO_KEY) && (currKey == NO_KEY)) {
                _repeatCount = 0;
                if (_keyRelease != NULL) {
                    (*_keyRelease)(_prevKey);
                }
            }
           
            _prevKey = currKey;
        }
    };
   
   
    void setKeyPressHandler(keyEventHandler f) {
        _keyPress = f;
    };
   
   
    void setKeyReleaseHandler(keyEventHandler f) {
        _keyRelease = f;
    };
   
   
    void setKeyRepeatHandler(keyEventHandler f) {
        _keyRepeat = f;
    };
   
   
    void setRanges(int* ranges) {
        _ranges = ranges;
    }
   
   
private:
    byte getKey() {
        if (_ranges == NULL) {
            return getKey1();
        }
        else {
            return getKey2();
        }
    }
   
    byte getKey1() {
        int value = analogRead(_analogPin);
        byte key = map(value, _lowest, _highest, 0, _numKeys);
        return key == _numKeys ? NO_KEY : key;
    };
   
    byte getKey2() {
        int value = analogRead(_analogPin);
       
        for (byte i = 0; i < _numKeys; i++) {
           
            int low  = _ranges[i * 2];
            int high = _ranges[i * 2 + 1];
           
            if ((low <= value) && (value <= high)) {
                return i;
            }
        }
       
        return NO_KEY;
    }

    static const byte NO_KEY = 0xFF;
    unsigned long _prevMillis;
    byte _analogPin;
    byte _numKeys;
    byte _prevKey;
    unsigned int _lowest;
    unsigned int _highest;
    unsigned long _readIntervalMs;
    int* _ranges;
    byte _repeatCount;
    byte _repeatCountMax;
   
    void (*_keyPress)(byte keyNumber);
    void (*_keyRelease)(byte keyNumber);
    void (*_keyRepeat)(byte keyNumber);
};

#endif


Example sketch:
Code:
#include "AnalogKeyboard2.h"

const byte ANALOG_PIN = 0;


void keyPress(byte k) {
    Serial.print("press ");
    Serial.println(k);
}


void keyRelease(byte k) {
    Serial.print("release ");
    Serial.println(k);
}


void keyRepeat(byte k) {
    Serial.print("repeat ");
    Serial.println(k);
}


AnalogKeyboard2 keyb(ANALOG_PIN, 5);


int ranges[] = {
      0,  100,
    101,  200,
    201,  400,
    401,  600,
    601,  800,
};


void setup() {
    Serial.begin(115200);

    keyb.setKeyPressHandler(keyPress);
    keyb.setKeyReleaseHandler(keyRelease);
    keyb.setKeyRepeatHandler(keyRepeat);
    // the following line is optional:
    keyb.setRanges(ranges);
}


void loop() {
    keyb.run();
}
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Slightly update version - has a longer delay for the first repeat, shorter for subsequent repeats.

Code:
#ifndef _ANALOG_KEYBOARD2_H
#define _ANALOG_KEYBOARD2_H


#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif


typedef void (*keyEventHandler)(byte keyId);


class AnalogKeyboard2 {
public:
    AnalogKeyboard2(byte analogPin, byte numKeys) {
        _analogPin = analogPin;
        _numKeys = numKeys;
       
        _lowest = 0;
        _highest = 1023;
        _readIntervalMs = 30;
       
        _prevKey = NO_KEY;
       
        _keyPress = NULL;
        _keyRelease = NULL;
        _keyRepeat = NULL;
       
        _repeatEnabled = true;
        _repeatCountMaxFirst = 14;
        _repeatCountMaxNext = 7;
       
        _repeatCountMax = _repeatCountMaxFirst;
       
        _ranges = (int*)NULL;
    };
   
   
    void enableRepeat() {
        if (!_repeatEnabled) {
            _repeatEnabled = true;
            _repeatCount = 0;
            _repeatCountMax = _repeatCountMaxFirst;
        }
    }
   
   
    void disableRepeat() {
        _repeatEnabled = false;
    }
   
   
    void run() {
        if (millis() - _prevMillis >= _readIntervalMs) {
            _prevMillis = millis();
           
            byte currKey = getKey();
           
            if ((currKey != NO_KEY) && (_prevKey == currKey)) {
                if (_repeatEnabled) {
                    _repeatCount++;
                    if (_repeatCount >= _repeatCountMax) {
                        _repeatCount = 0;
                        if (_keyRepeat != NULL) {
                            (*_keyRepeat)(currKey);
                        }
                       
                        if (_repeatCountMax == _repeatCountMaxFirst) {
                            _repeatCountMax = _repeatCountMaxNext;
                        }
                    }
                }
            }
            else if ((_prevKey == NO_KEY) && (currKey != NO_KEY)) {
                _repeatCount = 0;
                _repeatCountMax = _repeatCountMaxFirst;
                if (_keyPress != NULL) {
                    (*_keyPress)(currKey);
                }
            }
            else if ((_prevKey != NO_KEY) && (currKey == NO_KEY)) {
                if (_keyRelease != NULL) {
                    (*_keyRelease)(_prevKey);
                }
            }
           
            _prevKey = currKey;
        }
    };
   
   
    void setKeyPressHandler(keyEventHandler f) {
        _keyPress = f;
    };
   
   
    void setKeyReleaseHandler(keyEventHandler f) {
        _keyRelease = f;
    };
   
   
    void setKeyRepeatHandler(keyEventHandler f) {
        _keyRepeat = f;
    };
   
   
    void setRanges(int* ranges) {
        _ranges = ranges;
    }
   
   
private:
    byte getKey() {
        if (_ranges == NULL) {
            return getKey1();
        }
        else {
            return getKey2();
        }
    }
   
    byte getKey1() {
        int value = analogRead(_analogPin);
        byte key = map(value, _lowest, _highest, 0, _numKeys);
        return key == _numKeys ? NO_KEY : key;
    };
   
    byte getKey2() {
        int value = analogRead(_analogPin);
       
        for (byte i = 0; i < _numKeys; i++) {
           
            int low  = _ranges[i * 2];
            int high = _ranges[i * 2 + 1];
           
            if ((low <= value) && (value <= high)) {
                return i;
            }
        }
       
        return NO_KEY;
    }

    static const byte NO_KEY = 0xFF;
    unsigned long _prevMillis;
    byte _analogPin;
    byte _numKeys;
    byte _prevKey;
    unsigned int _lowest;
    unsigned int _highest;
    unsigned long _readIntervalMs;
    int* _ranges;
    byte _repeatCount;            // conteggio ripetizione tasto
    byte _repeatCountMax;         // quando il counter raggiunge questo valore, scatta l'evento di ripetizione
    byte _repeatCountMaxFirst;    // ritardo prima ripetizione
    byte _repeatCountMaxNext;     // ritardo ripetizioni successive
    boolean _repeatEnabled;
   
    void (*_keyPress)(byte keyNumber);
    void (*_keyRelease)(byte keyNumber);
    void (*_keyRepeat)(byte keyNumber);
};

#endif
Logged

Pages: [1]   Go Up
Jump to: