In this fourth part of our series on the I2C-Bus, we take a look at the BH1750 light sensor on the Raspberry Pi. This sensor component typically operates in the 1 to 65535 Lux range with a resolution of 1 Lux. The chip is frequently found in mobile phones, where it is used for lowering power consumption by adapting background lighting to the light in the surrounding environment.
The term Lux refers to a physical unit of measurement for light intensity. The word lux comes from Latin and means "light". The formal symbol used for this unit is lx. A simple candle creates about 1 lux of light intensity at a distance of 1 meter. On a cloudless summer day, outdoor light will register at up to 100,000 lux.
The BH1750 module can be smoothly integrated into every Raspberry Pi project, where it will deliver results in a format very similar to plain text. The cost for this product is extremely low, at around US$3.00, yet it can perform many tasks. For example, the module can do things like determine actual hours of sunlight or reposition solar cells.
The BH1750 comes in a WSOF61 SMD case which is so tiny that you definitely shouldn't try to attach it yourself with a soldering iron. Fortunately you can buy a small board that already comes with the component [1]. The connections on the module are found on a pin bar, a feature traditionally very popular among hobbyists (Figure 1).
Figure 1: The compact component BH1750 delivers measurement values in a practical resolution given the intensity of ambient light. It is shown here mounted and ready to go on a mini board.
The board comes with all of the parts in place that you'll need to use the sensor. The BH1750 responds on the I2C-Bus under the addresses 0x23h (0 Volt on ADDR) and 0x5Ch (3.3 Volt on ADDR). The set up for a first use attempt is therefore fairly easy. Attach the voltage supply to VCC and GND. The component cannot handle more than 3.6 volts, so connect it to the 3.3V output of the Raspberry Pi. Connect SCL and SDA with the corresponding connections on the GPIO. Set the ADDR to 0 Volt load (Figure 2).
Figure 2: The first test performed with the sensor works with this straightforward setup.
Starting Up
If you have completed the steps described in Part 1 of this series, then the BH1750 should be able to signal to the bus without any problems. You can test whether this is the case from a terminal using the command I2cdetect
. Listing 1 shows the result. The desired operating mode should be specified using a write operation on the base address for the BH1750 (See Operating Modes table)
$ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- --
You will now need to wait for a certain length of time relative to the operating mode before using a word read operation for reading measurements. The high byte and low byte of the measurement results are deceptive in the way they are represented. You will need to reverse both of them. The operating method of the BH1750 also restricts itself to this. The data sheet [2] for the component contains additional technical information that we do not need for our simple example program.
The BH1750 only needs a modest 190 microamperes when operating in continuous mode. Its frugal power drain is different from a typical low current LED which consumes 3 mA – around sixteen times as much. If you switch it into power-down mode, the power consumption sinks even lower to 1 microampere. The one time modes save you the trouble of switching manually. After each measurement, the BH1750 switches automatically to energy efficiency by going into power down mode. In order to continue with data collection, you need to first wake up the component with an explicit power on.
Part
| Subject
| Issue
| Link
|
Part 1
|
I2C-Bus Basics
|
RPG 01/2015
|
http://www.raspberry-pi-geek.com/Archive/2015/09/Getting-to-know-the-Raspberry-Pi-I2C-bus/
|
Part 2
|
Clock modules PCF8583
|
RPG 02/2015
|
http://www.raspberry-pi-geek.com/Archive/2015/11/Using-the-PCF8583-as-a-clock-component-on-the-I2C-bus-of-the-Raspberry-Pi/
|
Part 3
|
Temperature Sensor
|
RPG 03/2015
|
http://www.raspberry-pi-geek.com/Archive/2015/12/Controlling-the-LM75-temperature-sensor-on-the-I2C-bus/
|
Test Program
Our simple test program from Listing 2 sends the control code for continuous measurement in high resolution mode with 1 lux precision to the BH1750 in Line 5. The value 0x10h, corresponds to 00010000. After a short wait (Line 6), the code reads the measurement results (line 7). The bytes then return to the correct order (line 8), and display the measurement result (line 9).
01 #include <wiringPiI2C.h>
02 #include <stdio.h>
03 int main (void) {
04 int handle = wiringPiI2CSetup(0x23) ;
05 wiringPiI2CWrite(handle,0x10);
06 sleep(1);
07 int word=wiringPiI2CReadReg16(handle,0x00);
08 int lux=((word & 0xff00)>>8) | ((word & 0x00ff)<<8);
09 printf("Current light intensity in Lux:%d \n",lux);
10 return 0;
11 }
As you can see from the program output in Listing 3, the test run took place in a relatively dark room in a basement. Geeks are known for working in such nocturnal environments after all, as well as having a penchant for guzzling Coke and eating pizza.
$ cc bh1750.c -lwiringPi
$ ./a.out
Current Light Intensity in Lux: 63
The return bytes will appear in reverse order. This is not a bug but due to the working method used by many of the popular processor architectures, including those belonging to the x86 Intel family. In the language of the trade, this architecture is referred to as little Endian. Prominent representatives of the big Endian CPUs which also return values in reverse order include those employed by Motorola. If you want to learn more, there is an excellent, descriptive Wikipedia article on this subject [3].
Control code
| Command
| Comment
|
00000000
|
Power down
|
Device is inactive
|
00000001
|
Power on
|
Device ready to begin measuring
|
00000111
|
Reset
|
Reverses the data index; no Power-down-Mode
|
00010000
|
Continuously H-Resolution Mode
|
continuous high resolution measurements (Resolution 1lx, Period of time 120minutes)
|
00010001
|
Continuously H-Resolution Mode2
|
continuous high resolution meausurements (Resolution 0,5lx, period of time 120minutes)
|
00010011
|
Continuously L-Resolution Mode
|
continuous low resolution measurements (Resolution 4lx, period of time 16minutes)
|
00100000
|
One Time H-Resolution Mode
|
one time high resolution Measurement (resolution 1lx, period of time 120minutes)
|
00100001
|
One Time H-Resolution Mode2
|
one time high resolution Measurement (resolution 0,5lx, period of time 120minutes)
|
00100011
|
One Time L-Resolution Mode
|
one time low resolution measurement (resolution 4lx, period of time 16minutes)
|
01000<xxx>
|
Change Measurement Time (High Bit)
|
relative measurement time (Bits 7, 6, 5)
|
011<xxxxx>
|
Change Measurement Time (Low Bit)
|
relative measurement time (Bits 4, 3, 2, 1, 0)
|
The results for the measurment are found after 2 x measurement time in the data index. The standard measurement time corresponds to a value of 01000101. Resolutions up to 0.111x can be achieved with a longer measurement time (maximum: 11111110 = 3.68 x standard)
|