Before adding a new sensor, make sure the sensor's driver is available in Zephyr RTOS and uses the Zephyr Sensor API. Zephyr includes such a driver for the Bosch BMM350 magnetometer.
-
Add the sensor to the devicetree and enable it. This step:
- Instantiates a devicetree node for the sensor.
- Initializes the driver and the sensor during boot.
In the case of the Bosch BMM350 magnetometer, the device is already added to the devicetree. The node can be found in the nRF Connect SDK in the
nrf/boards/nordic/thingy91x/thingy91x_common.dtsifile.To enable the sensor, add the following to the Asset Tracker Template's board-specific devicetree overlay file
app/boards/thingy91x_nrf9151_ns.overlay:&magnetometer { status = "okay"; }; -
Update the environmental module's state structure in the
app/src/modules/environmental/environmental.cfile to include the magnetometer device reference and data fields:struct environmental_state_object { /* ... existing fields ... */ /* BMM350 sensor device reference */ const struct device *const bmm350; /* Magnetic field measurements (X, Y, Z) in Gauss */ double magnetic_field[3]; }; -
In the module's thread function
env_module_thread()in the same file, find the initialization of theenvironmental_statestructure and add the reference to the device using the devicetree label:struct environmental_state_object environmental_state = { .bme680 = DEVICE_DT_GET(DT_NODELABEL(bme680)), .bmm350 = DEVICE_DT_GET(DT_NODELABEL(magnetometer)), /* Add this line */ }; -
In the same file, update the sensor sampling function signature to include the magnetometer device:
static void sample_sensors(const struct device *const bme680, const struct device *const bmm350) -
In the
state_running_run()function in the same file, update the call tosample_sensors():sample_sensors(state_object->bme680, state_object->bmm350); -
Update the
sample_sensors()function in the same file to sample from the new sensor and add the data to the outgoing message (the message struct is extended in the next step):static void sample_sensors(const struct device *const bme680, const struct device *const bmm350) { /* ... existing code, calls to sensor_sample_fetch() and sensor_channel_get() ... */ struct sensor_value magnetic_field[3] = { {0}, {0}, {0} }; err = sensor_sample_fetch(bmm350); if (err) { LOG_ERR("Failed to fetch magnetometer sample: %d", err); SEND_FATAL_ERROR(); return; } err = sensor_channel_get(bmm350, SENSOR_CHAN_MAGN_XYZ, magnetic_field); if (err) { LOG_ERR("Failed to get magnetometer data: %d", err); SEND_FATAL_ERROR(); return; } LOG_DBG("Magnetic field: X: %.2f G, Y: %.2f G, Z: %.2f G", sensor_value_to_double(&magnetic_field[0]), sensor_value_to_double(&magnetic_field[1]), sensor_value_to_double(&magnetic_field[2])); struct environmental_msg msg = { /* ... existing fields ... */ .magnetic_field[0] = sensor_value_to_double(&magnetic_field[0]), .magnetic_field[1] = sensor_value_to_double(&magnetic_field[1]), .magnetic_field[2] = sensor_value_to_double(&magnetic_field[2]), }; /* ... existing code to timestamp and publish the message ... */ } -
Update the
environmental_msgstructure inapp/src/modules/environmental/environmental.hto include the magnetic field data:struct environmental_msg { /* ... existing fields ... */ /** Magnetic field measurements (X, Y, Z) in Gauss */ double magnetic_field[3]; }; -
Add cloud integration in the
cloud_environmental_send()function inapp/src/modules/cloud/cloud_environmental.cto send magnetometer data to nRF Cloud. There is no predefined application ID for magnetometer data, so the following code uses a custom"MAGNETIC_FIELD"ID. Update the function as follows:int cloud_environmental_send(const struct environmental_msg *env, int64_t timestamp_ms, bool confirmable) { int err; /* ... existing code to send temperature, pressure and humidity ... */ char mag_message[64]; /* Format magnetometer data as a string with three values */ snprintk(mag_message, sizeof(mag_message), "%.2f %.2f %.2f", env->magnetic_field[0], env->magnetic_field[1], env->magnetic_field[2]); err = nrf_cloud_coap_message_send("MAGNETIC_FIELD", mag_message, false, timestamp_ms, confirmable); if (err) { LOG_ERR("Failed to send magnetometer data to cloud, error: %d", err); return err; } LOG_DBG("Magnetometer data sent to cloud: %s", mag_message); return 0; } -
Build and run the modified application.
-
Confirm that the custom messages appear in the Terminal card in nRF Cloud, as shown below: