PCF8575 expansion board input not pulling up

Hi.
So, for a project I am doing I want to use the PCF8575 IO expander module on an ESP32.
I followed this howto as I have almost identical parts and modules and it works

I want to use the input and output function and the output with a blinking LED works okay.

HOWEVER I am not happy about connecting the input to +3.3 or even +5V with a pulldown resistor to GND as in the howto. This seems to be the only way that works though, I tried using a pullup instead or use "INPUT_PULLUP" in the code as a Pinmode setting and also tried to write Digitalwrite to HIGH before converting the pin to INPUT mode. In all those cases I cannot use the switch in any way and always get a LOW when reading the pin. So the only way it ready something from a switch button is to connect the button to Vcc. This does consume almost 50mA though if I measure it and this seems not right for just an input signal. I thing the module will burn out eventually if I use 10 buttons like this. I tried using a 1k resistor in the line to limit current but then of course it reads 0 again.

I feel like the pins are pulled strongly to GND and I cannot get them to be floating so I can use my own pullup resistor and pulldown button.

What can I do to make this module read a button correctly without funneling a lot of current through it?

Thank you
Aurora

Please post code and schematics.

Here's how do create questions: How to get the best out of this forum - Using Arduino / IDE 1.x - Arduino Forum

1 Like

Here is the schematic from the howto:

The code is

#include "Arduino.h"
#include "PCF8575.h"

// Set i2c address
PCF8575 pcf8575(0x20);

void setup()
{
  Serial.begin(9600);

  pcf8575.pinMode(P0, INPUT);
  pcf8575.pinMode(P1, OUTPUT);

  pcf8575.begin();
}

void loop()
{
  uint8_t val = pcf8575.digitalRead(P0);
  if (val == HIGH)
  {
    pcf8575.digitalWrite(P1, HIGH);
  }
  else
  {
    pcf8575.digitalWrite(P1, LOW);
  }

  delay(50);
}

This does actually work, but the current flowing from Vcc to the Pin0 on the board is 50mA, which in my opinion is too much. I would expect the Pin to be pulled up and then I can put in a button to pull it to GND to set the input to low with a minimal current - or the pin is floating in which case I would put a 10k pullup resistor in and then the button can pull it to GND. As it is, there is a pulldown resistor in the schematics, which is not needed as the pin is firmly pulled down by the board.
How can I change this so the pin is floating or at least not drawing so much current?

Maybe there is a better library for the chip? I looked up some others, but they seem to either be rather specialized or not so well documented, but maybe someone can tell me which works better and how to make these simple read and write calls with it.

Thank you

The button shown looks strange having connections both at the corners and the middle of the side. To be safe, move the resistor switch side to the yellow/orange connection going to the blue circuit.

Yes it is apparently a 3d depiction. The resistor is connected to the input pin as the two pins on those buttons are connected.

So basically it's as you described.
And it does work, with our without the resistor. In default the pin is at gnd and zero or low. Pressing the button connects it to Vcc and the pin readout goes to 1 or high. But the module gets hot and a lot of current goes into that pin, so it's likely not the intended use. I found similar schematics otherwise as well though, others connect the button to gnd instead, which makes sense if the pin could be set to not be at low by default but at high or floating, the resistor would then have to go from the blue chip pin to Vcc of course. But that does not work, I only get a reading of low from the pin that way, no matter what.

I somehow suspect that the pin is not set to input despite the line in the code

Not sure where you got 100 ohms from for the pulldown, I found this text for the input description, right below the image you posted:

Add a 10K pull-down resistor connected to the ground.

That's a more reasonable value. These devices do work this way, though I use them with pullups instead.
The button depiction isn't necessarily wrong, just possibly misleading. The buttons have four legs, connected in side-by-side pairs. We usually ensure unambiguous communication by wiring either VCC or GND to one corner, and both the resistor and lead-to-arduino get wired to the diagonally opposite pin. That way, regardless of how you rotate the device, you can't get the connection wrong.

Yes, it's 10k. I did not mention 100 ohm.
The problem is not the resistor. I can leave it out completely and still only connecting the pin to Vcc will get a high input signal and still a 50mA current from Vcc into that pin, heating the circuit.

Again, the setup works as described, but it's not a good solution for any buttons that are pressed longer or even switches that permanently set the input to high.

There is some error in that whole setup that does not show when just assembling or as a demo for a short time

Here you mention the 100 Ohm, albeit indirectly: 5V, 50 mA gives 100 Ohm resistance.

It also suggests to me that you connect something incorrectly. Make sure you know between which pins the switch operates - there are four pins, in pairs indeed. Use your multimeter to confirm which pins are always connected, and how they form the pairs.

To check this I already removed the switch and just use a jumper wire to connect or disconnect. Or the Multimeter cable. The 50mA and thus 100 Ohm resistance are whats happening inside the chip. The pin seems to be at LOW (despite being initialized as "Mode INPUT") [I also tried this on 5 other pins with same result by the way], so it seems to be connected by just 100 Ohm to GND. If I put a jumper cable running from Vcc to the pin now, it will read as HIGH, but at the cost of a lot of current flow. The resistor in the schematics does not play any role at all, maybe it will increase the current by a milliAmp or so, I left it out in the test now.
So the test now is more simple - I just dont have the resistor or switch but just use a jumper cable or the multimeter cable to connect Vcc or GND to the "input" pin. It does switch the digitalread output HIGH or LOW but uses a lot of current. I found yet no other way to get a "high" result from the digitalread command for the pins designated as "input" by the code. Hence I think the pins are not actually set to input but rather to "output, LOW" - so by connecting them to Vcc (as in the schematic), I force them to high despite them being set to low. This is not good. But then how do I properly set them?

