diff --git a/app/src/applications/compass/compass_app.c b/app/src/applications/compass/compass_app.c index 243c40e5..47d74ed9 100644 --- a/app/src/applications/compass/compass_app.c +++ b/app/src/applications/compass/compass_app.c @@ -15,6 +15,7 @@ static void compass_app_stop(void); // Functions related to app functionality static void timer_callback(lv_timer_t *timer); +static void on_start_calibration(void); LV_IMG_DECLARE(move); @@ -31,13 +32,9 @@ static uint32_t cal_start_ms; static void compass_app_start(lv_obj_t *root, lv_group_t *group) { - compass_ui_show(root); + compass_ui_show(root, on_start_calibration); refresh_timer = lv_timer_create(timer_callback, CONFIG_DEFAULT_CONFIGURATION_COMPASS_REFRESH_INTERVAL_MS, NULL); zsw_magnetometer_set_enable(true); - zsw_magnetometer_start_calibration(); - is_calibrating = true; - cal_start_ms = lv_tick_get(); - zsw_popup_show("Calibration", "Spin around 360 degrees for 10.", NULL, 100, false); } static void compass_app_stop(void) @@ -51,6 +48,15 @@ static void compass_app_stop(void) } } +static void on_start_calibration(void) +{ + zsw_magnetometer_start_calibration(); + is_calibrating = true; + cal_start_ms = lv_tick_get(); + zsw_popup_show("Calibration", + "Spin the watch around 360 degrees\nand do some random rotations in 3D space for 10 seconds.", NULL, 10, false); +} + static void timer_callback(lv_timer_t *timer) { if (is_calibrating && diff --git a/app/src/applications/compass/compass_ui.c b/app/src/applications/compass/compass_ui.c index 5f3ad47b..010356cd 100644 --- a/app/src/applications/compass/compass_ui.c +++ b/app/src/applications/compass/compass_ui.c @@ -7,8 +7,20 @@ static lv_obj_t *compass_panel; static lv_obj_t *compass_img; static lv_obj_t *compass_label; +static on_start_calibraion_cb_t start_cal; + +static void calibrate_button_event_cb(lv_event_t *e) +{ + if (start_cal) { + start_cal(); + } +} + static void create_ui(lv_obj_t *parent) { + lv_obj_t *cal_btn; + lv_obj_t *cal_btn_label; + LV_IMG_DECLARE(cardinal_point) compass_panel = lv_obj_create(parent); lv_obj_set_width(compass_panel, 240); @@ -19,6 +31,16 @@ static void create_ui(lv_obj_t *parent) lv_obj_set_style_bg_opa(compass_panel, LV_OPA_TRANSP, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_border_width(compass_panel, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + cal_btn = lv_btn_create(compass_panel); + lv_obj_set_style_pad_all(cal_btn, 3, LV_PART_MAIN); + lv_obj_set_align(cal_btn, LV_ALIGN_CENTER); + lv_obj_set_pos(cal_btn, 0, 80); + lv_obj_set_size(cal_btn, 70, 25); + lv_obj_set_style_bg_color(cal_btn, lv_palette_main(LV_PALETTE_ORANGE), LV_PART_MAIN | LV_STATE_DEFAULT); + cal_btn_label = lv_label_create(cal_btn); + lv_label_set_text(cal_btn_label, "Calibrate"); + lv_obj_add_event_cb(cal_btn, calibrate_button_event_cb, LV_EVENT_CLICKED, NULL); + compass_img = lv_img_create(compass_panel); lv_img_set_src(compass_img, &cardinal_point); lv_obj_set_width(compass_img, LV_SIZE_CONTENT); @@ -36,7 +58,7 @@ static void create_ui(lv_obj_t *parent) lv_obj_set_style_text_opa(compass_label, 255, LV_PART_MAIN | LV_STATE_DEFAULT); } -void compass_ui_show(lv_obj_t *root) +void compass_ui_show(lv_obj_t *root, on_start_calibraion_cb_t start_cal_cb) { assert(root_page == NULL); @@ -48,6 +70,8 @@ void compass_ui_show(lv_obj_t *root) lv_obj_set_size(root_page, LV_PCT(100), LV_PCT(100)); lv_obj_clear_flag(root_page, LV_OBJ_FLAG_SCROLLABLE); + start_cal = start_cal_cb; + create_ui(root_page); } diff --git a/app/src/applications/compass/compass_ui.h b/app/src/applications/compass/compass_ui.h index 50cbe5cf..9ed5b9ea 100644 --- a/app/src/applications/compass/compass_ui.h +++ b/app/src/applications/compass/compass_ui.h @@ -3,7 +3,9 @@ #include #include -void compass_ui_show(lv_obj_t *root); +typedef void(*on_start_calibraion_cb_t)(void); + +void compass_ui_show(lv_obj_t *root, on_start_calibraion_cb_t start_cal_cb); void compass_ui_remove(void); diff --git a/app/src/sensors/zsw_magnetometer.c b/app/src/sensors/zsw_magnetometer.c index af30bc8f..58148dad 100644 --- a/app/src/sensors/zsw_magnetometer.c +++ b/app/src/sensors/zsw_magnetometer.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,16 @@ LOG_MODULE_REGISTER(zsw_magnetometer, CONFIG_ZSW_SENSORS_LOG_LEVEL); #define M_PI 3.14159265358979323846 #endif +#define SETTINGS_NAME_MAGN "magn" +#define SETTINGS_KEY_CALIB "calibr" +#define SETTINGS_MAGN_CALIB SETTINGS_NAME_MAGN "/" SETTINGS_KEY_CALIB + +typedef struct { + float offset_x; + float offset_y; + float offset_z; +} magn_calib_data_t; + static double last_heading; static double last_x; static double last_y; @@ -30,9 +41,7 @@ static double min_x; static double min_y; static double min_z; static bool is_calibrating; -static float offset_x; -static float offset_y; -static float offset_z; +static magn_calib_data_t calibration_data; static void zbus_periodic_slow_callback(const struct zbus_channel *chan); @@ -116,15 +125,33 @@ static void lis2mdl_trigger_handler(const struct device *dev, } } - last_x = last_x - offset_x; - last_y = last_y - offset_y; - last_z = last_z - offset_z; + last_x = last_x - calibration_data.offset_x; + last_y = last_y - calibration_data.offset_y; + last_z = last_z - calibration_data.offset_z; last_heading = xyz_to_rotation(last_x, last_y, last_z); LOG_DBG("Rotation: %f", last_heading); } +static int magn_cal_load(const char *p_key, size_t len, + settings_read_cb read_cb, void *p_cb_arg, void *p_param) +{ + ARG_UNUSED(p_key); + + if (len != sizeof(magn_calib_data_t)) { + LOG_ERR("Invalid length of magn calibration data"); + return -EINVAL; + } + + if (read_cb(p_cb_arg, &calibration_data, len) != sizeof(magn_calib_data_t)) { + LOG_ERR("Error reading magn calibration data"); + return -EIO; + } + + return 0; +} + int zsw_magnetometer_init(void) { if (!device_is_ready(magnetometer)) { @@ -132,6 +159,16 @@ int zsw_magnetometer_init(void) return -ENODEV; } + if (settings_subsys_init()) { + LOG_ERR("Error during settings_subsys_init!"); + return -EFAULT; + } + + if (settings_load_subtree_direct(SETTINGS_MAGN_CALIB, magn_cal_load, NULL)) { + LOG_ERR("Error during settings_load_subtree!"); + return -EFAULT; + } + struct sensor_trigger trig; struct sensor_value odr_attr; @@ -205,9 +242,11 @@ int zsw_magnetometer_stop_calibration(void) } is_calibrating = false; - offset_x = (max_x + min_x) / 2; - offset_y = (max_y + min_y) / 2; - offset_z = (max_z + min_z) / 2; + calibration_data.offset_x = (max_x + min_x) / 2; + calibration_data.offset_y = (max_y + min_y) / 2; + calibration_data.offset_z = (max_z + min_z) / 2; + + settings_save_one(SETTINGS_MAGN_CALIB, &calibration_data, sizeof(magn_calib_data_t)); return 0; }