-
• #2
Wire things up as shown in attached picture and use two no-repeat
setWatch(...)
on pinD1
initialized withpinMode(D1,"input_pullup")
. Setup first watch withedge:"falling"
to take the time witht0 = getTime()
and setup of second watch withedge:"rising"
with taking the time again (t1
) and re-setup first watch. Regarding the debounce time, you have to play a bit. In second watch you also calculate the difference of both times taken and show it somehow... for example by blinking as many seconds the button has been held. If it is a long time, you may use a green blinks for the tens of seconds and red blinks for the ones of seconds... ;-)
1 Attachment
-
• #3
For testing your wiring, upload this code. First, it sets pinMode of pin D1. After that - every 100[ms] - it writes to the LED1 the opposite what it reads from pin D1. When the switch is open, then D1 is (weak) pulled up (by internal resistor) and digital read returns 1 (or H/high or true), the opposite written to the LED1 turns it off. When switch is closed (pressed), D1 is pulled to Ground, D1 reads 0 (or L/low or false), and opposite written to LED1 turns it on. Variable iId - interval ID - is there so you can stop the program by entering
clearInterval(iId)
in the console.pinMode(D1,"input_pullup"); var iId = setInterval(function() { LED1.write(!digitalRead(D1)); }, 100);
2 Attachments
-
• #4
Below is the code as described in post #2. The cycle starts over again after display has completed. Display is a series of blinking green and red blinking:
- green for every 10 seconds
- red for every second remaining
very brief red flash for less then a second
// puckD1extPushButton.js pinMode(D1,"input_pullup"); var log = function() { console.log(arguments); } , lon = false // log on / off , blT = 200 // blinkTime (on and off time) , flT = 20 // flashTime (for less than a second pressed) , t0, t1 , wIdD, wIdU , down = function() { if (wIdU) clearWatch(wIdU); wIdD = null; t0 = getTime(); wIdU = setWatch(up,D1 ,{repeat:false, edge:"rising",debounce:10}); } , up = function() { if (wIdD) clearWatch(wIdD); wIdU = null; t1 = getTime(); setTimeout(show,10,Math.floor(t1 - t0)); } , show = function(t) { if (lon) log(t); if (t>10) { LED2.set(); setTimeout(function(){ LED2.reset(); setTimeout(show,blT,t-10); },blT); } else if (t>0) { LED1.set(); setTimeout(function(){ LED1.reset(); if (--t>0) { setTimeout(show,blT,t); } else{ start(); } },blT); } else { LED1.set(); setTimeout(function(){ LED1.reset(); setTimeout(start,blT); },flT); } } , start = function() { wIdD = setWatch(down,D1 ,{repeat:false, edge:"falling",debounce:10}); } ; function onInit() { start(); } setTimeout(onInit,999); // comment line before upload for save()
With a pretty decent - not much bouncing switch - there should be a much simpler solution... except for the display, which then gets a bit more complicated: results would have to be written to a queue and display would run asynchronously / simultaneously. To distinguish between flash/blink sequences, blue led could be flashed between the sequences.
- green for every 10 seconds
-
• #5
And here is the 'short' version:
// puckD1extPushButton2.js pinMode(D1,"input_pullup"); var log = function() { console.log(arguments); } , lon = false // log on / off , wId , change = function(evt) { if (lon) log(evt); if (evt.state) { setTimeout(note,1,(Math.floor(evt.time - evt.lastTime))); } } , note = function (t) { // note (for show) console.log(t); } , start = function() { wId = setWatch(change,D1 ,{repeat:true, edge:"both",debounce:10}); } ; function onInit() { start(); } setTimeout(onInit,999); // comment line before upload for save()
If you turn the logging on (lon = true), then you see what is goin on:
The
evt
is the event object passed to the functionchange()
called by the watch. The watch is now setuprepeat:true
andedge:"both"
: In other words,change()
is called on press AND on release of the push button. The event object passed has 3 very convenient properties:- The
state
tells the state of the pin / what the has changed to - on press it is L/false and on release it is H/true, - The
lastTime
tells when the watch fired the last time. If it is the first time, then it isundefined
- The
time
tells the time of the current watch firing.
Using the event object simplifies the code a lot. Below show the log of the event object. Notice the first time - when the button was pressed for the first time - lastTime is undefined. On press event of the button we have to do nothing, but on release, we calculate the difference and pass it to the show function. In this example, the show function just logs the value in the console.
Notice, that with this solution, we could run into time binds: new press and release events may happen faster than display can happen. Some queueing and asynchronous display of the result can help to avoid it. Calling
note()
with a timeout makes it also asynchronous. The functionnote()
would then putt
into a FIFO / Queue and - when it is the first entry - start the display process. The display process would then take value by value out of the FIFO / Queue and show the value until the FIFO/Queue is empty. Consuming the queue follows the same asynchronous pattern as in previous example the show function.[ { "state": false, "lastTime": undefined, "time": 1644153426.08500003814 } ] [ { "state": true, "lastTime": 1644153426.08500003814, "time": 1644153428.08899998664 } ] [ { "state": false, "lastTime": 1644153428.08899998664, "time": 1644153429.83899998664 } ] [ { "state": true, "lastTime": 1644153429.83899998664, "time": 1644153431.21399998664 } ] [ { "state": false, "lastTime": 1644153431.21399998664, "time": 1644153433.33699989318 } ] ....
Now, @user140111 - Alberto - it's your turn to complete the code and add the display logic with the queue and show. What makes the things so easy to understand is that there is only one thread executing JS... (speaking in os terms...).
(PS: My dad's first name was Albert - the German version of yours...).
- The
-
• #6
Thank you very much for your very detailed instructions. You are very kind. I'll try and let you know if everything is clear to me. You're right, my name has German origins even though I'm Italian and my ancestors have French origins.
I would like to add an external button and count how many seconds this is pressed. Can someone help me?
Alberto