Small engine dyno need help to reset my counter after run

I believe the count function is working.

It seem like my hall effects may be counting high (1) and low (0) instead of just counting the high input

I have added a gauge to the dashboard. count revs
the gauge reads the sensor input. At the end of the test the gauge displays the count revs.
Now when i go to start the next run i need to reset the gauge to zero because the gauge is still displaying the last run.

Add a Switch node (not a ui_switch) to the GPIO, checking for payload of 1 and sending that to output 1, and ignoring any other values. Then only the high values will get to the function.

great the switch fixed the input
I will have to name the dyno Colin

For the gauge replace the function with this, which has an additional output with the total count on it. Join output 2 to the gauge.

[{"id":"12c451d2.0c1b5e","type":"function","z":"84405ff5.25fa6","name":"Count Revs","func":"// starts timing when counts reach low threshold\n// when high threshold is reached then passes on time difference in msec\n// Count can be reset by passing a message with topic \"reset\"\n// Set low and high thresholds by passing in topic of \"lowThreshold\" or \"highThreshold\"\n// with value in payload.\n// Any other topic is assumed to be a sensor input\n\nswitch(msg.topic) {\n    case \"reset\":\n        // reset counter\n        context.set(\"counter\", 0)\n        msg = null\n        break;\n        \n    case \"lowThreshold\":\n        context.set(\"lowThreshold\", msg.payload)\n        msg = null\n        break;\n        \n    case \"highThreshold\":\n        context.set(\"highThreshold\", msg.payload)\n        msg = null\n        break;\n        \n    default:\n        // sensor input\n        handleSensor()\n        break;\n}\nreturn [msg, {payload: context.get(\"counter\")}]\n\nfunction handleSensor() {\n    const lowThreshold = context.get(\"lowThreshold\")\n    const highThreshold = context.get(\"highThreshold\")\n    counter = context.get(\"counter\") || 0\n    counter++\n    if (counter == lowThreshold) {\n        // we have hit the first threshold, remember the current time in msec\n        const now = new Date().getTime()\n        context.set(\"startTime\", now)\n        //node.warn(`startTime: ${now}`)\n        msg = null      // don't send anything\n    } else if (counter == highThreshold) {\n        const highNow = new Date().getTime()\n        // we have hit the second threshold, work out the time difference\n        msg.payload = highNow - context.get(\"startTime\")\n    } else {\n        // neither threshold so do nothing\n        msg = null\n    }\n    context.set(\"counter\", counter)\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","x":430,"y":1100,"wires":[["4ee39ede.8ba78"],["eab55674.b14b48"]]}]

this latest update works.
the gauge shows last count until the next run is finished
how can we reset the gauge to zero with the clear counter

Have you connected the gauge to output 2?

It should clear when you hit the reset. If it doesn't then post the flow so I can check it.

Gauge connected to the wrong output works perfect
Thanks

you sent me two types of functions
I like this one because it gives me the time in msec. it only has one output.
you added an output on the count function.
I would like to add a second output to the msec function to reset the gauge.
i looked at both functions and dont see a difference as to how you reset the gauge .
The msec function will be called time with a gauge.
i would like another gauge for rpm
This will allow me to see both time of run and the rpm
Thanks
Donn

You do not need to change the function to clear the msec gauge when you press the reset button. Configure the button to output a payload of zero an topic of "reset" as it already is, and connect the button to the gauge as well as to the function. Then the function will send to msec value to the gauge and button will send zero to the gauge to set it back to zero.

Do you know what RPM stands for?

revolutions per minute

How are you going to calculate the revolutions per minute?

i will not be running the engine for a minute, so i need a math function
Angular velocity (rad/sec)

Once again I misunderstood. I thought you were once again confused between the count value and rpm.

If you feed the input sensor (after the Switch node) into a function containing this it will tell you the rpm by measuring the time between pulses.

let lastTime = context.get("lastTime") || 0
const now = new Date().getTime()
let rpm = 0
if (lastTime > 0) {
    const interval = now - lastTime  // time for a rev in msec
    rpm = 60000/interval
}
msg.payload = rpm
context.set("lastTime", now)
return msg

now where talkin.
my reading is 3000.98765421456
How would i eliminate everything after the .98765421456

