My newest development in interfacing arduino with input hardware

As some of you may know, I have developed several arduino open-source libraries, phi_buttons, phi_prompt, phi_big_font,phi_morse, phi_super_font, etc.

My main focus is to interface arduino with inputs such as buttons, keypads, etc. and outputs such as LCDs so a project developer doesn't have to through all the trouble to create these themselves. I've been successful with these libraries so far but I'm not completely satisfied with how contributed libraries are maintained.

The reason I developed these codes is that the current status of contributed libraries is that each library is managed by an individual and in order to say use a matrix keypad and a couple of rotary encoders, you need at least two libraries and they follow different conventions and you are expected to learn different things with each new library you come across. And most of them don't even support hold-and-repeat! Not to mention lots of them are no longer maintained and are left to rot. There has to be some common basis among some of the libraries so a general expectations are met, such as each keypad library should have a getKey for getting a key press regardless who wrote the library, through inheriting from a common interface.

Here is what I've just done in the past few weeks, using what I already had as basis:

I've made a new library called phi_interfaces library. At the moment it contains classes such as single buttons, matrix keypads, analog buttons (essentially a keypad in nature), rotary encoders, and liudr keypad, plus some nice things shared by these classes.

To write a project, you just need to include one library, the phi_interfaces.h, and you can create objects such as single buttons, matrix keypads, rotary encoders etc and they all behave as expected.

The matrix keypads, analog buttons (keypad in nature), rotary encoders, and liudr keypads (or any other future keypads) are all inheriting from multiple_button_input, which has a function called getKey, same as the popular keypads library. Any of these objects can provide buttons pressed with this function. They all support hold-and-repeat and essentially can support my multi-tap codes if they have at least 10 number keys. If you are interested in expanding this interface to a different type of keypad, say a capacitive keypad, all you have to do is to write a sense_all() code to provide the interface a handle to sense all possible buttons and give an immediate status. All the debouncing and status changes are handled by interface functions and eventually by the getKey. So even a library developer will save time by not having to write their own debouncing etc. while we can all contribute to the polishing of these basic codes.

This also makes my library expansion much easier.

The buttons class is a subclass of the single_button_input class (interface). The interface has a few functions, sense() being the most useful function. Any classes using this interface will need to implement this function so they can be controlled the same way.

Future development will support IR remote, PS/2 keyboard, etc under the multiple_button_input, which will all support the getKey method.

Attached is an organization chart for the classes. Any suggestions?

Blog page:

I like the idea of having a total HMI interface in a single library.

Are all appropriate inputs debounced and if so is the time adjustable?

Encoders - grey scale as well as binary.

Keypads - X and Y configurable.


Rob

Graynomad:
I like the idea of having a total HMI interface in a single library.

Are all appropriate inputs debounced and if so is the time adjustable?

Encoders - grey scale as well as binary.

Keypads - X and Y configurable.


Rob

Rob,

Thanks for the kind words. All buttons and keypads are debounced but at the moment they are defined. This can be easily changed and the interface could support such functions easily. Encoder is not debounced since I am using the sequence {0,1,3,2,0,1,3,2,0} with a binary number that is made up by chnA and chnB combined. A successful dial click up or down has to follow all four numbers to register so this makes debouncing unnecessary.

The encoder keeps record of its orientation (0 to detent-1) you can call rotary_encoder.get_angle().

You may have any dimension for rows and columns.

All keypad subclasses are sensed and translated the same way with a char array of key names like:

char key_mapping_matrix[]={'1','2','3','A','4','5','6','B','7','8','9','C','*','0','#','D'};

All keypads also return NO_KEY just like the popular keypad library does.

If you start with an analog keypad LCD shield and then run out of buttons then you can just switch to a matrix keypad and don't need to change code since all the interfaces are the same. Only the underlying sense_all() is different for each type of keypad.

{0,1,3,2,0,1,3,2,0}

Looks like a grey code to me. But how can you enforce this, there are different types of encodes are there not?


Rob

Graynomad:

{0,1,3,2,0,1,3,2,0}

Looks like a grey code to me. But how can you enforce this, there are different types of encodes are there not?


Rob

I actually didn't know what grey code meant. Just googled it :slight_smile: I know only two types, the always-off, common to GND ({3,2,0,1,3,2,0,1,3}), and the always-on, common to GND ({0,1,3,2,0,1,3,2,0}), both have detent. At the moment one can choose one of the two by changing the line in the library. I can certainly make an option of this. I'm expecting the user to stick with one type, instead of finding random parts and hodgepodge them together :slight_smile:

Are there any more grey codes? For common to 5V? Thanks!

Are there any more grey codes?

There will be, I haven't looked at them for years but IIRC there are versions with a lot more codes than you have there, a grey code after all is just a code where only a single bit changes for every new value.

Grey codes are normally used for absolute encoders I thought, a relative encoder should have no need for such things.


Rob

@liudr,
2 Q's:

  • can you tell any details about footprint of your new lib?
  • 1.0 compatibility?

robtillaart:
@liudr,
2 Q's:

  • can you tell any details about footprint of your new lib?
  • 1.0 compatibility?

The footprint of my library is hard to tell. Do you want me to create one object of each class in a sample code and see how big the binary code is? Or what do you suggest to test its footprint? I have a keypads class with functions to handle status change etc so each sub class only handles the actual reading of the keypad, one function that is, for each additional keypad type + special functions that keypad could define.

