Blastgate Automation Flow

Hey,

I would like to install a blastgate automation in my woodworking shop. The hardware is already installed and all components work as planned. Unfortunately, creating a flow for my application is now much more complicated than I would have thought. Maybe there is someone here who already has a similar flow and would like to share it with me. As soon as my project is finished, I plan to publish a post describing exactly how I implemented the project, i.e. hardware, software and assembly.

This is the code for the connected components:

[
    {
        "id": "14c53feff2182fde",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Start",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 150,
        "y": 160,
        "wires": [
            [
                "4adbacfb9daaf4be",
                "e5d15942fc82112a"
            ]
        ]
    },
    {
        "id": "4adbacfb9daaf4be",
        "type": "ads1x15-raspi",
        "z": "8aed75ad9c3e8301",
        "property": "payload",
        "name": "Planer",
        "chip": "IC_ADS1115",
        "i2c_address": "ADDRESS_0x48",
        "channel": "CHANNEL_0",
        "samplesPerSecond0": "SPS_920",
        "samplesPerSecond1": "SPS_128",
        "progGainAmp": "PGA_4_096V",
        "x": 370,
        "y": 120,
        "wires": [
            []
        ]
    },
    {
        "id": "e5d15942fc82112a",
        "type": "ads1x15-raspi",
        "z": "8aed75ad9c3e8301",
        "property": "payload",
        "name": "Saw",
        "chip": "IC_ADS1115",
        "i2c_address": "ADDRESS_0x48",
        "channel": "CHANNEL_1",
        "samplesPerSecond0": "SPS_920",
        "samplesPerSecond1": "SPS_8",
        "progGainAmp": "PGA_4_096V",
        "x": 370,
        "y": 200,
        "wires": [
            []
        ]
    },
    {
        "id": "dd3b1ee7fe45eabb",
        "type": "rpi-gpio out",
        "z": "8aed75ad9c3e8301",
        "name": "Dustcollector",
        "pin": "4",
        "set": "",
        "level": "0",
        "freq": "",
        "out": "out",
        "bcm": true,
        "x": 550,
        "y": 340,
        "wires": []
    },
    {
        "id": "80212d7fcb963d57",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Off",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1",
        "payloadType": "num",
        "x": 150,
        "y": 380,
        "wires": [
            [
                "dd3b1ee7fe45eabb"
            ]
        ]
    },
    {
        "id": "4fe83268343d4ea8",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "On",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "0",
        "payloadType": "num",
        "x": 150,
        "y": 320,
        "wires": [
            [
                "dd3b1ee7fe45eabb"
            ]
        ]
    },
    {
        "id": "da07adb97048ae4c",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Open",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1000",
        "payloadType": "num",
        "x": 150,
        "y": 640,
        "wires": [
            [
                "2e80a2332dee5c7e"
            ]
        ]
    },
    {
        "id": "8a65215c20276aa4",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Close",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "2000",
        "payloadType": "num",
        "x": 150,
        "y": 680,
        "wires": [
            [
                "2e80a2332dee5c7e"
            ]
        ]
    },
    {
        "id": "440980de1e4fc8c3",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Off",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "0",
        "payloadType": "num",
        "x": 150,
        "y": 720,
        "wires": [
            [
                "2e80a2332dee5c7e"
            ]
        ]
    },
    {
        "id": "2e80a2332dee5c7e",
        "type": "PCA9685 out",
        "z": "8aed75ad9c3e8301",
        "name": "Blastgate 2",
        "pca9685": "6095e8fcd95f1634",
        "channel": "2",
        "payload": "[msg.payload]",
        "unit": "microseconds",
        "onStep": "0",
        "x": 590,
        "y": 680,
        "wires": []
    },
    {
        "id": "3132cd7a08b28b20",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Open",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1000",
        "payloadType": "num",
        "x": 150,
        "y": 780,
        "wires": [
            [
                "ee2d5cfc17685f95"
            ]
        ]
    },
    {
        "id": "670c415b65b80479",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Close",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "2000",
        "payloadType": "num",
        "x": 150,
        "y": 820,
        "wires": [
            [
                "ee2d5cfc17685f95"
            ]
        ]
    },
    {
        "id": "70ae7e7c9cd4e89a",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Off",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "0",
        "payloadType": "num",
        "x": 150,
        "y": 860,
        "wires": [
            [
                "ee2d5cfc17685f95"
            ]
        ]
    },
    {
        "id": "ee2d5cfc17685f95",
        "type": "PCA9685 out",
        "z": "8aed75ad9c3e8301",
        "name": "Blastgate 3",
        "pca9685": "6095e8fcd95f1634",
        "channel": "3",
        "payload": "[msg.payload]",
        "unit": "microseconds",
        "onStep": "0",
        "x": 590,
        "y": 820,
        "wires": []
    },
    {
        "id": "e6df165adcef1f01",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Open",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1000",
        "payloadType": "num",
        "x": 150,
        "y": 500,
        "wires": [
            [
                "ae004bab1749b688"
            ]
        ]
    },
    {
        "id": "1e8ad0320a99f44a",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Close",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "2000",
        "payloadType": "num",
        "x": 150,
        "y": 540,
        "wires": [
            [
                "ae004bab1749b688"
            ]
        ]
    },
    {
        "id": "efb9da6614d9fd7d",
        "type": "inject",
        "z": "8aed75ad9c3e8301",
        "name": "Off",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "0",
        "payloadType": "num",
        "x": 150,
        "y": 580,
        "wires": [
            [
                "ae004bab1749b688"
            ]
        ]
    },
    {
        "id": "ae004bab1749b688",
        "type": "PCA9685 out",
        "z": "8aed75ad9c3e8301",
        "name": "Blastgate 1",
        "pca9685": "6095e8fcd95f1634",
        "channel": "1",
        "payload": "[msg.payload]",
        "unit": "microseconds",
        "onStep": "0",
        "x": 590,
        "y": 540,
        "wires": []
    },
    {
        "id": "6095e8fcd95f1634",
        "type": "PCA9685",
        "deviceNumber": "0",
        "address": "64",
        "frequency": "50"
    }
]

