# New MCP23017 PCF8574 All-In-One node

**URL:** <https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087>\
**Category:** Developing Nodes\
**Created:** [19 March 2022 19:43 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087 "2022-03-19T19:43:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [19 March 2022 19:43 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/1 "2022-03-19T19:43:30Z")

</div>

After 14 month of work in my free (and work) time here I present my first AIO solution to handle 3 similar kind of Input-Output I2C chips with Node-Red:

> **[GitHub - PizzaProgram/MCP23017-PCF8574-AIO: This is a Node-Red node to...](https://github.com/PizzaProgram/MCP23017-PCF8574-AIO)**
>
> This is a Node-Red node to communicate with MCP23017 or PCF8574(A) chips on a I2C bus. Both Input + Output. - GitHub - PizzaProgram/MCP23017-PCF8574-AIO: This is a Node-Red node to communicate with...

I'm still searching a way to publish it to NPM.  
_(Do not know yet, how to "log in" to my NPM account on Rpi terminal to publish...)_

Please tell your opinion, and report any errors you may find.

The main differences to the original 0.1 version:

1. It supports INTERRUPTS
2. read can be triggered -\> you get a full JSON of all pins and read success
3. Node-Red does not crash if any errors happening
4. You can use multiple I2C buses!

![kép](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/d/0d1122a0736b4714cdbab3dfc301ee7ce304c7e9.png)

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [19 March 2022 20:39 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/2 "2022-03-19T20:39:32Z")

</div>

Successfully published:  
(took me 50 minutes to figure out)

> $ npm login  
> User: \*\*\*\*  
> Password: \*\*\*  
> $ cd   
> $ npm publish --access public

> **[@pizzaprogram/mcp-pcf-aio](https://flows.nodered.org/node/@pizzaprogram/mcp-pcf-aio)**
>
> Node-Red node for multiple MCP23017 chips (each 16 input or output) + PCF8574(A) (8 I/O). The I2C Bus number can be specified too.

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [21 March 2022 13:26 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/3 "2022-03-21T13:26:07Z")

</div>

Added publishing quick example to docs:

> **[Comparing node-red:master...PizzaProgram:patch-1 · node-red/node-red.github.io](https://github.com/node-red/node-red.github.io/compare/master...PizzaProgram:patch-1)**
>
> Node-RED Site. Contribute to node-red/node-red.github.io development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [21 March 2022 13:49 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/4 "2022-03-21T13:49:58Z")

</div>

# Help needed:

I've just noticed a very strange thing:

- if I set an MCP23017 node to a bit between [0-7]
- only the first 8 = [0-7] is turned on/off at the "All0" and "All1" command

But:

- if I set an MCP23017 node to a bit between [8-15]
- ALL is turning on/off just fine

Theoretically the code is not influenced by Bit number:

```JavaScript
_aBus.writeByteSync(_addr, BNK1_OLAT_A, OnOff & 0xFF);	//Set output A
_aBus.writeByteSync(_addr, BNK1_OLAT_B, OnOff & 0xFF);	//Set output B

```

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [24 March 2022 10:42 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/5 "2022-03-24T10:42:23Z")

</div>

# What is your oppinion?

I'd like to implement into this component a "direct-payload-control" method.  
`msg.payload` would be a special character, like "d"  
`msg.Pin = 0-15`  
`msg.State = true/false`

This way you don't need to place 8-16 of mcp-pcf-Out nodes in your flow one by one, it's enough to set 1 or 2.

What should be the payload "letter" in this case? ("All0" and "All1" is for setting ALL.)

_Poll ([view on site](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/5))_

It is possible the A or B side needs to be pre-initialized at MCP23017, so accepting all (0-15) is not possible at one node only, if there is no other node in the upper / lower range!

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [25 March 2022 10:48 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/6 "2022-03-25T10:48:43Z")

</div>

Updated NPM.

# New feature:

direct `msg` control for Out Node is finished.

Nobody voted. Choosed : `msg.payload = -1`

Example:

```auto
[
    {
        "id": "cdb554694af63c0b",
        "type": "inject",
        "z": "04823d5afca6d208",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 550,
        "y": 160,
        "wires": [
            [
                "c97d62672d3eb61e"
            ]
        ]
    },
    {
        "id": "83cfcef10524acd0",
        "type": "inject",
        "z": "04823d5afca6d208",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "false",
        "payloadType": "bool",
        "x": 550,
        "y": 200,
        "wires": [
            [
                "c97d62672d3eb61e"
            ]
        ]
    },
    {
        "id": "b29818dfe5fa6d8c",
        "type": "inject",
        "z": "04823d5afca6d208",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "All0",
        "payloadType": "str",
        "x": 550,
        "y": 60,
        "wires": [
            [
                "c97d62672d3eb61e"
            ]
        ]
    },
    {
        "id": "489cc4c35bb3839b",
        "type": "inject",
        "z": "04823d5afca6d208",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "All1",
        "payloadType": "str",
        "x": 550,
        "y": 100,
        "wires": [
            [
                "c97d62672d3eb61e"
            ]
        ]
    },
    {
        "id": "c97d62672d3eb61e",
        "type": "MCP PCF Out",
        "z": "04823d5afca6d208",
        "name": "MCP-23-5",
        "chip": "ad16f0140a10887d",
        "bitNum": "1",
        "invert": true,
        "x": 760,
        "y": 180,
        "wires": []
    },
    {
        "id": "997bc22c57525541",
        "type": "inject",
        "z": "04823d5afca6d208",
        "name": "Set-2-On",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "Pin",
                "v": "2",
                "vt": "num"
            },
            {
                "p": "State",
                "v": "true",
                "vt": "bool"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "-1",
        "payloadType": "str",
        "x": 500,
        "y": 260,
        "wires": [
            [
                "c97d62672d3eb61e"
            ]
        ]
    },
    {
        "id": "437dc37a9faf8f09",
        "type": "inject",
        "z": "04823d5afca6d208",
        "name": "Set-2-Off",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "Pin",
                "v": "2",
                "vt": "num"
            },
            {
                "p": "State",
                "v": "false",
                "vt": "bool"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "-1",
        "payloadType": "str",
        "x": 500,
        "y": 300,
        "wires": [
            [
                "c97d62672d3eb61e"
            ]
        ]
    },
    {
        "id": "ad16f0140a10887d",
        "type": "mcp_pcf_chip",
        "busNum": "22",
        "addr": "0x23",
        "interval": "0",
        "startAllHIGH": true
    }
]

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [25 March 2022 11:05 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/7 "2022-03-25T11:05:51Z")

</div>

Hi @PizzaProgram I don't use these but after a quick read through I would offer these suggestions...

1. Don't use Sentence case names (stick with lowercase and camelCase)
2. Instead of msg.Pin and msg.State, why not consider using topic and payload e.g. ...
  - topic: 1 payload: true = turn pin 1 on
  - topic: all, payload: true = turn all pins on
  - topic: 6 payload: false = turn pin 6 off
  - topic: "1,3,5" payload: true = turn pins 1, 3 & 5 on
  - topic: "set" payload: `0b10000001` = turn pins 7 & 0 on, 6 ~ 1 off

Better still, use typedInput widgets to let the user decide where the pin and value come from. (Saves user having to use change nodes to shift values around in the msg)

Just some thoughts off the top of my head. If I'm way off or misunderstanding something, my apologies.

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [25 March 2022 11:22 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/8 "2022-03-25T11:22:53Z")

</div>

# Hi,

1. OK, changing to pin + state lowercase now.
2. 

- This is not how this node concept is working. Each pin has to be / can be set differently. Payload is used normally for normal control of 1 pin. (Boolean). Backward compatible.

- `state` + `pin` is a SPECIAL case I've added, an extra feature to make it work similar to your 'topic' ider. So it has to be different.

- I don't like to use topic. It is usually used for different things at a house control. The direct pin number of a relay is never == of the topic.

- 1,3,5 \>\> too complicated, would mess up the current code, would exclude error control.

- `0b110100` \>\> good idea, let me think about it, how to implement.  
How about `if (msg.payload = "b") msg.binary ... `  
But it's lot of work.

> [@Steve-Mcl](#):
>
> use typedInput widgets

I have no idea, what that is. Link please!

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [25 March 2022 11:38 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/9 "2022-03-25T11:38:18Z")

</div>

> [@PizzaProgram](#):
>
> > [@Steve-Mcl](#):
> >
> > use typedInput widgets
> 
> I have no idea, what that is. Link please!

Sure you do (but you possibly just dont know the name 😛 )

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/5/055f7bdb6a298cb70612e5120ebe7d689a472adc.png)  
[docs/api/ui/typedInput/](https://nodered.org/docs/api/ui/typedInput/)

It permits a user to specify where the interesting value comes from (meaning they **dont** have to use a change node to set `msg.pin` for example)

  

> [@PizzaProgram](#):
>
> This is not how this node concept is working. Each pin has to be / can be set differently. Payload is used normally for normal control of 1 pin. (Boolean). Backward compatible.

You could easily add a checkbox called "lagacy mode" (set by default) then when it is unticked, use whatever msg inputs you wish - that make more sense. I.e. dont let compatibility force you to write something awkward to use - just work around it 🙂

> [@PizzaProgram](#):
>
> `state` + `pin` is a SPECIAL case I've added, an extra feature to make it work similar to your 'topic' ider. So it has to be different.

> [@PizzaProgram](#):
>
> `0b110100` \>\> good idea, let me think about it, how to implement.  
> How about `if (msg.payload = "b") msg.binary ... `  
> But it's lot of work.

Again, if you have 2 modes (i.e. " legacy mode") this is not necessary & would permit you to use topic & payload

  

> [@PizzaProgram](#):
>
> And if you are controlling Relays, it's NEVER a good idea to switch multiple at the same time. Too high Voltage needed, 16x stronger sparkles, failing. Leaving 20ms between 1-1 relay switch is better!

What is to stop someone putting 16 OUT nodes in parallel?  
at least if you offer the ability to set 16 via one OUT node, you can internally control this.

  

* * *
  

Another suggestion (if you dont mind?)  
IMO, the output node would have an output port to permit chaining. When wires are branched, under the hood, node-red clones the msg. 16 parallel outputs would make 16 clones. Also, it would be a reasonable feature to NOT send the msg through if the operation failed. e.g. consider these 2 flows...  
`inject 👉 set pin 1 👉 set pin 2 👉 reset pin 3 👉 send a success email`  
` catch node watching for errors in "set pin 1", "set pin 2" & "reset pin 3" nodes 👉 send a FAIL email`

Again, this "output port" can be optional if need be.

---

<div class="post-metadata">

**Author:** ![markost](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@markost](https://discourse.nodered.org/u/markost)\
**Post date:** [25 March 2022 13:35 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/10 "2022-03-25T13:35:11Z")

</div>

For control relay, maybe something simple (only msg.payload) as:

_Single output contol:_

**A10**

where:

- A is corresponding to the 1st 8 outputs (1-8);or B for 2nd 8 outputs (9-16) of chip

- 1 is first port in A or B;or 2-8 for others outputs

- 0 is output state;or 1 for opposite state

_All outputs control:_

**AA0**

where:

- A is 1st eight ports;or B for 2nd eight ports
- A is all ports in A or B;no other option
- 0 is output state, or 1 for opposite state

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [26 March 2022 09:54 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/11 "2022-03-26T09:54:52Z")

</div>

> [@markost](#):
>
> 1st 8 outputs (1-8);or B for 2nd 8 outputs (9-16) of chip

All the help, readme, changelog, default setup is using and mentioning: 0-7 + 8-15.  
Using 1-16 would be VERY confusing.

You can make a script-node that converts/splits your desired A/B 1-16 coding to `msg.pin=0-15` easily.

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [26 March 2022 10:02 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/12 "2022-03-26T10:02:03Z")

</div>

> [@Steve-Mcl](#):
>
> the output node would have an output port to permit chaining

First I had the same idea!  
So I did it.  
Realised how much extra work would it be, so I've disabled it.  
A [Catch] node can handle this "error-safe" method.  
Not so easily, as your pin1 \> pin2 \> email thing, but still possible.

_Maybe next year I start over and do that, but currently I'm happy it's working after 14 month. Still need to plug in all the wires, order some more chips, etc. to make my house work again after 2 years of "dark ages"._

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [26 March 2022 13:02 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/13 "2022-03-26T13:02:25Z")

</div>

> [@Steve-Mcl](#):
>
> [docs/api/ui/typedInput/](https://nodered.org/docs/api/ui/typedInput/)
> 
> It permits a user to specify where the interesting value comes from (meaning they **dont** have to use a change node to set `msg.pin` for example)

That is a GREAT idea!

But I need help to do that.

1. Last time I've changed something at the HTML code it took me TWO WEEKS to find the error, the whole node-red did not start.

2. I've looked into the examples, but did not find any multi-complex case similar to mine.  
[TypedInput Widget : Node-RED](https://nodered.org/docs/api/ui/typedInput/#examples)

msg.payload can be:  
true/false Bool  
_or_  
"All0", "All1" as string selectable  
_or_  
-1 as number

if `payload= -1`  
`msg.pin`  
`msg.state`  
should appear, otherwise hidden.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [26 March 2022 13:05 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/14 "2022-03-26T13:05:01Z")

</div>

If I get a chance tomorrow I'll post something for you. In the mean time, look at nodes like buffer-parser, Cron+ and even the http-response node. They have working examples.

---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [26 March 2022 13:05 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/15 "2022-03-26T13:05:42Z")

</div>

# Help needed:

- How do I publish a bundled example to this project?
- I've saved the flow.json file I've made
- created a "./examples" subdir and copied inside there

Now what's next? How do I make a NR example from it, that would be auto-installed when someone is installing from palette manager ?

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [25 May 2022 13:06 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/16 "2022-05-25T13:06:13Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [8 June 2022 08:11 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/17 "2022-06-08T08:11:46Z")

</div>



---

<div class="post-metadata">

**Author:** ![PizzaProgram](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/pizzaprogram/32/19431_2.png) [@PizzaProgram](https://discourse.nodered.org/u/PizzaProgram)\
**Post date:** [8 June 2022 08:49 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/18 "2022-06-08T08:49:41Z")

</div>

There is a new version of this node, check the Readme . 😉  
Open an issue at Github, if you find any problem. (See top link #1 )

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [8 June 2022 09:01 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/19 "2022-06-08T09:01:08Z")

</div>

Haha, yes not terribly obvious.

Well, now go turn on 2FA to prevent account takeover, do the same on GitHub as well.

---

<div class="post-metadata">

**Author:** ![SonoraTechnical](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sonoratechnical/32/20033_2.png) [@SonoraTechnical](https://discourse.nodered.org/u/SonoraTechnical)\
**Post date:** [8 June 2022 23:48 UTC](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087/20 "2022-06-08T23:48:31Z")

</div>

> [@Steve-Mcl](#):
>
> Don't use Sentence case names (stick with lowercase and camelCase)

hmm... I've always endeavored to apply Redicks VB Naming Conventions and Coding Conventions and applied them to any other language I learn where appropriate. (I even apply it to database objects, tblSales, viewMonthlySales, procPublishSales, rptRegionalSales, etc.. However, I don't do the same for column names in tables/views, but that's more or less to try to maintain compatability with allot of stuff that's out in the wild  
.)  
An example of a variable for a last name might look like this strLastName . He recommends prefacing the variable name with it's type and then continuing on with TitleCase for the rest of the name.

To each his own.

[Next page](https://discourse.nodered.org/t/new-mcp23017-pcf8574-all-in-one-node/60087.md?page=2)
