• This detector is able to notice sudden light changes and calls a callback function with true and false for increase and decrease of a value beyond a slope (dv / dt). The detector accepts a function for reading the value to adjust to any input: light for Puck, analog values, etc.

    Because I did not have the Puck at hand yet, I cross developed in an HTML5 document in the browser. The only failure was that the activity indicator flashing of the red LED impacted the light sensing... all depending the light conditions. Switching to the green LED allowed me to make a clip.

    HTML file is attached and can be run from link below. Clicking Create and Start button and then various Light Intensity buttons shows wether an on - increase - or off was detected. For subsequent increases only the first is triggering the callback.

    The detecter is part of another project which is also 'complete' but subject of a different conversation some time later: A Morse Code detector built with a Puck that interprets the dot-dash sequences and prints the message in clear text...

    From below HTML5/JavaScript code you make a straight copy-paste of the portion between ---BEG--- and ---END--- markers into the Espruino Puck Web IDE and uploaded it to the Puck.

    1. <html><head><title>LightDetector - DvDtDetector</title>
    2. <script> // Espruino Emulation setup
    3. var LED1 = // red LED1 emulation
    4. { id: "LED1"
    5. , setValue: function(value) {
    6. this.value = value;
    7. var node = document.getElementById(this.id);
    8. if (node) { node.style.backgroundColor = ((this.value) ? "red" : ""); } }
    9. , getValue: function() { return this.value; }
    10. };
    11. var LED2 = // green LED2 emulation
    12. { id: "LED2"
    13. , setValue: function(value) {
    14. this.value = value;
    15. var node = document.getElementById(this.id);
    16. if (node) { node.style.backgroundColor = ((this.value) ? "lightgreen" : ""); } }
    17. , getValue: function() { return this.value; }
    18. };
    19. function getTime() { return (new Date().getTime()) / 1000; }
    20. function digitalPulse(pin, value, time) { // digitalPulse() emulation
    21. pin.setValue(value);
    22. setTimeout(function() { pin.setValue(!value) }, time); }
    23. var Puck = // Puck emulation
    24. { _light: 0
    25. , light: function() { return this._light; }
    26. };
    27. var logger = // console 'helper'
    28. { log: function(s) {
    29. var logNode = document.getElementById("log");
    30. logNode.value = s + "\n" + logNode.value;
    31. }
    32. };
    33. </script>
    34. <script> // Espruino / Puck Code
    35. // Espruino / Puck Code
    36. /*
    37. DvDtDetector constructor function taking:
    38. - read: function(detector, time) to return a number
    39. taking (optionally):
    40. - detector: to have access to last time, value
    41. - time: current time getTime() (system time, secs)
    42. for example:
    43. function(){ return Puck.light(); }
    44. - rIntrv: read interval in milliseconds
    45. - slope: slope of increase / -decrease over 1 second
    46. (min change 'rate') to detected a 'switch'
    47. to overcome gradual changes over time,
    48. such as daylight / ambient light changes
    49. - cb: callback function(detected, value, value0)
    50. taking:
    51. - detected:
    52. - true for increase > slope
    53. - false for decrease > -slope
    54. - value: current value
    55. - time: current time (at value taken)
    56. - value0: previous value
    57. - time0: previous time
    58. - aIntrv // active indicator interval in reads, optional, (pos int)
    59. - active // active indicator function(), optional, for example,
    60. // function(b) { digitalPulse(LED2,1,3); }
    61. */
    62. // --- BEG -------
    63. var DvDtDetector = function(read, rIntrv, slope, cb, aIntrv, active) {
    64. this.read = read;
    65. this.rIntrv = rIntrv;
    66. this.slope = slope;
    67. this.cb = cb;
    68. this.aIntrv = aIntrv;
    69. this.active = active;
    70. this._slp = this.slope / this.rIntrv * 1000;
    71. this._sSt = null;
    72. this._iId = null;
    73. this._val = null;
    74. this._tim = null;
    75. this._aTC = 0;
    76. };
    77. DvDtDetector.prototype.start = function() {
    78. if (!this._iId) {
    79. this._val = this.read();
    80. this._tim = getTime();
    81. this._iId = setInterval(
    82. this._dtct.bind(this), this.rIntrv); } };
    83. DvDtDetector.prototype.stop = function() {
    84. if (this._iId) { clearInterval(this._iId); }
    85. this._iId = null; };
    86. DvDtDetector.prototype._dtct = function() {
    87. var v0 = this._val, t0 = this._tim, t = getTime(),
    88. s = ((this._val = this.read(this, t)) - v0)
    89. / ((this._tim = t) - t0);
    90. if (Math.abs(s) > this._slp) {
    91. if (s > 0) { s = null; if (this._sSt !== true) { s = true; }
    92. } else { s = null; if (this._sSt !== false) { s = false; } }
    93. if (s !== null) {
    94. this.cb(this._sSt=s,this._val,this._tim,v0,t0); } }
    95. if (this.aIntrv && (++this._aTC >= this.aIntrv)) {
    96. this.active(); this._aTC = 0; } };
    97. exports = DvDtDetector;
    98. var detector = null;
    99. function lightDetector(logger) {
    100. var d = new DvDtDetector(
    101. function(){ return Puck.light(); }
    102. , 200
    103. , 0.1
    104. , function(detected, value, time){
    105. logger.log( ((detected) ? "on " : "off") + " - v: " + value
    106. + " - t: " + time);
    107. }
    108. , 15
    109. , function(){ digitalPulse(LED2, 1, 50); }
    110. );
    111. return d;
    112. }
    113. var detector = null;
    114. // short cuts to command from console:
    115. function l() { if (!detector) { detector = lightDetector(console); } }
    116. function r() { detector.start(); }
    117. function s() { detector.stop(); }
    118. // --- END -------
    119. </script>
    120. </head>
    121. <body>
    122. <h3>LightDetector - DvDtDetector</h3>
    123. <button onclick="if (!detector) { detector = lightDetector(logger); }">Create</button><br>
    124. <button onclick="detector.start();">Start</button>
    125. <button onclick="detector.stop();">Stop</button>
    126. <br>
    127. Light values:<br>
    128. <button onclick="Puck._light=0.04;">0.04</button>
    129. <button onclick="Puck._light=0.05;">0.05</button>
    130. <button onclick="Puck._light=0.06;">0.06</button>
    131. <button onclick="Puck._light=0.10;">0.10</button>
    132. <button onclick="Puck._light=0.20;">0.20</button>
    133. <button onclick="Puck._light=0.60;">0.60</button>
    134. <button onclick="Puck._light=0.99;">0.99</button>
    135. <br>
    136. <table><tr><td valign="top" align="left">
    137. <table>
    138. <tr><td><div id="LED1" style="width:3em; height:3em;
    139. border-radius:50%; border: 0.3em red solid;"><div
    140. style="margin: 1em 0 0 0.25em;">LED1</div></div>
    141. </td></tr>
    142. <tr><td><div id="LED2" style="width:3em; height:3em;
    143. border-radius:50%; border: 0.3em lightgreen solid;"><div
    144. style="margin: 1em 0 0 0.25em;">LED2</div></div>
    145. </td></tr>
    146. </table>
    147. </td><td>
    148. <textarea id="log" rows="20" cols="40" readonly></textarea>
    149. </td></tr></table>
    150. <script>
    151. </script>
    152. </body>
    153. </html>

    After upload, the light detector is created by entering l() in the console, and started with r() (for run). Entering s() stops the detector, r() gets it going again.

    Shining light on the Puck or obstructing ling from reaching it creates different values. For the right slope the the callback reports an on or off in the console with the read value and time.


    4 Attachments

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
    • $ Donate
About

DvDtDetector for detecting sudden value changes for switching/triggering (on Puck: Light Intensity Changes)

Posted by Avatar for allObjects @allObjects

Actions