VCNL4000 - proximity sensor

Hi All,

I’m trying to get a VCNL4000 breakout board from sparkfun hooked up to my imp. I’m connecting the SCL to pin 1 and SDA to pin 2 but keep getting -2 or Null values. I’ve tried to adapt some of the code found on the forum for a temperature sensor and using the below code for an arduino, which i am trying to adapt to Squirrel.

I keep coming up against a brick wall so if anyone can possibly give me any pointers or point me in the right direction it would be greatly appreciated.

http://bildr.org/2012/11/vcnl4000-arduino/

Thanks

Lloyd

Lloyd -

I may be able to provide you some guidance as I am currently using the VCNL device (in my case the VCNL4020) in a project, but I think it’s probably best if you could first supply the Squirrel code you are trying. Then I (or perhaps more likely others) might pick up on something not quite right with the I2C, or device configuration, etc. that you’ve ported over from Arduino code.

Also, just getting the basics out of the way, have you included pullup resistors on the SDA and SCL lines? I believe I recall there being a number of posts on the forum where this has initially tripped folks up.

  • Larry

(In what mode are you attempting to use the part … just reading proximity and/or ambient light values, or trying to use the threshold/interrupt features also)?

Hi Larry,

Thanks for getting back to me, i’m still a bit of a newbie so you’ll have to bare with me. I’ve attached an image of my setup, the IR runs of 3.3-5v so i assumed it was ok to setup as i have.

As i mentioned i’m using a combination of imp examples and arduino to try and get it to work, but i’m not 100% sure i’m doing it right. All i need to get is the proximity values so i can tell how close someone is to it.

My basic code was trying to take the below from arduino and translate it to squirrel. All this code is currently doing is checking if its working.

Hope thats enough information thanks again, if you can give me any advice it would be really appreciated

Lloyd

/***** Arduino *****/
`
#include <Wire.h>
#define VCNL4000_ADDRESS 0x13 //I2C Address of the board

void setup(){
byte temp = readVCNLByte(0x81);

if (temp != 0x11){ // Product ID Should be 0x11
Serial.print(“initVCNL4000 failed to initialize”);
Serial.println(temp, HEX);
}else{
Serial.println(“VNCL4000 Online…”);
}
}

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

return data;
}

`

/***** Imp *****/
`
hardware.i2c12.configure(CLOCK_SPEED_400_KHZ);
local i2c = hardware.i2c12;

function readProximity()
{

i2c.write(0x13, “\x81” + “”);

imp.sleep(1.0);

local temp = i2c.read(0x13, “\x81”, 1);

server.log(“Temp” + temp);

}

readProximity();
`

Hi Lloyd -

I’ll have a bit more time later this morning to look into this, but one thing that caught my attention is the really low value pullup resistors you’re apparently using … if I’m reading the colors accurately (third band brown, not orange?), they look like 220 ohm?

If so, the Imp very likely wouldn’t have enough drive current (spec’d at 4ma) to pull the lines low. If you have a scope, you might just take a look at SDA/SCL to see if you’re getting a full logic level swing … I’d suspect not.

I’d suggest first let’s just try switching the pullups to a larger value. The actual values are quite forgiving … I’d say almost anything you might have laying around in the 10-100k range should work.

Why don’t you give that a shot. (There might be something code related also, but it’s first necessary to insure that you have good hardware logic levels).

  • Larry

Hi Larry,

I’ve changed over to 100k resistors but still getting null, have i set the pullups up correctly?

I’m using the addresses from the arduino code, not sure if this is correct as well.

thanks

L

Ok, let’s try something else to try to get your I2C working (though I think changing the pullups was also a good thing).

Because the I2C address occupies the 7 MSBs of the address space, I believe your 0x13 address needs to be shifted over 1 bit. (Seems common with addressing on several devices). Try this (I’ve modified your code a bit) …

I’ll look it over more, and send along a small class I wrote for the device … but try giving this a shot.

  • Larry

`
hardware.i2c12.configure(CLOCK_SPEED_400_KHZ);
local i2c = hardware.i2c12;
i2c_addr = 0x13 << 1 // shift it over 1 bit

function readProximity()
{
i2c.write(i2c_addr, “\x81” + “”);
imp.sleep(1.0);

local temp = i2c.read(i2c_addr, “\x81”, 1);
server.log(“Temp” + temp);
}

readProximity();`

Thanks again for your time Larry.

Tried the code but got

2014-02-13 19:21:43 UTC+0: [Device] ERROR: the index 'i2c_addr' does not exist 2014-02-13 19:21:43 UTC+0: [Device] ERROR: at main:5

So assumed it was because i2c_addr hadn’t been declared so change line 3 to

local i2c_addr = 0x13 << 1 // shift it over 1 bit

and got

[Device] Temp(null : 0x0)

Would it make any difference that i am running off a usb?

Sorry, my bad on omitting ‘local’ … and no, I don’t think USB power is likely the problem.

I haven’t worked with the device in a while, so will dust off my code and look a little deeper now that some of the simpler possibilities haven’t panned out.

Thanks

Hi Lloyd -

Quick update - Well, I did run your code (with slight modifications, below) on a hardware setup I have which has a VCNL device on the Imp I2C bus, and the I2C communications checks out fine. (For completeness - I’m running on pins 8/9, and have 4.7k pullups - but I don’t believe this is too significant).

I was able to read various registers, including the ID register ( \x81 ), without any problem … and didn’t get the [Device] Temp(null : 0x0) error you report. So, the I2C communication appears to be good.

Here’s the code. (You might note I added a [0] to the end of the read statement … this is just to get the string character back in byte format … it’s discussed in the i2c section of the API).

`hardware.i2c89.configure(CLOCK_SPEED_400_KHZ);
local i2c = hardware.i2c89;
local i2c_addr = 0x13 << 1; // shift it over 1 bit

function readProximity()
{
i2c.write(i2c_addr, “\x81” + “”);
imp.sleep(1.0);

local temp = i2c.read(i2c_addr, “\x81”, 1) [0];
server.log("Temp " + temp);
}

readProximity();`
So, I’m not exactly sure why you seem to still be experiencing the I2C problem. I’d say perhaps double check SCL and SDA and maybe change the pullups, but beyond that perhaps someone else can spot what I may be overlooking.

I’d try moving to pins 8/9 for I2C if you have a sparkfun (vs adafruit) breakout in case your imp is one with a pin1 that misbehaves in the sparkfun breakout.

Ahhh, d’oh! Why didn’t I think of this :slight_smile:

Thanks guys, moving to pin 8/9 now gives me back some results. I’ll try to port the rest of the code and see how i get on

I don’t suppose there is anyway to get 1 and 2 working as i have already wired up pins 8 and 9. Rookie mistake i know.

Thanks again for you time Larry

L

Happy to hear you got something going Lloyd by switching over to the other i2c pair of pins.

Understand that there’s likely nothing you’ve done wrong related to trying to get the i2c port running on pins 1 and 2. Rather - elaborating a bit on Hugo’s comment - there’s a well documented issue with occasional mechanical intermittent contact (primarily pin 1) between some (predominantly early vintage) imps, and some SD sockets. (There are a few threads on the forum related to this … here’s one of the more recent ones … http://forums.electricimp.com/discussion/2218/). I’ve been stung by this on occasion on past projects … something I simply overlooked in my earlier comments. I’m glad Hugo jumped in to mention this.

My experience and understanding is that the problem has been addressed with some mechanical modifications made to the imp card some time ago. EI has been very supportive at exchanging cards if you think you might have a problematic device. I suggest you might try this route.

Larry