|
|
@@ -0,0 +1,180 @@
|
|
|
+/*
|
|
|
+ * BH1750.c
|
|
|
+ *
|
|
|
+ * The MIT License.
|
|
|
+ * Created on: 06.11.2022
|
|
|
+ * Author: Oleksii Kutuzov
|
|
|
+ *
|
|
|
+ * Ported from:
|
|
|
+ * https://github.com/lamik/Light_Sensors_STM32
|
|
|
+ */
|
|
|
+
|
|
|
+#include "BH1750.h"
|
|
|
+
|
|
|
+BH1750* bh1750_alloc() {
|
|
|
+ BH1750* bh1750 = malloc(sizeof(BH1750));
|
|
|
+ bh1750->mode = BH1750_DEFAULT_MODE;
|
|
|
+ bh1750->mt_reg = BH1750_DEFAULT_MTREG;
|
|
|
+ return bh1750;
|
|
|
+}
|
|
|
+
|
|
|
+void bh1750_free(BH1750* bh1750) {
|
|
|
+ furi_assert(bh1750);
|
|
|
+ free(bh1750);
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// Initialization.
|
|
|
+//
|
|
|
+BH1750_STATUS bh1750_init(BH1750* bh1750) {
|
|
|
+ if(BH1750_OK == bh1750_reset(bh1750)) {
|
|
|
+ if(BH1750_OK == bh1750_set_mt_reg(bh1750, BH1750_DEFAULT_MTREG)) // Set default value;
|
|
|
+ return BH1750_OK;
|
|
|
+ }
|
|
|
+ return BH1750_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// Reset all registers to default value.
|
|
|
+//
|
|
|
+BH1750_STATUS bh1750_reset(BH1750* bh1750) {
|
|
|
+ UNUSED(bh1750);
|
|
|
+ uint8_t command = 0x07;
|
|
|
+ bool status;
|
|
|
+
|
|
|
+ furi_hal_i2c_acquire(I2C_BUS);
|
|
|
+ status = furi_hal_i2c_tx(I2C_BUS, BH1750_ADDRESS, &command, 1, I2C_TIMEOUT);
|
|
|
+ furi_hal_i2c_release(I2C_BUS);
|
|
|
+
|
|
|
+ if(status) {
|
|
|
+ return BH1750_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return BH1750_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// Set the power state.
|
|
|
+// 0 - sleep, low power.
|
|
|
+// 1 - running.
|
|
|
+//
|
|
|
+BH1750_STATUS bh1750_set_power_state(BH1750* bh1750, uint8_t PowerOn) {
|
|
|
+ UNUSED(bh1750);
|
|
|
+ PowerOn = (PowerOn ? 1 : 0);
|
|
|
+ bool status;
|
|
|
+
|
|
|
+ furi_hal_i2c_acquire(I2C_BUS);
|
|
|
+ status = furi_hal_i2c_tx(I2C_BUS, BH1750_ADDRESS, &PowerOn, 1, I2C_TIMEOUT);
|
|
|
+ furi_hal_i2c_release(I2C_BUS);
|
|
|
+
|
|
|
+ if(status) {
|
|
|
+ return BH1750_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return BH1750_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// Set the mode of converting. Look into bh1750_mode enum.
|
|
|
+//
|
|
|
+BH1750_STATUS bh1750_set_mode(BH1750* bh1750, BH1750_mode mode) {
|
|
|
+ if(!((mode >> 4) || (mode >> 5))) {
|
|
|
+ return BH1750_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ if((mode & 0x0F) > 3) {
|
|
|
+ return BH1750_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool status;
|
|
|
+
|
|
|
+ bh1750->mode = mode;
|
|
|
+
|
|
|
+ furi_hal_i2c_acquire(I2C_BUS);
|
|
|
+ status = furi_hal_i2c_tx(I2C_BUS, BH1750_ADDRESS, &mode, 1, I2C_TIMEOUT);
|
|
|
+ furi_hal_i2c_release(I2C_BUS);
|
|
|
+
|
|
|
+ if(status) {
|
|
|
+ return BH1750_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return BH1750_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// Set the Measurement Time register. It allows to increase or decrease the sensitivity.
|
|
|
+//
|
|
|
+BH1750_STATUS bh1750_set_mt_reg(BH1750* bh1750, uint8_t mt_reg) {
|
|
|
+ if(mt_reg < 31 || mt_reg > 254) {
|
|
|
+ return BH1750_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ bh1750->mt_reg = mt_reg;
|
|
|
+
|
|
|
+ uint8_t tmp[2];
|
|
|
+ bool status;
|
|
|
+
|
|
|
+ tmp[0] = (0x40 | (mt_reg >> 5));
|
|
|
+ tmp[1] = (0x60 | (mt_reg & 0x1F));
|
|
|
+
|
|
|
+ furi_hal_i2c_acquire(I2C_BUS);
|
|
|
+ status = furi_hal_i2c_tx(I2C_BUS, BH1750_ADDRESS, &tmp[0], 1, I2C_TIMEOUT);
|
|
|
+ furi_hal_i2c_release(I2C_BUS);
|
|
|
+ if(!status) {
|
|
|
+ return BH1750_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ furi_hal_i2c_acquire(I2C_BUS);
|
|
|
+ status = furi_hal_i2c_tx(I2C_BUS, BH1750_ADDRESS, &tmp[1], 1, I2C_TIMEOUT);
|
|
|
+ furi_hal_i2c_release(I2C_BUS);
|
|
|
+ if(status) {
|
|
|
+ return BH1750_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ return BH1750_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// Trigger the conversion in manual modes.
|
|
|
+// For low resolution conversion time is typical 16 ms,
|
|
|
+// for high resolution 120 ms. You need to wait until read the measurement value.
|
|
|
+// There is no need to exit low power mode for manual conversion. It makes automatically.
|
|
|
+//
|
|
|
+BH1750_STATUS bh1750_trigger_manual_conversion(BH1750* bh1750) {
|
|
|
+ if(BH1750_OK == bh1750_set_mode(bh1750, bh1750->mode)) {
|
|
|
+ return BH1750_OK;
|
|
|
+ }
|
|
|
+ return BH1750_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+// Read the converted value and calculate the result.
|
|
|
+//
|
|
|
+BH1750_STATUS bh1750_read_light(BH1750* bh1750, float* result) {
|
|
|
+ uint8_t mt_reg = bh1750->mt_reg;
|
|
|
+ BH1750_mode mode = bh1750->mode;
|
|
|
+ float result_tmp;
|
|
|
+ uint8_t rcv[2];
|
|
|
+ bool status;
|
|
|
+
|
|
|
+ furi_hal_i2c_acquire(I2C_BUS);
|
|
|
+ status = furi_hal_i2c_rx(I2C_BUS, BH1750_ADDRESS, rcv, 2, I2C_TIMEOUT);
|
|
|
+ furi_hal_i2c_release(I2C_BUS);
|
|
|
+
|
|
|
+ if(status) {
|
|
|
+ result_tmp = (rcv[0] << 8) | (rcv[1]);
|
|
|
+
|
|
|
+ if(mt_reg != BH1750_DEFAULT_MTREG) {
|
|
|
+ result_tmp *= (float)((uint8_t)BH1750_DEFAULT_MTREG / (float)mt_reg);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(mode == ONETIME_HIGH_RES_MODE_2 || mode == CONTINUOUS_HIGH_RES_MODE_2) {
|
|
|
+ result_tmp /= 2.0;
|
|
|
+ }
|
|
|
+
|
|
|
+ *result = result_tmp / BH1750_CONVERSION_FACTOR;
|
|
|
+
|
|
|
+ return BH1750_OK;
|
|
|
+ }
|
|
|
+ return BH1750_ERROR;
|
|
|
+}
|