Yes it's compatible with 0022 and 1.0 I compiled all my code in both versions.

two questions:

1 - do your matrix keypad functions detect multiple, simultaneous keypresses?
2 - when and where will it be available for download?

(see my question in "project guidance" for what i'm trying to accomplish: http://arduino.cc/forum/index.php/topic,86535.0.html)

Answers:
1 - Not at the moment. My library is focused on operating panel type of applications instead of full function keyboards. I can add a function to output a matrix that describes what keys are currently depressed but I don't know how to debounce that matrix.
2 - I'm still adding contents so I hope I can release soon. Everything I've added has been tested with my hardware to work flawlessly, which took time to do.

I read through your post. So you are trying to make a keyboard controller with arduino. It's certainly doable but again there's no ready-to-use code that I'm aware of to detect multiple key presses on a matrix keypad. I will ponder on this a bit to see how useful it is to arduino users to include this in my library.

Updates:

Now the classes have the following functions and static variables:

  virtual void set_hold(unsigned int ht) {buttons_hold_time=ht;}; // Key down time needed to be considered the key is held down
  virtual void set_debounce(unsigned int dt) {buttons_debounce_time=dt;}; // Key down time needed to be considered the key is not bouncing anymore
  virtual void set_dash_threshold(unsigned int dt) {buttons_dash_threshold=dt;}; // Key down time needed to be considered the key is held down long enough to repeat in a dash speed
  virtual void set_repeat(unsigned int rt) {buttons_repeat_time=rt;}; // Delay between repeating of a held key
  virtual void set_dash(unsigned int dt) {buttons_dash_time=dt;}; // Delay between dash repeating of a held key
  static unsigned int buttons_hold_time; // Key down time needed to be considered the key is held down
  static unsigned int buttons_debounce_time; // Key down time needed to be considered the key is not bouncing anymore
  static unsigned int buttons_dash_threshold; // Key down time needed to be considered the key is held down long enough to repeat in a dash speed
  static unsigned int buttons_repeat_time; // Delay between repeating of a held key
  static unsigned int buttons_dash_time; // Delay between dash repeating of a held key

The dash is a function that is engaged after the button is held for super long time to make the repeat faster. It's not implemented in keypad type inputs but only implemented in buttons.

I also added a phi_button_arrays sub class under phi_keypads. this is just a collection of buttons on input pins, no matrix or else. The benefit of this is you can at run time switch in and out button mappings so in certain routines, your buttons act as up/down/left/right/enter, and in other times they can act as 'A', 'B', 'C', 'D', enter or else.

This opens up a virtual layer between what buttons are pressed and what functions get executed I think. Just all the more freedom for programming. Plus, this mapped output could have come from a keypad, discrete buttons, or even serial input so you can switch out button sensing and switch in serial.read for debugging. Basically create a series of button pushes from serial port, cool?

New organization chart:

BTW, upload folder on forum server is full so I can only link to images now :slight_smile:

Hi liudr

Excellent idea. I really should combine this with m2tklib (instead of rewriting input procedures again...).

Is there a link from Playground to your lib (so that i can find it again without forum search)?
Is there something to download?

All in all: Good approach!

Oliver

Oliver,

I am glad to hear that you are interested in using this library for your display/user interface library. I will be sure to create a link on Playground this weekend. At the moment I am working on the documentation. Do you have any suggestions on the format for such documentation? I like the avr lib documentation. I wonder if there's any tool to automate such documentation creation.

At the moment I am working on the documentation.
Do you have any suggestions on the format for such documentation?

I do not maintain my own webspace, so I put all onto google code.
The google wiki is sufficient for documentation from my pespective. See the class reference
of my u8g library as an example:

http://code.google.com/p/u8glib/wiki/userreference

Images and code can be added easily, paragraph and text styles are a little bit limited.

Oliver

Thanks! I spent a hour or so extracting the format from the avr lib doc:

This is for library with no class definitions. I'm still thinking about how to better describe classes with this format.

I swear I heard this before but here it is, maybe one of the best and free program/library documentation software: Doxygen

http://www.stack.nl/~dimitri/doxygen/

I'm going to study it a bit and I highly recommend (from what I just read through) other library developers to use it to save time on documentation.

I uploaded a beta version of the library with sample code on every class, buttons, keypads, rotary encoder, analog button arrays (yes! you can use more than one analog pins and each pin hooks up to several buttons but all pins have to have identical resistor networks).

Here it is, with library, example code and an auto-doc. I'm writing an overview for beginners at the moment. Someone is already testing the code :slight_smile:

http://code.google.com/p/phi-prompt-user-interface-library/downloads/detail?name=phi_interfaces.zip#makechanges

With this library, you can arbitrarily change your interface without changing code. Say you start with matrix keypads and then decide go with 6 single buttons and two rotary encoders for the look. You don't have to change you code. Say you start with no buttons (too scared to hook up buttons and then decide to go with keypads?!), and you can use serial port to type in characters. The library has an object to streamline serial inputs into button outputs for your code so your code thinks it has a keypad. Then later you find out you only need like 4 buttons for everything you programmed and actually hooked up 4 buttons and change one line in the code (instantiate a phi_button_arrays object instead of phi_serials object), you're done!

I don't know when I will have time to try it out but, I downloaded it. Sounds really good, thanks!

cyclegadget:
I don't know when I will have time to try it out but, I downloaded it. Sounds really good, thanks!

Great! I'll get the overview doc done with a couple more example codes for the formal release soon.