diff --git a/README.md b/README.md
index 6e46c84..7afcbb5 100644
--- a/README.md
+++ b/README.md
@@ -241,9 +241,9 @@ It can be used to verify some of the basic features of a BNO08x device.
(back to top)
### Adding Tests
-Tests are implemented with the [esp-idf unity unit testing component](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/unit-tests.html).
+Tests are implemented with the [unity unit testing component](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/unit-tests.html).
-To add a test, create a new .cpp file, or modify one of the existing ones in `esp32_BNO08x/test/()`.
+To add a test, create a new .cpp file, or modify one of the existing ones in `esp32_BNO08x/test/`.
Follow the existing test structure as an example, use the `TEST_CASE(){}` macro.
Any tests added will automatically be detected at build time.
diff --git a/include/BNO08x.hpp b/include/BNO08x.hpp
index f8033ea..5b2cd46 100644
--- a/include/BNO08x.hpp
+++ b/include/BNO08x.hpp
@@ -69,7 +69,7 @@ class BNO08x
void enable_tap_detector(uint32_t time_between_reports);
void enable_step_counter(uint32_t time_between_reports);
void enable_stability_classifier(uint32_t time_between_reports);
- void enable_activity_classifier(uint32_t time_between_reports, uint32_t activities_to_enable, uint8_t (&activity_confidence_vals)[9]);
+ void enable_activity_classifier(uint32_t time_between_reports, ActivityClassifierEnable activities_to_enable, uint8_t (&activity_confidence_vals)[9]);
void enable_raw_mems_gyro(uint32_t time_between_reports);
void enable_raw_mems_accelerometer(uint32_t time_between_reports);
void enable_raw_mems_magnetometer(uint32_t time_between_reports);
@@ -179,8 +179,8 @@ class BNO08x
uint8_t get_tap_detector();
uint16_t get_step_count();
- int8_t get_stability_classifier();
- uint8_t get_activity_classifier();
+ Stability get_stability_classifier();
+ Activity get_activity_classifier();
// Metadata functions
int16_t get_Q1(uint16_t record_ID);
@@ -203,18 +203,6 @@ class BNO08x
static const constexpr uint16_t FRS_RECORD_ID_ROTATION_VECTOR =
0xE30BU; ///< Rotation vector record ID, to be passed in metadata functions like get_Q1()
- // Activity classifier bits
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_UNKNOWN_EN = (1U << 0U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_IN_VEHICLE_EN = (1U << 1U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_ON_BICYCLE_EN = (1U << 2U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_ON_FOOT_EN = (1U << 3U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_STILL_EN = (1U << 4U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_TILTING_EN = (1U << 5U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_WALKING_EN = (1U << 6U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_RUNNING_EN = (1U << 7U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_ON_STAIRS_EN = (1U << 8U);
- static const constexpr uint16_t ACTIVITY_CLASSIFIER_ALL_EN = 0x1FU;
-
static const constexpr uint8_t TARE_AXIS_ALL = 0x07U; ///< Tare all axes (used with tare now command)
static const constexpr uint8_t TARE_AXIS_Z = 0x04U; ///< Tar yaw axis only (used with tare now command)
diff --git a/include/BNO08xTestHelper.hpp b/include/BNO08xTestHelper.hpp
index 6364131..8f728ff 100644
--- a/include/BNO08xTestHelper.hpp
+++ b/include/BNO08xTestHelper.hpp
@@ -7,7 +7,6 @@
#include "stdio.h"
#include "BNO08x.hpp"
-
/**
* @class BNO08xTestHelper
* @brief BNO08x unit test helper class.
@@ -73,8 +72,8 @@ class BNO08xTestHelper
uint16_t raw_mems_gyro_z;
uint16_t step_count;
- uint8_t stability_classifier;
- uint8_t activity_classifier;
+ Stability stability_classifier;
+ Activity activity_classifier;
} imu_report_data_t;
@@ -602,8 +601,8 @@ class BNO08xTestHelper
test_imu->tap_detector = TEST_VAL_UINT8;
test_imu->step_count = TEST_VAL_UINT16;
- test_imu->stability_classifier = TEST_VAL_UINT8;
- test_imu->activity_classifier = TEST_VAL_UINT8;
+ test_imu->stability_classifier = static_cast(Stability::UNDEFINED);
+ test_imu->activity_classifier = static_cast(Activity::UNDEFINED);
test_imu->mems_raw_accel_X = TEST_VAL_UINT16;
test_imu->mems_raw_accel_Y = TEST_VAL_UINT16;
@@ -638,7 +637,67 @@ class BNO08xTestHelper
case BNO08xAccuracy::UNDEFINED:
return "UNDEFINED";
default:
- return "UNKNOWN"; // For undefined cases or future-proofing
+ return "INVALID";
}
};
+
+ /**
+ * @brief Converts Stability enum class object to string.
+ *
+ * @param stability Stability object to convert to string.
+ *
+ * @return The resulting string conversion.
+ */
+ static const char* BNO08xStability_to_str(Stability stability)
+ {
+ switch (stability)
+ {
+ case Stability::UNKNOWN:
+ return "UNKNOWN";
+ case Stability::ON_TABLE:
+ return "ON TABLE";
+ case Stability::STATIONARY:
+ return "STATIONARY";
+ case Stability::UNDEFINED:
+ return "UNDEFINED";
+ default:
+ return "INVALID";
+ }
+ }
+
+ /**
+ * @brief Converts Activity enum class object to string.
+ *
+ * @param activity Activity object to convert to string.
+ *
+ * @return The resulting string conversion.
+ */
+ static const char* BNO08xActivity_to_str(Activity activity)
+ {
+ switch (activity)
+ {
+ case Activity::UNKNOWN:
+ return "UNKNOWN";
+ case Activity::IN_VEHICLE:
+ return "IN VEHICLE";
+ case Activity::ON_BICYCLE:
+ return "ON BICYCLE";
+ case Activity::ON_FOOT:
+ return "ON FOOT";
+ case Activity::STILL:
+ return "STILL";
+ case Activity::TILTING:
+ return "TILTING";
+ case Activity::WALKING:
+ return "WALKING";
+ case Activity::RUNNING:
+ return "RUNNING";
+ case Activity::ON_STAIRS:
+ return "ON STAIRS";
+ case Activity::UNDEFINED:
+ return "UNDEFINED";
+ default:
+ return "INVALID";
+ }
+ }
};
\ No newline at end of file
diff --git a/include/BNO08xTestSuite.hpp b/include/BNO08xTestSuite.hpp
index 9f93250..f20f0ae 100644
--- a/include/BNO08xTestSuite.hpp
+++ b/include/BNO08xTestSuite.hpp
@@ -13,7 +13,6 @@
#include "unity.h"
#include "BNO08xTestHelper.hpp"
-
/**
* @class BNO08xTestSuite
* @brief BNO08x unit test launch point class.
@@ -38,6 +37,7 @@ class BNO08xTestSuite
run_init_deinit_tests(false);
run_single_report_tests(false);
run_multi_report_tests(false);
+ run_callback_tests(false);
UNITY_END();
}
@@ -86,4 +86,19 @@ class BNO08xTestSuite
print_end_tests_banner("multi_report_tests");
}
+
+ static void run_callback_tests(bool call_unity_end_begin = true)
+ {
+ print_begin_tests_banner("run_callback_tests");
+
+ if (call_unity_end_begin)
+ UNITY_BEGIN();
+
+ unity_run_tests_by_tag("[CallbackTests]", false);
+
+ if (call_unity_end_begin)
+ UNITY_END();
+
+ print_end_tests_banner("run_callback_tests");
+ }
};
\ No newline at end of file
diff --git a/include/BNO08x_global_types.hpp b/include/BNO08x_global_types.hpp
index e84f34b..6bda742 100644
--- a/include/BNO08x_global_types.hpp
+++ b/include/BNO08x_global_types.hpp
@@ -30,6 +30,45 @@ enum class BNO08xResetReason
};
using IMUResetReason = BNO08xResetReason; // legacy version compatibility
+/// @brief Activity Classifier enable bits passed to enable_activity_classifier()
+enum class ActivityClassifierEnable
+{
+ UNKNOWN = (1U << 0U),
+ IN_VEHICLE = (1U << 1U),
+ ON_BICYCLE = (1U << 2U),
+ ON_FOOT = (1U << 3U),
+ STILL = (1U << 4U),
+ TILTING = (1U << 5U),
+ WALKING = (1U << 6U),
+ RUNNING = (1U << 7U),
+ ON_STAIRS = (1U << 8U),
+ ALL = 0x1FU
+};
+
+/// @brief Activity states returned from get_activity_classifier()
+enum class Activity
+{
+ UNKNOWN = 0, // 0 = unknown
+ IN_VEHICLE = 1, // 1 = in vehicle
+ ON_BICYCLE = 2, // 2 = on bicycle
+ ON_FOOT = 3, // 3 = on foot
+ STILL = 4, // 4 = still
+ TILTING = 5, // 5 = tilting
+ WALKING = 6, // 6 = walking
+ RUNNING = 7, // 7 = running
+ ON_STAIRS = 8, // 8 = on stairs
+ UNDEFINED = 9 // used for unit tests
+};
+
+/// @brief Stability states returned from get_stability_classifier()
+enum class Stability
+{
+ UNKNOWN = 0, // 0 = unknown
+ ON_TABLE = 1, // 1 = on table
+ STATIONARY = 2, // 2 = stationary
+ UNDEFINED = 3 // used for unit tests
+};
+
/// @brief IMU configuration settings passed into constructor
typedef struct bno08x_config_t
{
diff --git a/source/BNO08x.cpp b/source/BNO08x.cpp
index b1bea04..8b43499 100644
--- a/source/BNO08x.cpp
+++ b/source/BNO08x.cpp
@@ -2173,10 +2173,12 @@ void BNO08x::enable_stability_classifier(uint32_t time_between_reports)
* @param activity_confidence_vals Returned activity level confidences.
* @return void, nothing to return
*/
-void BNO08x::enable_activity_classifier(uint32_t time_between_reports, uint32_t activities_to_enable, uint8_t (&activity_confidence_vals)[9])
+void BNO08x::enable_activity_classifier(
+ uint32_t time_between_reports, ActivityClassifierEnable activities_to_enable, uint8_t (&activity_confidence_vals)[9])
{
activity_confidences = activity_confidence_vals; // Store pointer to array
- enable_report(SENSOR_REPORT_ID_PERSONAL_ACTIVITY_CLASSIFIER, time_between_reports, EVT_GRP_RPT_ACTIVITY_CLASSIFIER_BIT, activities_to_enable);
+ enable_report(SENSOR_REPORT_ID_PERSONAL_ACTIVITY_CLASSIFIER, time_between_reports, EVT_GRP_RPT_ACTIVITY_CLASSIFIER_BIT,
+ static_cast(activities_to_enable));
}
/**
@@ -3301,9 +3303,9 @@ uint16_t BNO08x::get_step_count()
*
* @return The current stability (0 = unknown, 1 = on table, 2 = stationary)
*/
-int8_t BNO08x::get_stability_classifier()
+Stability BNO08x::get_stability_classifier()
{
- return stability_classifier;
+ return static_cast(stability_classifier);
}
/**
@@ -3320,9 +3322,9 @@ int8_t BNO08x::get_stability_classifier()
* 7 = runnning
* 8 = on stairs
*/
-uint8_t BNO08x::get_activity_classifier()
+Activity BNO08x::get_activity_classifier()
{
- return activity_classifier;
+ return static_cast(activity_classifier);
}
/**
@@ -3792,9 +3794,9 @@ void BNO08x::data_proc_task()
}
/**
- * @brief Launches spi_task and data_proc_task on constructor call.
+ * @brief Launches spi_task and data_proc_task on constructor call.
*
- * @return ESP_OK if tasks successfully created.
+ * @return ESP_OK if tasks successfully created.
*/
esp_err_t BNO08x::launch_tasks()
{
@@ -3834,9 +3836,9 @@ esp_err_t BNO08x::launch_tasks()
}
/**
- * @brief Deletes spi_task and data_proc_task safely on deconstructor call.
+ * @brief Deletes spi_task and data_proc_task safely on deconstructor call.
*
- * @return ESP_OK if tasks successfully deleted.
+ * @return ESP_OK if tasks successfully deleted.
*/
esp_err_t BNO08x::kill_all_tasks()
{
diff --git a/test/CallbackTests.cpp b/test/CallbackTests.cpp
new file mode 100644
index 0000000..f80538f
--- /dev/null
+++ b/test/CallbackTests.cpp
@@ -0,0 +1,167 @@
+#include "unity.h"
+#include "../include/BNO08xTestHelper.hpp"
+
+TEST_CASE("BNO08x Driver Creation for [CallbackTests] Tests", "[CallbackTests]")
+{
+ const constexpr char* TEST_TAG = "BNO08x Driver Creation for [CallbackTests] Tests";
+ BNO08x* imu = nullptr;
+
+ BNO08xTestHelper::print_test_msg(TEST_TAG, "Creating & initializing BNO08x driver.");
+ BNO08xTestHelper::create_test_imu();
+ imu = BNO08xTestHelper::get_test_imu();
+
+ // ensure IMU initialized successfully
+ TEST_ASSERT_EQUAL(true, imu->initialize());
+}
+
+TEST_CASE("Callback Receives New Data (Single Report)", "[CallbackTests]")
+{
+ const constexpr char* TEST_TAG = "Callback Receives New Data (Single Report)";
+ BNO08x* imu = nullptr;
+ BNO08xTestHelper::imu_report_data_t report_data;
+ BNO08xTestHelper::imu_report_data_t prev_report_data;
+ const constexpr uint8_t RX_REPORT_TRIAL_CNT = 5;
+ const constexpr uint32_t REPORT_PERIOD = 100000UL; // 100ms
+ bool new_data = false;
+ char msg_buff[200] = {};
+
+ imu = BNO08xTestHelper::get_test_imu();
+
+ // reset all data used in report test
+ BNO08xTestHelper::reset_all_imu_data_to_test_defaults();
+ BNO08xTestHelper::update_report_data(&report_data);
+
+ // register a callback and check for new data within it
+ imu->register_cb(
+ [&imu, &new_data, &report_data, &prev_report_data, &msg_buff]()
+ {
+ static int cb_execution_cnt = 0;
+
+ /* callback code */
+
+ cb_execution_cnt++;
+ // check if new data was received from enabled report(s)
+ BNO08xTestHelper::update_report_data(&report_data);
+
+ if (BNO08xTestHelper::accelerometer_data_is_new(&report_data, &prev_report_data))
+ {
+ new_data = true;
+
+ sprintf(msg_buff,
+ "Rx Data Trial %d Success: AngularAccel: aX: %.2lf accel aY: %.2lf accel aZ: "
+ "%.2lf Accuracy %s",
+ cb_execution_cnt, report_data.accel_x, report_data.accel_y, report_data.accel_z,
+ BNO08xTestHelper::BNO08xAccuracy_to_str(report_data.accel_accuracy));
+
+ BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
+ }
+ });
+
+ BNO08xTestHelper::print_test_msg(TEST_TAG, "Enabling report(s) and checking for new data through subscribed callback.");
+ imu->enable_accelerometer(REPORT_PERIOD);
+
+ for (int i = 0; i < RX_REPORT_TRIAL_CNT; i++)
+ {
+ if (imu->data_available())
+ {
+ // callbacks should ALWAYS execute before data_available returns true, therefore something has gone wrong if new_data is not set to true
+ TEST_ASSERT_EQUAL(true, new_data);
+
+ // reset all data used in report test
+ new_data = false;
+ BNO08xTestHelper::reset_all_imu_data_to_test_defaults();
+ BNO08xTestHelper::update_report_data(&report_data);
+ }
+ }
+
+ BNO08xTestHelper::print_test_msg(TEST_TAG, "Test complete, disabling report(s).");
+ imu->disable_accelerometer();
+}
+
+TEST_CASE("Callback Receives New Data (Dual Report)", "[CallbackTests]")
+{
+ const constexpr char* TEST_TAG = "Callback Receives New Data (Dual Report)";
+ BNO08x* imu = nullptr;
+ BNO08xTestHelper::imu_report_data_t report_data;
+ BNO08xTestHelper::imu_report_data_t prev_report_data;
+ const constexpr uint8_t ENABLED_REPORT_CNT = 2;
+ const constexpr uint8_t RX_REPORT_TRIAL_CNT = 2 * ENABLED_REPORT_CNT;
+ const constexpr uint32_t REPORT_PERIOD = 100000UL; // 100ms
+ bool new_data[2] = {false, false};
+ char msg_buff[200] = {};
+
+ imu = BNO08xTestHelper::get_test_imu();
+
+ // reset all data used in report test
+ BNO08xTestHelper::reset_all_imu_data_to_test_defaults();
+ BNO08xTestHelper::update_report_data(&report_data);
+
+ // register a callback and check for new data within it
+ imu->register_cb(
+ [&imu, &new_data, &report_data, &prev_report_data, &msg_buff]()
+ {
+ static int cb_execution_cnt = 0;
+
+ /* callback code */
+
+ cb_execution_cnt++;
+ // check if new data was received from enabled report(s)
+ BNO08xTestHelper::update_report_data(&report_data);
+
+ if (BNO08xTestHelper::accelerometer_data_is_new(&report_data, &prev_report_data))
+ {
+ new_data[0] = true;
+
+ sprintf(msg_buff,
+ "Rx Data Trial %d Success: AngularAccel: aX: %.2lf accel aY: %.2lf accel aZ: "
+ "%.2lf Accuracy %s",
+ cb_execution_cnt, report_data.accel_x, report_data.accel_y, report_data.accel_z,
+ BNO08xTestHelper::BNO08xAccuracy_to_str(report_data.accel_accuracy));
+
+ BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
+ }
+
+ if (BNO08xTestHelper::linear_accelerometer_data_is_new(&report_data, &prev_report_data))
+ {
+ new_data[1] = true;
+
+ sprintf(msg_buff,
+ "Rx Data Trial %d Success: LinearAccel: laX: %.2lf laY: %.2lf laZ: "
+ "%.2lf Accuracy: %s",
+ (cb_execution_cnt + 1), report_data.lin_accel_x, report_data.lin_accel_y, report_data.lin_accel_z,
+ BNO08xTestHelper::BNO08xAccuracy_to_str(report_data.lin_accel_accuracy));
+
+ BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
+ }
+ });
+
+ BNO08xTestHelper::print_test_msg(TEST_TAG, "Enabling report(s) and checking for new data through subscribed callback.");
+ imu->enable_accelerometer(REPORT_PERIOD);
+ imu->enable_linear_accelerometer(REPORT_PERIOD);
+
+ for (int i = 0; i < RX_REPORT_TRIAL_CNT; i++)
+ {
+ if (imu->data_available())
+ {
+ // callbacks should ALWAYS execute before data_available returns true
+ BNO08xTestHelper::reset_all_imu_data_to_test_defaults();
+ BNO08xTestHelper::update_report_data(&report_data);
+ }
+ }
+
+ // check that the callback received new data for all reports after all trials have completed
+ TEST_ASSERT_EQUAL(true, new_data[0]);
+ TEST_ASSERT_EQUAL(true, new_data[1]);
+
+ BNO08xTestHelper::print_test_msg(TEST_TAG, "Test complete, disabling report(s).");
+ imu->disable_accelerometer();
+ imu->disable_linear_accelerometer();
+}
+
+TEST_CASE("BNO08x Driver Cleanup for [CallbackTests] Tests", "[CallbackTests]")
+{
+ const constexpr char* TEST_TAG = "BNO08x Driver Cleanup for [CallbackTests] Tests";
+ BNO08xTestHelper::print_test_msg(TEST_TAG, "Destroying BNO08x Driver.");
+
+ BNO08xTestHelper::destroy_test_imu();
+}
diff --git a/test/SingleReportTests.cpp b/test/SingleReportTests.cpp
index 310ee75..f409e4d 100644
--- a/test/SingleReportTests.cpp
+++ b/test/SingleReportTests.cpp
@@ -1150,7 +1150,7 @@ TEST_CASE("Enable/Disable Stability Classifier", "[SingleReportEnableDisable]")
// assert that new data from respective report has been received
TEST_ASSERT_EQUAL(true, new_data);
- sprintf(msg_buff, "Rx Data Trial %d Success: StabilityClassifier: %d", (i + 1), report_data.stability_classifier);
+ sprintf(msg_buff, "Rx Data Trial %d Success: StabilityClassifier: %s", (i + 1), BNO08xTestHelper::BNO08xStability_to_str(report_data.stability_classifier));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
@@ -1180,7 +1180,7 @@ TEST_CASE("Enable/Disable Stability Classifier", "[SingleReportEnableDisable]")
// assert that no new data from respective report has been received
TEST_ASSERT_NOT_EQUAL(true, new_data);
- sprintf(msg_buff, "No Rx Data Trial %d Success: StabilityClassifierDefault: %d", (i + 1), report_data.stability_classifier);
+ sprintf(msg_buff, "No Rx Data Trial %d Success: StabilityClassifierDefault: %s", (i + 1), BNO08xTestHelper::BNO08xStability_to_str(report_data.stability_classifier));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
@@ -1214,7 +1214,7 @@ TEST_CASE("Enable/Disable Activity Classifier", "[SingleReportEnableDisable]")
BNO08xTestHelper::print_test_msg(TEST_TAG, "Report enabled testing phase started.");
/*enable respective report to test and ensure it reports new data */
- imu->enable_activity_classifier(5*REPORT_PERIOD, BNO08x::ACTIVITY_CLASSIFIER_ALL_EN, activity_confidence_vals);
+ imu->enable_activity_classifier(5*REPORT_PERIOD, ActivityClassifierEnable::ALL, activity_confidence_vals);
for (int i = 0; i < RX_REPORT_TRIAL_CNT; i++)
{
@@ -1232,7 +1232,7 @@ TEST_CASE("Enable/Disable Activity Classifier", "[SingleReportEnableDisable]")
// assert that new data from respective report has been received
TEST_ASSERT_EQUAL(true, new_data);
- sprintf(msg_buff, "Rx Data Trial %d Success: ActivityClassifier: %d", (i + 1), report_data.activity_classifier);
+ sprintf(msg_buff, "Rx Data Trial %d Success: ActivityClassifier: %s", (i + 1), BNO08xTestHelper::BNO08xActivity_to_str(report_data.activity_classifier));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
@@ -1262,7 +1262,7 @@ TEST_CASE("Enable/Disable Activity Classifier", "[SingleReportEnableDisable]")
// assert that no new data from respective report has been received
TEST_ASSERT_NOT_EQUAL(true, new_data);
- sprintf(msg_buff, "No Rx Data Trial %d Success: ActivityClassifierDefault: %d", (i + 1), report_data.activity_classifier);
+ sprintf(msg_buff, "No Rx Data Trial %d Success: ActivityClassifierDefault: %s", (i + 1), BNO08xTestHelper::BNO08xActivity_to_str(report_data.activity_classifier));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);