Projects
Node-RED Flows

Node-RED Flows

Connect the three circuits (Nano 1, Nano 2, and Pico) to the 3 USB ports on the Raspberry Pi or the personal computer running Node-RED and start the flows. You should start seeing the data published to the MQTT Broker.

Send data from the Node-RED flow to the Pico circuit which will read the data over the default Serial port and send control signals to the relay and motor.

To use Node-RED you need a computer and the circuits sending or receiving data need to be connected to the computer with an USB cable. This is an alternative approach to using wireless communication to send data to an MQTT broker over WiFi. The advantage of this approach is that you can configure Node-RED for the required functionality with very little code whereas if you want to use the ESP32 WiFi and MQTT capability you need to download libraries and write the required code.

For the solution variant that uses Node-RED, the ESP32 circuit is not required and neither is any inter-board communication. The Nano and Pico circuits will be connected to a Raspberry Pi and will exchange data directly with Node-RED.

We will be using a Raspberry Pi to run Node-RED but you can use your personal computer just as well.

The flows for each of the circuits are below:

Sensor Data Flow

The Node-RED flow for capturing sensor data from the Nano and Pico circuits is shown below.

capture_and_transmit_nano_circuit_fritzing

Code

You can recreate the flow by importing the code below into your Node-RED editor.

