The confusing part for me is the SLAVE_I2C_ADDRESS used in the example, i don't seem to know how to get that address from the datasheet of the sensor.
Basically, i need to read from the register that has the ambient light value
I just want to read the value of the ambiant light
Can anyone help me in that or give me some guidance on how to get that address ?
0x13 is the sensor address that i got when i used this code:
// --------------------------------------
// i2c_scanner
//
// Version 1
// This program (or code that looks like it)
// can be found in many places.
// For example on the Arduino.cc forum.
// The original author is not known.
// Version 2, Juni 2012, Using Arduino 1.0.1
// Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26 2013
// V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
// by Arduino.cc user Krodal.
// Changes by louarnold removed.
// Scanning addresses changed from 0...127 to 1...119,
// according to the i2c scanner by Nick Gammon
// https://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
// As version 4, but address scans now to 127.
// A sensor seems to use address 120.
// Version 6, November 27, 2015.
// Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
while (!Serial); // Leonardo: wait for Serial Monitor
Serial.println("\nI2C Scanner");
}
void loop() {
int nDevices = 0;
Serial.println("Scanning...");
for (byte address = 1; address < 127; ++address) {
// The i2c_scanner uses the return value of
// the Wire.endTransmission to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) {
Serial.print("0");
}
Serial.print(address, HEX);
Serial.println(" !");
++nDevices;
} else if (error == 4) {
Serial.print("Unknown error at address 0x");
if (address < 16) {
Serial.print("0");
}
Serial.println(address, HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
} else {
Serial.println("done\n");
}
delay(5000); // Wait 5 seconds for next scan
}
Apparently, i need to get the register address but the datasheet is so confusing for me and i'm from a different background so i can't understand electronic this much
The predefined 7 bit I2C bus address is set to 0010 011 = 13h. The least
significant bit (LSB) defines read or write mode. Accordingly, the bus address is set to 0010 011x = 26h for write, 27h for read.
I don't get it, do i simply use 0010 011 as register address? what about all these other paragraphs and tables talking about different registers? I just want to read the value of ambiant light and i'm not sure how to do that
As @anon73444976 noted, this is the required protocol:
You first Write the desired register address to the device then Read back the data byte from that register. Because ambient light is a 16-bit value, you must do this sequence twice. First for Register #5 then for Register #6.
Because register addresses start at 0x80 and because Register #5 (address 0x85) is the high-order byte, I think the code would look something like this:
const byte DeviceAddress = 0x13;
Wire.beginTransmission(DeviceAddress);
Wire.write(0x85); // Register #5 address
Wire.endTransmission();
Wire.requestFrom(DeviceAddress, 1);
uint16_t value = Wire.read();
value <<= 8; // Move to upper byte
Wire.beginTransmission(DeviceAddress);
Wire.write(0x86); // Register #6 address
Wire.endTransmision();
Wire.requestFrom(DeviceAddress, 1);
value |= Wire.read();
The cast is needed to suppress compiler warnings (complaints) about using the constant '2' (defaults to int) as argument to function looking for a uint8_t.
The R/W bit at the end of the address byte is handled by the Wire library. You just supply the 7-bit address, and beginTransmission() shifts it one bit to the left and adds a 0-bit which means write. Similarly, the requestFrom() does the same, but adds a 1-bit which means read.
So what I understood so far is the following:
The device address is: 0x13
The value of the ambient light measurement is stored in registers #5 and #6
And to read from a certain register I need to write its address first
So the sequence of the code should be like this:
1- Send a START condition using Wire.beginTransmission to the device address
2- Write the register #5 address
3- Read the data in that register using Wire.read(); after executing the Wire.requestFrom(); to the device address
4- then A repeated START condition as highlighted by @gfvalvo
5- Then write the register #6 address
6- then read from it using Wire.read(); after executing the Wire.requestFrom(); to the device address
7- Then i can send the STOP condition using Wire.end() to the device address
All this should allow me to read the value in the register every time i loop back into it @johnwasser your code really helped me thank you so much, but i don't understand why did you repeat this twice?
isn't it okay to do two starts without a stop in the middle? Also, this Wire.endTransmission(); is basically just the Wire.end(), corrct? or tha't a different function
but what about register #0 though, aren't i supposed to write to the device to initiate the measurement?
I understand that other registers are used to change some settings, and i can choose not to change them for now. But the first register though, isn't it supposed to be called and written to at least once?