Do you mean that with them configured as inputs the pin is pulling low?
What external components have got connected to the output?

Someone with more micro-electrical knowledge draw me this pic. (Paid him for advice.)

I think the 4.7k Ohm input resistors are not necessary between the opto-couplers and the IO chip, if I activate the built-in pull-up resistors.

Is this a Pi? You mustn't pull a pi gpio pin up to 5V, only to 3.3, and as you said you don't need it on outputs anyway, in fact in this application you should not have one at all. If you have pulled up to 5v through a 2.2k you may have blown the pin up, if not the pi itself.

The code is starting to feel safe now. No more NR crash, pin states are showing well:

Also if wrong Bus number is set. (See nice red "! Error" text...)

But there is still something wrong with bit masking, when I try to turn on/off:

let ip1 = 0x00;
if (bitNum < 8) { // first read current state of bank
	ip1 = _aBus.readByteSync(_addr, 0x12);
} else {
	ip1 = _aBus.readByteSync(_addr, 0x13);
if (newState) {
	ip1 = ip1 | 1 << bitNum;
} else {
	ip1 = ip1 & ~(1 << bitNum);
if (bitNum < 8) {
	_aBus.writeByteSync(_addr, 0x14, ip1 & 0xFF);	//Set output A
} else {
	_aBus.writeByteSync(_addr, 0x15, (ip1 >> 8) & 0xFF);	//Set output B

@Colin No. It's not a Pi.
MCP23017 (i2c bus, 5V). Driving it through an AtTiny85 USB adapter with i2c-tiny-usb firmware.
Tried Arduino Nano before that. (USB bus, 5V).

Found the error:

	if (bitNum < 8) {
		ip1 = _aBus.readByteSync(_addr, 0x12);
	} else {
		ip1 = _aBus.readByteSync(_addr, 0x13);
		ip1 = (ip1 << 8);        // <<< that was missing !

I tend to use a set of functions that help me avoid typos...

//Get bit
function getBit(number, bitPosition) {
  return (number & (1 << bitPosition)) === 0 ? 0 : 1;

//Set Bit
function setBit(number, bitPosition) {
  return number | (1 << bitPosition);

//Clear Bit
function clearBit(number, bitPosition) {
  const mask = ~(1 << bitPosition);
  return number & mask;

//Update Bit
function updateBit(number, bitPosition, bitValue) {
  const bitValueNormalized = bitValue ? 1 : 0;
  const clearMask = ~(1 << bitPosition);
  return (number & clearMask) | (bitValueNormalized << bitPosition);


let readVal = 0, writeVal = 0;
let writeByte = 0x14, readByte = 0x12, bit = bitNum;
if (bitNum >= 8) {
    writeByte = 0x15;
    readByte = 0x13
    bit = bitNum - 8;

readVal = _aBus.readByteSync(_addr, readByte); //read the value
writeVal = updateBit(readVal, bit, newState); //set/reset the bit
_aBus.writeByteSync(_addr, writeByte, writeVal & 0xFF); //write back new value


You said earlier in the thread:

The reference to node-red-contrib-gpio node having the same problem led me astray apparently.

Help to make Help ...

I still could not release the finished code, because wanted to add help to it.
But nothing is shown.

This is the code I've added to the .html file:

<script type="text/x-red" data-help-name="mcp23017ouput">
	<p>MCP23017 has 16 pins (0-15). Can be individually selected as in or out.</p>
	<p> The message to the output requires a payload.  If the <code>msg.payload</code> =true or =1 then it turns on</p>
	<p> Topic (and any other parts) are ignored</p>
	<p> Before each output command, the node reads the current value and sets only the changed bit.</p>
	<p> </p>
	<p> The "invert" checkbox forcing to send the opposite command to the chip, but still showing 1 = true = On. </p>
	<p> </p>
	<p> If any error occure, red sign is shown with "!Error" text under the Node.</p>
	<p> Possibilities are: wrong Bus or Address.</p>
	<p> </p>

	<h3>History of changes</h3>
	<h4> 2020-12-31 (by László Szakmári</h4>
			<strong><span style="color:#c0392b">!!! IMPORTANT CHANGE:</span></strong><br />
			&nbsp;-- [ x ] Inverse is now affecting Output too !<br />
			&nbsp;(Some relay boards are functioning &quot;the opposite way&quot;, turning ON if pin is Low.)
			Fixed NR crash: Added Error handling (try - catch) for each i2c bus operation.<br />
			&nbsp; Each operation has own value to report proper error text. (Bus opening failed ... etc)<br />
			&nbsp; (But execution time increased from 8ms to 12ms on Raspberri 4)
			Changed Bus open/close behaviour. Separate open before/after each read/write operation block.<br />
			&nbsp; (This way no more non-stop opened bus &gt; no more NodeRed crash if unexpected disconnect.)
		<li>Fixed 16pin array initialization (16x null)</li>
		<li>Added multiple/same pin initialization error handling. (Highlander: &quot;There Can Be Only One&quot; :-D )</li>
		<li>Added lots of comments and constants to mcp23017chip.js file (like IOCON, IODIR_A, etc...)</li>
		<li>Changed icon to a chip-like one. (font-awesome/fa-ticket)</li>
		<li>Faster initialisation: if set to output &gt;&gt; skips pullup &amp; invert writes.</li>
		<li>Prevents the input-timer to run if the previous function is still running.</li>
		<li>4 states of a node: On=green&nbsp;&nbsp; Off=grey&nbsp;&nbsp; Uninitialised=yellow&nbsp;&nbsp; Error=red</li>
	<p> </p>
	<h4> 2020-11-xx fix for run under NR </h4>


What am I doing wrong?

Presumably the name matches the node exactly?

Generally we don’t add a change list to the help as it doesn’t help use of the node. That is better off in the readme.

Assuming you are modifying the this shouldn't data-help-name="mcp23017ouput" be data-help-name="mcp23017ouputNode"?

Also, if you change type="text/x-red" to type="text/html" you will probably get syntax highlighting in your editor (you certainly do in vscode)

1 Like

You were right!
data-help-name="mcp23017ouput"> >> ouTput
(The only good thing of fixing other peoples mistakes is: you can blame them, not yourself! :laughing: )

Do you know the way, how to include a separate file inside the package and point with a link from the help? I couldn't figure out.

Great tip! Thanks :slight_smile:

There is no way to do this without a lot of unnecessary work.

If you want to link to something, link to its page on where the full readme will be displayed.

1 Like

After investing 100++ working hours to fix most of the problems, I've uploaded the finished code to github 7 weeks ago.

Created a Pull request on Jan.16, but nothing happened.

I'm still not even added to the project, as a contributor.

Well, so much to promises...

1 Like

Give it a few days, add a comment on the PR asking if/when he'll get a moment to review/accept your PR & if you get no joy, consider releasing your fork as a new npm package.

Hold off as long as you can as having multiple versions in the flow library can be equally confusing and problematic.

1 Like

< OFF >
OK, thanks for the encouraging words! I'll wait a few weeks longer than.

Exactly! And also the old ones won't get auto-updated. That's why I didn't released by myself.
I hoped I'll have +1 free month more during winter, so I can create a WHOLE new flow-friendly version of MCP23017 + scanner + PCF8574 All-in-one package.
But RL kicked in, had too many work lately.

Dear @Paul-Reed ,
can you maybe add me as a contributor too to that branch?
You are a member already.

Afraid not, I'm a contributor to the branch and not a collaborator, so I can't carry out any of the admin functions, such as accepting PR's or adding additional collaborators.

By their own admission, they are not so familiar with GitHub. So maybe they need a little coaxing to help get the PR merged.

Rather than complain about it here, have you contacted the owner privately to see where things stand?

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