From that logic, I tried to set them with digitalwrite to high before setting them to the input mode

pcf8575.digitalWrite(i, HIGH);
pcf8575.pinMode(i, INPUT);

but then the digitalread only comes out at LOW, no matter if I connect the pin to GND or Vcc...

So I did more search in this forum but it seems the problem is not uncommon but still found no good solution, just other people insisting that they cannot get the input pin to read high unless they short circuit it to +3.3V, potentially damaging the chip:

The weird thing is - according to all logic, setting the pin as INPUT should set it floating or pulled up to HIGH and then one should be able to pull it low with a button. But it never goes to HIGH. Setting its Mode to INPUT does not result in a digitalRead to give HIGH, neither does doing a digitalWrite HIGH result in the digitalRead to give a HIGH. Literally the only way that seems to work getting it to HIGH seems to short circuit it. But maybe I finally damaged the whole chip now, so I will try soldering a new one and try running again

Ok, so more information on the weirdness of the behaviour. I actually managed to get an input pin set on high and read out HIGH in rest and LOW when connected to GND - the expected behaviour in my opinion. HOWEVER this required to first declare it as an output pin, write HIGH to it and then declare it as an input pin. However the instant any other pin is written to (code line36), the setup falls apart and the pin reverts again to being permanently LOW (output line 22:08:10.042).

Here is the Code :

#include <Arduino.h>
#include <Wire.h> // Für I2P für Port Expander
#include "PCF8575.h" // Für Port Expander

// Port Expander
PCF8575 pcf8575(0x20);

int timestamp;
bool p2;
bool p1;

void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println("start"); 
  pcf8575.pinMode(P1, OUTPUT);
  pcf8575.pinMode(P2, OUTPUT);
  pcf8575.begin();
  printpins();
  delay (1000);
  pcf8575.digitalWrite(P1, HIGH);
  printpins();
  delay (1000);
  pcf8575.pinMode(P1, INPUT);
  printpins();
  delay (1000);
  printpins();
  delay (1000);  
  Serial.println("init"); 
}

void loop() {
  //pcf8575.digitalWrite(P2, HIGH);
  printpins();
  delay (1000);
  pcf8575.digitalWrite(P2, LOW);
  printpins();
  delay(1000);
  pcf8575.digitalWrite(P2, HIGH);
  printpins();
  delay (1000);
}

void printpins() {
  p1=pcf8575.digitalRead(P1);
  Serial.print(p1); 
  p2=pcf8575.digitalRead(P2);
  Serial.println(p2);
}

and the output:

22:08:05.037 -> start
22:08:05.037 -> 00
22:08:06.033 -> 10
22:08:07.026 -> 10
22:08:08.021 -> 10
22:08:09.013 -> init
22:08:09.013 -> 10
22:08:10.042 -> 00
22:08:11.037 -> 01
22:08:12.032 -> 01
22:08:13.035 -> 00
22:08:14.029 -> 01
22:08:15.021 -> 01

and I used this schematic here, but used P1 and P2 instead of P0 and P1 and did not connect the button for now. I then commented out all the blinking output and put the switch in, but connecting to GND and I could indeed get a LOW on press and HIGH on release - but the instant I do a digitalWrite on another pin, it is stopping.

My feeling is that something is off with the library - the chip can obviously behave properly, but the library seems to mess it up. Do you think this is a reasonable explanation or did I do something else wrong?

Ok, I think it was as I said, the library used was junk.
I changed the library and now I can use this code to make a LED blink at pin 2 (connected with a 220O resistor to Vcc 3.3V) and read the correct input from a switch which is connected to GND. Current running when switch pressed is 0.2mA! The pin seems to be naturally pulled up to HIGH and on button pressed it goes to LOW just as expected behaviour.
Here is the code:

#include <Arduino.h>
#include <Wire.h> // Für I2P für Port Expander
#include "PCF8575.h" // Für Port Expander - this is the new version

// Port Expander
PCF8575 pcf8575(0x20);

int timestamp;
bool p2;
bool p1;

void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println("start"); 
  pcf8575.begin();
  printpins();
  delay (1000);
  pcf8575.write(1, 1);
  printpins();
  delay (1000);
  pcf8575.write(2, 1);
  printpins();
  delay (1000);
  printpins();
  delay (1000);  
  Serial.println("init"); 
}

void loop() {
  printpins();
  pcf8575.write(2, 0);
  printpins();
  delay(1000);
  pcf8575.write(2, 1);
  printpins();
  delay (1000);
}

void printpins() {
  uint16_t val = pcf8575.read16();
  Serial.println(val); 
  Serial.println(pcf8575.read(1));

}

And this was now with this library:

instead of the previous one by Renzo Mischianti (sorry, but your library is just not working as intended for pin inputs!)

SOLVED

1 Like

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