HI,
I am trying to measure light intensity with sensor BH1750 and arduino uno.
Following is the wiring connection I made
VCC-3.3v
GND-GND
SCL-analog pin 5
SDA-analog pin 4
ADD-No connection
and the code is as follows
but i am not getting any lux values. I doubt that the execution doesn't go into the loop
if(2==BH1750_Read(BH1750address))
I got this program from Light_Sensor__SKU_SEN0097_-DFRobot
Can someone Pls explain me the working of the program so that I can understand where it is going wrong?!
I think the example is wrong, but I have to read the datasheet to understand how to read from the chip.
There should be no beginTransmission and endTransmission around the requestFrom. It is a common mistake, and sometimes the code works (or worked in a previous version or Arduino).
Hi peter,
Sorry for the late reply. Those values doesn't match with actual lux value (~300 lux) which I measured with a light meter
Can you Pls explain the following part of the code to me?
uint16_t val=0;
Is uint16_t is a data type of the variable val?. If it is so,Why doesn't my compiler display it in red font which it generally does for data types and commands?
if(2==BH1750_Read(BH1750address))
Why does if statement compares the array variable buff size to 2? does BH1750 send only two byte of data per communication?
val=((buff[0]<<8)|buff[1])/1.2;
what is the basis of this calculation?.i can understand that symbol << left shifts buff[0] value by 8 bits and it performs bit wise OR operation with buff[1] and the factor 1.2 is for some accuracy as per data sheet to find illuminance per count. But I couldn't understand how does this operation results in final illuminance value in lux!
Serial.print(F(", "));
as per this link Serial.print() - Arduino Reference
it says
You can pass flash-memory based strings to Serial.print() by wrapping them with F().
But what does flash memory based strings mean?
By knowing the code well,I will have a better idea of how it works and can debug easily. Your help will be greatly appreciated
Here is a short answer, just ask if you want to know more.
I read the datasheet, but I don't understand why you read 3000 with 300 lux.
The uint16_t is a notation for an unsigned int of 16-bits. The sensor returns 16-bits, so that is what should be used.
Using "unsigned int" could be 32-bit on other devices. http://arduino.cc/en/Reference/UnsignedInt
The Wire.requestFrom asks for 2 bytes. If everything is okay, 2 bytes are received. So "BH1750_Read(BH1750address)" returns the number 2 if everything is okay.
val = ( ( buff [ 0 ] << 8 ) | buff [ 1 ] )
Two bytes are received via I2C, and they should form an unsigned integer.
So how to do that. Shifting the high byte into place and just dropping the lower byte into place is one way to do it.
http://playground.arduino.cc/Learning/Memory
The use of memory can cause endless discussions. Some users get very personal when it comes to memory use
The RAM is very precious because that is where variables are stored.
The flash memory contains the sketch code.
When a string is used, it uses RAM memory, but with the 'F()' function, it is only in flash memory, next to the sketch code.
Using F(", ") is not very useful, since that string is only 3 bytes :~
Perhaps the sensor is damaged, but in most cases there is something wrong with the wiring.
If the i2c_scanner can't find the device, you can't do anything else.
Do you have a multimeter ? to measure the voltages ?
I would like to see a photo of your module (also called : breakout board). Is there a voltage regulator for 3.3V on that module ? If so, you can power it with 5V, which could make a difference for working or not-working I2C.
Or do you use a breadboard ? Those can have bad contacts, you can shift everything a few posisitions and check if that helps.
But when I try to combine lighting control and the sensing part together as in following program,i am not getting any output from the sensor.
#include <Wire.h> //BH1750 IIC Mode
#include <math.h>
const int analogOutPin = 11; // Analog output pin that the LED is attached to
int BH1750address = 0x23;
byte buff[2];
int outputValue = 0;
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(57600);
}
void loop() {
// read the analog in value:
int i;
uint16_t sensorval=0;
BH1750_Init(BH1750address);
delay(200);
if(2==BH1750_Read(BH1750address))
{
sensorval=((buff[0]<<8)|buff[1])/1.2;
sensorval=sensorval+15;
Serial.print(sensorval,DEC);
Serial.println("[lx]");
}
// map it to the range of the analog out:
outputValue = map(sensorval, 380, 0, 0, 255); //mapped lux value to output pwm value as i want output lux to be constant at 380
// change the analog out value:
digitalWrite(9, HIGH); //goes to In1 pin of LM 298 driver
digitalWrite(10, LOW); //goes to In2 pin of LM 298 driver
analogWrite(analogOutPin, outputValue); // goes to ENA pin of LM 298 driver
// print the results to the serial monitor:
Serial.print("\t output = ");
Serial.println(outputValue);
// wait 2 milliseconds before the next loop
// for the analog-to-digital converter to settle
// after the last reading:
delay(2);
}
int BH1750_Read(int address) //
{
int i=0;
Serial.println(F("Read function: ")); // added
Wire.requestFrom(address, 2);
while(Wire.available()) //
{
buff[i] = Wire.read(); // receive one byte
Serial.print(buff[i], DEC); // added
Serial.print(F(", ")); // added
i++;
}
Serial.println();
return i;
}
void BH1750_Init(int address)
{
Wire.beginTransmission(address);
Wire.write(0x10);//1lx reolution 120ms
Wire.endTransmission();
}
I doubt the program control doesn't go inside the following loop
I have attached my output with this post.you could see in that output stops after certain iterations.I don't understand what is happening.can you please help me out
An output of 255 could indicate that the I2C bus is not working.
When it is working, a Wire.requestFrom(address, 2) can be followed by Wire.available(), followed by two Wire.read(). Just as you have. That should be okay.
I assumed that the input of the map() function should be lower first, but I think it has changed.
It says that : Note that the "lower bounds" of either range may be larger or smaller than the "upper bounds"
So that should not be a problem for you.
The input of the map() function could be wrong, because the calculation is a mix of everything.
This line of code : sensorval=((buff[0]<<8)|buff[1])/1.2;
Is like this : uint16_t = ( (byte << 8) | byte ) / float
When you divide by 1.2, you have to make everything float.
and since initially I have set the sensorval to be zero,it maps that value to 255. I tried changing initial sensorval from 0 to 100 and output value changed to 187. So mapping function is working fine,but the issue is that wire.available() is not executing.
Yes I use a 8.2 ohm resistor in series with the LED lamp
When you do Wire.requestFrom(address,2), you request 2 data bytes. After that the Wire.available() should return 2, or something is wrong.
Instead of the while-loop, you can just check if Wire.available() returns the value 2.
I hope you use a series resistor of 150 to 1000 ohm, not 8.2 ohm !
Hi,
I am not using BH1750 for now.Reference lux value is set to 350 and I use a LDR to sense the light and calibrated it into lux value in the program.
But I observe flickering in the light output because the output doesn't settle at desired 350 Lux.It keeps on oscillating and I dont achieve the desired closed loop.The sensor is kept right below the LED lamp
Following is the code
#include<math.h>
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 11; // Analog output pin that the LED is attached to
int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
}
void loop() {
// read the analog in value:
sensorValue = analogRead(analogInPin);
// calibrate sensor value to lux value
float three=(-.000029333)*pow(sensorValue,3) ;
float two=(.0311)*pow(sensorValue,2);
float one=(-11.1963)*sensorValue;
float lux= three+two+one+1426;
//limit lux value in the range 0-350 so that PWM value remains within 0-255
if(lux<=0)
{
lux=0;
}
if(lux>=350)
{
lux=350;
}
Serial.println("lux= " );
Serial.println(lux);
// map it to the range of the analog out:
outputValue = map(lux, 350, 0, 0, 204);
// change the analog out value:
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
analogWrite(analogOutPin, outputValue);
// print the results to the serial monitor:
Serial.println("sensor = " );
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
// wait 2 milliseconds before the next loop
// for the analog-to-digital converter to settle
// after the last reading:
delay(2);
}