forked from claws/BH1750
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBH1750.cpp
executable file
·204 lines (155 loc) · 4.81 KB
/
BH1750.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
This is a library for the BH1750FVI Digital Light Sensor breakout board.
The BH1750 board uses I2C for communication. Two pins are required to
interface to the device. Configuring the I2C bus is expected to be done
in user code. The BH1750 library doesn't do this automatically.
Written by Christopher Laws, March, 2013.
*/
#include "BH1750.h"
// Define milliseconds delay for ESP8266 platform
#if defined(ESP8266)
#include <pgmspace.h>
#define _delay_ms(ms) delayMicroseconds((ms) * 1000)
// Use _delay_ms from utils for AVR-based platforms
#elif defined(__avr__)
#include <util/delay.h>
// Use Wiring's delay for compability with another platforms
#else
#define _delay_ms(ms) delay(ms)
#endif
// Legacy Wire.write() function fix
#if (ARDUINO >= 100)
#define __wire_write(d) Wire.write(d)
#else
#define __wire_write(d) Wire.send(d)
#endif
// Legacy Wire.read() function fix
#if (ARDUINO >= 100)
#define __wire_read() Wire.read()
#else
#define __wire_read() Wire.receive()
#endif
/**
* Constructor
* @params addr Sensor address (0x76 or 0x72, see datasheet)
*
* On most sensor boards, it was 0x76
*/
BH1750::BH1750(byte addr) {
BH1750_I2CADDR = addr;
}
/**
* Configure sensor
* @param mode Measurement mode
*/
bool BH1750::begin(Mode mode) {
// I2C is expected to be initialized outside this library
// Configure sensor in specified mode
return configure(mode);
}
/**
* Configure BH1750 with specified mode
* @param mode Measurement mode
*/
bool BH1750::configure(Mode mode) {
// default transmission result to a value out of normal range
byte ack = 5;
// Check measurement mode is valid
switch (mode) {
case BH1750::CONTINUOUS_HIGH_RES_MODE:
case BH1750::CONTINUOUS_HIGH_RES_MODE_2:
case BH1750::CONTINUOUS_LOW_RES_MODE:
case BH1750::ONE_TIME_HIGH_RES_MODE:
case BH1750::ONE_TIME_HIGH_RES_MODE_2:
case BH1750::ONE_TIME_LOW_RES_MODE:
// Send mode to sensor
Wire.beginTransmission(BH1750_I2CADDR);
__wire_write((uint8_t)BH1750_MODE);
ack = Wire.endTransmission();
// Wait a few moments to wake up
_delay_ms(10);
break;
default:
// Invalid measurement mode
Serial.println(F("[BH1750] ERROR: Invalid mode"));
break;
}
// Check result code
switch (ack) {
case 0:
BH1750_MODE = mode;
return true;
case 1: // too long for transmit buffer
Serial.println(F("[BH1750] ERROR: too long for transmit buffer"));
case 2: // received NACK on transmit of address
Serial.println(F("[BH1750] ERROR: received NACK on transmit of address"));
case 3: // received NACK on transmit of data
Serial.println(F("[BH1750] ERROR: received NACK on transmit of data"));
case 4: // other error
Serial.println(F("[BH1750] ERROR: other error"));
default:
Serial.println(F("[BH1750] ERROR: undefined error"));
break;
}
return false;
}
/**
* Read light level from sensor
* @return Light level in lux (0 ~ 65535)
*/
uint16_t BH1750::readLightLevel(bool maxWait) {
if (BH1750_MODE == UNCONFIGURED) {
Serial.println(F("[BH1750] Device is not configured!"));
return 0;
}
// Measurement result will be stored here
uint16_t level(NAN);
// Send mode to sensor
Wire.beginTransmission(BH1750_I2CADDR);
__wire_write((uint8_t)BH1750_MODE);
Wire.endTransmission();
// Wait for measurement to be taken.
// Measurements have a maximum measurement time and a typical measurement
// time. The maxWait argument determines which measurement wait time is
// used when a one-time mode is being used. The typical (shorter)
// measurement time is used by default and if maxWait is set to True then
// the maximum measurement time will be used. See data sheet pages 2, 5
// and 7 for more details.
// A continuous mode measurement can be read immediately after re-sending
// the mode command.
switch (BH1750_MODE) {
case BH1750::ONE_TIME_LOW_RES_MODE:
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);
}
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();
} else {
Wire.reset();
}
// 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;
// Print converted value if debug enabled
#ifdef BH1750_DEBUG
Serial.print(F("[BH1750] Converted value: "));
Serial.println(level);
#endif
return level;
}