0
\$\begingroup\$

I am designing a PCB that connects to a 40pin header (similar to RPi HAT header) on an AAEON embedded computer. The computer has a SIO chip and an API that allows I2C communication from the device.

The I2C bus has 2 devices connected to it: PCA9685 PWM LED dimmer, and a TCA9548A I2C MUX (for connecting many IO expansion boards in the future).

Initially I was using this board to test the TCA9548A, which worked on both the AAEON computer and an Arduino Uno I was using for testing.

After that I started designing the PCB in Altium. It's a 4-layer board (SIG-GND-3v3-SIG), and it has both the PCA9685 and TCA9548A on it.

Now here is the issue:

I am able to communicate with the PCA9685 perfectly fine. I can dim LED's individually and all my register writes are successful. But the TCA9548A is constantly misbehaving: even if it probes successfully, I am only able to send a value '2' to its control register and read it back, every other value written results in a '0' received back when I subsequently read the data after a write.

I connected the board to an Arduino Uno (and used a TCA9548 library) and the results are the same. Since the PWM chip works, I believe nothing is critically incorrect about my I2C bus. However, it seems to be the case that something is routed incorrectly to the TCA9548A, though I'm not sure what. As you can see on the schematic, the connections are pretty trivial

How could one route the TCA9548 multiplexer incorrectly?

P.S. The AAEON board has built in pull-ups on the I2C bus, and for the Uno I add 10k pullups on SCL,SDA.

P.P.S. All the MUX sub channels are pulled up to Vcc with 10k pullups and there are no devices connected to those sub-channels when testing

Day 2 Update: I made some scope shots with an arduino connected to the adafruit board and my PCB:

Arduino communicating with the Adafruit board: With this board, I am able to read the data back after I write it (as expected) Wrote 0x80 and read it back correctly Write zoomed Read zoomed

The issue appears when I use my PCB instead of the adafruit breakout: Here I am writing 0x0C to the board and reading 0x00 back:

Wrote 0x0C read 0x00 Write zoomed in Read zoomed in

Additional info

The board The board TCA9548A connections TCA9548 Schematic TCA9548A zoomed in on the board TCA9548 Pinout

\$\endgroup\$
6
  • 1
    \$\begingroup\$ The 0x01 is written correctly. How do you read it back? \$\endgroup\$
    – Justme
    Commented Apr 23 at 20:21
  • \$\begingroup\$ @Justme the arduino or the aaeon one? or both? On the Uno, i use the getChannelMask() method, while initially setting setForced(true) \$\endgroup\$
    – Denis
    Commented Apr 23 at 20:33
  • \$\begingroup\$ @Justme sorry I can't read apparently. I thought you said 'incorrectly' lol. The AAEON computer uses an EAPI written by the manufacturer and all the reads and writes are done through it. When I scope the 'read' command, I can definitely see that it's sending a 0 back after I write 1or16or128 or literally anything other than 2. I feel that the issue is somewhere on the hardware side \$\endgroup\$
    – Denis
    Commented Apr 23 at 20:44
  • \$\begingroup\$ Show a scope capture from failing transaction. It makes no sense it fails on those writes, unless the selected bus is jammed. What's behind the mux? \$\endgroup\$
    – Justme
    Commented Apr 23 at 20:52
  • 1
    \$\begingroup\$ Also add the the pull-up values on these bus segments behind the mux. \$\endgroup\$
    – Justme
    Commented Apr 23 at 21:00

1 Answer 1

1
\$\begingroup\$

Actually, what is the source of the problem reads in the LED driver data sheet.

You have the TCA9548A bus switch set to address 0xE0 (or 0x70 if you prefer 7-bit addresses).

The problem why you can't read back what you wrote is that the PCA9685 LED controller also reserves this very same address for LED All Call Address on powerup.

So both chips try to respond to address 0xE0 with the data they want to return.

Unfortnately the TCA9548A address can't be changed in your current hardware.

Fortunately, you can change the PCA9685 All Call address to be something else than 0xE0, by writing register 5 to something else than 0xE0, like 0xE4 for now. There is also a register called MODE1 where you can disable the ALL CALL and the three SUB addresses.

But as the PCA9685 already hogs multiple addresses which some can be changed and some not, be sure to make a checklist with all addresses that each chip will take or can take, and whether the addresses are fixed and not changeable, changeable in hardware which depending on schematics/PCB design is not possible to change, or changeable in software.

Address allocation can be a huge task even if the system contains just a couple of chips.

The PCA9685 hogs these addresses: 0x80 (?) : main address, set in HW design, unchangeable in your HW design 0xE0 : software changeable ALL CALL address 0xE2 : software changeable SUBADDR1 0xE4 : software changeable SUBADDR2 0xE8 : software changeable SUBADDR3 0x06 : Software Reset address

TCA9548A takes only one address: 0xE0 : only address, set in HW design, unchangeable in your HW design.

As a side note, it makes sense to have some jumper resistors for setting the hardware I2C address pins later, when address clashes have not been determined beforehand.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you! This sounds like it should help. I will test it and will mark this as correct as soon as I'm done. I was hoping to only use this board for some initial software testing. I never considered this potential bus conflict with the all-call address, so I didn't add the jumpers in this initial version \$\endgroup\$
    – Denis
    Commented Apr 24 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.