-
• #2
Sample output from KeypadMDS_Inline.js code (with AC control application in mind that toggles power and fan and 'ups' and 'down' temperature):
_____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v80 Copyright 2015 G.Williams >echo(0); =undefined 949377234.41604518890 scan si: 0 - di: 0 - s: 0 949377234.41604518890: Button # 0 pressed: pwr toggle 4.81315994262 scan si: 0 - di: 0 - s: 0 scan si: 0 - di: 1 - s: 0 949377241.43724060058: Button # 2 pressed: temp down -1.82220757007 2.95375728607 scan si: 0 - di: 0 - s: 0 scan si: 0 - di: 1 - s: 0 scan si: 0 - di: 2 - s: 0 949377246.60013008117: Button # 4 pressed: fan toggle 6.82493495941 scan si: 0 - di: 0 - s: 0 scan si: 0 - di: 1 - s: 0 949377255.63546943664: Button # 2 pressed: temp down 78.17845439910 scan si: 1 - di: 0 - s: 0 scan si: 1 - di: 1 - s: 0 949377336.02310276031: Button # 3 pressed: temp up -1.92238414287 2.93543815612 scan si: 1 - di: 0 - s: 0 949377341.16769027709: Button # 1 pressed: N/C 0.59415245056 scan si: 1 - di: 0 - s: 0 scan si: 1 - di: 1 - s: 0 scan si: 1 - di: 2 - s: 0 949377343.96973037719: Button # 5 pressed: N/C >
Noteworthy are lines with the negative numbers: Events in espruino are queued.... and with a lousy switch - I just used I wire to touch a Espruino Pico castellation pad which produced a lot of queud events... interestingly not on the touch, but on the 'move away' which then on scan did not show any buttons pressed. Therefore,
.np
- earliest / Next allowed Press time is set - with current time plus set debounce time - and checked to filter and ignore these events. It helos avoid faulty callbacks for now, but I'm not settled on it it yet. There must be a better approach... I hope.Verified module usage with this code:
var dbg = true; var log = function() { console.log(arguments.join("")); }; // var keypad = keypadModule.connect( // for inline use var keypad = require("KeypadMDS").connect( // for module use [B13,B14,B15], [B1,B10], function(btn,tme){ // 0,1,2,3... if (dbg) log("" + tme + ": Button # ",btn," pressed: " , [ "pwr toggle","N/C" , "temp down" ,"temp up" , "fan toggle","N/C" ][btn] ); });
Producing this output:
_____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v80 Copyright 2015 G.Williams >echo(0); =undefined 949385591.92534446716: Button # 3 pressed: temp up 949385600.08324909210: Button # 5 pressed: N/C 949385630.64551258087: Button # 0 pressed: pwr toggle 949385633.89211368560: Button # 2 pressed: temp down 949385641.41957569122: Button # 0 pressed: pwr toggle 949385645.01201820373: Button # 4 pressed: fan toggle >
-
• #3
Looks great - just wondered though, how is this different to the existing http://www.espruino.com/KeyPad module? I think that does a very similar thing with pullups/watches.
-
• #4
@Gordon, ...just returning from looking at it for he first time... :( ... :[ ... 8{... LOL
Intially, I had the feeling there must be already something because you listed a keypad under items with Espruino... but somehow did not look it up... and the problem kind of 'challenged' me. So my work was totally unbiased... may be because of the forum question and not finding a reference to the keypad module in your post there, I ventured into this exercise. Looking now at the existing moudule, it feels really like a programming excercise (like at a job interview)... but it was fun and is even more fun now to look at both and have 3rd thoughts (phase of 2nd thoughts have long gone).
Conceptually I find the same things: array of driving pins and array of sensing pins, setting and clearing watches. Differences are:
- 'both' and 'repeat' on watches vs. only falling or rising and single
- read/write with array of pins in one shot where possible vs. looping through pin arrays
- closure/ module using functions vs. object with methods
- user can ask status (scan status) when no callback is provided vs. always requires callback
- available module has no enable/disable
Have to test and figure out behavior... used just wire to touch the castellation pads (have no keypad and was too lazy to wire up a DIY), and got flurry of events, which puzzled me, because I asked for 'repeat: false' in setWatch-option. Initially, in scan (readStatus in existing module), I wanted to use just the digitalWrite/Read with implicite output / input pinMod() setting on the driving pins, but it did not do what I wanted... may be I missed something or most likely got derailed by some other temporary issues the code had.
Other than that, about the same... the available module looks a bit leaner due to function use and write/read of array. Both use set and clear watches... not much other way to do that.
- 'both' and 'repeat' on watches vs. only falling or rising and single
-
• #5
After having looked through both implementations side by side, I'm looking for some enhancement:
- control - restrict to or allow - single mutual and multiple simultaneous pressed buttons, respectivley (easier to implement in the readStatus() approach of existing module)
- information about button-down (press event) / button-up (release event) either by info in single callback or by having separate callbacks
- long-press support to call callback(s) multiple times with repetition speed option (useful in settings dialogs over a range with incrementing increments/decrements, 1 unit for 5 units or for defined time, 5...n units after that for number of units or defined time, n...m units after that...
I'm thinking about a simple and lean for simple requirements, and dynamically extensible for more elaborate requirements. Minification may though defeat that in standard use. Minify and split up could be an option... or just have two modules with compatible simple interface.
- control - restrict to or allow - single mutual and multiple simultaneous pressed buttons, respectivley (easier to implement in the readStatus() approach of existing module)
-
• #6
multiple simultaneous pressed buttons
That could be difficult - it was talked about in another thread on here, but unless you have diodes across each button it can get difficult to determine which button is pressed without 'ghosting'.
But yes, I'm happy for you to submit a separate KeyPad module with extra features in it...
'After-completed-comment': Check out existing KeyPad.js module and its doc... and look at this conversation's code as a programming exercise... and a different style of doing things in JS...
Adding a human interfac / user interface is always a challenge. Below code provides you with function to drive and sense a matrix key pad with any nuber of rows and columns directly with Espruino. You need no other things than a passive - bought or DIY - key pad. For DIY, you need only push buttons and wire them in a matrix and let each button connect its row with its column wire when pressed. Then you connect the row and column wires to Espruino GPIO pins.
Schema of market available or DIY key pad with 12 keys (4 rows, 3 cols):
No additional components are needed: GPIO pins provide the built-in pull-up/down resistors to supprt the press detection and scanning.
Usage in your applicaiton is very simple - for example, for a 12-key pad driven with 4 row pins A0..3 and sensed with 3 column pins A4..6 (and default values for start enabled, watching falling edge, and 200[ms] debouncing):
Principle of operation is:
The code inlcudes some more functions to avoid overlapping and overruning events. It also includes two console log/debug statments in
.scan()
- lines 73 and 80 - to be removed for use in your project. Code is attached for easy download and use. Placed in 'project sandbox modules' folder (see Espruiono IDE setings), it can be pulled as KeypadMDS module withrequire("KeypadMDS")
.*Fedback is welcome. 'Exercise' was triggered by - paraphrased - How can I do some Arduino(-like) loop to monitor my hardware events...* (see conversation).
3 Attachments