EZO pH flow for Calibration and readings

A dashboard UI based flow to allow calibration and reading of the Atlas Scientific EZO pH device. Although this device can communication over both I2C and Serial, this flow is designed around serial communication.

General Operation

The UI has two pages, one ('Main' tab) for displaying the pH value from the probe and if setup in the flow a temperature reading from a temperature probe ( Please see 'comment' node about temperature compensation). The other ('Calibration' tab) is used to calibrate the EZO pH probe and setup the reading rate if you have the correct firmware on your device.

There are several 'Comment' nodes in the flow which aid in setup and a description of what each section does.Also it is worth downloading the EZO ph datasheet from Atlas Scientific. This will give you a good idea of all the function of the unit.

Please note:

This flow is part of several flows used in my aquarium for monitoring and control. This flow is really a 'Get you started' flow for your own Ezo pH unit. The calibration steps in particular are just memory joggers and I would recommend clicking through the sets first with no device connected to get an idea of how it works.

[{"id":"b7af4e75.6ed8e8","type":"ui_button","z":"4703de07.5f73f","name":"","group":"258d7f77.cffb48","order":2,"width":"3","height":"1","passthru":false,"label":"Calibrate PH","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":156.25,"y":376.6666564941406,"wires":[["fbebb701.db851"]]},{"id":"b2e4bf1.612b44","type":"ui_button","z":"4703de07.5f73f","name":"","group":"258d7f77.cffb48","order":3,"width":"3","height":"1","passthru":false,"label":"Start","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"step","x":878.8056030273438,"y":288.2222900390625,"wires":[["3806fed0.498582"]]},{"id":"192a973b.659e79","type":"ui_text","z":"4703de07.5f73f","group":"258d7f77.cffb48","order":8,"width":"6","height":"4","name":"Instructions","label":"{{msg.topic}}","format":"{{msg.payload}}","layout":"col-center","x":896.25,"y":461.0833740234375,"wires":[]},{"id":"18b1c4fe.f2bc03","type":"ui_button","z":"4703de07.5f73f","name":"","group":"258d7f77.cffb48","order":4,"width":"2","height":"1","passthru":false,"label":"Mid Cal","color":"","bgcolor":"","icon":"","payload":"midcal","payloadType":"str","topic":"step","x":886.1387939453125,"y":326.5556945800781,"wires":[["cef6b586.f9084"]]},{"id":"91d69474.c4218","type":"ui_button","z":"4703de07.5f73f","name":"","group":"258d7f77.cffb48","order":5,"width":"2","height":"1","passthru":false,"label":"Low Cal","color":"","bgcolor":"","icon":"","payload":"lowcal","payloadType":"str","topic":"step","x":885.1388549804688,"y":366.2222595214844,"wires":[["cca82cfe.62abd8"]]},{"id":"fbebb701.db851","type":"change","z":"4703de07.5f73f","name":"Initialise","rules":[{"t":"set","p":"step","pt":"flow","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":305.36114501953125,"y":330.6666564941406,"wires":[["d564b68a.416a6"]]},{"id":"32b50c92.35915c","type":"ui_text","z":"4703de07.5f73f","group":"258d7f77.cffb48","order":6,"width":"0","height":"0","name":"Heading and Timer","label":"{{msg.topic}}","format":"{{msg.payload}}","layout":"row-spread","x":916.1668701171875,"y":503.7501220703125,"wires":[]},{"id":"b84440ca.a1c638","type":"function","z":"4703de07.5f73f","name":"Step Timer","func":"var time = flow.get(\"timer\");\nvar msg1 ={};\nvar step = flow.get(\"step\");\nvar cal = flow.get(\"calpoints\");\nmsg.topic = \"Timer:\";\n\nif(time === 0){\n    flow.set(\"running\",false);\n    step ++;\n    if(step == 9){step = 0;}\n    if(cal ==1 && step == 4){step = 8;}\n    if(cal ==2 && step == 6){step = 8;}\n    flow.set(\"step\",step);\n    msg.payload = time + \"s\";\n    msg1.topic = \"\";\n    msg1.payload =\"Step: \"+step;\n    return [msg1,msg];\n}\n\nif (time > 0 && flow.get(\"running\")){\n    msg.payload = time + \"s\";\n    time --;\n    flow.set(\"timer\",time);\n    return [null,msg];\n}\n\n","outputs":"2","noerr":0,"x":482.13885498046875,"y":440.77803548177087,"wires":[["d564b68a.416a6"],["32b50c92.35915c"]]},{"id":"cd17c253.a559c","type":"inject","z":"4703de07.5f73f","name":"1 sec timer","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":160.6944580078125,"y":437.33333333333337,"wires":[["59f3cafa.eb56cc"]]},{"id":"3806fed0.498582","type":"change","z":"4703de07.5f73f","name":"step 1","rules":[{"t":"set","p":"timer","pt":"flow","to":"10","tot":"num"},{"t":"set","p":"running","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1055.361083984375,"y":283.5555419921875,"wires":[["3cb28fcf.7799"]]},{"id":"529cbfc5.9036e8","type":"comment","z":"4703de07.5f73f","name":"Settings","info":"\nThe 'Continuous' switch on the UI will tell the Ezo unit to send\nreadings all the time (every 1sec). If this is off then you can set an\ninterval in seconds on the UI.\n\nThe 'Temperature Compensation Auto' switch when in auto will use a value\ncoming in from a temperature probe (see the 'Temperature Compensation' comment node)\nto compensate for buffer solution temperature when calibrating pH probe.\nIf this is turned off then the temperature value of the buffer solution can\nbe entered manually in the UI. \n\nSolution constants\nThese should be found on your buffer solution bottles ,but please check as\nmanufactures vary. Depending on if you are doing 1,2, or 3 point calibration set\neach value in the UI\n\nNote:\nI personally use the buffer constant on the bottle at the default 25°C then\nuse the temparture compensation of the unit to adjust automatically. To my\nknowledge this is correct, but if any body knows overwise please tell me. ","x":636.75,"y":556.75,"wires":[]},{"id":"283186a.6c9c8fa","type":"comment","z":"4703de07.5f73f","name":"Calibration pH README","info":"First thing is to read the 'Serial Commands' comment node to set up the serial\ncomms before doing anything else. The ph_EZO_datasheet.pdf is a good source of\ninformation from the Atlas Scientific site https://www.atlas-scientific.com/ for\nfull functionality and operations.\n\nThe readings per second switch and numeric selector on the UI is not\nstrictly part of calibrating but is a function of the serial port to get reading\nback from the EZO pH unit so I have added it here to get you started if needed.\n\n\n'Cal Points' UI selection can be set to 1,2, or 3 point calibration\nset this before pressing the Calibration button.\n\nThe 'Calibration' button will start the instruction process for calibrating\nthe pH probe. It is not essential but advised that if you have a temperature probe\nto measure the buffer solution, put it in know. There is a time period where you can\ndo it during the calibration step if you forget.\n\nBasically follow the instructions on screen for calibration. These are just reminders\nfor me when I do mine but if you look in the 'Calibration Steps' function block you can\nchange the text to what feels best for you. You can run through the steps with no serial\nport connected if you wish to get an idea of how the flow works.\n\nIn the flow are 2 named 'delay' nodes, these set the settle period for the steps when the probe\nis in the buffer solutions and when temperature compensating. If you feel they are too short\nor too long please adjust to your needs.\n\nPlease Note:\n\nThis flow is only released as a starting point for anyone wishing to use the EZO pH device\nover serial in a node red enviroment.\nI use this same flow along with other flows for my aquarium with no problem.\nBut it is a work in progress so it is up to yourself to verify that it works how you\nwant it to.","x":691.4444580078125,"y":57.083343505859375,"wires":[]},{"id":"d564b68a.416a6","type":"delay","z":"4703de07.5f73f","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":480.25006103515625,"y":334.8890075683594,"wires":[["9f0908c9.438c7","4c2884fd.e738e4"]]},{"id":"4e8f765.a531108","type":"ui_numeric","z":"4703de07.5f73f","name":"","label":"Mid cal pH","group":"ab1982f0.d809d8","order":2,"width":0,"height":0,"passthru":true,"topic":"mid","format":"{{value}}","min":"6.8","max":"7.2","step":"0.001","x":892.361124674479,"y":128,"wires":[["451a536d.f5b21c"]]},{"id":"f28ba0e2.7f077","type":"ui_numeric","z":"4703de07.5f73f","name":"","label":"Low cal pH","group":"ab1982f0.d809d8","order":3,"width":0,"height":0,"passthru":true,"topic":"low","format":"{{value}}","min":"3.8","max":"4.2","step":"0.001","x":892.02783203125,"y":166.44448852539062,"wires":[["a996ef84.5a7358"]]},{"id":"63666f80.cd32c","type":"change","z":"4703de07.5f73f","name":"mid","rules":[{"t":"set","p":"topic","pt":"msg","to":"mid","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"7.000","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":687.6944580078125,"y":155.33334350585938,"wires":[["4e8f765.a531108"]]},{"id":"44b03899.050b3","type":"change","z":"4703de07.5f73f","name":"low","rules":[{"t":"set","p":"topic","pt":"msg","to":"low","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"4.000","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":688.5833740234375,"y":191.11109924316406,"wires":[["f28ba0e2.7f077"]]},{"id":"9f0908c9.438c7","type":"function","z":"4703de07.5f73f","name":"Calibration Steps","func":"var msg1={};// header text\nvar msg2={};//instruction text\nvar msg3={};//commands to pH meter\nvar step = flow.get(\"step\");\n\nif(!flow.get(\"running\")){\nswitch(step){\n    case 0:\n       msg1.topic= \"\";\n       msg1.payload=\"\";\n       msg2.topic=\"\";\n       msg2.payload=\"\";\n       return [msg1,msg2,null];\n       \n    case 1:\n       msg1.topic=\"\";\n       msg1.payload=\"\";\n       msg2.topic=\"<h3>Rinse Probe</h3>\";\n       msg2.payload=\"Remove pH probe from tank and place in cup of tap water and move around to rinse off, then press the start when ready and wait for the timer to finish.\";\n       global.set(\"calstart\",true);\n       return [msg1,msg2,null];\n    case 2:\n       msg1.topic=\"\";\n       msg1.payload=\"\";\n       msg2.topic = \"<h3>Temperature Compensation</h3> </p> Put temperature probe into any of your buffer solutions.</p> If entering manually check value in 'Compensation temp °C' \";\n       if (flow.get(\"compensate\")){\n         msg2.payload = \"<center>Temperature probe is \" + global.get(\"watertemp\").toFixed(1) +\"°C</center>\";\n         msg3.payload=\"tempcomp\";\n       }else{\n         msg2.payload =\"<center>Manual temperature is \" + flow.get(\"comptemp\") +\"°</center>\";\n         msg3.payload=\"tempcomp\";  \n       }\n       \n       flow.set(\"running\",true);\n       flow.set(\"timer\",60);\n       return [msg1,msg2,msg3];\n    case 3:\n       msg1.topic = \"Temperature Compensated\";\n       msg1.payload = global.get(\"watertemp\").toFixed(1) +\"°C\";\n       msg2.topic=\"<h3>Mid Point Cal</h3>\";\n       msg2.payload=\"Set pH 7.0 solution value in Setpoints Mid cal pH,then put small amount of solution into cup as directed by manufacture of probe and then place the probe into the cup, when ready press MID CAL button\";\n       return [msg1,msg2,null];\n    case 4:\n       msg1.topic = \"\";\n       msg1.payload = \"\";\n       msg2.topic=\"<h3>Rinse Probe</h3>\";\n       msg2.payload=\"Remove probe from solution and place in cup of tap water,then press start when ready and wait for timer to finish\";\n       return [msg1,msg2,null];\n    case 5:\n       msg1.topic = \"\";\n       msg1.payload = \"\";\n       msg2.topic=\"<h3>Low Point Cal</h3>\";\n       msg2.payload=\"Set pH 4.0 solution value in Setpoints Low cal pH,then put small amount of solution into cup as directed by manufacture of probe and then place the probe into the cup, when ready press LOW CAL button\";\n       return [msg1,msg2,null];\n    case 6:\n       msg1.topic = \"\";\n       msg1.payload = \"\";\n       msg2.topic=\"<h3>Rinse Probe</h3>\";\n       msg2.payload=\"Remove probe from solution and place in cup of tap water,then press start when ready and wait for timer to finish\";\n       return [msg1,msg2,null];\n    case 7:\n       msg1.topic = \"\";\n       msg1.payload = \"\";\n       msg2.topic=\"<h3>High Point Cal</h3>\";\n       msg2.payload=\"Set pH 10.0 solution value in Setpoints High cal pH,then put small amount of solution into cup as directed by manufacture of probe and then place the probe into the cup, when ready press HIGH CAL button\";\n       return [msg1,msg2,null];\n    case 8:\n       msg1.topic = \"\";\n       msg1.payload = \"\";\n       msg2.topic=\"<h3>Calibration completed</h3>\";\n       msg2.payload=\"Remove probe from solution and place in cup of tap water and rinse off probe, then put back in tank\";\n       global.set(\"calstart\",false);\n       msg3.payload = \"completed\";\n       return [msg1,msg2,msg3];\n  }\n}\n","outputs":"3","noerr":0,"x":685.32421875,"y":415.9445495605469,"wires":[["32b50c92.35915c"],["192a973b.659e79"],["63a91053.c5a3d"]],"outputLabels":["start","mid cal","low cal"]},{"id":"cef6b586.f9084","type":"change","z":"4703de07.5f73f","name":"step 3","rules":[{"t":"set","p":"timer","pt":"flow","to":"120","tot":"num"},{"t":"set","p":"running","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1054.97216796875,"y":319.9722595214844,"wires":[["3cb28fcf.7799"]]},{"id":"cca82cfe.62abd8","type":"change","z":"4703de07.5f73f","name":"step 5","rules":[{"t":"set","p":"timer","pt":"flow","to":"120","tot":"num"},{"t":"set","p":"running","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1055.1944580078125,"y":359.52777099609375,"wires":[["3cb28fcf.7799"]]},{"id":"c2077d49.9e5708","type":"ui_numeric","z":"4703de07.5f73f","name":"cal points","label":"Cal Points","group":"258d7f77.cffb48","order":1,"width":0,"height":0,"passthru":false,"topic":"calpoints","format":"{{value}}","min":"1","max":"3","step":1,"x":887.5611572265625,"y":245.54998779296875,"wires":[["c83880c2.f274a8"]]},{"id":"7748753f.9826a4","type":"change","z":"4703de07.5f73f","name":"cal point","rules":[{"t":"set","p":"payload","pt":"msg","to":"2","tot":"num"},{"t":"set","p":"calpoints","pt":"flow","to":"2","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":697.5611572265625,"y":263.98333740234375,"wires":[["c2077d49.9e5708"]]},{"id":"a2b0d99.8d13928","type":"ui_button","z":"4703de07.5f73f","name":"","group":"258d7f77.cffb48","order":7,"width":"2","height":"1","passthru":false,"label":"High Cal","color":"","bgcolor":"","icon":"","payload":"highcal","payloadType":"str","topic":"topic","x":885.3335571289062,"y":408.861083984375,"wires":[["b62eeda3.318758"]]},{"id":"b62eeda3.318758","type":"change","z":"4703de07.5f73f","name":"step 7","rules":[{"t":"set","p":"timer","pt":"flow","to":"120","tot":"num"},{"t":"set","p":"running","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1055.861083984375,"y":398.1944580078125,"wires":[["3cb28fcf.7799"]]},{"id":"59f3cafa.eb56cc","type":"switch","z":"4703de07.5f73f","name":"","property":"running","propertyType":"flow","rules":[{"t":"true"}],"checkall":"false","outputs":1,"x":320.6944580078125,"y":437.33333333333337,"wires":[["b84440ca.a1c638"]]},{"id":"d488db50.a25598","type":"inject","z":"4703de07.5f73f","name":"start","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"x":157.1166534423828,"y":240.0777587890625,"wires":[["fa4dc880.cf9c38"]]},{"id":"fa4dc880.cf9c38","type":"change","z":"4703de07.5f73f","name":"initial","rules":[{"t":"set","p":"running","pt":"flow","to":"false","tot":"bool"},{"t":"set","p":"step","pt":"flow","to":"0","tot":"num"},{"t":"set","p":"calstart","pt":"global","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":318.6722412109375,"y":235.87225341796875,"wires":[["63666f80.cd32c","44b03899.050b3","7748753f.9826a4","d564b68a.416a6","bce23a88.900958","b1cd9561.eae5f8","e278c689.b0b99"]]},{"id":"4c2884fd.e738e4","type":"function","z":"4703de07.5f73f","name":"Button control","func":"var msg1={};//start button\nvar msg2={};//mid cal button\nvar msg3={};//low cal button\nvar msg4={};//high cal button\nvar step = flow.get(\"step\");\n\nif(!flow.get(\"running\")){\nswitch(step){\n    case 0:\n       msg1.enabled= false;\n       msg2.enabled= false;\n       msg3.enabled= false;\n       msg4.enabled= false;\n       return [msg1,msg2,msg3,msg4];\n       \n    case 1:\n       msg1.enabled= true;\n       msg2.enabled= false;\n       msg3.enabled= false;\n       msg4.enabled= false;\n       return [msg1,msg2,msg3,msg4];\n    case 2:\n       msg1.enabled= false;\n       msg2.enabled= false;\n       msg3.enabled= false;\n       msg4.enabled= false;\n       return [msg1,msg2,msg3,msg4];\n    case 3:\n       msg1.enabled= false;\n       msg2.enabled= true;\n       msg3.enabled= false;\n       msg4.enabled= false;\n       return [msg1,msg2,msg3,msg4];\n    case 4:\n       msg1.enabled= true;\n       msg2.enabled= false;\n       msg3.enabled= false;\n       msg4.enabled= false;\n       return [msg1,msg2,msg3,msg4];\n    case 5:\n       msg1.enabled= false;\n       msg2.enabled= false;\n       msg3.enabled= true;\n       msg4.enabled= false;\n       return [msg1,msg2,msg3,msg4];\n    case 6:\n       msg1.enabled= true;\n       msg2.enabled= false;\n       msg3.enabled= false;\n       msg4.enabled= false;\n       return [msg1,msg2,msg3,msg4];\n    case 7:\n       msg1.enabled= false;\n       msg2.enabled= false;\n       msg3.enabled= false;\n       msg4.enabled= true;\n       return [msg1,msg2,msg3,msg4];\n    case 8:\n       msg1.enabled= false;\n       msg2.enabled= false;\n       msg3.enabled= false;\n       msg4.enabled= false;\n       return [msg1,msg2,msg3,msg4];\n  }\n}\n","outputs":"4","noerr":0,"x":681.4500122070312,"y":338.1499938964844,"wires":[["b2e4bf1.612b44"],["18b1c4fe.f2bc03"],["91d69474.c4218"],["a2b0d99.8d13928"]]},{"id":"9147d0c6.74ce88","type":"ui_text","z":"4703de07.5f73f","group":"ab1982f0.d809d8","order":1,"width":0,"height":0,"name":"","label":"Solution Constants ","format":"{{msg.payload}}","layout":"row-center","x":243.9444580078125,"y":157.99998474121094,"wires":[]},{"id":"c83880c2.f274a8","type":"change","z":"4703de07.5f73f","name":"cal","rules":[{"t":"set","p":"calpoints","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1056.4351806640625,"y":246.33331298828125,"wires":[[]]},{"id":"d19af48d.360f4","type":"ui_ui_control","z":"4703de07.5f73f","name":"","x":144.21298217773438,"y":284.5185241699219,"wires":[["fa4dc880.cf9c38"]]},{"id":"a996ef84.5a7358","type":"change","z":"4703de07.5f73f","name":"lowcal","rules":[{"t":"set","p":"lowcal","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1057.5611572265625,"y":171.89999389648438,"wires":[[]]},{"id":"451a536d.f5b21c","type":"change","z":"4703de07.5f73f","name":"midcal","rules":[{"t":"set","p":"midcal","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1058.5611572265625,"y":128.89999389648438,"wires":[[]]},{"id":"5af20c98.fc8ef4","type":"ui_text","z":"4703de07.5f73f","group":"ab1982f0.d809d8","order":5,"width":0,"height":0,"name":"","label":"Readings in seconds","format":"{{msg.payload}}","layout":"row-center","x":251.9444580078125,"y":113.75,"wires":[]},{"id":"a83a87af.8180d8","type":"ui_numeric","z":"4703de07.5f73f","name":"","label":"pH every","group":"ab1982f0.d809d8","order":8,"width":0,"height":0,"passthru":true,"topic":"","format":" {{value}}","min":0,"max":10,"step":1,"x":697.5611572265625,"y":685.7166748046875,"wires":[["dfd3af74.386348"]]},{"id":"dfd3af74.386348","type":"change","z":"4703de07.5f73f","name":"phtime","rules":[{"t":"set","p":"phtime","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":871.6944580078125,"y":684.75,"wires":[[]]},{"id":"aa9f691d.2659e8","type":"function","z":"4703de07.5f73f","name":"Cmd to Ezo","func":"if(msg.payload==\"midcal\"){\n    msg.payload=\"Cal,mid,\"+flow.get(\"midcal\");\n    return msg;\n}\nif(msg.payload==\"lowcal\"){\n    msg.payload=\"Cal,low,\"+flow.get(\"lowcal\");\n    return msg;\n}\nif(msg.payload==\"highcal\"){\n    msg.payload=\"Cal,high,\"+flow.get(\"highcal\");\n    return msg;\n}\nif(msg.payload==\"tempcomp\"){\n    if(flow.get(\"compensate\")){\n      msg.payload=\"T,\"+ global.get(\"watertemp\").toFixed(1);\n      return msg;\n    }else{\n      msg.payload=\"T,\"+ flow.get(\"comptemp\");\n      return msg;\n    }\n\n}\nif(msg.topic==\"continuous\"){\n    if(global.get(\"continuous\")){\n      msg.payload=\"C,1\";\n      return msg;  \n    }else{\n       msg.payload=\"C,0\";\n      return msg;   \n    }\n\n}\nif(msg.payload==\"completed\"){\n    msg.payload=\"Slope,?\";\n    return msg;\n}\n","outputs":1,"noerr":0,"x":1243.3111572265625,"y":706.6500854492188,"wires":[["a2c54d5f.298b18"]]},{"id":"d73e47ea.e50208","type":"ui_numeric","z":"4703de07.5f73f","name":"","label":"High cal pH","group":"ab1982f0.d809d8","order":4,"width":0,"height":0,"passthru":true,"topic":"high","format":"{{value}}","min":"9.8","max":"10.2","step":"0.001","x":894.4444580078125,"y":205.75,"wires":[["dc5bcb2e.9fc0c8"]]},{"id":"bce23a88.900958","type":"change","z":"4703de07.5f73f","name":"high","rules":[{"t":"set","p":"topic","pt":"msg","to":"high","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"10.000","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":688,"y":227.41661071777344,"wires":[["d73e47ea.e50208"]]},{"id":"dc5bcb2e.9fc0c8","type":"change","z":"4703de07.5f73f","name":"highcal","rules":[{"t":"set","p":"highcal","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1056.977783203125,"y":208.20550537109375,"wires":[[]]},{"id":"63a91053.c5a3d","type":"delay","z":"4703de07.5f73f","name":"Compensation delay","pauseType":"delay","timeout":"50","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1260.5611572265625,"y":446.1500244140625,"wires":[["aa9f691d.2659e8"]]},{"id":"3cb28fcf.7799","type":"delay","z":"4703de07.5f73f","name":"Cal points delay","pauseType":"delay","timeout":"110","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1248.5611572265625,"y":393.3999938964844,"wires":[["aa9f691d.2659e8"]]},{"id":"3fe10832.30e82","type":"ui_switch","z":"4703de07.5f73f","name":"","label":"Continuous","group":"ab1982f0.d809d8","order":6,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"continuous","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":467.31109619140625,"y":588.2166748046875,"wires":[["1d0ae68f.d3a211","e734b7f7.9c321"]]},{"id":"1d0ae68f.d3a211","type":"switch","z":"4703de07.5f73f","name":"","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","outputs":2,"x":310.8111572265625,"y":690.4000244140625,"wires":[["2ff280ef.56428"],["83582c36.290e28"]]},{"id":"83582c36.290e28","type":"change","z":"4703de07.5f73f","name":"timed","rules":[{"t":"set","p":"enabled","pt":"msg","to":"true","tot":"bool"},{"t":"set","p":"payload","pt":"msg","to":"10","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":481.3111572265625,"y":704.9000244140625,"wires":[["a83a87af.8180d8"]]},{"id":"2ff280ef.56428","type":"change","z":"4703de07.5f73f","name":"cont","rules":[{"t":"set","p":"enabled","pt":"msg","to":"false","tot":"bool"},{"t":"set","p":"payload","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":482.6944580078125,"y":666.5,"wires":[["a83a87af.8180d8"]]},{"id":"b1cd9561.eae5f8","type":"change","z":"4703de07.5f73f","name":"0","rules":[{"t":"set","p":"payload","pt":"msg","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":289.0611267089844,"y":591.1499633789062,"wires":[["3fe10832.30e82"]]},{"id":"e734b7f7.9c321","type":"change","z":"4703de07.5f73f","name":"continuous","rules":[{"t":"set","p":"continuous","pt":"global","to":"payload","tot":"msg"},{"t":"set","p":"topic","pt":"msg","to":"continuous","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":889.5611572265625,"y":640.6500244140625,"wires":[["aa9f691d.2659e8"]]},{"id":"7460d0e4.8e0838","type":"ui_numeric","z":"4703de07.5f73f","name":"","label":"Compensation temp °C","group":"ab1982f0.d809d8","order":10,"width":0,"height":0,"passthru":true,"topic":"","format":" {{value}}","min":"0","max":"30","step":"0.1","x":670.1944580078125,"y":848.25,"wires":[["7e0f7690.8d5d6"]]},{"id":"8a37f76b.62d4d","type":"ui_switch","z":"4703de07.5f73f","name":"","label":"Temperature Compensate Auto","group":"ab1982f0.d809d8","order":9,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"continuous","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":398.1944580078125,"y":763.75,"wires":[["a3bd73dc.219938","c04b203e.a195e"]]},{"id":"a3bd73dc.219938","type":"switch","z":"4703de07.5f73f","name":"","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","outputs":2,"x":310.19439697265625,"y":846.433349609375,"wires":[["6d4d7923.a25398"],["432dbbc6.b4907c"]]},{"id":"6d4d7923.a25398","type":"change","z":"4703de07.5f73f","name":"auto","rules":[{"t":"set","p":"enabled","pt":"msg","to":"false","tot":"bool"},{"t":"set","p":"payload","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":475.8277587890625,"y":829.2833862304688,"wires":[["7460d0e4.8e0838"]]},{"id":"c04b203e.a195e","type":"change","z":"4703de07.5f73f","name":"compensate","rules":[{"t":"set","p":"compensate","pt":"flow","to":"payload","tot":"msg"},{"t":"set","p":"topic","pt":"msg","to":"compensate","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":886.1944580078125,"y":732.933349609375,"wires":[[]]},{"id":"432dbbc6.b4907c","type":"change","z":"4703de07.5f73f","name":"manual","rules":[{"t":"set","p":"enabled","pt":"msg","to":"true","tot":"bool"},{"t":"set","p":"payload","pt":"msg","to":"20.5","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":473.1944580078125,"y":874.25,"wires":[["7460d0e4.8e0838"]]},{"id":"e278c689.b0b99","type":"change","z":"4703de07.5f73f","name":"1","rules":[{"t":"set","p":"payload","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":119.69442749023438,"y":697.25,"wires":[["8a37f76b.62d4d"]]},{"id":"7e0f7690.8d5d6","type":"change","z":"4703de07.5f73f","name":"comptemp","rules":[{"t":"set","p":"comptemp","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":875.1944580078125,"y":782.5,"wires":[[]]},{"id":"79ea8048.9d9ae","type":"serial in","z":"4703de07.5f73f","name":"UART from Ezo pH","serial":"9d2245ba.027998","x":186.25,"y":1076.75,"wires":[["39a2e033.26161"]]},{"id":"c1fa972e.ff13c","type":"serial out","z":"4703de07.5f73f","name":"UART to Ezo pH","serial":"9d2245ba.027998","x":1326,"y":1079.25,"wires":[]},{"id":"a2c54d5f.298b18","type":"function","z":"4703de07.5f73f","name":"stringTobuffer","func":"var temp = Buffer.from(msg.payload);\nvar cr = new Buffer([0x0D]);\nmsg.payload = Buffer.concat([temp, cr]);\nreturn msg;","outputs":1,"noerr":0,"x":1100.5,"y":1044.75,"wires":[["c1fa972e.ff13c"]]},{"id":"39a2e033.26161","type":"function","z":"4703de07.5f73f","name":"Check response","func":"var temp = msg.payload;\ntemp = temp.trim();\nvar msg1 ={};\n\nif(isNaN(temp)){\n    msg.topic = \"ER\";\n    switch (temp){\n        case \"*OK\":\n            msg.topic = \"OK\";\n             msg.payload = \"Ok\";\n             break;\n        case \"*ER\":\n            msg.payload = \"Command failed\";\n            break;\n        case \"*OV\":\n            msg.payload = \"Over voltage (Vcc >= 5.5v)\";\n            break;\n        case \"*UV\":\n            msg.payload = \"Under voltage (Vcc <= 3.1v)\";\n            break;\n        case \"*RS\":\n            msg.payload = \"Unit has reset\";\n            break;\n        case \"*RE\":\n            msg.payload = \"Boot up complete, Ready\";\n            break;\n        case \"*SL\":\n            msg.topic = \"OK\";\n            msg.payload = \"Entering Sleep Mode\";\n            break;\n        case \"*WA\":\n            msg.topic = \"OK\";\n            msg.payload = \"Unit waking up\";\n            break;\n    }\n\n    return [msg,null];\n}else{\n    \n    msg1.payload=parseFloat(temp);\n    msg1.topic=\"pH\";\n    return [null,msg1];\n}\n","outputs":"2","noerr":0,"x":627.86669921875,"y":1101.6500244140625,"wires":[["22b20f27.3c9d9","a9c4ccbd.28fac"],["dd7e4447.1351a"]],"outputLabels":["response","reading"]},{"id":"52a4fa0d.9c1b2c","type":"inject","z":"4703de07.5f73f","name":"1 sec","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":453,"y":1039.75,"wires":[["3801cfee.7bf318"]]},{"id":"3801cfee.7bf318","type":"function","z":"4703de07.5f73f","name":"take reading","func":"var count = context.get(\"count\")||1;\nvar target = global.get(\"phtime\")||0;\nvar cal = global.get(\"calstart\")||false;\nif(!global.get(\"continuous\")){\n  if (count == target && !cal){\n    msg.payload=\"R\";\n    context.set(\"count\",0);\n    return msg;\n  }else{\n    count ++;\n    context.set(\"count\",count);\n  }\n}","outputs":1,"noerr":0,"x":616.5,"y":1039.7666015625,"wires":[["a2c54d5f.298b18"]]},{"id":"dd7e4447.1351a","type":"ui_gauge","z":"4703de07.5f73f","name":"PH","group":"8b0f9e98.0495a8","order":1,"width":"0","height":"0","gtype":"gage","title":"pH","label":"","format":"{{value | number:2}}","min":"1","max":"10","colors":["#ca3838","#008f00","#0200b7"],"seg1":"","seg2":"","x":995.25,"y":1160.75,"wires":[]},{"id":"1b44c4a1.31919b","type":"comment","z":"4703de07.5f73f","name":"Serial commands","info":"Commands for the Ezo pH unit over serial can be found\nin the pH_EZO datasheet.\nSerial send Node:\n\nOn itial copying of flow the Serial node will need setup:\n\nUse 'Search' symbol in node setup to find your serial port\non your device.ie /dev/usb:9600-8N1 or similar.\n\nBaud: 9600\nData bits: 8\nParity: None\nStop bits: 1\nSplit input: on the character  -then enter 0x0D in box\nand delivery: ascii string\n\nMake sure that both input and output Serial nodes have the\nsame configured port selected.If you look at the UI you\nshould see messeges displayed after the 'Status' label.\ninitial normal value would be 'Boot complete, Ready' or 'OK'","x":664,"y":983.5,"wires":[]},{"id":"1976c5d8.787d0a","type":"comment","z":"4703de07.5f73f","name":"Temperature compensation","info":"Temperature compensation when using buffer solutions can either\nbe entered in manually on the UI.\nIf available a temperature probe reading can be used instead\nof the 'Compensation temp' inject node, but how you get the reading\ninto node red is up to you.\nIf using a temperature probe this will need to be placed into the\nsolution during the Mid Cal step.","x":694.5,"y":1202.25,"wires":[]},{"id":"bef93206.0b46c8","type":"inject","z":"4703de07.5f73f","name":"Compensation temp","topic":"watertemp","payload":"25.0","payloadType":"num","repeat":"","crontab":"","once":true,"x":419.25,"y":1260.25,"wires":[["b65106e.d4006f8"]]},{"id":"b65106e.d4006f8","type":"change","z":"4703de07.5f73f","name":"","rules":[{"t":"set","p":"watertemp","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":663.75,"y":1266.25,"wires":[["50a3f222.4f27fc"]]},{"id":"50a3f222.4f27fc","type":"ui_gauge","z":"4703de07.5f73f","name":"","group":"8b0f9e98.0495a8","order":0,"width":0,"height":0,"gtype":"gage","title":"Temperature Solution","label":"units","format":"{{value}}","min":0,"max":"40","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":1048.75,"y":1268.25,"wires":[]},{"id":"22b20f27.3c9d9","type":"ui_text","z":"4703de07.5f73f","group":"258d7f77.cffb48","order":0,"width":0,"height":0,"name":"","label":"Status","format":"{{msg.payload}}","layout":"row-left","x":995.86669921875,"y":1122.5999755859375,"wires":[]},{"id":"a9c4ccbd.28fac","type":"switch","z":"4703de07.5f73f","name":"Error reset","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"ER","vt":"str"}],"checkall":"true","outputs":1,"x":860.36669921875,"y":1075,"wires":[["fa4dc880.cf9c38"]]},{"id":"258d7f77.cffb48","type":"ui_group","z":"","name":"Calibration","tab":"c7e10c4f.6a667","order":1,"disp":true,"width":"6"},{"id":"ab1982f0.d809d8","type":"ui_group","z":"","name":"Setpoints","tab":"c7e10c4f.6a667","order":2,"disp":true,"width":"6"},{"id":"9d2245ba.027998","type":"serial-port","z":"","serialport":"/dev/usb","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","newline":"0x0D","bin":"false","out":"char","addchar":false},{"id":"8b0f9e98.0495a8","type":"ui_group","z":"","name":"Readings","tab":"32cf1b63.7fb304","order":2,"disp":true,"width":"6"},{"id":"c7e10c4f.6a667","type":"ui_tab","z":"","name":"Calibration","icon":"dashboard","order":4},{"id":"32cf1b63.7fb304","type":"ui_tab","z":"","name":"Main","icon":"dashboard","order":1}]
jaseuk73

Flow Info

created 2 weeks, 2 days ago

Node Types

Core
  • change (x25)
  • comment (x4)
  • delay (x3)
  • function (x7)
  • inject (x4)
  • serial in (x1)
  • serial out (x1)
  • serial-port (x1)
  • switch (x4)
Other
  • ui_button (x5)
  • ui_gauge (x2)
  • ui_group (x3)
  • ui_numeric (x6)
  • ui_switch (x2)
  • ui_tab (x2)
  • ui_text (x5)
  • ui_ui_control (x1)

Tags

  • EZO-pH
  • dashboard
  • ui
  • serial
  • calibration
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option