Start by reading the help pane for the gauge node. In particular:
" The msg.payload is searched for a numeric value and is formatted in accordance with the defined Value Format , which can then be formatted using Angular filters.
For example : {{value | number:1}}% will round the value to one decimal place and append a % sign."

got it.
I'm all most done. one more issue.
I have a start run button that will reset my gauges and ready the run
my problem is i added two text boxes one to input the lowThreshold number and the other to set highThreshold. I have added a function between text box and count revs function my code is incorrect

[{"id":"c502d54b.368d98","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"8583a880.175fd8","type":"inject","z":"c502d54b.368d98","name":"Sensor","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":90,"y":420,"wires":[["db9f7109.1198a","656b0ac3.739494"]]},{"id":"4ee39ede.8ba78","type":"debug","z":"c502d54b.368d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":970,"y":380,"wires":[]},{"id":"acc6affc.931e5","type":"inject","z":"c502d54b.368d98","name":"Clear counter","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"reset","x":230,"y":60,"wires":[["db9f7109.1198a"]]},{"id":"aeac78ed.2ba2b8","type":"inject","z":"c502d54b.368d98","name":"Set low threshold 3","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"lowThreshold","payload":"3","payloadType":"num","x":230,"y":120,"wires":[["db9f7109.1198a"]]},{"id":"62f6b65a.24a0d8","type":"inject","z":"c502d54b.368d98","name":"Set high threshold 10","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"highThreshold","payload":"10","payloadType":"num","x":240,"y":180,"wires":[["db9f7109.1198a"]]},{"id":"2d4bf090.c32f","type":"ui_gauge","z":"c502d54b.368d98","name":"","group":"5d511d53.994404","order":3,"width":"3","height":"2","gtype":"gage","title":"Temperature","label":"deg c","format":"{{value}}","min":0,"max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":1090,"y":600,"wires":[]},{"id":"7d0425ab.6f341c","type":"ui_gauge","z":"c502d54b.368d98","name":"","group":"5d511d53.994404","order":1,"width":"3","height":"2","gtype":"gage","title":"Humidity","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":1100,"y":680,"wires":[]},{"id":"9f4b9f9e.69796","type":"rpi-gpio in","z":"c502d54b.368d98","name":"","pin":"11","intype":"tri","debounce":"25","read":false,"x":90,"y":500,"wires":[["7dbeb244.ee33ac"]]},{"id":"29d6f69c.5693ca","type":"function","z":"c502d54b.368d98","name":"Temperature","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":630,"y":640,"wires":[["2d4bf090.c32f","61fbe8f9.9bddb8"]]},{"id":"49cb0622.1dd118","type":"function","z":"c502d54b.368d98","name":"Humidity","func":"msg.payload = msg.humidity\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":620,"y":700,"wires":[["7d0425ab.6f341c","22bcffa3.858d7"]]},{"id":"bf3224a0.6e13b8","type":"rpi-dht22","z":"c502d54b.368d98","name":"","topic":"rpi-dht22","dht":"11","pintype":"0","pin":4,"x":280,"y":620,"wires":[["29d6f69c.5693ca","49cb0622.1dd118"]]},{"id":"61fbe8f9.9bddb8","type":"debug","z":"c502d54b.368d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":930,"y":640,"wires":[]},{"id":"22bcffa3.858d7","type":"debug","z":"c502d54b.368d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":950,"y":720,"wires":[]},{"id":"50cf5284.3f22ac","type":"ui_gauge","z":"c502d54b.368d98","name":"","group":"5d511d53.994404","order":2,"width":"6","height":"4","gtype":"gage","title":"TIME","label":"Msec","format":"{{value | number}}","min":0,"max":"10000","colors":["#00b500","#e6e600","#ca3838"],"seg1":"75000","seg2":"8000","x":1090,"y":300,"wires":[]},{"id":"7dbeb244.ee33ac","type":"switch","z":"c502d54b.368d98","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":230,"y":500,"wires":[["db9f7109.1198a","656b0ac3.739494","12c451d2.0c1b5e"]]},{"id":"12c451d2.0c1b5e","type":"function","z":"c502d54b.368d98","name":"Chart Revs","func":"// starts timing when counts reach low threshold\n// when high threshold is reached then passes on time difference in msec\n// Count can be reset by passing a message with topic \"reset\"\n// Set low and high thresholds by passing in topic of \"lowThreshold\" or \"highThreshold\"\n// with value in payload.\n// Any other topic is assumed to be a sensor input\n\nswitch(msg.topic) {\n    case \"reset\":\n        // reset counter\n        context.set(\"counter\", 0)\n        msg = null\n        break;\n        \n    case \"lowThreshold1\":\n        context.set(\"lowThreshold1\", msg.payload)\n        msg = null\n        break;\n        \n    case \"highThreshold1\":\n        context.set(\"highThreshold1\", msg.payload)\n        msg = null\n        break;\n        \n    default:\n        // sensor input\n        handleSensor()\n        break;\n}\nreturn [msg, {payload: context.get(\"counter\")}]\n\nfunction handleSensor() {\n    const lowThreshold1 = context.get(\"lowThreshold1\")\n    const highThreshold1 = context.get(\"highThreshold1\")\n    counter = context.get(\"counter\") || 0\n    counter++\n    if (counter == lowThreshold1) {\n        // we have hit the first threshold, remember the current time in msec\n        const now = new Date().getTime()\n        context.set(\"startTime\", now)\n        //node.warn(`startTime: ${now}`)\n        msg = null      // don't send anything\n    } else if (counter == highThreshold1) {\n        const highNow = new Date().getTime()\n        // we have hit the second threshold, work out the time difference\n        msg.payload = highNow - context.get(\"startTime\")\n    } else {\n        // neither threshold so do nothing\n        msg = null\n    }\n    context.set(\"counter\", counter)\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","x":630,"y":560,"wires":[["a9d87806.041058"],["70c8c6a6.3e9f08"]]},{"id":"db9f7109.1198a","type":"function","z":"c502d54b.368d98","name":"Count Revs","func":"// starts timing when counts reach low threshold\n// when high threshold is reached then passes on time difference in msec\n// Count can be reset by passing a message with topic \"reset\"\n// Set low and high thresholds by passing in topic of \"lowThreshold\" or \"highThreshold\"\n// with value in payload.\n// Any other topic is assumed to be a sensor input\n\nswitch(msg.topic) {\n    case \"reset\":\n        // reset counter\n        context.set(\"counter\", 0)\n        msg = null\n        break;\n        \n    case \"lowThreshold\":\n        context.set(\"lowThreshold\", msg.payload)\n        msg = null\n        break;\n        \n    case \"highThreshold\":\n        context.set(\"highThreshold\", msg.payload)\n        msg = null\n        break;\n        \n    default:\n        // sensor input\n        handleSensor()\n        break;\n}\nreturn msg\n\nfunction handleSensor() {\n    const lowThreshold = context.get(\"lowThreshold\")\n    const highThreshold = context.get(\"highThreshold\")\n    counter = context.get(\"counter\") || 0\n    counter++\n    if (counter == lowThreshold) {\n        // we have hit the first threshold, remember the current time in msec\n        const now = new Date().getTime()\n        context.set(\"startTime\", now)\n        node.warn(`startTime: ${now}`)\n        msg = null      // don't send anything\n    } else if (counter == highThreshold) {\n        const highNow = new Date().getTime()\n        // we have hit the second threshold, work out the time difference\n        msg.payload = highNow - context.get(\"startTime\")\n    } else {\n        // neither threshold so do nothing\n        msg = null\n    }\n    context.set(\"counter\", counter)\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":610,"y":400,"wires":[["50cf5284.3f22ac","4ee39ede.8ba78"]]},{"id":"656b0ac3.739494","type":"function","z":"c502d54b.368d98","name":"Tach","func":"let lastTime = context.get(\"lastTime\") || 0\nconst now = new Date().getTime()\nlet rpm = 0\nif (lastTime > 0) {\n        const interval = now - lastTime // time for rev in msec\n        rpm = 60000/interval\n}\nmsg.payload = rpm\ncontext.set(\"lastTime\", now)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":610,"y":480,"wires":[["42cb40fa.88d8","1aa0d08f.d201ff"]]},{"id":"42cb40fa.88d8","type":"debug","z":"c502d54b.368d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":970,"y":480,"wires":[]},{"id":"1aa0d08f.d201ff","type":"ui_gauge","z":"c502d54b.368d98","name":"","group":"9e96c901.0264f8","order":1,"width":0,"height":0,"gtype":"gage","title":"RPM","label":"","format":"{{value | number:0}}","min":0,"max":"10000","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":1090,"y":440,"wires":[]},{"id":"70c8c6a6.3e9f08","type":"ui_chart","z":"c502d54b.368d98","name":"","group":"3d76fdcd.ed3a22","order":0,"width":"6","height":"10","label":"chart","chartType":"line","legend":"false","xformat":"Seconds","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"50","removeOlder":"100","removeOlderPoints":"10000","removeOlderUnit":"60","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"x":1070,"y":520,"wires":[[]]},{"id":"69976a43.f5ca44","type":"ui_button","z":"c502d54b.368d98","name":"","group":"2c4c6cf8.d77924","order":1,"width":0,"height":0,"passthru":false,"label":"START Run","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"date","topic":"topic","topicType":"msg","x":70,"y":700,"wires":[["3994d8dd.b567c8","bf3224a0.6e13b8","e2d6d3b6.d0c67"]]},{"id":"f9c2255.34525d8","type":"ui_text_input","z":"c502d54b.368d98","name":"","label":"START RPM","tooltip":"","group":"2c4c6cf8.d77924","order":3,"width":"2","height":"1","passthru":true,"mode":"number","delay":"25","topic":"lowThreshold","topicType":"msg","x":130,"y":260,"wires":[["b1f89d2d.8cc59"]]},{"id":"3994d8dd.b567c8","type":"function","z":"c502d54b.368d98","name":"","func":"\nmsg.payload = [];\nmsg.topic = 0\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":280,"y":720,"wires":[["70c8c6a6.3e9f08","50cf5284.3f22ac","1aa0d08f.d201ff"]]},{"id":"38010d4.0a4a5f2","type":"debug","z":"c502d54b.368d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":860,"wires":[]},{"id":"d9cc6b77.bc2aa8","type":"ui_text","z":"c502d54b.368d98","group":"2c4c6cf8.d77924","order":2,"width":0,"height":0,"name":"DATE","label":"DATE","format":"{{value | uppercase}}","layout":"col-center","x":850,"y":800,"wires":[]},{"id":"f07057ad.3e2428","type":"ui_text_input","z":"c502d54b.368d98","name":"","label":"MAX RPM","tooltip":"","group":"2c4c6cf8.d77924","order":3,"width":"2","height":"1","passthru":true,"mode":"number","delay":"25","topic":"payload","topicType":"msg","x":130,"y":340,"wires":[["aed12744.b676e8"]]},{"id":"a9d87806.041058","type":"debug","z":"c502d54b.368d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":950,"y":560,"wires":[]},{"id":"b1f89d2d.8cc59","type":"debug","z":"c502d54b.368d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":740,"y":260,"wires":[]},{"id":"be5e0b01.9c6ea8","type":"debug","z":"c502d54b.368d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":740,"y":320,"wires":[]},{"id":"aed12744.b676e8","type":"function","z":"c502d54b.368d98","name":"","func":"msg.payload = highThreshold\nmsg.topic = highThreshold\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":350,"y":340,"wires":[["be5e0b01.9c6ea8","db9f7109.1198a"]]},{"id":"e2d6d3b6.d0c67","type":"function","z":"c502d54b.368d98","name":"","func":"var date = new Date(msg.payload);\nmsg.payload = date.toString();\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":290,"y":780,"wires":[["d9cc6b77.bc2aa8","38010d4.0a4a5f2"]]},{"id":"5d511d53.994404","type":"ui_group","name":"Weather","tab":"70eb2da0.452ad4","order":5,"disp":true,"width":"6","collapse":false},{"id":"9e96c901.0264f8","type":"ui_group","name":"DYNO","tab":"70eb2da0.452ad4","order":2,"disp":true,"width":"10","collapse":false},{"id":"3d76fdcd.ed3a22","type":"ui_group","name":"Chart","tab":"70eb2da0.452ad4","order":3,"disp":true,"width":"6","collapse":false},{"id":"2c4c6cf8.d77924","type":"ui_group","name":"Run Command","tab":"70eb2da0.452ad4","order":1,"disp":true,"width":"6","collapse":false},{"id":"70eb2da0.452ad4","type":"ui_tab","name":"LANGE RACING","icon":"dashboard","disabled":false,"hidden":false}]

You don't need a function node. Just configure the Text nodes to send the topic as Strings highThreshold and lowThreshold

image

And please change the labels, the thresholds are not revs per minute values, they are total revolutions. You have this at the moment.

image