diff --git a/applications/external/lightmeter/README.md b/applications/external/lightmeter/README.md index d9c071e67..e90630c03 100644 --- a/applications/external/lightmeter/README.md +++ b/applications/external/lightmeter/README.md @@ -1,21 +1,17 @@ -# flipperzero-lightmeter +## Lightmeter app for photography -[Original link](https://github.com/oleksiikutuzov/flipperzero-lightmeter) +An application that suggests settings for your manual camera based on the reading of the ambient light sensor. Can also be used in a pure lux meter mode. +## Supported sensors - +- BH1750 +- MAX44009 ## Wiring -``` -VCC -> 3.3V -GND -> GND -SCL -> C0 -SDA -> C1 -``` - -## TODO -- [ ] Save settings to sd card - -## References -App inspired by [lightmeter](https://github.com/vpominchuk/lightmeter) project for Arduino by [vpominchuk](https://github.com/vpominchuk). +| Sensor | Flipper Zero | +| ------ | ------------ | +| VCC | 3.3V | +| GND | GND | +| SCL | C0 | +| SDA | C1 | diff --git a/applications/external/lightmeter/application.fam b/applications/external/lightmeter/application.fam index fc46550fe..dcdf0d9f9 100644 --- a/applications/external/lightmeter/application.fam +++ b/applications/external/lightmeter/application.fam @@ -1,6 +1,6 @@ App( appid="lightmeter", - name="[BH1750] Lightmeter", + name="Lightmeter", apptype=FlipperAppType.EXTERNAL, entry_point="lightmeter_app", requires=[ @@ -8,6 +8,7 @@ App( ], stack_size=1 * 1024, order=90, + fap_version=(1, 1), fap_icon="lightmeter.png", fap_category="GPIO", fap_private_libs=[ @@ -18,9 +19,16 @@ App( "BH1750.c", ], ), + Lib( + name="MAX44009", + cincludes=["."], + sources=[ + "MAX44009.c", + ], + ), ], + fap_description="Lightmeter app for photography", + fap_author="Oleksii Kutuzov", + fap_weburl="https://github.com/oleksiikutuzov/flipperzero-lightmeter", fap_icon_assets="icons", - fap_author="@oleksiikutuzov", - fap_version="1.0", - fap_description="Lightmeter app for photography based on BH1750 sensor", ) diff --git a/applications/external/lightmeter/gui/scenes/lightmeter_scene_config.c b/applications/external/lightmeter/gui/scenes/lightmeter_scene_config.c index 3d6bd5803..aafa1f843 100644 --- a/applications/external/lightmeter/gui/scenes/lightmeter_scene_config.c +++ b/applications/external/lightmeter/gui/scenes/lightmeter_scene_config.c @@ -51,12 +51,18 @@ static const char* lux_only[] = { [LUX_ONLY_ON] = "On", }; +static const char* sensor_type[] = { + [SENSOR_BH1750] = "BH1750", + [SENSOR_MAX44009] = "MAX44009", +}; + enum LightMeterSubmenuIndex { LightMeterSubmenuIndexISO, LightMeterSubmenuIndexND, LightMeterSubmenuIndexDome, LightMeterSubmenuIndexBacklight, LightMeterSubmenuIndexLuxMeter, + LightMeterSubmenuIndexSensorType, LightMeterSubmenuIndexHelp, LightMeterSubmenuIndexAbout, }; @@ -127,6 +133,17 @@ static void lux_only_cb(VariableItem* item) { lightmeter_app_set_config(app, config); } +static void sensor_type_cb(VariableItem* item) { + LightMeterApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, sensor_type[index]); + + LightMeterConfig* config = app->config; + config->sensor_type = index; + lightmeter_app_set_config(app, config); +} + static void ok_cb(void* context, uint32_t index) { LightMeterApp* app = context; UNUSED(app); @@ -173,6 +190,11 @@ void lightmeter_scene_config_on_enter(void* context) { variable_item_set_current_value_index(item, config->lux_only); variable_item_set_current_value_text(item, lux_only[config->lux_only]); + item = variable_item_list_add( + var_item_list, "Sensor", COUNT_OF(sensor_type), sensor_type_cb, app); + variable_item_set_current_value_index(item, config->sensor_type); + variable_item_set_current_value_text(item, sensor_type[config->sensor_type]); + item = variable_item_list_add(var_item_list, "Help and Pinout", 0, NULL, NULL); item = variable_item_list_add(var_item_list, "About", 0, NULL, NULL); diff --git a/applications/external/lightmeter/gui/scenes/lightmeter_scene_help.c b/applications/external/lightmeter/gui/scenes/lightmeter_scene_help.c index 0441f0925..a5688ee2f 100644 --- a/applications/external/lightmeter/gui/scenes/lightmeter_scene_help.c +++ b/applications/external/lightmeter/gui/scenes/lightmeter_scene_help.c @@ -6,7 +6,8 @@ void lightmeter_scene_help_on_enter(void* context) { FuriString* temp_str; temp_str = furi_string_alloc(); furi_string_printf( - temp_str, "App works with BH1750\nambient light sensor\nconnected via I2C interface\n\n"); + temp_str, + "App works with BH1750 and MAX44409 ambient light sensor connected via I2C interface\n\n"); furi_string_cat(temp_str, "\e#Pinout:\r\n"); furi_string_cat( temp_str, diff --git a/applications/external/lightmeter/gui/scenes/lightmeter_scene_main.c b/applications/external/lightmeter/gui/scenes/lightmeter_scene_main.c index 8ba474461..3b4789e99 100644 --- a/applications/external/lightmeter/gui/scenes/lightmeter_scene_main.c +++ b/applications/external/lightmeter/gui/scenes/lightmeter_scene_main.c @@ -9,6 +9,7 @@ static void lightmeter_scene_main_on_left(void* context) { void lightmeter_scene_main_on_enter(void* context) { LightMeterApp* app = context; + lightmeter_app_i2c_init_sensor(context); lightmeter_main_view_set_left_callback(app->main_view, lightmeter_scene_main_on_left, app); view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewMainView); } @@ -39,5 +40,5 @@ bool lightmeter_scene_main_on_event(void* context, SceneManagerEvent event) { } void lightmeter_scene_main_on_exit(void* context) { - UNUSED(context); + lightmeter_app_i2c_deinit_sensor(context); } diff --git a/applications/external/lightmeter/lib/MAX44009/MAX44009.c b/applications/external/lightmeter/lib/MAX44009/MAX44009.c new file mode 100644 index 000000000..211f6a9ba --- /dev/null +++ b/applications/external/lightmeter/lib/MAX44009/MAX44009.c @@ -0,0 +1,27 @@ +#include +#include +#include + +void max44009_init() { + furi_hal_i2c_acquire(I2C_BUS); + furi_hal_i2c_write_reg_8(I2C_BUS, MAX44009_ADDR, + MAX44009_REG_CONFIG, MAX44009_REG_CONFIG_CONT_MODE, I2C_TIMEOUT); + furi_hal_i2c_release(I2C_BUS); +} + +int max44009_read_light(float* result) { + uint8_t data_one = 0; + uint8_t exp, mantissa; + int status; + + furi_hal_i2c_acquire(I2C_BUS); + furi_hal_i2c_read_reg_8(I2C_BUS, MAX44009_ADDR, MAX44009_REG_LUX_HI, &data_one, I2C_TIMEOUT); + exp = (data_one & MAX44009_REG_LUX_HI_EXP_MASK) >> 4; + mantissa = (data_one & MAX44009_REG_LUX_HI_MANT_HI_MASK) << 4; + status = furi_hal_i2c_read_reg_8(I2C_BUS, MAX44009_ADDR, MAX44009_REG_LUX_LO, &data_one, I2C_TIMEOUT); + mantissa |= (data_one & MAX44009_REG_LUX_LO_MANT_LO_MASK); + furi_hal_i2c_release(I2C_BUS); + *result = (float)pow(2, exp) * mantissa * 0.045; + FURI_LOG_D("MAX44009", "exp %d, mant %d, lux %f", exp, mantissa, (double)*result); + return status; +} \ No newline at end of file diff --git a/applications/external/lightmeter/lib/MAX44009/MAX44009.h b/applications/external/lightmeter/lib/MAX44009/MAX44009.h new file mode 100644 index 000000000..fb350653d --- /dev/null +++ b/applications/external/lightmeter/lib/MAX44009/MAX44009.h @@ -0,0 +1,26 @@ +#include +#include + +#pragma once + +// I2C BUS +#define I2C_BUS &furi_hal_i2c_handle_external +#define I2C_TIMEOUT 10 + +#define MAX44009_ADDR (0x4A << 1) + +#define MAX44009_REG_INT_STATUS 0x00 +#define MAX44009_REG_INT_EN 0x01 +#define MAX44009_REG_CONFIG 0x02 +#define MAX44009_REG_CONFIG_CONT_MODE (1 << 7) +#define MAX44009_REG_LUX_HI 0x03 +#define MAX44009_REG_LUX_HI_EXP_MASK 0xF0 +#define MAX44009_REG_LUX_HI_MANT_HI_MASK 0x0F +#define MAX44009_REG_LUX_LO 0x04 +#define MAX44009_REG_LUX_LO_MANT_LO_MASK 0x0F +#define MAX44009_REG_THRESH_HI 0x05 +#define MAX44009_REG_THRESH_LO 0x06 +#define MAX44009_REG_INT_TIME 0x07 + +void max44009_init(); +int max44009_read_light(float* result); diff --git a/applications/external/lightmeter/lightmeter.c b/applications/external/lightmeter/lightmeter.c index 07661d2d4..b128e334f 100644 --- a/applications/external/lightmeter/lightmeter.c +++ b/applications/external/lightmeter/lightmeter.c @@ -27,11 +27,6 @@ static void lightmeter_tick_event_callback(void* context) { LightMeterApp* lightmeter_app_alloc(uint32_t first_scene) { LightMeterApp* app = malloc(sizeof(LightMeterApp)); - // Sensor - bh1750_set_power_state(1); - bh1750_init(); - bh1750_set_mode(ONETIME_HIGH_RES_MODE); - // Set default values to config app->config = malloc(sizeof(LightMeterConfig)); app->config->iso = DEFAULT_ISO; @@ -117,8 +112,6 @@ void lightmeter_app_free(LightMeterApp* app) { } furi_record_close(RECORD_NOTIFICATION); - bh1750_set_power_state(0); - free(app->config); free(app); } @@ -138,6 +131,38 @@ void lightmeter_app_set_config(LightMeterApp* context, LightMeterConfig* config) app->config = config; } +void lightmeter_app_i2c_init_sensor(LightMeterApp* context) { + LightMeterApp* app = context; + switch(app->config->sensor_type) { + case SENSOR_BH1750: + bh1750_set_power_state(1); + bh1750_init(); + bh1750_set_mode(ONETIME_HIGH_RES_MODE); + break; + case SENSOR_MAX44009: + max44009_init(); + break; + default: + FURI_LOG_E(TAG, "Invalid sensor type %d", app->config->sensor_type); + return; + } +} + +void lightmeter_app_i2c_deinit_sensor(LightMeterApp* context) { + LightMeterApp* app = context; + switch(app->config->sensor_type) { + case SENSOR_BH1750: + bh1750_set_power_state(0); + break; + case SENSOR_MAX44009: + // nothing + break; + default: + FURI_LOG_E(TAG, "Invalid sensor type %d", app->config->sensor_type); + return; + } +} + void lightmeter_app_i2c_callback(LightMeterApp* context) { LightMeterApp* app = context; @@ -145,16 +170,18 @@ void lightmeter_app_i2c_callback(LightMeterApp* context) { float lux = 0; bool response = 0; - if(bh1750_trigger_manual_conversion() == BH1750_OK) response = 1; - - if(response) { - bh1750_read_light(&lux); - - if(main_view_get_dome(app->main_view)) lux *= DOME_COEFFICIENT; - - EV = lux2ev(lux); + if(app->config->sensor_type == SENSOR_BH1750) { + if(bh1750_trigger_manual_conversion() == BH1750_OK) { + bh1750_read_light(&lux); + response = 1; + } + } else if(app->config->sensor_type == SENSOR_MAX44009) { + if(max44009_read_light(&lux)) response = 1; } + if(main_view_get_dome(app->main_view)) lux *= DOME_COEFFICIENT; + EV = lux2ev(lux); + main_view_set_lux(app->main_view, lux); main_view_set_EV(app->main_view, EV); main_view_set_response(app->main_view, response); diff --git a/applications/external/lightmeter/lightmeter.h b/applications/external/lightmeter/lightmeter.h index 2558be3c5..75bc09b02 100644 --- a/applications/external/lightmeter/lightmeter.h +++ b/applications/external/lightmeter/lightmeter.h @@ -18,6 +18,7 @@ #include "lightmeter_config.h" #include +#include typedef struct { int iso; @@ -26,6 +27,7 @@ typedef struct { int dome; int backlight; int lux_only; + int sensor_type; } LightMeterConfig; typedef struct { @@ -55,4 +57,6 @@ typedef enum { void lightmeter_app_set_config(LightMeterApp* context, LightMeterConfig* config); +void lightmeter_app_i2c_init_sensor(LightMeterApp* context); +void lightmeter_app_i2c_deinit_sensor(LightMeterApp* context); void lightmeter_app_i2c_callback(LightMeterApp* context); diff --git a/applications/external/lightmeter/lightmeter_config.h b/applications/external/lightmeter/lightmeter_config.h index 5edbdce0a..d46f0cd38 100644 --- a/applications/external/lightmeter/lightmeter_config.h +++ b/applications/external/lightmeter/lightmeter_config.h @@ -1,6 +1,6 @@ #pragma once -#define LM_VERSION_APP "0.7" +#define LM_VERSION_APP "1.1" #define LM_DEVELOPED "Oleksii Kutuzov" #define LM_GITHUB "https://github.com/oleksiikutuzov/flipperzero-lightmeter" @@ -105,4 +105,9 @@ typedef enum { LUX_ONLY_ON, } LightMeterLuxOnlyMode; +typedef enum { + SENSOR_BH1750, + SENSOR_MAX44009, +} LightMeterSensorType; + typedef enum { BACKLIGHT_AUTO, BACKLIGHT_ON } LightMeterBacklight;