Problem using I2C with 8 Channel MUX and proximity sensors

Hello, I am a new user on this forum and very new to Arduino and I2C.

Project description:

I am building a proximity sensor array using Sparkfun VCNL4000 Infrared Proximity Breakout boards (8 in total) all of which are connected to a PCA9548A I2C multiplexer and an Arduino Uno. I have built the multiplexer board and Arduino Uno board myself and because of this I understand and accept that I may have messed up the hardware side of this project. Because of this I will provide a schematic and board layout of everything I have done, and reference all my sources of code.

My Arduino board works just fine and can run and collect data from a single VCNL4000 sensor board without any trouble. The problem starts when I try to connect a single sensor through the multiplexer board.

Some background information on my boards.

My custom Arduino does not have a usb interface and runs only on LDO regulated 3.3v (max current draw is 0.5A). So i program using the ISP pinheader and can only debug using analog output pins for things like LEDs (and of course my brain, what ever that’s worth :P).

Because of these limitations the multiplexer and sensors all run off only 3.3v.

Here is the current code I am trying to use. With thanks to Jim Lindblom and Kerry D. Wong for the sample code and assistance.

   Hardware:
   This code was developed using the SparkFun breakout board:
   http://www.sparkfun.com/products/10901
   Connections are:
   VCNL4000 Breakout ---------------- Arduino
        3.3V  -----------------------  3.3V
        GND  ------------------------  GND
        SCL  ------------------------  A5
        SDA  ------------------------  A4
        IR+  ------------------------  5V (3.3V is fine too)
 */
#include <Wire.h>

#define PCA9548ADDR				0x74 //1110100-

#define STOP					        0x00 //0000 0000
#define CHANNEL_0				0x01 //0000 0001
#define CHANNEL_1				0x02 //0000 0010
#define CHANNEL_2				0x04 //0000 0100
#define CHANNEL_3				0x08 //0000 1000 
#define CHANNEL_4				0x10 //0001 0000 
#define CHANNEL_5				0x20 //0010 0000 
#define CHANNEL_6				0x40 //0100 0000 
#define CHANNEL_7				0x80 //0100 0000 

#define VCNL4000_ADDRESS 0x13  // 0x26 write, 0x27 read

// VCNL4000 Register Map
#define COMMAND_0				0x80  // starts measurments, relays data ready info
#define PRODUCT_ID				0x81  // product ID/revision ID, should read 0x11 
#define IR_CURRENT				0x83  // sets IR current in steps of 10mA 0-200mA 
#define AMBIENT_PARAMETER		0x84  // Configures ambient light measures 
#define AMBIENT_RESULT_MSB	0x85  // high byte of ambient light measure
#define AMBIENT_RESULT_LSB		0x86  // low byte of ambient light measure
#define PROXIMITY_RESULT_MSB	0x87  // High byte of proximity measure 
#define PROXIMITY_RESULT_LSB	0x88  // low byte of proximity measure 
#define PROXIMITY_FREQ			0x89  // Proximity IR test signal freq, 0-3 
#define PROXIMITY_MOD			0x8A  // proximity modulator timing 

int ambientValue, proximityValue;

int led1 = A3;

bool blink = false;

void setup()
{
  ambientValue = proximityValue = 0;
  pinMode(led1, OUTPUT);
  
  multiplexer_init();
  
  selectI2CChannels(CHANNEL_0); //select channel 0
  
  Wire.begin();  // initialize I2C stuff
  
  /* Test that the device is working correctly */
  byte temp = readByte(PRODUCT_ID);
  if (temp != 0x11)  // Product ID Should be 0x11
  {
     blink = true;
  }
  else
  {
	 blink = false;
	    /* Now some VNCL400 initialization stuff
     Feel free to play with any of these values, but check the datasheet first!*/
	 writeByte(AMBIENT_PARAMETER, 0x0F);  // Single conversion mode, 128 averages
	 writeByte(IR_CURRENT, 20);  // Set IR current to 200mA
	 writeByte(PROXIMITY_FREQ, 2);  // 781.25 kHz
	 writeByte(PROXIMITY_MOD, 0x81);  // 129, recommended by Vishay
  }
}

void loop()
{ 
  
  if(blink)
  {
	  digitalWrite(led1, HIGH);
	  delay(1000);
	  digitalWrite(led1, LOW);
	  delay(1000); 
  }
  else
  {
	  ambientValue = readAmbient();
	  proximityValue = readProximity();
	  
	  if(proximityValue > 0)
	  {
		  digitalWrite(led1, HIGH);
	  }
	  else
	  {
		   digitalWrite(led1, LOW);
	  }
	  
	  // delay(100);  // You may want to uncomment this for visibility
  } 
}

