[Solved]Problem getting outputs for I2C I/O Port Expander using PCA9538

I’m having problem getting the outputs.

My A1 is connected to the ground and A0 is connected to 3.3V power. I know the two I2C lines are 5V. Could that be the cause for not getting the output?

I’m new to this. Can someone please take a look at the code for me and tell me if anything is wrong?

Thank you.

Here is the data sheet for the PCA9538: http://www.nxp.com/documents/data_sheet/PCA9538.pdf

#include <Wire.h>

#define U1_ADDR 0x71  // part address is 1110001
#define U2_ADDR 0x70  // part address is 1110000

void setup()
{
  Serial.begin(9600);
  Wire.begin();  // join i2c bus
  Wire.beginTransmission(U1_ADDR);
  Wire.write(0x03);  // Command byte
  Wire.write(0x00);  // Output pin 00000000
  Wire.endTransmission();
}


void binaryCount()
{
  for (byte a=0; a<256; a++)
  {
    Wire.beginTransmission(U1_ADDR);
    Wire.write(0x01); // Command Byte Output Port
    Wire.write(a); // Data to port
    Wire.endTransmission();
  }
}

void loop()
{
  binaryCount();
  delay(500);
}

From the datasheet:

Operating power supply voltage range of 2.3 V to 5.5 V (3.0 V to 5.5 V for PCA9538PW/Q900)

You may operate the PCA9538 with 5V. Do you use 3V3? If yes, why? Please post your schematics.

You don't check for the return value of Wire.endTransmission() so you don't know if the data was sent/received to/by the chip.

How do you check for the outputs to go high/low? Do you use a scope? The binaryCount() routine will end in about 0.01s. Don't expect that to see visually (LEDs).

Thank you for your replay. I have the schematics attached.

pylon:
You don’t check for the return value of Wire.endTransmission() so you don’t know if the data was sent/received to/by the chip.

I also wrote a code like this which checks the sent/received value. It’s similar to the code you wrote for another post.

void loop()
{
  IOWrite(0,0);  // IO0
  delay(100);  
  IOWrite(1,0);  // IO1
  delay(100);  
  IOWrite(2,0);  // IO2
  delay(100);  
  IOWrite(3,0);  // IO3
  delay(100);  
  IOWrite(4,0);  // IO4
  delay(100);  
  IOWrite(5,0);  // IO5
  delay(100);  
  IOWrite(6,0);  // IO6
  delay(100);  
  IOWrite(7,0);  // IO7
  delay(100);  
}

void IOWrite(uint8_t pin, uint8_t value)
{
  Wire.requestFrom(U1_ADDR, 1);
  uint8_t old_value = Wire.read();
  Serial.println(old_value);
  bitWrite(old_value, pin , value);
  Wire.beginTransmission(U1_ADDR);
  Wire.write(0x01);
  Serial.println(old_value);
  Wire.write(old_value);
  Wire.endTransmission();
}

The old_value originally received was 255.

pylon:
How do you check for the outputs to go high/low? Do you use a scope? The binaryCount() routine will end in about 0.01s. Don’t expect that to see visually (LEDs).

Yes I am checking the output signals using a scope.

PXMCXM_TESTCARD.pdf (66.8 KB)

xxOOxx:
I also wrote a code like this which checks the sent/received value. It’s similar to the code you wrote for another post.

void loop()

{
  IOWrite(0,0);  // IO0
  delay(100); 
  IOWrite(1,0);  // IO1
  delay(100); 
  IOWrite(2,0);  // IO2
  delay(100); 
  IOWrite(3,0);  // IO3
  delay(100); 
  IOWrite(4,0);  // IO4
  delay(100); 
  IOWrite(5,0);  // IO5
  delay(100); 
  IOWrite(6,0);  // IO6
  delay(100); 
  IOWrite(7,0);  // IO7
  delay(100); 
}

void IOWrite(uint8_t pin, uint8_t value)
{
  Wire.requestFrom(U1_ADDR, 1);
  uint8_t old_value = Wire.read();
  Serial.println(old_value);
  bitWrite(old_value, pin , value);
  Wire.beginTransmission(U1_ADDR);
  Wire.write(0x01);
  Serial.println(old_value);
  Wire.write(old_value);
  Wire.endTransmission();
}




