Library for BH1750 I2C light sensor. Supports autoranging! True to datasheet. (beware: calls are blocking at the moment)

So there is this light sensor (like the one present in any phone), BH1750. I got mine soldered to some nice breakout board.

Few facts about this library: it is very true to the datasheet. it takes advantage of MTreg (time of measurement), which lets you to increase resolution up to 3.86 times at the cost of time it takes to perform a measurement. Measurement is blocking ! I've also implemented an autoranging feature. Just like in those fancy multimeters! It works as follows, thresholds are hard-coded:

  1. <5 lx switches to Hi-res2 and to max MTreg (so measurement time is like 500ms)
  2. <1000 lx Hi-res, MTreg default.
  3. above there is no real need for Hi-res, so Low-res mode is used.

Last note: I greatly recommend you to use log10 value of the luminosity data. it makes much more sense, because it becomes linear.

Committer:
amateusz
Date:
Tue Aug 22 00:29:50 2017 +0000
Revision:
0:a7280a6c3c9b
initial commit. supports autoranging, addresss selection, all continous modes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
amateusz 0:a7280a6c3c9b 1 #include "BH1750.h"
amateusz 0:a7280a6c3c9b 2
amateusz 0:a7280a6c3c9b 3
amateusz 0:a7280a6c3c9b 4 BH1750::BH1750(I2C & i2c_inst, bool autoRange, bool addressPinState): _i2c_inst(i2c_inst) {
amateusz 0:a7280a6c3c9b 5 if (addressPinState == true) _address = ADDRESS_HIGH;
amateusz 0:a7280a6c3c9b 6 else _address = ADDRESS_LOW;
amateusz 0:a7280a6c3c9b 7
amateusz 0:a7280a6c3c9b 8 _autoModeAdjustSwitch = autoRange;
amateusz 0:a7280a6c3c9b 9 }
amateusz 0:a7280a6c3c9b 10
amateusz 0:a7280a6c3c9b 11
amateusz 0:a7280a6c3c9b 12 void BH1750::_sendCommand(char toSend) {
amateusz 0:a7280a6c3c9b 13 char toSendPseudoArray[] = {toSend};
amateusz 0:a7280a6c3c9b 14 _i2c_inst.write(_address << 1, toSendPseudoArray, 1);
amateusz 0:a7280a6c3c9b 15 }
amateusz 0:a7280a6c3c9b 16
amateusz 0:a7280a6c3c9b 17 unsigned int BH1750::_readRaw() {
amateusz 0:a7280a6c3c9b 18 unsigned int measurement;
amateusz 0:a7280a6c3c9b 19 char measurement_intermediate [2];
amateusz 0:a7280a6c3c9b 20 _i2c_inst.read(_address << 1, measurement_intermediate, 2);
amateusz 0:a7280a6c3c9b 21 measurement = (measurement_intermediate[0] << 8) + measurement_intermediate[1];
amateusz 0:a7280a6c3c9b 22 return measurement;
amateusz 0:a7280a6c3c9b 23 }
amateusz 0:a7280a6c3c9b 24 bool BH1750::_autoModeAdjust(float measurement) { // returns if adjusted or left alone
amateusz 0:a7280a6c3c9b 25 // printf("\tcurrentMode: %d\r\n", _currentMode);
amateusz 0:a7280a6c3c9b 26 char previousMode = _currentMode;
amateusz 0:a7280a6c3c9b 27 char previousMtreg = _currentMtreg;
amateusz 0:a7280a6c3c9b 28 bool changed = false;
amateusz 0:a7280a6c3c9b 29
amateusz 0:a7280a6c3c9b 30 if (measurement < 5.0 ) {
amateusz 0:a7280a6c3c9b 31 if (_currentMode != CONTINOUS_H2_RES_CMD ) {
amateusz 0:a7280a6c3c9b 32 setMode(CONTINOUS_H2_RES_CMD);
amateusz 0:a7280a6c3c9b 33 setMtreg(254); //maximum
amateusz 0:a7280a6c3c9b 34 changed = true;
amateusz 0:a7280a6c3c9b 35 }
amateusz 0:a7280a6c3c9b 36 } else if (measurement < 1000.0) {
amateusz 0:a7280a6c3c9b 37 if (_currentMode != CONTINOUS_H_RES_CMD ) {
amateusz 0:a7280a6c3c9b 38
amateusz 0:a7280a6c3c9b 39 setMtreg(DEFAULTMTREG);
amateusz 0:a7280a6c3c9b 40 setMode(CONTINOUS_H_RES_CMD);
amateusz 0:a7280a6c3c9b 41 changed = true;
amateusz 0:a7280a6c3c9b 42 }
amateusz 0:a7280a6c3c9b 43 } else if (_currentMode != CONTINOUS_L_RES_CMD) {
amateusz 0:a7280a6c3c9b 44 setMtreg(DEFAULTMTREG);
amateusz 0:a7280a6c3c9b 45 setMode(CONTINOUS_L_RES_CMD);
amateusz 0:a7280a6c3c9b 46 changed = true;
amateusz 0:a7280a6c3c9b 47 }
amateusz 0:a7280a6c3c9b 48
amateusz 0:a7280a6c3c9b 49 if (changed) {
amateusz 0:a7280a6c3c9b 50 wait_ms(_waitForMeasurement); // one more wait in PREVIOUS state. guarantees valid values on state transitions
amateusz 0:a7280a6c3c9b 51 return true;
amateusz 0:a7280a6c3c9b 52 } else
amateusz 0:a7280a6c3c9b 53 return false;
amateusz 0:a7280a6c3c9b 54 }
amateusz 0:a7280a6c3c9b 55
amateusz 0:a7280a6c3c9b 56 float BH1750::_readSingle() {
amateusz 0:a7280a6c3c9b 57 float measurement;
amateusz 0:a7280a6c3c9b 58 // measurement switch
amateusz 0:a7280a6c3c9b 59 switch(_currentMode) {
amateusz 0:a7280a6c3c9b 60 case ONETIME_L_RES_CMD:
amateusz 0:a7280a6c3c9b 61 _sendCommand(_currentMode);
amateusz 0:a7280a6c3c9b 62 _waitForMeasurement = L_RES_MEASUREMENT_TIME;
amateusz 0:a7280a6c3c9b 63 break;
amateusz 0:a7280a6c3c9b 64 case ONETIME_H_RES_CMD:
amateusz 0:a7280a6c3c9b 65 _sendCommand(_currentMode);
amateusz 0:a7280a6c3c9b 66 _waitForMeasurement = H_RES_MEASUREMENT_TIME;
amateusz 0:a7280a6c3c9b 67 break;
amateusz 0:a7280a6c3c9b 68 case ONETIME_H2_RES_CMD:
amateusz 0:a7280a6c3c9b 69 _sendCommand(_currentMode);
amateusz 0:a7280a6c3c9b 70 _waitForMeasurement = H_RES_MEASUREMENT_TIME;
amateusz 0:a7280a6c3c9b 71 break;
amateusz 0:a7280a6c3c9b 72 case CONTINOUS_L_RES_CMD:
amateusz 0:a7280a6c3c9b 73 _waitForMeasurement = L_RES_MEASUREMENT_TIME;
amateusz 0:a7280a6c3c9b 74 break;
amateusz 0:a7280a6c3c9b 75 case CONTINOUS_H_RES_CMD:
amateusz 0:a7280a6c3c9b 76 _waitForMeasurement = H_RES_MEASUREMENT_TIME;
amateusz 0:a7280a6c3c9b 77 break;
amateusz 0:a7280a6c3c9b 78 case CONTINOUS_H2_RES_CMD:
amateusz 0:a7280a6c3c9b 79 _waitForMeasurement = H_RES_MEASUREMENT_TIME;
amateusz 0:a7280a6c3c9b 80 break;
amateusz 0:a7280a6c3c9b 81 }
amateusz 0:a7280a6c3c9b 82
amateusz 0:a7280a6c3c9b 83 _waitForMeasurement *= (unsigned int) ((float) _currentMtreg / (float) DEFAULTMTREG); // a bit too late, but nevermind
amateusz 0:a7280a6c3c9b 84 wait_ms(_waitForMeasurement);
amateusz 0:a7280a6c3c9b 85 measurement = (float)_readRaw();
amateusz 0:a7280a6c3c9b 86
amateusz 0:a7280a6c3c9b 87 // post-measurement switch
amateusz 0:a7280a6c3c9b 88 switch(_currentMode) {
amateusz 0:a7280a6c3c9b 89 case ONETIME_L_RES_CMD:
amateusz 0:a7280a6c3c9b 90 case ONETIME_H_RES_CMD:
amateusz 0:a7280a6c3c9b 91 case ONETIME_H2_RES_CMD:
amateusz 0:a7280a6c3c9b 92 break;
amateusz 0:a7280a6c3c9b 93
amateusz 0:a7280a6c3c9b 94 case CONTINOUS_L_RES_CMD:
amateusz 0:a7280a6c3c9b 95 break;
amateusz 0:a7280a6c3c9b 96 case CONTINOUS_H_RES_CMD:
amateusz 0:a7280a6c3c9b 97 break;
amateusz 0:a7280a6c3c9b 98 case CONTINOUS_H2_RES_CMD:
amateusz 0:a7280a6c3c9b 99 measurement /= 2.0;
amateusz 0:a7280a6c3c9b 100 break;
amateusz 0:a7280a6c3c9b 101 }
amateusz 0:a7280a6c3c9b 102
amateusz 0:a7280a6c3c9b 103 // printf("wait for meas value: %d\r\n", _waitForMeasurement);
amateusz 0:a7280a6c3c9b 104
amateusz 0:a7280a6c3c9b 105 measurement = measurement / 1.2 * (float) DEFAULTMTREG / (float) _currentMtreg;
amateusz 0:a7280a6c3c9b 106 return measurement;
amateusz 0:a7280a6c3c9b 107 }
amateusz 0:a7280a6c3c9b 108
amateusz 0:a7280a6c3c9b 109 void BH1750::power(bool state) {
amateusz 0:a7280a6c3c9b 110 if (state == true) {// power on
amateusz 0:a7280a6c3c9b 111 _sendCommand(powerOn_cmd);
amateusz 0:a7280a6c3c9b 112 } else { // power off}
amateusz 0:a7280a6c3c9b 113 _sendCommand(powerDown_cmd);
amateusz 0:a7280a6c3c9b 114 }
amateusz 0:a7280a6c3c9b 115 }
amateusz 0:a7280a6c3c9b 116
amateusz 0:a7280a6c3c9b 117 float BH1750::read() {
amateusz 0:a7280a6c3c9b 118 float measurement;
amateusz 0:a7280a6c3c9b 119 do {
amateusz 0:a7280a6c3c9b 120 measurement = _readSingle();
amateusz 0:a7280a6c3c9b 121 // printf("measurement do while: %.1f\r\n", measurement);
amateusz 0:a7280a6c3c9b 122 if (!_autoModeAdjustSwitch) break;
amateusz 0:a7280a6c3c9b 123 // else continue
amateusz 0:a7280a6c3c9b 124 // wait_ms(1.3*_waitForMeasurement);
amateusz 0:a7280a6c3c9b 125 } while(_autoModeAdjust(measurement));
amateusz 0:a7280a6c3c9b 126 return measurement;
amateusz 0:a7280a6c3c9b 127 }
amateusz 0:a7280a6c3c9b 128
amateusz 0:a7280a6c3c9b 129 void BH1750::setMode(const char mode) {
amateusz 0:a7280a6c3c9b 130 _sendCommand(mode);
amateusz 0:a7280a6c3c9b 131 _currentMode = mode;
amateusz 0:a7280a6c3c9b 132 wait(.01);
amateusz 0:a7280a6c3c9b 133 }
amateusz 0:a7280a6c3c9b 134
amateusz 0:a7280a6c3c9b 135 void BH1750::setMtreg(char newMtreg) {
amateusz 0:a7280a6c3c9b 136 // min. 31
amateusz 0:a7280a6c3c9b 137 // default 69
amateusz 0:a7280a6c3c9b 138 // max. 254
amateusz 0:a7280a6c3c9b 139 if (newMtreg >= 31 && newMtreg <= 254) {
amateusz 0:a7280a6c3c9b 140 _sendCommand((0b01000 << 3) | (newMtreg >> 5));
amateusz 0:a7280a6c3c9b 141 _sendCommand((0b011 << 5 ) | (newMtreg & 0b111));
amateusz 0:a7280a6c3c9b 142 _currentMtreg = newMtreg;
amateusz 0:a7280a6c3c9b 143 }
amateusz 0:a7280a6c3c9b 144 }