Merge pull request #46 from coelner/HResMode2

H res mode2
This commit is contained in:
claws
2018-10-04 07:49:07 +09:30
committed by GitHub
9 changed files with 242 additions and 44 deletions
Executable → Regular
+106 -28
View File
@@ -132,20 +132,88 @@ bool BH1750::configure(Mode mode) {
}
/**
* Configure BH1750 MTreg value
* MT reg = Measurement Time register
* @param MTreg a value between 32 and 254. Default: 69
* @return bool true if MTReg successful set
* false if MTreg not changed or parameter out of range
*/
bool BH1750::setMTreg(byte MTreg) {
//Bug: lowest value seems to be 32!
if (MTreg <= 31 || MTreg > 254) {
Serial.println(F("[BH1750] ERROR: MTreg out of range"));
return false;
}
byte ack = 5;
// Send MTreg and the current mode to the sensor
// High bit: 01000_MT[7,6,5]
// Low bit: 011_MT[4,3,2,1,0]
Wire.beginTransmission(BH1750_I2CADDR);
__wire_write((0b01000 << 3) | (MTreg >> 5));
ack = Wire.endTransmission();
Wire.beginTransmission(BH1750_I2CADDR);
__wire_write((0b011 << 5 ) | (MTreg & 0b111));
ack = ack | Wire.endTransmission();
Wire.beginTransmission(BH1750_I2CADDR);
__wire_write(BH1750_MODE);
ack = ack | Wire.endTransmission();
// Wait a few moments to wake up
_delay_ms(10);
// Check result code
switch (ack) {
case 0:
BH1750_MTreg = MTreg;
//Delay for specific continious mode to get valid values
switch (BH1750_MODE) {
case BH1750::CONTINUOUS_LOW_RES_MODE:
_delay_ms(24 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG);
break;
case BH1750::CONTINUOUS_HIGH_RES_MODE:
case BH1750::CONTINUOUS_HIGH_RES_MODE_2:
_delay_ms(180 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG);
break;
default: break;
}
return true;
case 1: // too long for transmit buffer
Serial.println(F("[BH1750] ERROR: too long for transmit buffer"));
break;
case 2: // received NACK on transmit of address
Serial.println(F("[BH1750] ERROR: received NACK on transmit of address"));
break;
case 3: // received NACK on transmit of data
Serial.println(F("[BH1750] ERROR: received NACK on transmit of data"));
break;
case 4: // other error
Serial.println(F("[BH1750] ERROR: other error"));
break;
default:
Serial.println(F("[BH1750] ERROR: undefined error"));
break;
}
return false;
}
/**
* Read light level from sensor
* @return Light level in lux (0 ~ 65535)
* The return value differs if the MTreg value is changed. The global maximum value is noted in the square brackets
* @return Light level in lux (0.0 ~ 54612,5 [117758,203])
* -1 : no valid return value
* -2 : sensor not configured
*/
uint16_t BH1750::readLightLevel(bool maxWait) {
float BH1750::readLightLevel(bool maxWait) {
if (BH1750_MODE == UNCONFIGURED) {
Serial.println(F("[BH1750] Device is not configured!"));
return 0;
return -2.0;
}
// Measurement result will be stored here
uint16_t level=65535;
float level = -1.0;
// Send mode to sensor
Wire.beginTransmission(BH1750_I2CADDR);
@@ -165,42 +233,52 @@ uint16_t BH1750::readLightLevel(bool maxWait) {
switch (BH1750_MODE) {
case BH1750::ONE_TIME_LOW_RES_MODE:
maxWait ? _delay_ms(24 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG) : _delay_ms(16 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG);
break;
case BH1750::ONE_TIME_HIGH_RES_MODE:
case BH1750::ONE_TIME_HIGH_RES_MODE_2:
if (BH1750_MODE == BH1750::ONE_TIME_LOW_RES_MODE) {
maxWait ? _delay_ms(24) : _delay_ms(16);
}
else {
maxWait ? _delay_ms(180) :_delay_ms(120);
}
maxWait ? _delay_ms(180 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG) :_delay_ms(120 * BH1750_MTreg/(byte)BH1750_DEFAULT_MTREG);
break;
default: break;
}
// Read two bytes from the sensor, which are low and high parts of the sensor
// value
Wire.requestFrom(BH1750_I2CADDR, 2);
if (Wire.available() == 2) {
level = __wire_read();
level <<= 8;
level |= __wire_read();
if (2 == Wire.requestFrom((int)BH1750_I2CADDR, (int)2)) {
unsigned int tmp = 0;
tmp = __wire_read();
tmp <<= 8;
tmp |= __wire_read();
level = tmp;
}
// Print raw value if debug enabled
#ifdef BH1750_DEBUG
Serial.print(F("[BH1750] Raw value: "));
Serial.println(level);
#endif
if (level != -1.0) {
// Print raw value if debug enabled
#ifdef BH1750_DEBUG
Serial.print(F("[BH1750] Raw value: "));
Serial.println(level);
#endif
// Convert raw value to lux
level /= 1.2;
if (BH1750_MTreg != BH1750_DEFAULT_MTREG) {
level *= (float)((byte)BH1750_DEFAULT_MTREG/(float)BH1750_MTreg);
// Print MTreg factor if debug enabled
#ifdef BH1750_DEBUG
Serial.print(F("[BH1750] MTreg factor: "));
Serial.println( String((float)((byte)BH1750_DEFAULT_MTREG/(float)BH1750_MTreg)) );
#endif
}
if (BH1750_MODE == BH1750::ONE_TIME_HIGH_RES_MODE_2 || BH1750_MODE == BH1750::CONTINUOUS_HIGH_RES_MODE_2) {
level /= 2;
}
// Convert raw value to lux
level /= BH1750_CONV_FACTOR;
// Print converted value if debug enabled
#ifdef BH1750_DEBUG
Serial.print(F("[BH1750] Converted value: "));
Serial.println(level);
#endif
// Print converted value if debug enabled
#ifdef BH1750_DEBUG
Serial.print(F("[BH1750] Converted float value: "));
Serial.println(level);
#endif
}
return level;
+10 -2
View File
@@ -36,6 +36,9 @@
// Reset data register value - not accepted in POWER_DOWN mode
#define BH1750_RESET 0x07
// Default MTreg value
#define BH1750_DEFAULT_MTREG 69
class BH1750 {
public:
@@ -60,10 +63,15 @@ class BH1750 {
BH1750(byte addr = 0x23);
bool begin(Mode mode = CONTINUOUS_HIGH_RES_MODE);
bool configure(Mode mode);
uint16_t readLightLevel(bool maxWait = false);
bool setMTreg(byte MTreg);
float readLightLevel(bool maxWait = false);
private:
int BH1750_I2CADDR;
byte BH1750_I2CADDR;
byte BH1750_MTreg = (byte)BH1750_DEFAULT_MTREG;
// Correction factor used to calculate lux. Typical value is 1.2 but can range from 0.96 to 1.44.
// See data sheet (p.2, Measurement Accuracy) for more information.
const float BH1750_CONV_FACTOR = 1.2;
Mode BH1750_MODE = UNCONFIGURED;
};
+25 -8
View File
@@ -39,6 +39,23 @@ back into One-Time mode. This library has been implemented to automatically
reconfigure the sensor when you next attempt a measurement so you should not
have to worry about such low level details.
Usually you will get an integer value which represent the lux equivalent.
- Low Resolution Mode - (generic range: 0.0 up to 54612.5 lux)
- High Resolution Mode - (generic range: 0.0 up to 54612.5 lux)
- High Resolution Mode 2 - (generic range: 0.0 up to 27306.25 lux)
The sensor itself returns a 16 bit unsigned integer. Therefore the maximum value is limited in general.
The standard conversion between the so called 'counts' to lux is 1/1.2, that means you get a smaller value.
As we use float, if an error occurs you will get a negative value.
- -1 no valid data was transmitted from the sensor
- -2 device is not configured
Otherwise the measured counts are converted to lux and returned. If no advanced parameters are changed the maximum lux value is 54612.5 lx.
As the sensor counts impact of light in a specific time frame you could change this time frame.
This is needed if you use an overlay windows or compensate environmental influence like darkness.
This time frame is defined by a register which is called MTreg. Therefore you could choose a value between 32 and 254.
The default value is 69; keep in mind that the measurement time is changed accordingly.
The datasheet for the BH1750 chip can be obtained [here](http://www.elechouse.com/elechouse/images/product/Digital%20light%20Sensor/bh1750fvi-e.pdf)
@@ -117,7 +134,7 @@ void setup(){
void loop() {
uint16_t lux = lightMeter.readLightLevel();
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
@@ -131,12 +148,12 @@ void loop() {
Moving the sensor to face more light results in the lux measurements increasing.
```
BH1750 Test
Light: 70 lx
Light: 70 lx
Light: 59 lx
Light: 328 lx
Light: 333 lx
Light: 335 lx
Light: 332 lx
Light: 70.0 lx
Light: 70.0 lx
Light: 59.0 lx
Light: 328.0 lx
Light: 333.0 lx
Light: 335.0 lx
Light: 332.0 lx
```
There are more examples in the examples directory.
+1 -2
View File
@@ -23,7 +23,6 @@
#include <BH1750.h>
/*
BH1750 can be physically configured to use two I2C addresses:
- 0x23 (most common) (if ADD pin had < 0.7VCC voltage)
- 0x5C (if ADD pin had > 0.7VCC voltage)
@@ -87,7 +86,7 @@ void setup(){
void loop() {
uint16_t lux = lightMeter.readLightLevel();
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
@@ -0,0 +1,94 @@
/*
Example of BH1750 library usage.
This example initialises the BH1750 object using the default high resolution
one shot mode and then makes a light level reading every five second.
After the measurement the MTreg value is changed according to the result:
lux > 40000 ==> MTreg = 32
lux < 40000 ==> MTreg = 69 (default)
lux < 10 ==> MTreg = 138
Remember to test your specific sensor! Maybe the MTreg value range from 32 up to 254 is not applicable to your unit.
Connection:
VCC -> 3V3 or 5V
GND -> GND
SCL -> SCL (A5 on Arduino Uno, Leonardo, etc or 21 on Mega and Due, on esp8266 free selectable)
SDA -> SDA (A4 on Arduino Uno, Leonardo, etc or 20 on Mega and Due, on esp8266 free selectable)
ADD -> (not connected) or GND
ADD pin is used to set sensor I2C address. If it has voltage greater or equal to
0.7VCC voltage (e.g. you've connected it to VCC) the sensor address will be
0x5C. In other case (if ADD voltage less than 0.7 * VCC) the sensor address will
be 0x23 (by default).
*/
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter;
void setup(){
Serial.begin(9600);
// Initialize the I2C bus (BH1750 library doesn't do this automatically)
Wire.begin();
// On esp8266 you can select SCL and SDA pins using Wire.begin(D4, D3);
lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE);
//lightMeter.setMTreg(69); //not needed, only mentioning it
Serial.println(F("BH1750 Test begin"));
}
void loop() {
//we use here the maxWait option due fail save
float lux = lightMeter.readLightLevel(true);
Serial.print(F("Light: "));
Serial.print(lux);
Serial.println(F(" lx"));
if (lux < 0) {
Serial.println(F("[DEBUG]: Error condition detected"));
}
else {
if (lux > 40000.0) {
// reduce measurement time - needed in direct sun light
if (lightMeter.setMTreg(32)) {
Serial.println(F("Setting MTReg to low value for high light environment"));
}
else {
Serial.println(F("Error setting MTReg to default value for normal light environment"));
}
}
else {
if (lux > 10.0) {
// typical light environment
if (lightMeter.setMTreg(69)) {
Serial.println(F("Setting MTReg to default value for normal light environment"));
}
else {
Serial.println(F("Error setting MTReg to default value for normal light environment"));
}
}
else {
if (lux <= 10.0) {
//very low light environment
if (lightMeter.setMTreg(138)) {
Serial.println(F("Setting MTReg to high value for low light environment"));
}
else {
Serial.println(F("Error setting MTReg to high value for low light environment"));
}
}
}
}
}
Serial.println(F("--------------------------------------"));
delay(5000);
}
+1 -1
View File
@@ -33,7 +33,7 @@ void setup(){
void loop() {
uint16_t lux = lightMeter.readLightLevel();
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
+2 -1
View File
@@ -20,6 +20,7 @@
*/
#include <Wire.h>
#include <BH1750.h>
@@ -43,7 +44,7 @@ void setup(){
void loop() {
uint16_t lux = lightMeter.readLightLevel();
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
+2 -1
View File
@@ -14,9 +14,9 @@ BH1750 KEYWORD1
begin KEYWORD2
configure KEYWORD2
setMTreg KEYWORD2
readLightLevel KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
@@ -31,3 +31,4 @@ BH1750_CONTINUOUS_LOW_RES_MODE LITERAL1
BH1750_ONE_TIME_HIGH_RES_MODE LITERAL1
BH1750_ONE_TIME_HIGH_RES_MODE_2 LITERAL1
BH1750_ONE_TIME_LOW_RES_MODE LITERAL1
BH1750_DEFAULT_MTREG LITERAL1
+1 -1
View File
@@ -1,5 +1,5 @@
name=BH1750
version=1.1.3
version=1.1.4
author=Christopher Laws
maintainer=Christopher Laws
sentence=Digital light sensor breakout boards containing the BH1750FVI IC