The old_value originally received was 255.

I meant something completely different:

uint8_t IOWrite(uint8_t pin, uint8_t value)
{
  uint8_t ret;
  Wire.requestFrom(U1_ADDR, 1);
  uint8_t old_value = Wire.read();
  Serial.println(old_value);
  bitWrite(old_value, pin , value);
  Wire.beginTransmission(U1_ADDR);
  Wire.write(0x01);
  Serial.println(old_value);
  Wire.write(old_value);
  if (ret = Wire.endTransmission()) return ret;
  return 0;
}

This way the return value tells you if the transmission went wrong (NAK received).

And your code is wrong that’s why you get 255: the port is set as an output and you’re reading the input register. Correct code is:

uint8_t IOWrite(uint8_t pin, uint8_t value)
{
  uint8_t ret;
  Wire.beginTransmission(U1_ADDR);
  Wire.write(0x01);
  if (ret = Wire.endTransmission()) return ret;
  if (Wire.requestFrom(U1_ADDR, 1) != 1) return 100;
  uint8_t old_value = Wire.read();
  Serial.println(old_value);
  bitWrite(old_value, pin , value);
  Wire.beginTransmission(U1_ADDR);
  Wire.write(0x01);
  Serial.println(old_value);
  Wire.write(old_value);
  if (ret = Wire.endTransmission()) return ret;
}

You still didn’t specify why you’re driving the PCA with 3V3 instead of 5V.

pylon: I meant something completely different:

This way the return value tells you if the transmission went wrong (NAK received).

Oh I see. I am receiving 2 for Wire.endTransmission(). I looked it up and it says it means that I received NACK on transmit of address. So I did a I2C address scan with this code (http://playground.arduino.cc/Main/I2cScanner) provided here but it says no device is found... Could something be wrong with the PCA? I am receiving signals from the SCL and the SDA pins on the PCA though. What should I do to fix this?

pylon: And your code is wrong that's why you get 255: the port is set as an output and you're reading the input register. Correct code is:

Thank you for the correction.

pylon: You still didn't specify why you're driving the PCA with 3V3 instead of 5V.

I'm not sure why they do it. But they designed the board that way so I guess I have to work with it. I can't really make any changes to the voltage.

I'm not sure why they do it. But they designed the board that way so I guess I have to work with it. I can't really make any changes to the voltage.

How are "they"? What board are we talking about?

Could something be wrong with the PCA? I am receiving signals from the SCL and the SDA pins on the PCA though. What should I do to fix this?

Sounds a bit like you fried the chip. If the chip is driven by 3V3 the signal lines should not hold more than that value. The datasheet doesn't specify this explicitly so may be it's 5V tolerant, but I wouldn't bet on it.

How did you wire it? What type of Arduino are you using? What do you use the outputs for?

pylon:
Sounds a bit like you fried the chip. If the chip is driven by 3V3 the signal lines should not hold more than that value. The datasheet doesn’t specify this explicitly so may be it’s 5V tolerant, but I wouldn’t bet on it.

:fearful: :fearful: :fearful: Could getting a level converter help?

pylon:
How are “they”? What board are we talking about?

How did you wire it? What type of Arduino are you using? What do you use the outputs for?

This is a PXM/CXM Test Card that is asked to be build by our company. The I2C is used to control the IO port and we can test and communicate with the green card (build by us, not sure what it does). The green card doesn’t have any intelligence yet. I just need to write a program that can control the output of the IO port for the PCA at will.
There were a lot of problems with it. The original idea is to attach the Arduino Uno directly to the card and they can communicate using I2C. But the tracing is wrong and the two voltage pins are grounded. So I had to separate them and it looks like the pxmcxm image. SDA to SDA, SCL to SCL and GND to GND.
I also tried to use 4.5K (3 1.5K in series) pull-up resistors to 3.3V for the SDA and SCL lines hoping it could work. Didn’t make any difference though. Maybe I did destroyed the chip.
Oh the orange wire coming out of the GND pin of the Arduino is the scope.

Edit: Solved with a level converter and making the reset “high”.

pull-up.png

pxmcxm.jpg