// readProximity() returns a 16-bit value from the VCNL4000's proximity data registers
unsigned int readProximity()
{
	unsigned int data;
	byte temp;
  
	temp = readByte(COMMAND_0);
	writeByte(COMMAND_0, temp | 0x08);  // command the sensor to perform a proximity measure
  
	while(!(readByte(COMMAND_0)&0x20));  // Wait for the proximity data ready bit to be set
	data = readByte(PROXIMITY_RESULT_MSB) << 8;
	data |= readByte(PROXIMITY_RESULT_LSB);
  
	return data;
}

// readAmbient() returns a 16-bit value from the VCNL4000's ambient light data registers
unsigned int readAmbient()
{
	unsigned int data; 
	byte temp; 
  
	temp = readByte(COMMAND_0);
	writeByte(COMMAND_0, temp | 0x10);  // command the sensor to perform ambient measure
  
	while(!(readByte(COMMAND_0)&0x40));  // wait for the proximity data ready bit to be set 
	data = readByte(AMBIENT_RESULT_MSB) << 8; 
	data |= readByte(AMBIENT_RESULT_LSB); 
  
	return data; 
}

// writeByte(address, data) writes a single byte of data to address
void writeByte(byte address, byte data)
{
	Wire.beginTransmission(VCNL4000_ADDRESS);
	Wire.write(address); 
	Wire.write(data);
	Wire.endTransmission();
}

// readByte(address) reads a single byte of data from address
byte readByte(byte address)
{
	byte data;
  
	Wire.beginTransmission(VCNL4000_ADDRESS);
	Wire.write(address);
	Wire.endTransmission();
	Wire.requestFrom(VCNL4000_ADDRESS, 1); 
	while(!Wire.available()); 
	data = Wire.read(); 

	return data; 
}

void selectI2CChannels(int channels)
{
	Wire.beginTransmission(PCA9548ADDR); 
	Wire.write(channels);
	Wire.endTransmission(); 
}

void multiplexer_init()
{
	pinMode(A0, OUTPUT);
	pinMode(A1, OUTPUT);
	pinMode(A2, OUTPUT);
	
	digitalWrite(A0, LOW);
	digitalWrite(A1, LOW);
	digitalWrite(A2, HIGH); 
}

Ok big block of code so ill try to explain what I was trying to accomplish.

All I want to have working right now is a single sensor that turns on and off an LED when i get real close to the sensor board.

Setup()

So first thing I did was initialize an unused analog pin to be my output. Then I set the A0 and A1 pins to logic LOW and A2 pin to logic HIGH ( I did this because the address for the multiplexer is 0x74 and looking at the data sheet that would make the A2 = 1 , A1 = 0 , A0 = 0 ? I’m not sure how those pins control this chip entirely so I’m probably totally wrong about how this works and could use clarification on this)

next I used selectI2CChannels(CHANNEL_0) to pick out the channel that has the sensor or it.

Next I begin attempting to communicate with the sensor because as far as I understand these components once the channel is selected I should be able to talk with a recognized device on I2C as if the MUX is transparent.

Problems:

The code gets hung up at the product ID reading part. I’ve run a few tests where I’ve commented out various parts to get any output at all on the LED. I don’t think I am communicating over the I2C line correctly with the MUX, how exactly I’ve gone wrong I don’t know (debugging is hard without serial out :frowning: )

I am a college student and as such I don’t have this project directly in front of me as I type this from home. I will be at my college within the next 24 hours for pretty much the whole day and will have the circuits and everything in front of me to respond to you fine folk here and answer more questions and hopefully get feedback.

I hope this is enough information to at least begin the process of getting assistance, thank you to anyone who wishes to help.

References:

http://dlnmh9ip6v2uc.cloudfront.net/datasheets/BreakoutBoards/VCNL4000_Example.pde
http://www.kerrywong.com/2012/10/08/i2c-multiplexer-shield-testing/
http://www.nxp.com/documents/data_sheet/PCA9548A.pdf

UPDATE:

So spent the day troubleshooting my MUX board and i found a few errors, but im still not convinced my code is correct.

board faults:

-reset was being pulled low (OMG im stupid :frowning: )
-SDA and SCL are reversed on the pinheader so no communication between shield and microcontroller lol really big problem there
-useless resistor (did i mention i’m not working alone on this project lol my partners contribution to the board layout)

I will be testing these corrections tomorrow at school, and will continue to update this post with my findings and progress. Even if no one helps or sees this post it will be here to showcase how to use these components.

Hello,

If you have solved the problem could you please share the solution. I am using the same multiplexer but when I connect the ground pin it does not work at all.