Go Down

Topic: PCF8575TS I2C to 16 digital i/o questions (Read 2684 times) previous topic - next topic

stealthtransam

I got a Phillips PCF8575 and I'm having problem reading the inputs. I have no problems writing to the pins but reading from them is another story.  I've looked at some example code for the Maxim 21952b and it doesn't seam to help me read inputs with this chip.  Does anyone know how to tell it to change an output to an input and read it back into the Arduino with this chip?  It looks like a lot of I2C stuff uses the same 8th bit to change from an Read to a Write.

My device address is 32 (hexadecimal equivalent 0x20)(binary equivalent 0100000) and that works to write to it but when i try to write to (0x41 what is 01000001) it does nothing?  how do i change that last address bit (8th Bit) from a 0 to a 1 without changing the address using the Arduino Wire Platform?

Any help would be greatly appreciated and thanks in advance.  Below is the code I'm using to address pin 4 as  an output toggling it between low and high at 500ms flash rate.
Code: [Select]
#include "Wire.h"

int x= 500;
byte address = 32;  // 0x20 hex, 32 dec, 100000 binary

void setup()
{
  Wire.begin();
}

void loop()
{
  Wire.beginTransmission(address);
  Wire.send(0xFE);
  Wire.send(0x00);
  Wire.endTransmission();

  delay(x);

  Wire.beginTransmission(address);
  Wire.send(0xFF);
  Wire.send(0x00);
  Wire.endTransmission();

  delay(x);
}

Grumpy_Mike

While I haven't got a PCF8575, this is code I wrote to read the PCA9685, it might help:-

Code: [Select]
//********************* Functions ***********************************   


void PCA_write(byte address, byte control, byte data) {
  //  Send device address
  Wire.beginTransmission(address);
  Wire.send(control);    //  set control register
  Wire.send(data );    //  send byte
  Wire.endTransmission();
}

void PCA_read(uint8_t address, uint8_t numberOfBytes) {
  int data = 0, i=0;
  Serial.print("Read ");
  Serial.print(numberOfBytes,DEC);
  Serial.println("bytes ");
    //  Connect to device and request  bytes
  Wire.requestFrom(address, numberOfBytes);
  while(Wire.available() && i<numberOfBytes){
  {
    data = Wire.receive(); // receive a byte as character
    i++;
    Serial.println(data,HEX); // print it out
  }
   }
   Serial.println("Read request finished");
}

stealthtransam

Thanks mike.  I looked at the data sheet for the PCA9685 and it is registry based the PCF8575TS is not.  So I can't address each register separately.  I have to address each bank in a group. and this is done by setting a bit in the device address itself.  That is where my breakdown is occurring.

 

Grumpy_Mike

Quote
and this is done by setting a bit in the device address itself.


Do you mean where it says:-
Quote
By setting the last bit of the byte containing the slave address to logic 1 the read mode is entered.


If it is then you don't have to bother with this, it is done automatically on the arduino when you specify read or write, that is why you use a shifted address. It looks to me like you just request two bytes from the bus.

stealthtransam

The code I listed above had nothing to do with my read question.  It is really just to prove that I can send data to the I2C GPIO device and change the state of an output.  Really more just a proof of concept that i'm communicating with the chip.  Receiving data on the other hand is where i'm having the problem all together.  I'm really looking for some example code that can get me over the hurdle of receiving data from bank 0 or bank 1 instead of just changing the output state of it.


Grumpy_Mike

Can you not just use the  PCA_read() function I posted, there is nothing chip specific with that? Just call it with your address and the bytes count set to two.

stealthtransam

If I could use your code I would need to know a control register for each bank of this chip and I do not see any documentation in the datasheet for said registers.  Thanks for your input though it is appreciated.

stealthtransam

I was able to get it to work after some deeper understanding of the Wire.h library.  The problem was that I wanted to send it Raw HEX data and the wire library will not allow you to do that.  it wants to handle the acknowledgment bits, the start bit, and the read/write bit automatically.  This is not very well documented unless you go into the wire library and really tear it apart.  Below is a very simple example code I wrote to read data from all the gpio's.

Code: [Select]
#include "Wire.h"

int delaytime = 1000;
byte Address = 32;
byte one;
byte two;

void setup()
{
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(Address);
Wire.send(0xFF);
Wire.send(0xFF);
Wire.endTransmission();

}

void loop()
{
  Serial.print("The address in HEX is: ");
  Serial.println(Address,HEX);
  Serial.println();
  Serial.println();
 
 
  Wire.beginTransmission(Address);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(0x20, 2);
 
  while (Wire.available())
  {
    one = Wire.receive();
    two = Wire.receive();
  }
 
  Serial.print("The first byte of data in HEX is: ");
  Serial.println(one, HEX);
  Serial.println();
  Serial.println();
  Serial.print("The Second byte of data in HEX is: ");
  Serial.println(two, HEX);
  Serial.println();
  Serial.println();
  delay(delaytime);
}

Grumpy_Mike

Quote
If I could use your code I would need to know a control register for each bank of this chip and I do not see any documentation in the datasheet for said registers.

Data sheet page 11 shows you there are only two bytes with no register to send, so simply don't send one. The void PCA_read() is all you need.

Quote
The problem was that I wanted to send it Raw HEX data and the wire library will not allow you to do that.

Yes it will.

This code is a bit wrong:-
Code: [Select]
while (Wire.available())
  {
    one = Wire.receive();
    two = Wire.receive();
  }

because it can delve into reading two bytes when only one has arrived.

Anyway glad you got it working.

Go Up