I2C Ambient light sensor

Hi,

I'm wondering if anyone has tried hooking there arduino up to an I2C ambient light sensor. The sensor I have is this one: http://www.avagotech.com/docs/AV02-2315EN.

Is it possible to interface this component with arduino?

I don't really understand the address select input pin on the component, any ideas?

Thanks in advance!

there is an I2C library:

should work fine... if the device is I2C conformant... :slight_smile:

Is it possible to interface this component with arduino?

Yes, I don't see a reason against it.

I don't really understand the address select input pin on the component, any ideas?

The address selection pin can have 3 states:

  1. Connected to ground => address = 0x29
  2. Connected to Vcc => address = 0x49
  3. Not connected (floating) => address = 0x39

I would use one of the connected states because the floating is the most error prone (some dirt may make enough connection to switch to another state)

Thanks for the replies!

I've been learning about the I2C library and have written some code that I thought would work. However, on page 7 of the datasheet it seems as if I need to send: start bit - address byte - write bit - command code byte - repeated start condition bit - address byte - read bit, just to obtain a data byte. I don't understand what the command code byte and repeated start condition bit are.

I have this program which successfully connects to the component but doesn't receive any meaningful output. I currently receive first byte (a) = 0, and second byte (b) = 2 always.

#include "Wire.h"
#define address 0x29

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

void getdata(byte *a, byte *b){
  
  Wire.beginTransmission(address);
  Wire.write(0); 
  Wire.endTransmission(); 

  Wire.requestFrom(address, 2);
  *a = Wire.read();
  *b = Wire.read();
}

void showdata(){
  byte aa,bb;
  getdata(&aa,&bb);
  
  Serial.println(aa);
  Serial.println(bb);
  delay(1000);
}

void loop(){
  showdata();
}

My serial output after 3secs is:
0
2
0
2
0
2

Thanks again.

However, on page 7 of the datasheet it seems as if I need to send: start bit - address byte - write bit - command code byte - repeated start condition bit - address byte - read bit, just to obtain a data byte.

This explains the details of the I2C communication. With the Wire library it's quite easy. Figure 7 translates to

Wire.beginTransmission(Slave_Address);
Wire.write(Common_code);
Wire.write(Data_Byte);
Wire.endTransmission();

while Figure 8 (read) translates to:

Wire.beginTransmission(SlaveAddress);
Wire.write(Command_Code);
Wire.endTransmission();
Wire.requestFrom((SlaveAddress,1);
uint8_t value = Wire.read();

Get the current value (channel 0, for channel 1 the register is 0x0E) is then:

#define address 0x29
Wire.beginTransmission(address);
Wire.write(0x0C);
Wire.endTransmission();
Wire.requestFrom(address, 2);
uint16_t val_low = Wire.read();
uint16_t val = Wire.read();
val <<= 8;
val |= val_low;

Thanks pylon,

I understand it better now but still am not getting any good output.

Here's my code:

void getdata(byte *a){
  
  Wire.beginTransmission(address);
  Wire.write(0x0C); 
  Wire.endTransmission(); 

  Wire.requestFrom(address, 1);
  *a = Wire.read();
}

I still just get constant values:
C: 12
D: 13
E: 14
F: 63

Do I have to send read and write bits or maybe send the slave address again as it shows in figure 8?

What is the full code I need to obtain the channel 0 low, channel 0 high, channel 1 low, channel 1 high.

Thanks!

Excuse me, I guess I misunderstood the datasheet on the first reading. Seems like the command byte has to have bit 7 always set to store the register address.

So your function reads:

uint16_t getdata(uint8_t channel){
  
  Wire.beginTransmission(address);
  Wire.write(0x8C + channel << 1); 
  Wire.endTransmission(); 

  Wire.requestFrom(address, 2);
  uint8_t lowbyte = Wire.read();
  uint16_t value = Wire.read();
  value <<= 8;
  value += lowbyte;
  return value;
}

where channel is 0 or 1 to select the channel you like to read.

Hi, I tried your suggestion but it still gives a meaningless output of:
520
522
520
522

Here's the code I used:

#include "Wire.h"
#define address 0x29

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

uint16_t getdata(uint8_t channel){
  
  Wire.beginTransmission(address);
  Wire.write(0x8C + channel << 1); 
  Wire.endTransmission(); 

  Wire.requestFrom(address, 2);
  uint8_t lowbyte = Wire.read();
  uint16_t value = Wire.read();
  value <<= 8;
  value += lowbyte;
  return value;
}

void loop(){
  Serial.println(getdata(0));
  Serial.println(getdata(1));
  delay(1000);
}

I'm running it on a mega2560 if that makes any difference. I've also tried it with two of these sensors but with the same output. Any ideas?

does it make a difference when u change the address to 0x28? :slight_smile:
i mean: r u really talking to that thingy?

what if u put a paper bag over that sensor?
does the 520 change?

Yeh, the address is correct, any other address gives a different output but the same as any other address other than 29 if that makes sense. ie. 26,27,28,30,31 give the same output but 29 is different.

No I've still not had any output that varies at all; once I achieve this then I can probably work the rest out.

How have you wired the sensor to your Arduino?

I've wired it as shown on the last page of the datasheet using 1k resistors. Although I've just realised that I've not connected interrupt (since I don't need it), so it has no pull-up resistor or connected to arduino so it is floating. I don't think this would cause a problem though.

Tell exactly what pin on the Arduino you took for these signals: VDD, SCL, SDA. I also guess you wired pin 3 of the sensor to GND, didn't you?

I'm asking because the sensor is running on 3V3 I guess (max VDD is 3V8 on the datasheet). If pullups go to 3V3 the logical 1 of the sensor (3V3) is just at the limit of the Arduino to recognize (60-70% of Vcc => 3V to 3V5). If there is only the smallest change in the supply voltage the signal may drop below that and you have problems. Best would be to use a level converter (two way) like this: Logic Level Converter - Microcontroller Accessories Interface - Boxtec Onlineshop, although I cannot guarantee that your problem go away with it.

1k is a bit too low, do you have 2k2 resistors to change?

what is ur supply voltage?
it shall not be more that 3.6V...
so u use arduino's 3V3 pin?

  1. @pylon
    the IO pin is read high (according to the ATmega168 datasheet) when it is above 2.5V...
    i dont think that the 3.3V rail has that much ripple/inaccuracy...

what if u read the "ID register"?
it is command code: 0x8A - i guess :stuck_out_tongue:
read just 1 byte...
the response should be 0x5N... where N is the revision number...