That`s the overview:

And that`s the control:

Hi and welcome to the forum.

It is 03:00 (local) here and I am not really awake.

So the equipment sends a signal (eg 0/1) for OFF / ON.

And the blast gates want a signal to tell them to open/close.
Open being they let stuff through.

If true:
Without wanting to spoil your attempt:
You could do that with basic electronics.

When the/a machine is turned on, it sends a 1 (for example)
To better clarify: It applies a voltage to an output pin.

The blastgates are looking for an input on one of their pins.

If it is HIGH (or a 1) they open and allow airflow.
Otherwise they are closed and don't allow airflow.

So: You connect the output of the device/machine to the input of the blastgate.

NOTE:

You may need some isolating circuits and/or level changers if they talk different voltage levels.

Or

If the machine's output is not the same as I described.
That is: If it puts the pin LOW (0) when on and the gate wants a 1 to be open.
You would just use an inverter chip to swap the levels.

Just a thought.

Mutually exclusive setup which says that it is one man shop. Perfectly fine but is it intentional?

(Sorry, I didn't look at the flow or load it.)

So these machines send actual MQTT messages?

Wow! Mind blown.

Hey, you're right of course, my sketch shows it in a very simplified way. It is a hobby workshop in which I usually work alone. But it would be better if there was a method in which all blastgates are open as soon as both machines are in turned on.

I can't say whether the message comes in the MQTT protocol.

The condition of the two machines (saw & planner) is measured with a current sensor that is mounted directly in the control cabinet. These sensors are connected to the Raspberry Pi via an analog/digital converter and output a value in volts. Here it would of course not be necessary to be able to define a threshold value at which value the machine is then defined as on or off.

I know that the project could have been realized with very simple components. However, I wanted to have a certain flexibility if more machines were added and there are also some features that should be built in. These features are described on the sheet with the sketch.

I plan to publish the project on instructables, it is currently still a draft, but so that you have a little more insight I am sharing the link here:

https://www.instructables.com/Blastgate-Automatin/


1 Like

Sorry for the long delay in my reply.

@steffstereo
That flow is very good.
Basic and easy to understand.

Dumb/silly question: Why 3 INPUTS? Open / Close and Off?

From what you've described the flow should be fairly easy to make/do.

Analogue input from the device.
Get value.
Above a certain level - indicating the machine is on
Turn on blastgate
If below said level
Turn off blastgate

Copy / repeat for each device.

At first I thought it should be very easy, but I need some features that make it a little more complicated for me.

Features i would need:

  • Servo-motors should have a delay of 1 second to eachother.
    (less load for powersupply)

  • Servo-motor sholud switch off 2 seconds after operation.
    (If the servo were blocked it would keep pushing and at some point the motor would perhaps burn out)

  • After switching of the saw or planer the blastgates shold keep their position.
    (If I use the same machine several times in a row, the servos would open and close again and again, which would be unnecessary)

  • After switching off the saw or planer the dustcollector should run for 10 more seconds.
    (The dustcollector should continue to run so that all dust is removed from the pipe)

  • If both machines are switched on (saw and planner) the extraction system should continue to run and all blastgates should open.

  • There should be a dashboard where the blastgates and dustcollector can be controlled individually by touchscreen. Manual intervention should override the automatic.
    (For example, if I cut aluminum or plastic with the saw, I would like to deactivate the dustcollector)

  • The extraction system should be switched on with a delay of 5 seconds.
    (This is to prevent the blastgates from having unnecessarily much resistance, so first open the blastgates, then turn on the dust collector)

For sure the main controller needs some kind of feedback from servos.
What kind of communication is planned here?

Meanwhile I made a valve representaion for dashboard. (dashboard 2)

[{"id":"ba31437764d0a2fa","type":"ui-template","z":"765bf42177e58b83","group":"e5fba2e141cfe49e","page":"","ui":"","name":"valve 1","order":4,"width":"2","height":"2","head":"","format":"<template>\n    <div class=\"servo-valve\">\n        <div class=\"valve\" :style=\"`--position:${value};`\"></div>\n        <div class=\"frame\"></div>\n        <div class=\"label\">{{name}}</div>\n    </div>\n</template>\n\n<script>\n    export default {\n        data() {\n           \n            return {\n               value:0,\n               name:\"valve 1\"\n            }\n        },\n        watch: {\n           msg:function(){\n                if(this.msg?.payload != undefined){\n                    this.value = this.msg.payload\n                }\n           }\n        },\n        computed: {\n          \n        },\n        methods: {\n            \n        },\n        mounted() {\n            // code here when the component is first loaded\n        },\n        unmounted() {\n            // code here when the component is removed from the Dashboard\n            // i.e. when the user navigates away from the page\n        }\n    }\n</script>\n<style>\n    .servo-valve{\n        position:relative;\n        height:calc(var(--widget-row-height) * 2 + var(--widget-gap));\n        aspect-ratio:1;\n        border-radius:100vh;\n        overflow:hidden;        \n    }\n    .servo-valve .frame{\n        position: absolute;\n        inset: 0;\n        border-radius: 100vh;\n        width: 100%;\n        height: 100%;\n        outline: 4px solid gray;\n        outline-offset: -4px;    \n    }\n    .servo-valve .valve{\n        position: absolute;\n        inset: 5%;\n        border-radius: 100vh;\n        width: 90%;\n        height: 90%;\n        background: #d8d8d5;\n        transform: translateX(calc(var(--position)*1%));\n    }\n    .servo-valve .label{\n        position: absolute;\n        display: flex;\n        align-items: center;\n        justify-content: center; \n        height: 100%;\n        width: 100%;\n        color:rgb(var(--v-theme-primary));\n    }\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":680,"y":1360,"wires":[[]]},{"id":"b561cfbbf31c4703","type":"ui-slider","z":"765bf42177e58b83","group":"e5fba2e141cfe49e","name":"","label":"valve 1","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"outs":"all","topic":"topic","topicType":"msg","thumbLabel":"true","showTicks":"false","min":0,"max":"100","step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":440,"y":1360,"wires":[["ba31437764d0a2fa"]]},{"id":"591b9570efcd2c9b","type":"ui-template","z":"765bf42177e58b83","group":"e5fba2e141cfe49e","page":"","ui":"","name":"valve 2","order":5,"width":"2","height":"2","head":"","format":"<template>\n    <div class=\"servo-valve\">\n        <div class=\"valve\" :style=\"`--position:${value};`\"></div>\n        <div class=\"frame\"></div>\n        <div class=\"label\">{{name}}</div>\n    </div>\n</template>\n\n<script>\n    export default {\n        data() {\n           \n            return {\n               value:0,\n               name:\"valve 2\"\n            }\n        },\n        watch: {\n           msg:function(){\n                if(this.msg?.payload != undefined){\n                    this.value = this.msg.payload\n                }\n           }\n        },\n        computed: {\n          \n        },\n        methods: {\n            \n        },\n        mounted() {\n            // code here when the component is first loaded\n        },\n        unmounted() {\n            // code here when the component is removed from the Dashboard\n            // i.e. when the user navigates away from the page\n        }\n    }\n</script>\n<style>\n    .servo-valve{\n        position:relative;\n        height:calc(var(--widget-row-height) * 2 + var(--widget-gap));\n        aspect-ratio:1;\n        border-radius:100vh;\n        overflow:hidden;        \n    }\n    .servo-valve .frame{\n        position: absolute;\n        inset: 0;\n        border-radius: 100vh;\n        width: 100%;\n        height: 100%;\n        outline: 4px solid gray;\n        outline-offset: -4px;    \n    }\n    .servo-valve .valve{\n        position: absolute;\n        inset: 5%;\n        border-radius: 100vh;\n        width: 90%;\n        height: 90%;\n        background: #d8d8d5;\n        transform: translateX(calc(var(--position)*1%));\n    }\n    .servo-valve .label{\n        position: absolute;\n        display: flex;\n        align-items: center;\n        justify-content: center; \n        height: 100%;\n        width: 100%;\n        color:rgb(var(--v-theme-primary));\n    }\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":680,"y":1400,"wires":[[]]},{"id":"9739a5b0ab22a635","type":"ui-template","z":"765bf42177e58b83","group":"e5fba2e141cfe49e","page":"","ui":"","name":"valve 3","order":6,"width":"2","height":"2","head":"","format":"<template>\n    <div class=\"servo-valve\">\n        <div class=\"valve\" :style=\"`--position:${value};`\"></div>\n        <div class=\"frame\"></div>\n        <div class=\"label\">{{name}}</div>\n    </div>\n</template>\n\n<script>\n    export default {\n        data() {\n           \n            return {\n               value:0,\n               name:\"valve 3\"\n            }\n        },\n        watch: {\n           msg:function(){\n                if(this.msg?.payload != undefined){\n                    this.value = this.msg.payload\n                }\n           }\n        },\n        computed: {\n          \n        },\n        methods: {\n            \n        },\n        mounted() {\n            // code here when the component is first loaded\n        },\n        unmounted() {\n            // code here when the component is removed from the Dashboard\n            // i.e. when the user navigates away from the page\n        }\n    }\n</script>\n<style>\n    .servo-valve{\n        position:relative;\n        height:calc(var(--widget-row-height) * 2 + var(--widget-gap));\n        aspect-ratio:1;\n        border-radius:100vh;\n        overflow:hidden;        \n    }\n    .servo-valve .frame{\n        position: absolute;\n        inset: 0;\n        border-radius: 100vh;\n        width: 100%;\n        height: 100%;\n        outline: 4px solid gray;\n        outline-offset: -4px;    \n    }\n    .servo-valve .valve{\n        position: absolute;\n        inset: 5%;\n        border-radius: 100vh;\n        width: 90%;\n        height: 90%;\n        background: #d8d8d5;\n        transform: translateX(calc(var(--position)*1%));\n    }\n    .servo-valve .label{\n        position: absolute;\n        display: flex;\n        align-items: center;\n        justify-content: center; \n        height: 100%;\n        width: 100%;\n        color:rgb(var(--v-theme-primary));\n    }\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":680,"y":1440,"wires":[[]]},{"id":"93e59bb75434aa50","type":"ui-slider","z":"765bf42177e58b83","group":"e5fba2e141cfe49e","name":"","label":"valve 2","tooltip":"","order":2,"width":0,"height":0,"passthru":false,"outs":"all","topic":"topic","topicType":"msg","thumbLabel":"true","showTicks":"false","min":0,"max":"100","step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":440,"y":1400,"wires":[["591b9570efcd2c9b"]]},{"id":"fa32d651d0d42953","type":"ui-slider","z":"765bf42177e58b83","group":"e5fba2e141cfe49e","name":"","label":"valve 3","tooltip":"","order":3,"width":0,"height":0,"passthru":false,"outs":"all","topic":"topic","topicType":"msg","thumbLabel":"true","showTicks":"false","min":0,"max":"100","step":1,"className":"","iconPrepend":"","iconAppend":"","color":"","colorTrack":"","colorThumb":"","x":440,"y":1440,"wires":[["9739a5b0ab22a635"]]},{"id":"e5fba2e141cfe49e","type":"ui-group","name":"Blast","page":"c77bb1a2d6cd012f","width":"6","height":"1","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"c77bb1a2d6cd012f","type":"ui-page","name":"Shop","ui":"5c0986aff71f902a","path":"/shop","icon":"home","layout":"grid","theme":"0879be4b9aa7780a","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":1,"className":"","visible":"true","disabled":"false"},{"id":"5c0986aff71f902a","type":"ui-base","name":"Dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"default","titleBarStyle":"default"},{"id":"0879be4b9aa7780a","type":"ui-theme","name":"Shop","colors":{"surface":"#595959","primary":"#0ba800","bgPage":"#383838","groupBg":"#262626","groupOutline":"#42bd00"},"sizes":{"density":"default","pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]

Just because I like your project.

3 Likes

@hotNipi oh thank you very much for the dashboard, that looks very cool. I'll try to install it later.

I'm not sure if there's a way to do a proper status query when it comes to the servos. I use a PCA9685 connected via SCL/SDA to control the servos.

I've been racking my brain for a while now about how to create a good flow. During my first attempts at programming, effects occurred in certain situations that were not intended. so there were logic errors. I have now created a new mind map for a possible flow. what do you think about that?

I have updated the current status again on instructables.com:

That isn't a problem.

Just a delay node.

As above.
And actually you would use NMAE 17 type servos. (I think that is the type.)
They don't need to constantly be powered.

Now you are complicating things.
But again: a delay node would work.
You just put it in a different part of the flow.

I again say: the delay node.

Some of these things are flow things and some are more hardware things.

Example flow code:

[{"id":"51b8de0580de1a14","type":"inject","z":"26262ba1.62dcbc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"ON","payloadType":"str","x":4470,"y":5380,"wires":[["4acc4a49f8528982","9bd4806e0a3847a9"]]},{"id":"41849061de3d30a4","type":"inject","z":"26262ba1.62dcbc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"OFF","payloadType":"str","x":4470,"y":5340,"wires":[["6cdc93016a74ff57","b487c8e23a1e84ab"]]},{"id":"4acc4a49f8528982","type":"delay","z":"26262ba1.62dcbc","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":4670,"y":5380,"wires":[["6cdc93016a74ff57"]]},{"id":"8b45a688c1b7532a","type":"debug","z":"26262ba1.62dcbc","name":"SERVO motor","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":5020,"y":5380,"wires":[]},{"id":"6cdc93016a74ff57","type":"trigger","z":"26262ba1.62dcbc","name":"","op1":"","op2":"Power down","op1type":"pay","op2type":"str","duration":"2","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":4830,"y":5380,"wires":[["8b45a688c1b7532a"]]},{"id":"b487c8e23a1e84ab","type":"delay","z":"26262ba1.62dcbc","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":4670,"y":5280,"wires":[["9bd4806e0a3847a9"]]},{"id":"9bd4806e0a3847a9","type":"debug","z":"26262ba1.62dcbc","name":"DUST COLLECTOR motor","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":5060,"y":5280,"wires":[]},{"id":"158e686693664780","type":"comment","z":"26262ba1.62dcbc","name":"from machine","info":"","x":4480,"y":5280,"wires":[]}]

You will have to but a bit of code, but for the structure of how to do it.

Here is a quick flow that seems to do what you want.

Yes, there is work to be done with messages, but for the sake of what you want to happen.

There are node.warn() lines in there but just for showing you what's going on.
They aren't needed for it to work.

[{"id":"53cf46170d3d36e7","type":"function","z":"26262ba1.62dcbc","name":"function 185","func":"let device = msg.topic\nlet saw = context.get(\"SAW\") || 0\nlet planer = context.get(\"PLANER\") || 0\nlet state = 0\n\nlet condition = msg.payload\nif (condition == \"OFF\")\n{\n    state = 0\n}\nif (condition == \"ON\")\n{\n    state = 1\n}\n\ncontext.set(device,state)\n\nif (condition == \"ON\")\n{\n    //  ON\n    let saw = context.get(\"SAW\") || 0\n    let planer = context.get(\"PLANER\") || 0\n    node.status({\"text\":\"Saw \" + saw + \" Planer \" + planer})\n    return msg;\n}\n\nif (condition == \"OFF\")\n{\n    //  OFF\n    let saw = context.get(\"SAW\") || 0\n    let planer = context.get(\"PLANER\") || 0\n    node.status({ \"text\": \"Saw \" + saw + \" Planer \" + planer })\n    if (saw == 0 && planer == 0)\n    {\n        //\n        //node.status({\"text\":\"Saw \" + saw + \" Planer \" + planer})\n        node.warn(\"ALL OFF\")\n        return msg;\n    }\n}\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":5010,"y":5800,"wires":[["15e9fb0f0a1f1b24"]]},{"id":"5b39933458554e2e","type":"delay","z":"26262ba1.62dcbc","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":4670,"y":5580,"wires":[["53cf46170d3d36e7"]]},{"id":"6441da4aa3516314","type":"delay","z":"26262ba1.62dcbc","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":4670,"y":5910,"wires":[["53cf46170d3d36e7"]]},{"id":"41a83f3b5e5f89f6","type":"inject","z":"26262ba1.62dcbc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SAW","payload":"ON","payloadType":"str","x":4480,"y":5680,"wires":[["a9b6a40eb3aa47e4","53cf46170d3d36e7"]]},{"id":"10fa602f04135666","type":"inject","z":"26262ba1.62dcbc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"PLANER","payload":"ON","payloadType":"str","x":4480,"y":6010,"wires":[["7a5ac58351fbd927","53cf46170d3d36e7"]]},{"id":"15e9fb0f0a1f1b24","type":"debug","z":"26262ba1.62dcbc","name":"DUST COLLECTOR motor","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":5270,"y":5800,"wires":[]},{"id":"a663d98f9bf9a3ba","type":"inject","z":"26262ba1.62dcbc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SAW","payload":"OFF","payloadType":"str","x":4480,"y":5640,"wires":[["a5372f1c531cd7d8","5b39933458554e2e"]]},{"id":"5257560d69f3eae0","type":"inject","z":"26262ba1.62dcbc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"PLANER","payload":"OFF","payloadType":"str","x":4480,"y":5970,"wires":[["199ae53abb153243","6441da4aa3516314"]]},{"id":"a9b6a40eb3aa47e4","type":"delay","z":"26262ba1.62dcbc","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":4670,"y":5680,"wires":[["a5372f1c531cd7d8"]]},{"id":"7a5ac58351fbd927","type":"delay","z":"26262ba1.62dcbc","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":4670,"y":6010,"wires":[["199ae53abb153243"]]},{"id":"a5372f1c531cd7d8","type":"trigger","z":"26262ba1.62dcbc","name":"","op1":"","op2":"Power down","op1type":"pay","op2type":"str","duration":"2","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":4830,"y":5680,"wires":[["76850b9c757d313c"]]},{"id":"199ae53abb153243","type":"trigger","z":"26262ba1.62dcbc","name":"","op1":"","op2":"Power down","op1type":"pay","op2type":"str","duration":"2","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":4830,"y":6010,"wires":[["c5070974567b4cf7"]]},{"id":"76850b9c757d313c","type":"debug","z":"26262ba1.62dcbc","name":"SERVO motor","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":5020,"y":5680,"wires":[]},{"id":"c5070974567b4cf7","type":"debug","z":"26262ba1.62dcbc","name":"SERVO motor","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":5020,"y":6010,"wires":[]}]

hey, thank you very much for your efforts, I'll try the code out straight away :slight_smile:

I think it looks very good at first glance, I'm excited!

Progress?

After a few tries and tests, I decided to create a new concept for the flow. This time I did the visualization with Drawio, which was a lot easier. I know the symbols aren't all the way you actually use them, but I only discovered later that there is a standard for the different types of flow elements.

After I had finished this flow chart, I searched somebody to create a flow for me based on the flow chart. I'm currently waiting for it to be completed and then I'm looking forward to the tests. There will certainly be a few more revisions necessary until the project is finished. But I'll share the result here!

Yeah, ok. Fair enough.

I do like that you have used a flow chart to lay out what you want doing and how.
That will be useful for you in the future with other things you want to do.

I'm having a real bad time just now remembering things.

The MANUAL CONTROL and CHECK STATUS features weren't in your original ask.
No problems.

But the flow I posted does 90%* of what you want to do.

  • Well, pretty much all. I picked 90 as a fairly good number.

I could probably have continued working with your flow, that's true. but I found it a bit difficult to understand it all. It was easier to understand when I was starting from scratch. It was then that the desire arose to query the status and implement the dashboard/manual control. I'm still working on the flow at the moment, the hardware also has some limitations for which I first have to find a work-around. Unfortunately, this cannot be predicted in theory, but practice brings you back down to earth :x