[{"id":"17fd02ad03f50979","type":"tab","label":"Sensor Data Flow","disabled":false,"info":"","env":[]},{"id":"3edd400a453b4f21","type":"serial in","z":"17fd02ad03f50979","name":"NanoSerialIn","serial":"e89ac83158ba7533","x":1110,"y":920,"wires":[["0d921c733e07d93f","e881775a18644168"]]},{"id":"404b7711d9c92a1e","type":"debug","z":"17fd02ad03f50979","name":"PublishedJSONDebug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2740,"y":800,"wires":[]},{"id":"0d921c733e07d93f","type":"json","z":"17fd02ad03f50979","name":"","property":"payload","action":"obj","pretty":false,"x":1310,"y":1000,"wires":[["46824651894c1ac2"]]},{"id":"c5e22e7fdb94fac1","type":"switch","z":"17fd02ad03f50979","name":"IdentifySensor","property":"payload.parameter","propertyType":"msg","rules":[{"t":"eq","v":"Temperature","vt":"str"},{"t":"eq","v":"Humidity","vt":"str"},{"t":"eq","v":"Distance","vt":"str"},{"t":"eq","v":"Motion","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":5,"x":1720,"y":1060,"wires":[["f95b17a8d7c7525c"],["c5e0d1088934d392"],["5201a765e1a3fc67"],["52f3a6ef80c34eba"],["6a43760cee75ade1"]]},{"id":"133bf93cea305ff2","type":"mqtt out","z":"17fd02ad03f50979","name":"Publish - STEMVentorHiveMQ","topic":"sensor-data","qos":"","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"90844ce0ad4c8dc2","x":2770,"y":1060,"wires":[]},{"id":"6a43760cee75ade1","type":"function","z":"17fd02ad03f50979","name":"ReturnInvalidSensorMsg","func":"return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2030,"y":1220,"wires":[[]]},{"id":"9ac05a055933820b","type":"json","z":"17fd02ad03f50979","name":"","property":"payload","action":"str","pretty":false,"x":2530,"y":1060,"wires":[["133bf93cea305ff2","404b7711d9c92a1e"]]},{"id":"1c3bf67106b1c424","type":"comment","z":"17fd02ad03f50979","name":"Note on URL","info":"For MQTT brokers Node-RED uses the TCP URL and Port unlike the mobile app that uses the Websocket URL and port. For the private STEMVentor HiveMQ cluster select the TLS option and provide userid and password but no TLS Config or certificates are required.","x":2710,"y":1120,"wires":[]},{"id":"c04c603d78aadd68","type":"debug","z":"17fd02ad03f50979","name":"Messages","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1710,"y":800,"wires":[]},{"id":"46824651894c1ac2","type":"switch","z":"17fd02ad03f50979","name":"DataType","property":"payload.data_type","propertyType":"msg","rules":[{"t":"eq","v":"Message","vt":"str"},{"t":"eq","v":"Data","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1500,"y":1000,"wires":[["c04c603d78aadd68"],["c5e22e7fdb94fac1"]]},{"id":"2dc7832ade2af12d","type":"function","z":"17fd02ad03f50979","name":"processDistance","func":"// Add the timestamp in epoch (milliseconds)\nmsg.payload.timestamp = Date.now();\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2240,"y":1060,"wires":[["9ac05a055933820b"]]},{"id":"cf96bff4412d1477","type":"function","z":"17fd02ad03f50979","name":"processMotion","func":"// Add the timestamp in epoch (milliseconds)\nmsg.payload.timestamp = Date.now();\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2240,"y":1140,"wires":[["9ac05a055933820b"]]},{"id":"e881775a18644168","type":"debug","z":"17fd02ad03f50979","name":"NanoSerialInDebug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1350,"y":800,"wires":[]},{"id":"7aee33ebc7b44878","type":"serial in","z":"17fd02ad03f50979","name":"PicoSerialIn","serial":"98dbac6f7bfc9d91","x":1110,"y":1100,"wires":[["0d921c733e07d93f","280dedb91781091a"]]},{"id":"280dedb91781091a","type":"debug","z":"17fd02ad03f50979","name":"PicoSerialInDebug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1350,"y":1200,"wires":[]},{"id":"f95b17a8d7c7525c","type":"range","z":"17fd02ad03f50979","minin":"15","maxin":"35","minout":"15","maxout":"35","action":"drop","round":true,"property":"payload.value","name":"FilterTemperature","x":2010,"y":900,"wires":[["541878ed8f414687"]]},{"id":"541878ed8f414687","type":"function","z":"17fd02ad03f50979","name":"processTemperature","func":"// Add the timestamp in epoch (milliseconds)\nmsg.payload.timestamp = Date.now();\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2260,"y":900,"wires":[["9ac05a055933820b"]]},{"id":"c5e0d1088934d392","type":"range","z":"17fd02ad03f50979","minin":"40","maxin":"100","minout":"40","maxout":"100","action":"drop","round":true,"property":"payload.value","name":"FilterHumidity","x":2000,"y":980,"wires":[["b4e5d26662e0bab1"]]},{"id":"b4e5d26662e0bab1","type":"function","z":"17fd02ad03f50979","name":"processHumidity","func":"// Add the timestamp in epoch (milliseconds)\nmsg.payload.timestamp = Date.now();\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2240,"y":980,"wires":[["9ac05a055933820b"]]},{"id":"5201a765e1a3fc67","type":"range","z":"17fd02ad03f50979","minin":"0","maxin":"25","minout":"0","maxout":"25","action":"drop","round":true,"property":"payload.value","name":"FilterDistance","x":2000,"y":1060,"wires":[["2dc7832ade2af12d"]]},{"id":"52f3a6ef80c34eba","type":"range","z":"17fd02ad03f50979","minin":"0","maxin":"1","minout":"0","maxout":"1","action":"drop","round":true,"property":"payload.value","name":"FilterMotion","x":1990,"y":1140,"wires":[["cf96bff4412d1477"]]},{"id":"e89ac83158ba7533","type":"serial-port","name":"","serialport":"COM3","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"\\n","bin":"false","out":"char","addchar":"\\n","responsetimeout":"10000"},{"id":"90844ce0ad4c8dc2","type":"mqtt-broker","name":"STEMVentor HiveMQ","broker":"0d7e686af22d4bada5068acbd9312761.s1.eu.hivemq.cloud","port":"8883","tls":"","clientid":"","autoConnect":true,"usetls":true,"protocolVersion":"5","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"98dbac6f7bfc9d91","type":"serial-port","name":"","serialport":"COM11","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"\\n","bin":"false","out":"char","addchar":"\\n","responsetimeout":"10000"}]

Control Signals Flow

The Node-RED flow for sending control signals to the Nano circuit is shown below.

capture_and_transmit_nano_circuit_fritzing

Code

You can recreate the flow by importing the code below into your Node-RED editor.

[{"id":"9dfab80c77ae7237","type":"tab","label":"Control Signal Flow","disabled":false,"info":"","env":[]},{"id":"db681470950d87aa","type":"mqtt in","z":"9dfab80c77ae7237","name":"Subscribe - STEMVentorHiveMQ - control-signals","topic":"control-signals","qos":"2","datatype":"auto-detect","broker":"90844ce0ad4c8dc2","nl":false,"rap":false,"rh":0,"inputs":0,"x":300,"y":360,"wires":[["fe332e922abb0a3a"]]},{"id":"fe332e922abb0a3a","type":"json","z":"9dfab80c77ae7237","name":"","property":"payload","action":"obj","pretty":false,"x":590,"y":360,"wires":[["3d0cd9a77e6c03a7","b4033ac821a6be3a"]]},{"id":"3d0cd9a77e6c03a7","type":"switch","z":"9dfab80c77ae7237","name":"IdentifyBoard","property":"payload.board_name","propertyType":"msg","rules":[{"t":"eq","v":"Arduino Nano","vt":"str"},{"t":"eq","v":"Raspberry Pico","vt":"str"},{"t":"eq","v":"ESP32","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":4,"x":770,"y":360,"wires":[["b4bd0ac8099249ec"],["289145d7bc5199fc"],["9342167c41316e31"],["8881be9f7401b3b0"]]},{"id":"8881be9f7401b3b0","type":"function","z":"9dfab80c77ae7237","name":"ReturnInvalidBoardMsg","func":"\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1090,"y":480,"wires":[[]]},{"id":"9c6364c3c1dbbfcd","type":"json","z":"9dfab80c77ae7237","name":"ToJSONString","property":"payload","action":"str","pretty":false,"x":1620,"y":240,"wires":[["481f86170625ab01","6e84a3ff74d48ea7"]]},{"id":"b4bd0ac8099249ec","type":"function","z":"9dfab80c77ae7237","name":"ReducePayload","func":"// Once the board has been identified\n// only send the pin and value to it to reduce overhead.\n\nvar reduced_msg = {\n    payload:{\n        pin: msg.payload.pin,\n        value: msg.payload.value,\n        timestamp: msg.payload.timestamp\n    }\n}\n\nreturn reduced_msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":240,"wires":[["b99b1ae572c19a1b"]]},{"id":"fb362a2aaea82d41","type":"serial out","z":"9dfab80c77ae7237","name":"PicoSerialOut","serial":"98dbac6f7bfc9d91","x":1520,"y":320,"wires":[]},{"id":"289145d7bc5199fc","type":"function","z":"9dfab80c77ae7237","name":"ReducePayload","func":"// Once the board has been identified\n// only send the pin and value to it to reduce overhead.\n\nvar reduced_msg = {\n    payload: {\n        pin: msg.payload.pin,\n        value: msg.payload.value,\n        timestamp: msg.payload.timestamp\n    }\n}\n\nreturn reduced_msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":320,"wires":[["78d91f59d8f10558"]]},{"id":"78d91f59d8f10558","type":"json","z":"9dfab80c77ae7237","name":"ToJSONString","property":"payload","action":"str","pretty":false,"x":1280,"y":320,"wires":[["fb362a2aaea82d41"]]},{"id":"9342167c41316e31","type":"function","z":"9dfab80c77ae7237","name":"ReducePayload","func":"// Once the board has been identified\n// only send the pin and value to it to reduce overhead.\n\nvar reduced_msg = {\n    payload: {\n        pin: msg.payload.pin,\n        value: msg.payload.value,\n        timestamp: msg.payload.timestamp\n    }\n}\n\nreturn reduced_msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":400,"wires":[["955200fc7e66d866"]]},{"id":"955200fc7e66d866","type":"json","z":"9dfab80c77ae7237","name":"ToJSONString","property":"payload","action":"str","pretty":false,"x":1280,"y":400,"wires":[["32b48993f582f8bf"]]},{"id":"32b48993f582f8bf","type":"serial out","z":"9dfab80c77ae7237","name":"ESP32SerialOut","serial":"98dbac6f7bfc9d91","x":1520,"y":400,"wires":[]},{"id":"b4033ac821a6be3a","type":"debug","z":"9dfab80c77ae7237","name":"debug 5","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":780,"y":580,"wires":[]},{"id":"481f86170625ab01","type":"serial out","z":"9dfab80c77ae7237","name":"NanoSerialOut","serial":"e89ac83158ba7533","x":1840,"y":240,"wires":[]},{"id":"b99b1ae572c19a1b","type":"switch","z":"9dfab80c77ae7237","name":"","property":"payload.pin","propertyType":"msg","rules":[{"t":"eq","v":"D4","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":1270,"y":240,"wires":[["587ab94174a9d58f"],["9c6364c3c1dbbfcd"]]},{"id":"587ab94174a9d58f","type":"range","z":"9dfab80c77ae7237","minin":"0","maxin":"10","minout":"0","maxout":"180","action":"scale","round":true,"property":"payload.value","name":"","x":1440,"y":180,"wires":[["9c6364c3c1dbbfcd"]]},{"id":"6e84a3ff74d48ea7","type":"debug","z":"9dfab80c77ae7237","name":"debug 6","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1840,"y":340,"wires":[]},{"id":"90844ce0ad4c8dc2","type":"mqtt-broker","name":"STEMVentor HiveMQ","broker":"0d7e686af22d4bada5068acbd9312761.s1.eu.hivemq.cloud","port":"8883","tls":"","clientid":"","autoConnect":true,"usetls":true,"protocolVersion":"5","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"98dbac6f7bfc9d91","type":"serial-port","name":"","serialport":"COM11","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"\\n","bin":"false","out":"char","addchar":"\\n","responsetimeout":"10000"},{"id":"e89ac83158ba7533","type":"serial-port","name":"","serialport":"COM3","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"\\n","bin":"false","out":"char","addchar":"\\n","responsetimeout":"10000"}]