Zyncoder library and MCP23017


IMHO there is a bug in zyncoder.c setting up MCP23017 pullups?

// enable pullups on the unused pins (high two bits on each bank)
reg = 0x60;
wiringPiI2CWriteReg8(mcp23017_node->fd, MCP23x17_GPPUA, reg);
wiringPiI2CWriteReg8(mcp23017_node->fd, MCP23x17_GPPUB, reg);

0x60 is 0110 0000b, but looking on schematics two MSB-s are unused - port bits 6 and 7, so IMHO correct value must be 0xC0 (1100 0000b)? But this isn’t real issue, please read further.

Second and real problem - inputs connected to encoders don’t use pullups at all, when those corresponding register bits bits are zeros. So MCP23017 generates spurious interrupts all the time (tested with zyncoder_test program). I think that real and correct value will be reg = 0xFF , so all pullups must be enabled (according to Microchip datasheet, paragraph 3.5.7 - pullup configuration register).


Whoaooo! I will check tomorrow. If it’s really true, we will free a few “high priority” CPU cycles and improve the overall performance. Nice!:grinning:

Thanks a lot for diving so deep! :muscle:


Hi @Werewolf!

I’ve been testing and can’t reproduce the “spurious” interrupts. Curiously my zynthian works OK with any value: 0x60, 0xC0 or 0xFF :wink:

Anyway, your rationale have sense, so I open the thread to the community so more people can test it …

Thanks and Regards!



the data sheet is pretty clear, I think Werewold is correct. I can’t actually test it though, but on paper it should be 0xFF.


I have different encoders - Arduino compatible KY-040 with already installed 10k pullups, connected to +5V contact (on picture seen one 5 pin header). When i left +5V unconnected (common Vcc for 10k pullups), then at least with my setup even waving an hand over encoders generates interrupts. I got now my custom zynthian to work with two modifications - removing all pullup resistors on encoder boards AND setting GPPUx registers to 0xFF. Playing with different GPPUx values (0x60, 0x00, 0xC0) more or less makes interrupt routine to be called at random times (switching living room lamps on and off for example). At least this means for me, that MCP23017 even those internal weak (100 kohm) pullups left unconnected - on old times with TTL logic 5k…10k pullups are used everywhere - and various electrical noise makes expander input register to change at random times, which again generates interrupt as port state changed etc. Zynthian official metallic case maybe screens some noise, capacitors filter some glitches too, plain wires in my makeshift plastic case just act as small antennas. Bad luck, but can be cured - i have now working setup here with KY-040 encoders and without capacitors and resistors. IMHO really electrically correct method is to use proper external pullups, at least 20k per pin and ignore GPPUx registers, as those weak pullups are barely sufficient anyway. At least enabling internal pullups helps some, but in noisy environment this may be not enough.

Googling gives some glue that this question is older - this and this. General consensus is - if it works, then fine, if not, make correct level ‘1’ to expander pins and try again.



Really interesting … thanks a lot for the info. I will repeat my tests with the aluminum case open and some source of noise :wink:

Anyway, I’m testing the change to 0xFF and i will merge it as soon as i’m sure there is no secondary effects.

The best!


OK! After a week testing the change, i’ve not noticed any problem or secondary effect, so i’ve pushed the change to master.



@Werewolf I also have the KY-040 encoders, wouldn’t it just be best to run 5v to the module boards and leave all the pullups on the module and disable pullups in the MCP23017?


Yes, i considered this is an option too. Next time (buliding next Zynthian :wink: ) i leave resistors in place and connect +5V to encoders.

MCP23017 pullups better remain on (GPPUx = 0xFF), as those weak pullups won’t affect nothing negatively. Without external pullups at least helps a bit.