{"id":25486,"date":"2026-01-17T14:28:44","date_gmt":"2026-01-17T14:28:44","guid":{"rendered":"https:\/\/wolles-elektronikkiste.de\/?p=25486"},"modified":"2026-02-01T09:29:00","modified_gmt":"2026-02-01T09:29:00","slug":"bno08x-9-dof-imus","status":"publish","type":"post","link":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus","title":{"rendered":"BNO08x &#8211; 9-DoF-IMUs"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">About this Post<\/h2>\n<p>In this article, I will explain the features of the BNO08x modules and show you how to use them with common libraries. The BNO08x modules contain a 3-axis accelerometer, a 3-axis gyroscope, and a 3-axis magnetic field sensor. I have already described such multi-talents in my previous posts about the <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/icm-20948-9-axis-sensor-part-i\" target=\"_blank\" rel=\"noopener\">ICM-20948<\/a> and the <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/mpu9250-9-axis-sensor-module-part-1\" target=\"_blank\" rel=\"noopener\">MPU9250<\/a>. Nevertheless, it is worth taking a look at the BNO08x modules: they not only provide the sensor data but also use it to calculate the absolute spatial orientation and also recognize complex movement patterns such as steps, shaking, or tapping.   <\/p>\n<p>I will discuss the little brother of the BNO08x modules, the BNO055, in a separate article.<\/p>\n<p>This is what you can expect in this article:<\/p>\n<ul>\n<li><a href=\"#overview\">BNO08x at a glance<\/a><\/li>\n<li><a href=\"#detailed\">BNO08x in detail<\/a>\n<ul>\n<li><a href=\"#modules\">Common BNO08x modules<\/a><\/li>\n<li><a href=\"#electrical_characteristics\">Key electrical characteristics<\/a><\/li>\n<li><a href=\"#communication\">Communication<\/a><\/li>\n<li><a href=\"#reports\">Outputs (reports) of the BNO08x modules<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#libraries\">Libraries &#8211; Sparkfun and Adafruit<\/a><\/li>\n<li><a href=\"#calibration\">Calibration<\/a><\/li>\n<li><a href=\"#wiring\">Connecting the BNO08x modules to the microcontroller (I\u00b2C)<\/a><\/li>\n<li><a href=\"#examples\">Selected example sketches<\/a>\n<ul>\n<li><a href=\"#motion_example\">Motion &#8211; Accelerometer values<\/a><\/li>\n<li><a href=\"#orientation_example\">Orientation &#8211; Rotation vector (Euler angle)<\/a><\/li>\n<li><a href=\"#classification_example\">Classification &#8211; Step counter<\/a><\/li>\n<li><a href=\"#combined_reports\">Combining reports<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#appendix\">Appendix &#8211; SPI, UART, UART-RVC, 5-volt boards<\/a>\n<ul>\n<li><a href=\"#appendix_spi\">SPI control of the BNO08x modules<\/a><\/li>\n<li><a href=\"#appendix_uart\">UART control (Adafruit only)<\/a><\/li>\n<li><a href=\"#appendix_uart_rvc\">UART-RVC control (Adafruit only)<\/a><\/li>\n<li><a href=\"#appendix_5v_boards\">Use of 5-volt boards using the example of the UNO R4 Minima<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n<h2 class=\"wp-block-heading\" id=\"overview\">BNO08x at a glance<\/h2>\n<p>According to the <a href=\"https:\/\/www.ceva-ip.com\/wp-content\/uploads\/BNO080_085-Datasheet.pdf\" target=\"_blank\" rel=\"noopener\">data sheet<\/a>, the BNO08X family includes the BNO085 and the BNO086. Their predecessor, the BNO080 (<a href=\"https:\/\/cdn.sparkfun.com\/assets\/1\/3\/4\/5\/9\/BNO080_Datasheet_v1.3.pdf\" target=\"_blank\" rel=\"noopener\">link<\/a> to data sheet), is no longer manufactured. Nevertheless, you might still come across it. The good news is that the BNO080, BNO085, and BNO086 are largely compatible. <\/p>\n<p>All three are <strong>&#8220;9-DoF IMUs<\/strong>&#8220;:<\/p>\n<ul>\n<li><strong>9-DoF<\/strong> = 9 Degrees of Freedom. Three axes each for the acceleration sensor, the gyroscope, and the magnetic sensor. <\/li>\n<li><strong>IMU<\/strong> = Inertial Measurement Unit, i.e. sensors based on inertia (Latin: inertia). I have described the measuring principle <a href=\"https:\/\/wolles-elektronikkiste.de\/en\/mpu6050-accelerometer-and-gyroscope#anker1\" target=\"_blank\" rel=\"noopener\">here<\/a> in my article about the MPU6050.  <\/li>\n<\/ul>\n<p>The conversion of the sensor data into the absolute orientation in space and the recognition of movement patterns is called sensor fusion. As sensor fusion is very computationally intensive, the BNO08x sensors have their own microcontroller (ARM Cortex-M0+), which takes over this task and relieves your connected microcontroller. <\/p>\n<p>The internal microcontroller runs CEVA&#8217;s SH-2 software. SH-2 was originally developed by Hillcrest Labs, which was later taken over by CEVA. <\/p>\n<p>The actual acceleration, gyroscope, and magnetic sensors are supplied by Bosch Sensortec.<\/p>\n<p>If you control or read out sensors via I\u00b2C, SPI or UART, access is normally made directly via registers of the respective hardware. This is different with the BNO08x: Here you do not access the sensor hardware directly. Instead, the SH-2 software forms the interface between your microcontroller and the internal sensors. If you want to receive data from the BNO08x, you request it via so-called report IDs. Each report ID stands for a specific data type or a specific calculation, such as acceleration values, Euler angles, or the step counter.    <\/p>\n\n<h4 class=\"wp-block-heading\">High performance &#8211; high demands<\/h4>\n\n<p>However, the high performance of the BNO08x modules comes at a price. The libraries from SparkFun and Adafruit that I will discuss cannot be used on classic Arduino boards based on the ATmega328P, as the available SRAM is not sufficient. &nbsp;<\/p>\n<p>In addition, comparatively large buffers are required for UART operation (at least 300 bytes), while ATmega328P-based boards only provide 64 bytes as standard.<\/p>\n<p>The modules are also quite demanding in terms of their power requirements (see below), which can limit their use in battery-powered applications.<\/p>\n<p>If you would like to work with smaller microcontrollers and don&#8217;t need the full range of functions of the BNO08x modules, you should take a look at their little brother, the BNO055.<\/p>\n\n<h2 class=\"wp-block-heading\" id=\"detailed\">BNO08x in detail<\/h2>\n\n<h3 class=\"wp-block-heading\" id=\"modules\">Common BNO08x modules<\/h3>\n<p>I assume that most of you are not using the bare BNO08x ICs, but modules. Here are some representatives that I have tried out: <\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/all_bno08x-1024x365.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"365\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/all_bno08x-1024x365.webp\" alt=\"\" class=\"wp-image-25340\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/all_bno08x-1024x365.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/all_bno08x-300x107.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/all_bno08x-768x273.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/all_bno08x-1536x547.webp 1536w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/all_bno08x-1320x470.webp 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/all_bno08x.webp 2000w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">BNO08x modules: Sparkfun, no-name, and Adafruit<\/figcaption><\/figure>\n<p>They all work fine, but differ in some respects. For example, the I\u00b2C address of the Sparkfun and the no-name module is preset to 0x4B (ADO = HIGH). The default setting for the Adafruit module is 0x4A (ADO = LOW). Both the Adafruit and the Sparkfun modules are equipped with the very practical QWIIC connector for I\u00b2C communication. All three modules have pull-up resistors for the I\u00b2C lines.     <\/p>\n<p>Only the Adafruit module can be operated with 5 volts. It has a voltage regulator and level shifters for the inputs and outputs.  <\/p>\n\n<h3 class=\"wp-block-heading\" id=\"electrical_characteristics\">Key electrical characteristics<\/h3>\n<ul>\n<li><strong>Power supply<\/strong>: 2.4 &#8211; 3.6 volts (Adafruit module: also 5V).<\/li>\n<li><strong>Power consumption<\/strong>: The power consumption depends on various factors, such as the data rates (see data sheet, chapter 6.10).\n<ul>\n<li><strong>As a guide: <\/strong>I measured the following values with the Sparkfun sketch &#8220;Example_18_Sleep.ino&#8221; at 3.3 volts power supply and I\u00b2C communication:\n<ul>\n<li>Sleep mode: approx. 0.2 mA.<\/li>\n<li>Awake mode: approx. 12.3 mA.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n<h3 class=\"wp-block-heading\" id=\"communication\">Communication<\/h3>\n<p>The BNO08x modules can handle I\u00b2C, SPI, UART and UART-RVC. UART-RVC is a UART variant that only requires a single data cable (RVC = <strong>R<\/strong>otation <strong>V<\/strong>ector <strong>C<\/strong>hannel). The disadvantage of this variant is that only a limited range of functions is available to you. You also need a separate library.   <\/p>\n<p>You select the communication protocol via the PS pins <strong>(Protocoll<\/strong> <strong>Selection<\/strong>):<\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/protocoll_setting.png\"><img loading=\"lazy\" decoding=\"async\" width=\"945\" height=\"246\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/protocoll_setting.png\" alt=\"\" class=\"wp-image-25356\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/protocoll_setting.png 945w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/protocoll_setting-300x78.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/protocoll_setting-768x200.png 768w\" sizes=\"auto, (max-width: 945px) 100vw, 945px\" \/><\/a><figcaption class=\"wp-element-caption\">Protocol selection via PS pins<\/figcaption><\/figure>\n<p>For all three modules shown above, PS0 and PS1 are connected to GND with pull-down resistors. You can set them permanently to HIGH via solder bridges on the back of the modules. Alternatively, you can use the pins.   <\/p>\n\n<h3 class=\"wp-block-heading\" id=\"reports\">Outputs (reports) of the BNO08x modules<\/h3>\n<p>The measurement data from the BNO08x modules is requested as so-called reports. You define what you want once and then receive the corresponding data continuously. In principle, it&#8217;s like a newspaper subscription. You know approximately when to expect the deliveries, but you only know the exact time when the delivery actually arrives.   <\/p>\n<p>The range of reports is impressive. They can be divided into three groups: <\/p>\n\n<h4 class=\"wp-block-heading\">1. Motion reports<\/h4>\n<p>These reports contain raw or processed data from the individual sensors. <\/p>\n<ul>\n<li><strong>Acceleration values<\/strong>:\n<ul>\n<li>Calibrated acceleration data, including gravity (in <sup>m\/s\u00b2<\/sup>)<\/li>\n<li>Linear acceleration: Acceleration data, excluding gravity (in <sup>m\/s\u00b2<\/sup>)<\/li>\n<li>Acceleration due to gravity: pure gravity (in <sup>m\/s\u00b2<\/sup>)<\/li>\n<li>Uncalibrated raw data of the A\/D converter<\/li>\n<\/ul>\n<\/li>\n<li><strong>Angular velocity<\/strong>:\n<ul>\n<li>Calibrated gyroscope data (in rad\/s)<\/li>\n<li>Uncalibrated gyroscope data (in rad\/s)<\/li>\n<li>Uncalibrated raw data of the AD\/converter<\/li>\n<\/ul>\n<\/li>\n<li><strong>Magnetometer processing<\/strong>:\n<ul>\n<li>Calibrated magnetic field (\u00b5Tesla)<\/li>\n<li>Uncalibrated magnetic field (\u00b5Tesla)<\/li>\n<li>Uncalibrated raw data of the A\/D converter<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n<h4 class=\"wp-block-heading\">2. Orientation reports<\/h4>\n<p>If the data from the sensors is combined (&#8220;sensor fusion&#8221;), the absolute orientation of the module in space or in relation to a reference point can be determined. The reports usually output the data as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Quaternion\" target=\"_blank\" rel=\"noopener\">quaternions<\/a>. Quaternions are a mathematical method for describing the spatial rotation of bodies. Further mathematical operations are required to obtain descriptive data from quaternions. The detour via quaternions is necessary because the use of angles (&#8220;Yaw&#8221;, &#8220;Pitch&#8221;, &#8220;Roll&#8221;) can lead to problems such as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Gimbal_lock\" target=\"_blank\" rel=\"noopener\">gimbal lock<\/a> in certain borderline cases.     <\/p>\n<p>The selection of the orientation report is always a trade-off between precision and speed or latency. You can choose from: <\/p>\n<ul>\n<li><strong>Geomagnetic Rotation Vector<\/strong>: Orientation referenced to magnetic north and gravity. Only the magnetometer and accelerometer are used, not the gyroscope.  <\/li>\n<li><strong>Game Rotation Vector<\/strong>: Based on the accelerometer and the gyroscope. As the magnetometer is not used, the yaw angle can drift over time. The advantage of this method is its low latency, which makes it particularly suitable for game and VR applications.\n<ul>\n<li><strong>AR\/VR Stabilized Game Rotation Vector<\/strong>: Corrected variant (see data sheet, section 2.2.3) <\/li>\n<\/ul>\n<\/li>\n<li><strong>Rotation Vector<\/strong>: Uses accelerometer, gyroscope and magnetometer and therefore provides the most accurate absolute orientation.\n<ul>\n<li><strong>AR\/VR Stabilized Rotation Vector<\/strong>: Corrected variant (see data sheet, section 2.2.5).<\/li>\n<\/ul>\n<\/li>\n<li><strong>Gyro rotation vector<\/strong>: Special variant of the rotation or game rotation vector. (see data sheet, section 2.2.6) <\/li>\n<li><strong>Gyro Rotation Vector Prediction<\/strong>: Prediction of where the Gyro Protection Vector will move to next (see data sheet, section 2.2.7).<\/li>\n<\/ul>\n\n<h4 class=\"wp-block-heading\">3. Classification reports<\/h4>\n<p>More complex movement patterns can be derived from the change in movement and orientation data over time. These are the so-called classification reports:  <\/p>\n<ul>\n<li><strong>Stability Detection and Classification<\/strong>:\n<ul>\n<li>On table: Sensor lies absolutely still.<\/li>\n<li>Stable: Sensor is held steady in the hand.  <\/li>\n<li>Motion: Sensor is moved.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Tap Detector<\/strong>: Detects taps.<\/li>\n<li><strong>Step Counter:<\/strong> Counts steps.<\/li>\n<li><strong>Activity Classification<\/strong>: Still, walking, or running.<\/li>\n<li><strong>Significant Motion Detector<\/strong>: Detects significant motion.<\/li>\n<li><strong>Shake Detector: <\/strong>Detects shaking.<\/li>\n<\/ul>\n\n<h4 class=\"wp-block-heading\">Report frequencies<\/h4>\n<p>The number of reports per second that the BNO08x modules can deliver depends on the speed of the communication protocol (i.e. I\u00b2C, SPI, UART) and the internal processing time. In addition, the maximum data rates of the underlying sensors must be considered, whereby not all sensors can deliver the maximum data rate at the same time.  <\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/report_rates-1024x341.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"341\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/report_rates-1024x341.png\" alt=\"Maximum BNO08x report frequencies\" class=\"wp-image-25380\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/report_rates-1024x341.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/report_rates-300x100.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/report_rates-768x256.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/report_rates.png 1169w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Maximum data rates<\/figcaption><\/figure>\n<p>As you will see, the time between reports can be configured (within reasonable limits). However, the actual report rate can be 0.9 to 2.1 times the desired value. <\/p>\n\n<h3 class=\"wp-block-heading\" id=\"calibration\">Calibration<\/h3>\n<p>The BNO08x modules can be calibrated dynamically, i.e. during operation:<\/p>\n<ul>\n<li><strong>Accelerometer<\/strong>: Removal of the &#8220;zero-g offset&#8221;. At rest, only the force of gravity acts on the sensor. Any deviations from this are eliminated during calibration.  <\/li>\n<li><strong>Gyroscope<\/strong>: Removal of the &#8220;zero rate offset&#8221;. At rest, the gyroscope sensors should display an angular velocity of 0. All deviations from this are eliminated during calibration.  <\/li>\n<li><strong>Magnetometer<\/strong>: Elimination of interference with the magnetic field, e.g. from magnets, loudspeakers or ferromagnetic materials. <\/li>\n<\/ul>\n<p>The better the calibration, the more accurate the measurement results. The accuracy of the values is classified on a scale from 0 (unreliable) to 3 (high reliability).  <\/p>\n\n<h2 class=\"wp-block-heading\" id=\"libraries\">Libraries &#8211; Sparkfun and Adafruit<\/h2>\n<p>In this article, I will look at the libraries &#8220;<a href=\"https:\/\/github.com\/sparkfun\/SparkFun_BNO08x_Arduino_Library\" target=\"_blank\" rel=\"noopener\">SparkFun BNO08x Cortex Based IMU<\/a>&#8221; and &#8220;<a href=\"https:\/\/github.com\/adafruit\/Adafruit_BNO08x\" target=\"_blank\" rel=\"noopener\">Adafruit BNO08x<\/a>&#8220;. Tutorials on the libraries and the respective modules can be found <a href=\"https:\/\/docs.sparkfun.com\/SparkFun_VR_IMU_Breakout_BNO086_QWIIC\/introduction\/\" target=\"_blank\" rel=\"noopener\">here<\/a> on the Sparkfun website or <a href=\"https:\/\/learn.adafruit.com\/adafruit-9-dof-orientation-imu-fusion-breakout-bno085\/overview\" target=\"_blank\" rel=\"noopener\">here<\/a> on the Adafruit website.<\/p>\n<p>In principle, both libraries work well. However, they have their strengths and weaknesses. In favor of the <strong>Sparkfun library<\/strong> (in my opinion and based on the current versions of the libraries!):   <\/p>\n<ul>\n<li>Contains many example sketches. <\/li>\n<li>Implementation of sleep mode. <\/li>\n<li>The calibration is more transparent (see example sketch no. 20). <\/li>\n<li>More stable I\u00b2C communication.<\/li>\n<\/ul>\n<p>This speaks in favor of the <strong>Adafruit library<\/strong>:<\/p>\n<ul>\n<li>Implementation of UART (UART-RVC is implemented in a separate Adafruit library).<\/li>\n<li>Setting the report period is more flexible. For the Sparkfun library, the period is (currently) limited to a maximum of 65 milliseconds.  <\/li>\n<li>The Adafruit library is closer to the SH-2 software and the <a href=\"https:\/\/github.com\/ceva-dsp\/sh2\" target=\"_blank\" rel=\"noopener\">SH-2 API<\/a>.<\/li>\n<\/ul>\n\n<h2 class=\"wp-block-heading\" id=\"wiring\">Connecting the BNO08x modules to the microcontroller (I\u00b2C)<\/h2>\n<p>How you connect your module to the microcontroller depends on the module and the desired communication protocol. I will show everything here using the example of the no-name module, which is controlled via an ESP32 development board. I have chosen I\u00b2C as the protocol for the example sketches. In the appendix, you will find circuit diagrams and example sketches using SPI, UART, and UART-RVC. Moreover, I will also show you how to use 5-volt boards.     <\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/bno08x_i2c-1024x482.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"482\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/bno08x_i2c-1024x482.webp\" alt=\"BNO08x module, connected to an ESP32 board via I&#xB2;C \" class=\"wp-image-25342\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/bno08x_i2c-1024x482.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/bno08x_i2c-300x141.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/bno08x_i2c-768x361.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/bno08x_i2c-1320x621.webp 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/bno08x_i2c.webp 1347w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">BNO08x module, connected to an ESP32 board via I\u00b2C<\/figcaption><\/figure>\n<p>In this configuration, the connections to PS0, PS1, and ADO are redundant, as the no-name board has corresponding pull-up and pull-down resistors. If you use the Adafruit library, you do not need to connect INT and RST. <\/p>\n<p>Instructions for wiring the Adafruit module can be found <a href=\"https:\/\/learn.adafruit.com\/adafruit-9-dof-orientation-imu-fusion-breakout-bno085\/arduino\" target=\"_blank\" rel=\"noopener\">here<\/a>, for wiring the Sparkfun module look <a href=\"https:\/\/docs.sparkfun.com\/SparkFun_VR_IMU_Breakout_BNO086_QWIIC\/hardware_hookup\/\" target=\"_blank\" rel=\"noopener\">here<\/a>. <\/p>\n\n<p>When using the Sparkfun library, you should connect INT and RST for all communication protocols.&nbsp;<\/p>\n<p><strong>I\u00b2C can cause problems with the BNO08x modules (see <a href=\"https:\/\/learn.adafruit.com\/adafruit-9-dof-orientation-imu-fusion-breakout-bno085\/arduino\" target=\"_blank\" rel=\"noopener\">here<\/a>). If this is the case for you, then it is best to switch to SPI. SPI is also ahead of the pack when it comes to speed. <\/strong><\/p>\n\n<h2 class=\"wp-block-heading\" id=\"examples\">Selected example sketches<\/h2>\n<p>Now we can finally turn to the practical side of things. I cannot go through all the report functions in this article. I will show you an example of a motion report, one for an orientation report and one for a classification report. Finally, let&#8217;s take a look at how to output several reports.     <\/p>\n\n<h3 class=\"wp-block-heading\" id=\"motion_example\">Motion example: Accelerometer values<\/h3>\n\n<h4 class=\"wp-block-heading\">Accelerometer values using the Sparkfun library<\/h4>\n<p>The Sparkfun library contains example sketches for almost all reports. We will take a look at the example sketch Example_02_Accelerometer.ino which I have modified regarding the reset and the interrupt pin.  <\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"SF_Example_02_Accelerometer.ino\" data-enlighter-title=\"SF_Example_02_Accelerometer.ino\">\/*\n  Using the BNO08x IMU\n\n  This example shows how to output accelerometer values.\n\n  By: Nathan Seidle\n  SparkFun Electronics\n  Date: December 21st, 2017\n  SparkFun code, firmware, and software is released under the MIT License.\n  Please see LICENSE.md for further details.\n\n  Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017\n\n  Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the\n  CEVA Sensor Hub Driver, found here:\n  https:\/\/github.com\/ceva-dsp\/sh2\n\n  Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert\n  for Adafruit Industries. Found here:\n  https:\/\/github.com\/adafruit\/Adafruit_BNO08x\n\n  Also, utilizing I2C and SPI read\/write functions and code from the Adafruit\n  BusIO library found here:\n  https:\/\/github.com\/adafruit\/Adafruit_BusIO\n\n  Hardware Connections: \/\/ changed for this blog post by Wolfgang Ewald\n  ESP32 --&gt; BNO08x\n  19  --&gt; INT \n  18  --&gt; RST\n\n  BNO08x \"mode\" jumpers set for I2C (default):\n  PSO: Open\n  PS1: Open\n\n  Serial.print it out at 115200 baud to serial monitor.\n\n  Feel like supporting our work? Buy a board from SparkFun!\n  https:\/\/www.sparkfun.com\/products\/22857\n*\/\n\n#include &lt;Wire.h&gt;\n\n#include \"SparkFun_BNO08x_Arduino_Library.h\" \/\/ CTRL+Click here to get the library: http:\/\/librarymanager\/All#SparkFun_BNO08x\nBNO08x myIMU;\n\n\/\/ For the most reliable interaction with the SHTP bus, we need\n\/\/ to use hardware reset control, and to monitor the H_INT pin.\n\/\/ The H_INT pin will go low when its okay to talk on the SHTP bus.\n\/\/ Note, these can be other GPIO if you like.\n\/\/ Define as -1 to disable these features.\n#define BNO08X_INT  19\n\/\/#define BNO08X_INT  -1\n#define BNO08X_RST  18\n\/\/#define BNO08X_RST  -1\n\n#define BNO08X_ADDR 0x4B  \/\/ SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B\n\/\/#define BNO08X_ADDR 0x4A \/\/ Alternate address if ADR jumper is closed\n\nvoid setup() {\n  Serial.begin(115200);\n  \n  while(!Serial) delay(10); \/\/ Wait for Serial to become available.\n  \/\/ Necessary for boards with native USB (like the SAMD51 Thing+).\n  \/\/ For a final version of a project that does not need serial debug (or a USB cable plugged in),\n  \/\/ Comment out this while loop, or it will prevent the remaining code from running.\n  \n  Serial.println();\n  Serial.println(\"BNO08x Read Example\");\n\n  Wire.begin();\n\n  \/\/if (myIMU.begin() == false) {  \/\/ Setup without INT\/RST control (Not Recommended)\n  if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) {\n    Serial.println(\"BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing...\");\n    while (1)\n      ;\n  }\n  Serial.println(\"BNO08x found!\");\n\n  \/\/ Wire.setClock(400000); \/\/Increase I2C data rate to 400kHz\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (myIMU.enableAccelerometer() == true) {\n    Serial.println(F(\"Accelerometer enabled\"));\n    Serial.println(F(\"Output in form x, y, z, in m\/s^2\"));\n  } else {\n    Serial.println(\"Could not enable accelerometer\");\n  }\n}\n\nvoid loop() {\n  delay(10);\n\n  if (myIMU.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n\n  \/\/ Has a new event come in on the Sensor Hub Bus?\n  if (myIMU.getSensorEvent() == true) {\n\n    \/\/ is it the correct sensor data we want?\n    if (myIMU.getSensorEventID() == SENSOR_REPORTID_ACCELEROMETER) {\n\n      float x = myIMU.getAccelX();\n      float y = myIMU.getAccelY();\n      float z = myIMU.getAccelZ();\n\n      Serial.print(x, 2);\n      Serial.print(F(\",\"));\n      Serial.print(y, 2);\n      Serial.print(F(\",\"));\n      Serial.print(z, 2);\n\n      Serial.println();\n    }\n  }\n}\n<\/pre>\n<\/div>\n<p>\n<p>I won&#8217;t go into every single line of code because most of it should be self-explanatory. With <code>begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST)<\/code>, youitialize your BNO08x object and pass the I\u00b2C address, the wire object, the interrupt pin, and the reset pin. <\/p>\n<p>In <code>setReports()<\/code>, the accelerometer or accelerometer reports are activated via <code>enableAccelerometer()<\/code>. In <code>loop()<\/code>, <code>getSensorEvent()<\/code> queries whether there is an event. If so, <code>getSensorEventID()<\/code> determines the ID of the event. If this is the accelerometer report ID, the x, y, and z values are queried and output. The unit of the values is <sup>m\/s\u00b2<\/sup>. To convert them into g-values, divide them by 9.81.     <\/p>\n<p>If a reset of the BNO08x was necessary (<code>wasReset() == true<\/code>), the reports are automatically reset.<\/p>\n<p>Here is the output I obtained:<\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_example_02_accelerometer.png\"><img loading=\"lazy\" decoding=\"async\" width=\"623\" height=\"94\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_example_02_accelerometer.png\" alt=\"Output SF_Example_02_Accelerometer.ino\" class=\"wp-image-25326\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_example_02_accelerometer.png 623w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_example_02_accelerometer-300x45.png 300w\" sizes=\"auto, (max-width: 623px) 100vw, 623px\" \/><\/a><figcaption class=\"wp-element-caption\">Output SF_Example_02_Accelerometer.ino<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Accelerometer values using the Adafruit library<\/h4>\n<p>The Adafruit library is equipped with fewer example sketches, but you can use the example sketch more_reports.ino as a basis and delete the parts that you don&#8217;t need. This is how I prepared this sketch.  <\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"Ada_acceleration_example.ino\" data-enlighter-title=\"Ada_acceleration_example.ino\">\/\/ Basic demo for readings from Adafruit BNO08x\n#include &lt;Adafruit_BNO08x.h&gt;\n\n\/\/ For SPI mode, we need a CS pin\n#define BNO08X_CS 10\n#define BNO08X_INT 19\n\n\/\/ For SPI mode, we also need a RESET \n\/\/#define BNO08X_RESET 5\n\/\/ but not for I2C or UART\n#define BNO08X_RESET -1\n\nAdafruit_BNO08x  bno08x(BNO08X_RESET);\nsh2_SensorValue_t sensorValue;\n\nvoid setup(void) {\n  Serial.begin(115200);\n  while (!Serial) delay(10);     \/\/ will pause Zero, Leonardo, etc until serial console opens\n\n  Serial.println(\"Adafruit BNO08x Accelerometer test!\");\n\n  \/\/ Try to initialize!\n  if (!bno08x.begin_I2C(\/* 0x4B *\/)) {\n  \/\/if (!bno08x.begin_UART(&amp;Serial1)) {  \/\/ Requires a device with &gt; 300 byte UART buffer!\n  \/\/if (!bno08x.begin_SPI(BNO08X_CS, BNO08X_INT)) {\n    Serial.println(\"Failed to find BNO08x chip\");\n    while (1) { delay(10); }\n  }\n  Serial.println(\"BNO08x Found!\");\n\n  for (int n = 0; n &lt; bno08x.prodIds.numEntries; n++) {\n    Serial.print(\"Part \");\n    Serial.print(bno08x.prodIds.entry[n].swPartNumber);\n    Serial.print(\": Version :\");\n    Serial.print(bno08x.prodIds.entry[n].swVersionMajor);\n    Serial.print(\".\");\n    Serial.print(bno08x.prodIds.entry[n].swVersionMinor);\n    Serial.print(\".\");\n    Serial.print(bno08x.prodIds.entry[n].swVersionPatch);\n    Serial.print(\" Build \");\n    Serial.println(bno08x.prodIds.entry[n].swBuildNumber);\n  }\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (! bno08x.enableReport(SH2_ACCELEROMETER)) {\n    Serial.println(\"Could not enable accelerometerame vector\");\n  }\n}\n\n\nvoid loop() {\n  delay(10);\n\n  if (bno08x.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n  \n  if (! bno08x.getSensorEvent(&amp;sensorValue)) {\n    return;\n  }\n  \n  switch (sensorValue.sensorId) {\n    \n    case SH2_ACCELEROMETER:\n      Serial.print(\"Accelerometer - x: \");\n      Serial.print(sensorValue.un.accelerometer.x);\n      Serial.print(\" y: \");\n      Serial.print(sensorValue.un.accelerometer.y);\n      Serial.print(\" z: \");\n      Serial.println(sensorValue.un.accelerometer.z);\n      break;\n  }\n}<\/pre>\n<\/div>\n<p>\n<p>First, you create a BNO08x object as usual. In addition, you create the structure <code>sensorValue<\/code> of type <code>sh2_SensorValue_t<\/code>, which you later pass to the function <code>getSensorEvent()<\/code> in <code>loop()<\/code> as a reference. <code>sensorValue<\/code> is a form, so to speak, in which the values are entered. It is worth taking a look at the file <a href=\"https:\/\/github.com\/adafruit\/Adafruit_BNO08x\/blob\/master\/src\/sh2_SensorValue.h\" target=\"_blank\" rel=\"noopener\">sh2_SensorValue.h<\/a> to understand the composition of this structure. <code>sh2_SensorValue.h<\/code> is also used by the Sparkfun library &#8211; but there it is somewhat more hidden behind the scenes.  <\/p>\n<p>You initialize the module with <code>begin_I2C()<\/code>. You can optionally pass the I\u00b2C address. The large for-construct in <code>setup()<\/code> tells you details about the module. You can also omit this if you like.    <\/p>\n<p>In <code>setupReports()<\/code>, use <code>enableReport(SH2_REPORTNAME)<\/code> to activate the report of your choice. You can find the report names or the corresponding IDs either in the example sketch moreReports.ino, or you can look in the file <a href=\"https:\/\/github.com\/adafruit\/Adafruit_BNO08x\/blob\/master\/src\/sh2.h\" target=\"_blank\" rel=\"noopener\">sh2.h<\/a>, in which the names are defined in the enum sh2_SensorId_e.  <\/p>\n<p>Personally, I like how closely the Adafruit library follows the SH-2 API. Expressions like <code>sensorValue.un.accelerometer.z<\/code> may seem a bit cumbersome compared to a slim <code>myIMU.getAccelZ();<\/code> at first glance, but I like the logical structure behind it.  <\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_accelerometer_example.png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"111\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_accelerometer_example.png\" alt=\"\" class=\"wp-image-25328\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_accelerometer_example.png 605w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_accelerometer_example-300x55.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_accelerometer_example-600x111.png 600w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><figcaption class=\"wp-element-caption\">Output ada_example_accelerometer.ino<\/figcaption><\/figure>\n\n<h3 class=\"wp-block-heading\" id=\"orientation_example\">Example Orientation: Rotation vector (Euler angles)<\/h3>\n\n<h4 class=\"wp-block-heading\">Rotation vector using the Sparkfun lib<\/h4>\n<p>The following sketch outputs the orientation of the BNO08x in three-dimensional space as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Aircraft_principal_axes\" target=\"_blank\" rel=\"noopener\">yaw, pitch and roll angles<\/a>. Yaw, pitch and roll are known as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Euler_angles\" target=\"_blank\" rel=\"noopener\">Euler angles<\/a>.<\/p>\n<p>The Rotation Vector Report actually returns the orientation as a quaternion; the Sparkfun library converts the quaternions into Euler angles in the background, which are then converted from rad to degrees. Apart from that, the sketch does not actually contain anything new.  <\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"SF_Example_13_EulerAngles.ino\" data-enlighter-title=\"SF_Example_13_EulerAngles.ino\">\/*\n  Using the BNO08x IMU\n\n  Example : Euler Angles\n  By: Paul Clark\n  Date: April 28th, 2020\n\n  This example shows how to output the Euler angles: roll, pitch and yaw.\n  The yaw (compass heading) is tilt-compensated, which is nice.\n  https:\/\/en.wikipedia.org\/wiki\/Conversion_between_quaternions_and_Euler_angles\n  https:\/\/github.com\/sparkfun\/SparkFun_MPU-9250-DMP_Arduino_Library\/issues\/5#issuecomment-306509440\n\n  By: Nathan Seidle\n  SparkFun Electronics\n  Date: December 21st, 2017\n  SparkFun code, firmware, and software is released under the MIT License.\n  Please see LICENSE.md for further details.\n\n  Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017\n\n  Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the\n  CEVA Sensor Hub Driver, found here:\n  https:\/\/github.com\/ceva-dsp\/sh2\n\n  Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert\n  for Adafruit Industries. Found here:\n  https:\/\/github.com\/adafruit\/Adafruit_BNO08x\n\n  Also, utilizing I2C and SPI read\/write functions and code from the Adafruit\n  BusIO library found here:\n  https:\/\/github.com\/adafruit\/Adafruit_BusIO\n\n  Hardware Connections:\n  IoT RedBoard --&gt; BNO08x\n  QWIIC --&gt; QWIIC\n  A4  --&gt; INT\n  A5  --&gt; RST\n\n  BNO08x \"mode\" jumpers set for I2C (default):\n  PSO: OPEN\n  PS1: OPEN\n\n  Serial.print it out at 115200 baud to serial monitor.\n\n  Feel like supporting our work? Buy a board from SparkFun!\n  https:\/\/www.sparkfun.com\/products\/22857\n*\/\n\n#include &lt;Wire.h&gt;\n\n#include \"SparkFun_BNO08x_Arduino_Library.h\"  \/\/ CTRL+Click here to get the library: http:\/\/librarymanager\/All#SparkFun_BNO08x\nBNO08x myIMU;\n\n\/\/ For the most reliable interaction with the SHTP bus, we need\n\/\/ to use hardware reset control, and to monitor the H_INT pin.\n\/\/ The H_INT pin will go low when its okay to talk on the SHTP bus.\n\/\/ Note, these can be other GPIO if you like.\n\/\/ Define as -1 to disable these features.\n#define BNO08X_INT  19\n\/\/#define BNO08X_INT  -1\n#define BNO08X_RST  18\n\/\/#define BNO08X_RST  -1\n\n#define BNO08X_ADDR 0x4B  \/\/ SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B\n\/\/#define BNO08X_ADDR 0x4A \/\/ Alternate address if ADR jumper is closed\n\nvoid setup() {\n  Serial.begin(115200);\n  \n  while(!Serial) delay(10); \/\/ Wait for Serial to become available.\n  \/\/ Necessary for boards with native USB (like the SAMD51 Thing+).\n  \/\/ For a final version of a project that does not need serial debug (or a USB cable plugged in),\n  \/\/ Comment out this while loop, or it will prevent the remaining code from running.\n  \n  Serial.println();\n  Serial.println(\"BNO08x Read Example\");\n\n  Wire.begin();\n\n  \/\/if (myIMU.begin() == false) {  \/\/ Setup without INT\/RST control (Not Recommended)\n  if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) {\n    Serial.println(\"BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing...\");\n    while (1)\n      ;\n  }\n  Serial.println(\"BNO08x found!\");\n\n  \/\/ Wire.setClock(400000); \/\/Increase I2C data rate to 400kHz\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (myIMU.enableRotationVector() == true) {\n    Serial.println(F(\"Rotation vector enabled\"));\n    Serial.println(F(\"Output in form roll, pitch, yaw\"));\n  } else {\n    Serial.println(\"Could not enable rotation vector\");\n  }\n}\n\nvoid loop() {\n  delay(10);\n\n  if (myIMU.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n\n  \/\/ Has a new event come in on the Sensor Hub Bus?\n  if (myIMU.getSensorEvent() == true) {\n\n    \/\/ is it the correct sensor data we want?\n    if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) {\n\n    float roll = (myIMU.getRoll()) * 180.0 \/ PI; \/\/ Convert roll to degrees\n    float pitch = (myIMU.getPitch()) * 180.0 \/ PI; \/\/ Convert pitch to degrees\n    float yaw = (myIMU.getYaw()) * 180.0 \/ PI; \/\/ Convert yaw \/ heading to degrees\n\n    Serial.print(roll, 1);\n    Serial.print(F(\",\"));\n    Serial.print(pitch, 1);\n    Serial.print(F(\",\"));\n    Serial.print(yaw, 1);\n\n    Serial.println();\n    }\n  }\n}\n<\/pre>\n<\/div>\n<p>\n<p>The function <code>enableRotationVector()<\/code> activates the rotation vector report, which has the ID <code>SENSOR_REPORTID_ROTATION_VECTOR<\/code>. If a corresponding report is available, the angles are queried with <code>getRoll()<\/code>, <code>getPitch()<\/code> and <code>getYaw()<\/code> and converted from rad to degrees.  <\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_example_13_euler_angles.png\"><img loading=\"lazy\" decoding=\"async\" width=\"486\" height=\"111\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_example_13_euler_angles.png\" alt=\"Output SF_Example_13_EulerAngles.ino\" class=\"wp-image-25337\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_example_13_euler_angles.png 486w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_example_13_euler_angles-300x69.png 300w\" sizes=\"auto, (max-width: 486px) 100vw, 486px\" \/><\/a><figcaption class=\"wp-element-caption\">Output SF_Example_13_EulerAngles.ino<\/figcaption><\/figure>\n\n<h5 class=\"wp-block-heading\">Alternative rotation vectors<\/h5>\n<p>Instead of the rotation vector, you could also have selected a different rotation vector as the basis for the Euler angles. For example: If you wanted to use the &#8220;AR\/VR Stabilized Game Rotation Vector&#8221;, you would have to replace the following: <\/p>\n<ul>\n<li>Line 99: <code>enableRotationVector()<\/code> through <code>enableARVRStabilizedGameRotationVector(timeBetweenReports)<\/code>. The report period (timeBetweenReports) must be transferred in milliseconds.  <\/li>\n<li>Line 119: <code>SENSOR_REPORTID_ROTATION_VECTOR<\/code> through <code>SENSOR_REPORTID_AR_VR_STABILIZED_GAME_ROTATION_VECTOR<\/code>. <\/li>\n<\/ul>\n<p>The Sparkfun library could be a little better documented here. I have therefore summarized the rotation vector report IDs and the associated enable functions in a table (see below). It is not clear to me why the time between the reports is not specified for some enable functions.   <\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports-1024x192.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"192\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports-1024x192.png\" alt=\"Rotation Vector Report IDs and enable-functions\" class=\"wp-image-25399\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports-1024x192.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports-300x56.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports-768x144.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports-1320x247.png 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports.png 1347w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Rotation vector report IDs and enable-functions<\/figcaption><\/figure>\n\n<h3 class=\"wp-block-heading\">Rotation vector using the Adafruit lib<\/h3>\n<p>The Adafruit library is also equipped with an example sketch for the output of Euler angles. In contrast to the Sparkfun library, the conversion of the quaternions does not take place in the background but is part of the sketch.  <\/p>\n<p><strong>The sketch got stuck after a while when I used I\u00b2C and an ESP32 development board<\/strong>. Adafruit points out that there may be problems with I\u00b2C in conjunction with some boards (see <a href=\"https:\/\/learn.adafruit.com\/adafruit-9-dof-orientation-imu-fusion-breakout-bno085\/arduino\" target=\"_blank\" rel=\"noopener\">here<\/a>). Mit SPI gab es bei mir keine Probleme. <\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"Ada_quaternion_yaw_pitch_roll.ino\" data-enlighter-title=\"Ada_quaternion_yaw_pitch_roll.ino\">#include &lt;Arduino.h&gt;\n\/\/ This demo explores two reports (SH2_ARVR_STABILIZED_RV and SH2_GYRO_INTEGRATED_RV) both can be used to give \n\/\/ quartenion and euler (yaw, pitch roll) angles.  Toggle the FAST_MODE define to see other report.  \n\/\/ Note sensorValue.status gives calibration accuracy (which improves over time)\n#include &lt;Adafruit_BNO08x.h&gt;\n\n\/\/ For SPI mode, we need a CS pin\n#define BNO08X_CS 10\n#define BNO08X_INT 19\n\n\n\/\/ #define FAST_MODE\n\n\/\/ For SPI mode, we also need a RESET \n\/\/#define BNO08X_RESET 5\n\/\/ but not for I2C or UART\n#define BNO08X_RESET -1\n\nstruct euler_t {\n  float yaw;\n  float pitch;\n  float roll;\n} ypr;\n\nAdafruit_BNO08x  bno08x(BNO08X_RESET);\nsh2_SensorValue_t sensorValue;\n\n#ifdef FAST_MODE\n  \/\/ Top frequency is reported to be 1000Hz (but freq is somewhat variable)\n  sh2_SensorId_t reportType = SH2_GYRO_INTEGRATED_RV;\n  long reportIntervalUs = 2000;\n#else\n  \/\/ Top frequency is about 250Hz but this report is more accurate\n  sh2_SensorId_t reportType = SH2_ARVR_STABILIZED_RV;\n  long reportIntervalUs = 5000;\n#endif\nvoid setReports(sh2_SensorId_t reportType, long report_interval) {\n  Serial.println(\"Setting desired reports\");\n  if (! bno08x.enableReport(reportType, report_interval)) {\n    Serial.println(\"Could not enable stabilized remote vector\");\n  }\n}\n\nvoid setup(void) {\n\n  Serial.begin(115200);\n  while (!Serial) delay(10);     \/\/ will pause Zero, Leonardo, etc until serial console opens\n\n  Serial.println(\"Adafruit BNO08x test!\");\n\n  \/\/ Try to initialize!\n  if (!bno08x.begin_I2C(\/* 0x4B *\/)) {  \/\/ ADO = HIGH =&gt; I2C Address = 0x4B\n  \/\/if (!bno08x.begin_UART(&amp;Serial1)) {  \/\/ Requires a device with &gt; 300 byte UART buffer!\n  \/\/if (!bno08x.begin_SPI(BNO08X_CS, BNO08X_INT)) {\n    Serial.println(\"Failed to find BNO08x chip\");\n    while (1) { delay(10); }\n  }\n  Serial.println(\"BNO08x Found!\");\n\n\n  setReports(reportType, reportIntervalUs);\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\nvoid quaternionToEuler(float qr, float qi, float qj, float qk, euler_t* ypr, bool degrees = false) {\n\n    float sqr = sq(qr);\n    float sqi = sq(qi);\n    float sqj = sq(qj);\n    float sqk = sq(qk);\n\n    ypr-&gt;yaw = atan2(2.0 * (qi * qj + qk * qr), (sqi - sqj - sqk + sqr));\n    ypr-&gt;pitch = asin(-2.0 * (qi * qk - qj * qr) \/ (sqi + sqj + sqk + sqr));\n    ypr-&gt;roll = atan2(2.0 * (qj * qk + qi * qr), (-sqi - sqj + sqk + sqr));\n\n    if (degrees) {\n      ypr-&gt;yaw *= RAD_TO_DEG;\n      ypr-&gt;pitch *= RAD_TO_DEG;\n      ypr-&gt;roll *= RAD_TO_DEG;\n    }\n}\n\nvoid quaternionToEulerRV(sh2_RotationVectorWAcc_t* rotational_vector, euler_t* ypr, bool degrees = false) {\n    quaternionToEuler(rotational_vector-&gt;real, rotational_vector-&gt;i, rotational_vector-&gt;j, rotational_vector-&gt;k, ypr, degrees);\n}\n\nvoid quaternionToEulerGI(sh2_GyroIntegratedRV_t* rotational_vector, euler_t* ypr, bool degrees = false) {\n    quaternionToEuler(rotational_vector-&gt;real, rotational_vector-&gt;i, rotational_vector-&gt;j, rotational_vector-&gt;k, ypr, degrees);\n}\n\nvoid loop() {\n\n  if (bno08x.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports(reportType, reportIntervalUs);\n  }\n  \n  if (bno08x.getSensorEvent(&amp;sensorValue)) {\n    \/\/ in this demo only one report type will be received depending on FAST_MODE define (above)\n    switch (sensorValue.sensorId) {\n      case SH2_ARVR_STABILIZED_RV:\n        quaternionToEulerRV(&amp;sensorValue.un.arvrStabilizedRV, &amp;ypr, true);\n      case SH2_GYRO_INTEGRATED_RV:\n        \/\/ faster (more noise?)\n        quaternionToEulerGI(&amp;sensorValue.un.gyroIntegratedRV, &amp;ypr, true);\n        break;\n    }\n    static long last = 0;\n    long now = micros();\n    Serial.print(now - last);             Serial.print(\"\\t\");\n    last = now;\n    Serial.print(sensorValue.status);     Serial.print(\"\\t\");  \/\/ This is accuracy in the range of 0 to 3\n    Serial.print(ypr.yaw);                Serial.print(\"\\t\");\n    Serial.print(ypr.pitch);              Serial.print(\"\\t\");\n    Serial.println(ypr.roll);\n  }\n\n}\n<\/pre>\n<\/div>\n<p>\u00a0<\/p>\n<p>\n<p>As you can see, in this example you can switch between the AR\/VR Stabilized Rotation Vector and the Gyro Rotation Vector (which is faster but less precise) as a basis using by (un-)commenting <code>#define FAST_MODE<\/code>. <\/p>\n<p>In addition to the Euler angles, the sketch shows the time between the report outputs and the reliability of the values (accuracy). The following output example indicates that the time between reports can deviate quite considerably from the configured (5000 \u00b5s): <\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/output_ada_quaternion_yaw_pitch_roll.png\"><img loading=\"lazy\" decoding=\"async\" width=\"702\" height=\"129\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/output_ada_quaternion_yaw_pitch_roll.png\" alt=\"Output Ada_quaternion_yaw_pitch_roll.ino\" class=\"wp-image-25402\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/output_ada_quaternion_yaw_pitch_roll.png 702w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/output_ada_quaternion_yaw_pitch_roll-300x55.png 300w\" sizes=\"auto, (max-width: 702px) 100vw, 702px\" \/><\/a><figcaption class=\"wp-element-caption\">Output Ada_quaternion_yaw_pitch_roll.ino<\/figcaption><\/figure>\n<p>It is also possible to use other Rotation Vector reports. However, you need to know the names of the report IDs and the associated variable types. You can find them in <a href=\"https:\/\/github.com\/adafruit\/Adafruit_BNO08x\/blob\/master\/src\/sh2_SensorValue.h\" target=\"_blank\" rel=\"noopener\">sh2_SensorValue.h<\/a> or in this table:  <\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports_adafruit-1024x258.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"258\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports_adafruit-1024x258.png\" alt=\"Rotation Vector Report_IDs and variable types\" class=\"wp-image-25404\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports_adafruit-1024x258.png 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports_adafruit-300x76.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports_adafruit-768x193.png 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/rotation_vector_reports_adafruit.png 1179w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Rotation Vector Report_IDs and variable types<\/figcaption><\/figure>\n\n<h3 class=\"wp-block-heading\" id=\"classification_example\">Example Classification &#8211; Step Counter<\/h3>\n<p>As an example of a classification report, let&#8217;s take a look at the step counter. <\/p>\n\n<h4 class=\"wp-block-heading\">Step Counter using the Sparkfun lib<\/h4>\n<p>Apart from the fact that we are activating the step counter report here, there is nothing fundamentally new in this sketch. <\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"SF_Example_05_StepCounter.ino\" data-enlighter-title=\"SF_Example_05_StepCounter.ino\">\/*\n  Using the BNO08x IMU\n\n  This example shows the step count. Tap the IC a few times to emulate a step.\n\n  By: Nathan Seidle\n  SparkFun Electronics\n  Date: December 21st, 2017\n  SparkFun code, firmware, and software is released under the MIT License.\n  Please see LICENSE.md for further details.\n\n  Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017\n\n  Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the\n  CEVA Sensor Hub Driver, found here:\n  https:\/\/github.com\/ceva-dsp\/sh2\n\n  Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert\n  for Adafruit Industries. Found here:\n  https:\/\/github.com\/adafruit\/Adafruit_BNO08x\n\n  Also, utilizing I2C and SPI read\/write functions and code from the Adafruit\n  BusIO library found here:\n  https:\/\/github.com\/adafruit\/Adafruit_BusIO\n\n  Hardware Connections:\n  IoT RedBoard --&gt; BNO08x\n  QWIIC --&gt; QWIIC\n  A4  --&gt; INT\n  A5  --&gt; RST\n\n  BNO08x \"mode\" jumpers set for I2C (default):\n  PSO: OPEN\n  PS1: OPEN\n\n  Serial.print it out at 115200 baud to serial monitor.\n\n  Feel like supporting our work? Buy a board from SparkFun!\n  https:\/\/www.sparkfun.com\/products\/22857\n*\/\n\n#include &lt;Wire.h&gt;\n\n#include \"SparkFun_BNO08x_Arduino_Library.h\" \/\/ CTRL+Click here to get the library: http:\/\/librarymanager\/All#SparkFun_BNO08x\nBNO08x myIMU;\n\n\/\/ For the most reliable interaction with the SHTP bus, we need\n\/\/ to use hardware reset control, and to monitor the H_INT pin.\n\/\/ The H_INT pin will go low when its okay to talk on the SHTP bus.\n\/\/ Note, these can be other GPIO if you like.\n\/\/ Define as -1 to disable these features.\n#define BNO08X_INT  19\n\/\/#define BNO08X_INT  -1\n#define BNO08X_RST  18\n\/\/#define BNO08X_RST  -1\n\n#define BNO08X_ADDR 0x4B  \/\/ SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B\n\/\/#define BNO08X_ADDR 0x4A \/\/ Alternate address if ADR jumper is closed\n\nvoid setup() {\n  Serial.begin(115200);\n  \n  while(!Serial) delay(10); \/\/ Wait for Serial to become available.\n  \/\/ Necessary for boards with native USB (like the SAMD51 Thing+).\n  \/\/ For a final version of a project that does not need serial debug (or a USB cable plugged in),\n  \/\/ Comment out this while loop, or it will prevent the remaining code from running.\n  \n  Serial.println();\n  Serial.println(\"BNO08x Read Example\");\n\n  Wire.begin();\n\n  \/\/if (myIMU.begin() == false) {  \/\/ Setup without INT\/RST control (Not Recommended)\n  if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) {\n    Serial.println(\"BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing...\");\n    while (1)\n      ;\n  }\n  Serial.println(\"BNO08x found!\");\n\n  \/\/ Wire.setClock(400000); \/\/Increase I2C data rate to 400kHz\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (myIMU.enableStepCounter(65) == true) { \/\/Send data update every 65 ms (maximum)\n    Serial.println(F(\"Step Counter enabled\"));\n    Serial.println(F(\"Step count since sketch started:\"));\n  } else {\n    Serial.println(\"Could not step counter\");\n  }\n}\n\nvoid loop() {\n  delay(500); \/\/ step counter needs a little longer of delay (200ms or more)\n\n  if (myIMU.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n\n  \/\/ Has a new event come in on the Sensor Hub Bus?\n  if (myIMU.getSensorEvent() == true) {\n\n    \/\/ is it the correct sensor data we want?\n    if (myIMU.getSensorEventID() == SENSOR_REPORTID_STEP_COUNTER) {\n\n      unsigned int steps = myIMU.getStepCount();\n\n      Serial.print(steps);\n\n      Serial.println();\n    }\n  }\n}\n<\/pre>\n<\/div>\n<p>\n<p>Here is an excerpt from the output of the sketch. To test the function, I took a few steps while standing in front of my desk with the breadboard in my hand (which probably looked pretty stupid). It works really well.  <\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/output_sf_example5_step_counter.png\"><img loading=\"lazy\" decoding=\"async\" width=\"561\" height=\"146\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/output_sf_example5_step_counter.png\" alt=\"Output of SF_Example_05_StepCounter.ino\" class=\"wp-image-25408\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/output_sf_example5_step_counter.png 561w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/output_sf_example5_step_counter-300x78.png 300w\" sizes=\"auto, (max-width: 561px) 100vw, 561px\" \/><\/a><figcaption class=\"wp-element-caption\">Output of SF_Example_05_StepCounter.ino<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Step counter using the Adafruit lib<\/h4>\n<p>The Adafruit sketch for the step counter is also not very surprising. Only one aspect is new, namely the latency in microseconds with <code>sensorValue.un.stepCounter.latency<\/code>. The latency is the delay between the movement and the triggering of the event.  <\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"Ada_step_counter.ino\" data-enlighter-title=\"Ada_step_counter.ino\">\/\/ Basic demo for readings from Adafruit BNO08x\n#include &lt;Adafruit_BNO08x.h&gt;\n\n\/\/ For SPI mode, we need a CS pin\n#define BNO08X_CS 10\n#define BNO08X_INT 19\n\n\/\/ For SPI mode, we also need a RESET\n\/\/#define BNO08X_RESET 5\n\/\/ but not for I2C or UART\n#define BNO08X_RESET -1\n\nAdafruit_BNO08x bno08x(BNO08X_RESET);\nsh2_SensorValue_t sensorValue;\n\nvoid setup(void) {\n  Serial.begin(115200);\n  while (!Serial)\n    delay(10); \/\/ will pause Zero, Leonardo, etc until serial console opens\n\n  Serial.println(\"Adafruit BNO08x test!\");\n\n  \/\/ Try to initialize!\n  if (!bno08x.begin_I2C()) {\n    \/\/ if (!bno08x.begin_UART(&amp;Serial1)) {  \/\/ Requires a device with &gt; 300 byte\n    \/\/ UART buffer! if (!bno08x.begin_SPI(BNO08X_CS, BNO08X_INT)) {\n    Serial.println(\"Failed to find BNO08x chip\");\n    while (1) {\n      delay(10);\n    }\n  }\n  Serial.println(\"BNO08x Found!\");\n\n  setReports();\n\n  Serial.println(\"Reading Step Counter events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (!bno08x.enableReport(SH2_STEP_COUNTER)) {\n    Serial.println(\"Could not enable step counter\");\n }\n}\n\nvoid loop() {\n  delay(10);\n\n  if (bno08x.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n\n  if (!bno08x.getSensorEvent(&amp;sensorValue)) {\n    return;\n  }\n\n  switch (sensorValue.sensorId) {\n\n  case SH2_STEP_COUNTER:\n    Serial.print(\"Step Counter - steps: \");\n    Serial.print(sensorValue.un.stepCounter.steps);\n    Serial.print(\" latency: \");\n    Serial.println(sensorValue.un.stepCounter.latency);\n    break;\n  }\n}<\/pre>\n<\/div>\n<p>\n<p>Here is the output on my serial monitor:<\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_step_counter.png\"><img loading=\"lazy\" decoding=\"async\" width=\"661\" height=\"96\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_step_counter.png\" alt=\"Output of ada_step_counter.ino\" class=\"wp-image-25344\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_step_counter.png 661w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_step_counter-300x44.png 300w\" sizes=\"auto, (max-width: 661px) 100vw, 661px\" \/><\/a><figcaption class=\"wp-element-caption\">Output of ada_step_counter.ino<\/figcaption><\/figure>\n<p>The latency values are extremely low while walking. If you start walking again after a pause, you will see that the latency for the first step is considerably higher.  <\/p>\n\n<h3 class=\"wp-block-heading\" id=\"combined_reports\">Combining reports<\/h3>\n<p>So far we have only activated one report at a time. However, you can also activate several reports in parallel.  <\/p>\n\n<h4 class=\"wp-block-heading\">&#8220;Unordered&#8221; output using the example of Adafruit<\/h4>\n<p>I will start with the Adafruit library, as there is a sample sketch for it (<a href=\"https:\/\/github.com\/adafruit\/Adafruit_BNO08x\/blob\/master\/examples\/more_reports\/more_reports.ino\" target=\"_blank\" rel=\"noopener\">more_reports.ino<\/a>). In the screenshot below, you can see that the reports are displayed in a rather disorderly manner. For applications that just need to respond to certain conditions, that&#8217;s fine. <\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_more_reports.png\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"312\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_more_reports.png\" alt=\"Issue more_reports.ino\" class=\"wp-image-25350\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_more_reports.png 800w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_more_reports-300x117.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ada_more_reports-768x300.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><figcaption class=\"wp-element-caption\">Issue more_reports.ino<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Step Counter and Stability Classification with Sparkfun<\/h4>\n<p>Using the step counter and activity classification, let&#8217;s take a look at how you can combine and time two reports. <\/p>\n<p>The time between the reports can be set in the Sparkfun library with <code>enablexxxx(timeBetweenReports)<\/code>. Here xxxx is the respective report, and timeBetweenReports is the period in milliseconds. Unfortunately, the period can (currently) only be extended to a maximum of 65 milliseconds. The default setting is 10 milliseconds.    <\/p>\n<p>My aim was to generate an output of the two reports approximately every second. This is beyond 65 milliseconds, and therefore the following sketch controls the output frequency of the step counter via <code>millis()<\/code>. The stability classification is only output if the steps have been output beforehand.   <\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"SF_steps_and_stability.ino\" data-enlighter-title=\"SF_steps_and_stability.ino\">#include &lt;Wire.h&gt;\n#include \"SparkFun_BNO08x_Arduino_Library.h\" \/\/ CTRL+Click here to get the library: http:\/\/librarymanager\/All#SparkFun_BNO08x\n\nBNO08x myIMU;\n\n#define BNO08X_INT  19\n\/\/#define BNO08X_INT  -1\n#define BNO08X_RST  18\n\/\/#define BNO08X_RST  -1\n\n#define BNO08X_ADDR 0x4B  \/\/ SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B\n\/\/#define BNO08X_ADDR 0x4A \/\/ Alternate address if ADR jumper is closed\n\n#define OUTPUT_PERIOD_MS 1000 \/\/ One output per second\n\nvoid setup() {\n  Serial.begin(115200);\n  \n  while(!Serial) delay(10); \n\n  Serial.println();\n  Serial.println(\"BNO08x Read Example\");\n\n  Wire.begin();\n\n  \/\/if (myIMU.begin() == false) {  \/\/ Setup without INT\/RST control (Not Recommended)\n  if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) {\n    Serial.println(\"BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing...\");\n    while (1)\n      ;\n  }\n  Serial.println(\"BNO08x found!\");\n\n  \/\/ Wire.setClock(400000); \/\/Increase I2C data rate to 400kHz\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  \n  if (myIMU.enableStepCounter(65) == true) { \/\/Send data update every 65 (\n    Serial.println(F(\"Step Counter enabled\"));\n    Serial.println(F(\"Step count since sketch started:\"));\n  } else {\n    Serial.println(\"Could not step counter\");\n  }\n\n  if (myIMU.enableStabilityClassifier(65) == true) {\n    Serial.println(F(\"Stability Classifier enabled\"));\n  } else {\n    Serial.println(\"Could not enable Stability Classifier\");\n  }\n}\n\nvoid loop() {\n  static unsigned long lastUpdateStepCounter = 0;\n  static bool lastUpdateWasStepCounter = false;\n   \n  if (myIMU.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n\n  if (myIMU.getSensorEvent() == true) {\n  \n    \/\/ is it the correct sensor data we want?\n    if (myIMU.getSensorEventID() == SENSOR_REPORTID_STEP_COUNTER) {\n      if(millis() - lastUpdateStepCounter &gt; OUTPUT_PERIOD_MS){\n        unsigned int steps = myIMU.getStepCount();\n\n        Serial.print(\"Steps: \");\n        Serial.println(steps);\n        lastUpdateWasStepCounter = true;\n        lastUpdateStepCounter = millis();\n      }\n    }\n\n    if (myIMU.getSensorEventID() == SENSOR_REPORTID_STABILITY_CLASSIFIER) {\n      if(lastUpdateWasStepCounter){\n        byte classification = myIMU.getStabilityClassifier();\n\n        if(classification == STABILITY_CLASSIFIER_UNKNOWN) Serial.print(F(\"Unknown classification\"));\n        else if(classification == STABILITY_CLASSIFIER_ON_TABLE) Serial.print(F(\"On table\"));\n        else if(classification == STABILITY_CLASSIFIER_STATIONARY) Serial.print(F(\"Stationary\"));\n        else if(classification == STABILITY_CLASSIFIER_STABLE) Serial.print(F(\"Stable\"));\n        else if(classification == STABILITY_CLASSIFIER_MOTION) Serial.print(F(\"Motion\"));\n        else if(classification == STABILITY_CLASSIFIER_RESERVED) Serial.print(F(\"[Reserved]\"));\n\n        Serial.println();\n        lastUpdateWasStepCounter = false;\n      }\n    }\n  }\n}<\/pre>\n<\/div>\n<p>\n<p>Here is a screenshot of the serial monitor:<\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_steps_and_stability.png\"><img loading=\"lazy\" decoding=\"async\" width=\"670\" height=\"166\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_steps_and_stability.png\" alt=\"\" class=\"wp-image-25348\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_steps_and_stability.png 670w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_sf_steps_and_stability-300x74.png 300w\" sizes=\"auto, (max-width: 670px) 100vw, 670px\" \/><\/a><figcaption class=\"wp-element-caption\">Output of sf_steps_and_stability.ino<\/figcaption><\/figure>\n\n<h4 class=\"wp-block-heading\">Step Counter and Stability Classification with Adafruit<\/h4>\n<p>With the Adafruit library, it is easier to synchronize the outputs, as there is no restriction on the time between the reports (except that it is a uint32_t value). You pass this period to the function <code>enableReport()<\/code> as the second parameter in microseconds.  <\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"Ada_step_and_stability.ino\" data-enlighter-title=\"Ada_step_and_stability.ino\">\/\/ Basic demo for readings from Adafruit BNO08x\n#include &lt;Adafruit_BNO08x.h&gt;\n\n\/\/ For SPI mode, we need a CS pin\n#define BNO08X_CS 10\n#define BNO08X_INT 19\n\n\/\/ For SPI mode, we also need a RESET\n\/\/#define BNO08X_RESET 5\n\/\/ but not for I2C or UART\n#define BNO08X_RESET -1\n\nAdafruit_BNO08x bno08x(BNO08X_RESET);\nsh2_SensorValue_t sensorValue;\n\nvoid setup(void) {\n  Serial.begin(115200);\n  while (!Serial)\n    delay(10); \/\/ will pause Zero, Leonardo, etc. until serial console opens\n\n  Serial.println(\"Adafruit BNO08x test!\");\n\n  \/\/ Try to initialize!\n  if (!bno08x.begin_I2C()) {\n    \/\/ if (!bno08x.begin_UART(&amp;Serial1)) {  \/\/ Requires a device with &gt; 300 byte\n    \/\/ UART buffer! if (!bno08x.begin_SPI(BNO08X_CS, BNO08X_INT)) {\n    Serial.println(\"Failed to find BNO08x chip\");\n    while (1) {\n      delay(10);\n    }\n  }\n  Serial.println(\"BNO08x Found!\");\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (!bno08x.enableReport(SH2_STEP_COUNTER, 2000000)) { \/\/ period: 2s\n    Serial.println(\"Could not enable step counter\");\n  }\n  if (!bno08x.enableReport(SH2_STABILITY_CLASSIFIER, 2000000)) {  \/\/period: 2s\n    Serial.println(\"Could not enable stability classifier\");\n  }\n}\n\nvoid loop() {\n  delay(10);\n  if (bno08x.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n\n  if (!bno08x.getSensorEvent(&amp;sensorValue)) {\n    return;\n  }\n\n  switch (sensorValue.sensorId) {\n\n    case SH2_STEP_COUNTER:\n      Serial.print(\"Step Counter - steps: \");\n      Serial.print(sensorValue.un.stepCounter.steps);\n      Serial.print(\" latency: \");\n      Serial.println(sensorValue.un.stepCounter.latency);\n      break;\n\n    case SH2_STABILITY_CLASSIFIER: {\n      Serial.print(\"Stability Classification: \");\n      sh2_StabilityClassifier_t stability = sensorValue.un.stabilityClassifier;\n      switch (stability.classification) {\n      case STABILITY_CLASSIFIER_UNKNOWN:\n        Serial.println(\"Unknown\");\n        break;\n      case STABILITY_CLASSIFIER_ON_TABLE:\n        Serial.println(\"On Table\");\n        break;\n      case STABILITY_CLASSIFIER_STATIONARY:\n        Serial.println(\"Stationary\");\n        break;\n      case STABILITY_CLASSIFIER_STABLE:\n        Serial.println(\"Stable\");\n        break;\n      case STABILITY_CLASSIFIER_MOTION:\n        Serial.println(\"In Motion\");\n        break;\n      }\n      break;\n    }\n  }\n}<\/pre>\n<\/div>\n<p>\u00a0<\/p>\n<p>\n<p>Here is the corresponding output:<\/p>\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ads_steps_and_stability.png\"><img loading=\"lazy\" decoding=\"async\" width=\"873\" height=\"148\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ads_steps_and_stability.png\" alt=\"Output of Ada_step_and_stability.ino\" class=\"wp-image-25349\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ads_steps_and_stability.png 873w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ads_steps_and_stability-300x51.png 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2025\/12\/output_ads_steps_and_stability-768x130.png 768w\" sizes=\"auto, (max-width: 873px) 100vw, 873px\" \/><\/a><figcaption class=\"wp-element-caption\">Output of Ada_step_and_stability.ino<\/figcaption><\/figure>\n\n<h2 class=\"wp-block-heading\" id=\"appendix\">Appendix &#8211; SPI, UART, UART-RVC, 5-volt boards<\/h2>\n<p>In the appendix, you will find circuits and sketches for alternative communication protocols and an example of the wiring for a 5-volt-based board. <\/p>\n\n<h3 class=\"wp-block-heading\" id=\"appendix_spi\">SPI control of the BNO08x modules<\/h3>\n<p>Here is an example of connecting the no-name BNO08x module to an ESP32 development board via SPI:<\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_spi-1024x536.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"536\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_spi-1024x536.webp\" alt=\"Connection of a BNO08x to an ESP32 board via SPI\" class=\"wp-image-25367\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_spi-1024x536.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_spi-300x157.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_spi-768x402.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_spi-1320x691.webp 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_spi.webp 1416w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">BNO08x on the ESP32 board via SPI<\/figcaption><\/figure>\n<p>If you want to save cables, then pull up PS0 and PS1 by connecting the solder pads on the back of the module. If you only use one SPI device on the SPI interface, you could also pull CS permanently to GND.  <\/p>\n\n<h4 class=\"wp-block-heading\">SPI with Sparkfun<\/h4>\n<p>This is what the accelerometer sketch for the SPI connection looks like:<\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"SF_spi_acceleration.ino\" data-enlighter-title=\"SF_spi_acceleration.ino\">#include \"SparkFun_BNO08x_Arduino_Library.h\" \nBNO08x myIMU;\n\n#define BNO08X_CS   5\n#define BNO08X_INT  22\n#define BNO08X_RST  4\n\nvoid setup() {\n  Serial.begin(115200);\n  \n  while(!Serial) delay(10); \/\/ Wait for Serial to become available.\n  \n  Serial.println();\n  Serial.println(\"BNO08x Read Example\");\n\n if (myIMU.beginSPI(BNO08X_CS, BNO08X_INT, BNO08X_RST) == false) {\n    Serial.println(\"BNO08x not detected. Check your jumpers and the hookup guide. Freezing...\");\n    while (1)\n      ;\n  }\n  Serial.println(\"BNO08x found!\");\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (myIMU.enableAccelerometer() == true) {\n    Serial.println(F(\"Accelerometer enabled\"));\n    Serial.println(F(\"Output in form x, y, z, in m\/s^2\"));\n  } else {\n    Serial.println(\"Could not enable accelerometer\");\n  }\n  delay(100); \/\/ important for SPI!\n  \n}\n\nvoid loop() {\n  delay(10);\n\n  if (myIMU.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n\n  \/\/ Has a new event come in on the Sensor Hub Bus?\n  if (myIMU.getSensorEvent() == true) {\n\n    \/\/ is it the correct sensor data we want?\n    if (myIMU.getSensorEventID() == SENSOR_REPORTID_ACCELEROMETER) {\n\n      float x = myIMU.getAccelX();\n      float y = myIMU.getAccelY();\n      float z = myIMU.getAccelZ();\n\n      Serial.print(x, 2);\n      Serial.print(F(\",\"));\n      Serial.print(y, 2);\n      Serial.print(F(\",\"));\n      Serial.print(z, 2);\n\n      Serial.println();\n    }\n  }\n}<\/pre>\n<\/div>\n<p>\n\n<h4 class=\"wp-block-heading\">SPI with Adafruit<\/h4>\n<p>Here is the Adafruit SPI version:<\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"Ada_spi_acceleration.ino\" data-enlighter-title=\"Ada_spi_acceleration.ino\">#include &lt;Adafruit_BNO08x.h&gt;\n\n#define BNO08X_CS 5\n#define BNO08X_INT 22\n#define BNO08X_RESET 4\n\nAdafruit_BNO08x  bno08x(BNO08X_RESET);\nsh2_SensorValue_t sensorValue;\n\nvoid setup(void) {\n  Serial.begin(115200);\n  while (!Serial) delay(10);     \/\/ will pause Zero, Leonardo, etc until serial console opens\n\n  Serial.println(\"Adafruit BNO08x Accelerometer test!\");\n\n  \/\/ Try to initialize!\n  if (!bno08x.begin_SPI(BNO08X_CS, BNO08X_INT)) {\n    Serial.println(\"Failed to find BNO08x chip\");\n    while (1) { delay(10); }\n  }\n  Serial.println(\"BNO08x Found!\");\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (! bno08x.enableReport(SH2_ACCELEROMETER)) {\n    Serial.println(\"Could not enable accelerometerame vector\");\n  }\n}\n\n\nvoid loop() {\n  delay(10);\n\n  if (bno08x.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n  \n  if (! bno08x.getSensorEvent(&amp;sensorValue)) {\n    return;\n  }\n  \n  switch (sensorValue.sensorId) {\n    \n    case SH2_ACCELEROMETER:\n      Serial.print(\"Accelerometer - x: \");\n      Serial.print(sensorValue.un.accelerometer.x);\n      Serial.print(\" y: \");\n      Serial.print(sensorValue.un.accelerometer.y);\n      Serial.print(\" z: \");\n      Serial.println(sensorValue.un.accelerometer.z);\n      break;\n  }\n}<\/pre>\n<\/div>\n<p>\n\n<h3 class=\"wp-block-heading\" id=\"appendix_uart\">UART control (Adafruit only)<\/h3>\n<p>The UART control is only implemented in the Adafruit library. It is advisable not to use the same serial interface as for the connection to the serial monitor. In my example circuit and the associated sketch, I use pins 18 and 19 as RX2 and TX2 respectively.    <\/p>\n<p>If you are using a board like the one shown below: I could also have used the pins labeled RX2 and TX2. However, they are assigned to GPIOs 16 and 17. In the ESP32 board package, however, RX2 and TX2 are assigned to pins 4 and 25. Because of this confusion, I decided to use other pins.   <\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart-1024x426.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"426\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart-1024x426.webp\" alt=\"BNO08x on the ESP32 via UART\" class=\"wp-image-25360\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart-1024x426.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart-300x125.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart-768x320.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart-1320x549.webp 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart.webp 1439w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">BNO08x on the ESP32 via UART<\/figcaption><\/figure>\n<p>Here is the example sketch:<\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"Ada_uart_acceleration.ino\" data-enlighter-title=\"Ada_uart_acceleration.ino\">#include &lt;Adafruit_BNO08x.h&gt;\n\n#define BNO08X_RESET -1\n#define RX2 18\n#define TX2 19\n\nAdafruit_BNO08x  bno08x(BNO08X_RESET);\nsh2_SensorValue_t sensorValue;\n\nvoid setup(void) {\n  Serial.begin(115200);\n  Serial2.begin(115200, SERIAL_8N1, RX2, TX2);\n  while (!Serial) delay(10);     \/\/ will pause Zero, Leonardo, etc until serial console opens\n  while (!Serial2) delay(10); \n\n  Serial.println(\"Adafruit BNO08x Accelerometer test!\");\n\n  \/\/ Try to initialize!\n  if (!bno08x.begin_UART(&amp;Serial2)) {  \/\/ Requires a device with &gt; 300 byte UART buffer!\n    Serial.println(\"Failed to find BNO08x chip\");\n    while (1) { delay(10); }\n  }\n  Serial.println(\"BNO08x Found!\");\n\n  setReports();\n\n  Serial.println(\"Reading events\");\n  delay(100);\n}\n\n\/\/ Here is where you define the sensor outputs you want to receive\nvoid setReports(void) {\n  Serial.println(\"Setting desired reports\");\n  if (! bno08x.enableReport(SH2_ACCELEROMETER)) {\n    Serial.println(\"Could not enable accelerometerame vector\");\n  }\n}\n\n\nvoid loop() {\n  delay(10);\n\n  if (bno08x.wasReset()) {\n    Serial.print(\"sensor was reset \");\n    setReports();\n  }\n  \n  if (! bno08x.getSensorEvent(&amp;sensorValue)) {\n    return;\n  }\n  \n  switch (sensorValue.sensorId) {\n    \n    case SH2_ACCELEROMETER:\n      Serial.print(\"Accelerometer - x: \");\n      Serial.print(sensorValue.un.accelerometer.x);\n      Serial.print(\" y: \");\n      Serial.print(sensorValue.un.accelerometer.y);\n      Serial.print(\" z: \");\n      Serial.println(sensorValue.un.accelerometer.z);\n      break;\n  }\n}<\/pre>\n<\/div>\n<p>\n\n<h3 class=\"wp-block-heading\" id=\"appendix_uart_rvc\">UART-RVC control (Adafruit only)<\/h3>\n<p>For the UART-RVC variant, you will need to use a different library, such as <a href=\"https:\/\/github.com\/adafruit\/Adafruit_BNO08x_RVC\" target=\"_blank\" rel=\"noopener\">Adafruit BNO08x RVC<\/a>. It has a very limited range of functions, but this is not due to the library, but to the SH-2 firmware. You can only use it to determine the rotation vector and the accelerometer values. However, this can be sufficient for many applications. <\/p>\n<p>Here is the wiring:<\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart_rvc-1024x429.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"429\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart_rvc-1024x429.webp\" alt=\"BNO08x connected to an ESP32 board via UART-RVC\" class=\"wp-image-25361\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart_rvc-1024x429.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart_rvc-300x126.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart_rvc-768x322.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart_rvc-1320x553.webp 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/bno08x_uart_rvc.webp 1425w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">BNO08x connected to an ESP32 board via UART-RVC<\/figcaption><\/figure>\n<p>And here is the corresponding example sketch:<\/p>\n<\/p>\n<div class=\"scroll-paragraph\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-group=\"Ada_uart_rvc_accel_euler.ino\" data-enlighter-title=\"Ada_uart_rvc_accel_euler.ino\">#include \"Adafruit_BNO08x_RVC.h\"\n\n#define RX2 18\n#define TX2 19\n\nAdafruit_BNO08x_RVC rvc = Adafruit_BNO08x_RVC();\n\nvoid setup() {\n  \/\/ Wait for serial monitor to open\n  Serial.begin(115200);\n  Serial2.begin(115200, SERIAL_8N1, RX2, TX2);\n  while (!Serial) delay(10);\n  while (!Serial2) delay(10); \n\n  Serial.println(\"Adafruit BNO08x IMU - UART-RVC mode\");\n\n  Serial1.begin(115200); \/\/ This is the baud rate specified by the datasheet\n  while (!Serial1)\n    delay(10);\n\n  if (!rvc.begin(&amp;Serial2)) { \/\/ connect to the sensor over hardware serial\n    Serial.println(\"Could not find BNO08x!\");\n    while (1)\n      delay(10);\n  }\n\n  Serial.println(\"BNO08x found!\");\n}\n\nvoid loop() {\n  BNO08x_RVC_Data heading;\n\n  if (!rvc.read(&amp;heading)) {\n    return;\n  }\n\n  Serial.println();\n  Serial.println(F(\"---------------------------------------\"));\n  Serial.println(F(\"Principal Axes:\"));\n  Serial.println(F(\"---------------------------------------\"));\n  Serial.print(F(\"Yaw: \"));\n  Serial.print(heading.yaw);\n  Serial.print(F(\"\\tPitch: \"));\n  Serial.print(heading.pitch);\n  Serial.print(F(\"\\tRoll: \"));\n  Serial.println(heading.roll);\n  Serial.println(F(\"---------------------------------------\"));\n  Serial.println(F(\"Acceleration\"));\n  Serial.println(F(\"---------------------------------------\"));\n  Serial.print(F(\"X: \"));\n  Serial.print(heading.x_accel);\n  Serial.print(F(\"\\tY: \"));\n  Serial.print(heading.y_accel);\n  Serial.print(F(\"\\tZ: \"));\n  Serial.println(heading.z_accel);\n  Serial.println(F(\"---------------------------------------\"));\n\n\n  \/\/  delay(200);\n}<\/pre>\n<\/div>\n<p>\n\n<h3 class=\"wp-block-heading\" id=\"appendix_5v_boards\">Use of 5-volt boards using the example of the UNO R4 Minima<\/h3>\n<p>And finally, I wanted to show that you can, of course, also use 5-volt boards such as the Arduino UNO R4 Minima. If you don&#8217;t have a 5-volt-capable BNO08x module like the one from Adafruit, you&#8217;ll have to use a level shifter (e.g. the TXS0108E). Nevertheless, your microcontroller board must, of course, still meet the high demands on the RAM.  <\/p>\n<p>Here is an example of the circuit for an Arduino UNO R4 Minima with TXS0108E level shifter using SPI:<\/p>\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/r4_minima_bno08x__spi-1024x525.webp\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"525\" src=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/r4_minima_bno08x__spi-1024x525.webp\" alt=\"BNO08x module on the Arduino UNO R4 Minima\" class=\"wp-image-25433\" srcset=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/r4_minima_bno08x__spi-1024x525.webp 1024w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/r4_minima_bno08x__spi-300x154.webp 300w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/r4_minima_bno08x__spi-768x394.webp 768w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/r4_minima_bno08x__spi-1536x787.webp 1536w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/r4_minima_bno08x__spi-1320x677.webp 1320w, https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/r4_minima_bno08x__spi.webp 1639w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">BNO08x module on the Arduino UNO R4 Minima<\/figcaption><\/figure>\n<p>That is quite a lot of plugging or soldering work. <\/p>\n\n<h2 class=\"wp-block-heading\">Acknowledgement<\/h2>\n\n<p>The coordinate cross in the foreground of my post image(<a href=\"https:\/\/pixabay.com\/de\/vectors\/erde-geometrie-kugel-breite-40452\/\" target=\"_blank\" rel=\"noopener\">link<\/a>) comes from Clker-Free-Vector-Images on <a href=\"https:\/\/pixabay.com\/de\/\/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=40452\" target=\"_blank\" rel=\"noopener\">Pixabay<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The BNO08x family comprises 9-DoF IMUs that use sensor fusion to detect orientation in space and complex movement patterns such as footsteps. I will show you how to control these sensors with suitable libraries.  <\/p>\n","protected":false},"author":1,"featured_media":25485,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[919,572],"tags":[2857,556,2850,2851,2849,1117,2863,2860,1338,666,2867,2862,2856,2865,2858,2859,2855,2853,2866,2861,2854,1750,1503,1502,2852,2864],"class_list":["post-25486","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-acceleration","category-sensors","tag-adafruit","tag-arduino-en-2","tag-bno085","tag-bno086","tag-bno08x","tag-calibration","tag-classification","tag-euler-angle","tag-gyroscope","tag-i2c-en","tag-magnetic-field-sensor","tag-orientation","tag-pedometer","tag-pitch","tag-ps0","tag-ps1","tag-quaternion","tag-report-id","tag-roll","tag-rotation-vector","tag-sh-2","tag-sparkfun-en","tag-spi-en","tag-uart-en","tag-uart-rvc","tag-yaw"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>BNO08x - 9-DoF-IMUs &#8226; Wolles Elektronikkiste<\/title>\n<meta name=\"description\" content=\"The BNO08x family comprises 9-DoF IMUs that use sensor fusion to recognize orientation in space and complex movement patterns (e.g. steps).\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"BNO08x - 9-DoF-IMUs &#8226; Wolles Elektronikkiste\" \/>\n<meta property=\"og:description\" content=\"The BNO08x family comprises 9-DoF IMUs that use sensor fusion to recognize orientation in space and complex movement patterns (e.g. steps).\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus\" \/>\n<meta property=\"og:site_name\" content=\"Wolles Elektronikkiste\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-17T14:28:44+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-02-01T09:29:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/post_image_bno08x_3.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1000\" \/>\n\t<meta property=\"og:image:height\" content=\"1000\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Wolfgang Ewald\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Wolfgang Ewald\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"41 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus\"},\"author\":{\"name\":\"Wolfgang Ewald\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"headline\":\"BNO08x &#8211; 9-DoF-IMUs\",\"datePublished\":\"2026-01-17T14:28:44+00:00\",\"dateModified\":\"2026-02-01T09:29:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus\"},\"wordCount\":3810,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/post_image_bno08x_3.jpg\",\"keywords\":[\"Adafruit\",\"Arduino\",\"BNO085\",\"BNO086\",\"BNO08x\",\"Calibration\",\"Classification\",\"Euler angle\",\"gyroscope\",\"I2C\",\"Magnetic field sensor\",\"orientation\",\"Pedometer\",\"Pitch\",\"PS0\",\"PS1\",\"Quaternion\",\"Report ID\",\"Roll\",\"Rotation vector\",\"SH-2\",\"Sparkfun\",\"SPI\",\"UART\",\"UART-RVC\",\"Yaw\"],\"articleSection\":[\"Acceleration\",\"Sensors\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus\",\"name\":\"BNO08x - 9-DoF-IMUs &#8226; Wolles Elektronikkiste\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/post_image_bno08x_3.jpg\",\"datePublished\":\"2026-01-17T14:28:44+00:00\",\"dateModified\":\"2026-02-01T09:29:00+00:00\",\"description\":\"The BNO08x family comprises 9-DoF IMUs that use sensor fusion to recognize orientation in space and complex movement patterns (e.g. steps).\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus#primaryimage\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/post_image_bno08x_3.jpg\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/post_image_bno08x_3.jpg\",\"width\":1000,\"height\":1000},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\\\/bno08x-9-dof-imus#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"BNO08x &#8211; 9-DoF-IMUs\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#website\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en\",\"name\":\"Wolles Elektronikkiste\",\"description\":\"Die wunderbare Welt der Elektronik\",\"publisher\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/en#\\\/schema\\\/person\\\/b774e4d64b4766889a2f7c6e5ec85b46\",\"name\":\"Wolfgang Ewald\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"url\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"contentUrl\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\",\"width\":512,\"height\":512,\"caption\":\"Wolfgang Ewald\"},\"logo\":{\"@id\":\"https:\\\/\\\/wolles-elektronikkiste.de\\\/wp-content\\\/uploads\\\/2019\\\/03\\\/cropped-Logo-1.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"BNO08x - 9-DoF-IMUs &#8226; Wolles Elektronikkiste","description":"The BNO08x family comprises 9-DoF IMUs that use sensor fusion to recognize orientation in space and complex movement patterns (e.g. steps).","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus","og_locale":"en_US","og_type":"article","og_title":"BNO08x - 9-DoF-IMUs &#8226; Wolles Elektronikkiste","og_description":"The BNO08x family comprises 9-DoF IMUs that use sensor fusion to recognize orientation in space and complex movement patterns (e.g. steps).","og_url":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus","og_site_name":"Wolles Elektronikkiste","article_published_time":"2026-01-17T14:28:44+00:00","article_modified_time":"2026-02-01T09:29:00+00:00","og_image":[{"width":1000,"height":1000,"url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/post_image_bno08x_3.jpg","type":"image\/jpeg"}],"author":"Wolfgang Ewald","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Wolfgang Ewald","Est. reading time":"41 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus#article","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus"},"author":{"name":"Wolfgang Ewald","@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"headline":"BNO08x &#8211; 9-DoF-IMUs","datePublished":"2026-01-17T14:28:44+00:00","dateModified":"2026-02-01T09:29:00+00:00","mainEntityOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus"},"wordCount":3810,"commentCount":0,"publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/post_image_bno08x_3.jpg","keywords":["Adafruit","Arduino","BNO085","BNO086","BNO08x","Calibration","Classification","Euler angle","gyroscope","I2C","Magnetic field sensor","orientation","Pedometer","Pitch","PS0","PS1","Quaternion","Report ID","Roll","Rotation vector","SH-2","Sparkfun","SPI","UART","UART-RVC","Yaw"],"articleSection":["Acceleration","Sensors"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus#respond"]}]},{"@type":"WebPage","@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus","url":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus","name":"BNO08x - 9-DoF-IMUs &#8226; Wolles Elektronikkiste","isPartOf":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#website"},"primaryImageOfPage":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus#primaryimage"},"image":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus#primaryimage"},"thumbnailUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/post_image_bno08x_3.jpg","datePublished":"2026-01-17T14:28:44+00:00","dateModified":"2026-02-01T09:29:00+00:00","description":"The BNO08x family comprises 9-DoF IMUs that use sensor fusion to recognize orientation in space and complex movement patterns (e.g. steps).","breadcrumb":{"@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus#primaryimage","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/post_image_bno08x_3.jpg","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2026\/01\/post_image_bno08x_3.jpg","width":1000,"height":1000},{"@type":"BreadcrumbList","@id":"https:\/\/wolles-elektronikkiste.de\/en\/bno08x-9-dof-imus#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/wolles-elektronikkiste.de\/en"},{"@type":"ListItem","position":2,"name":"BNO08x &#8211; 9-DoF-IMUs"}]},{"@type":"WebSite","@id":"https:\/\/wolles-elektronikkiste.de\/en#website","url":"https:\/\/wolles-elektronikkiste.de\/en","name":"Wolles Elektronikkiste","description":"Die wunderbare Welt der Elektronik","publisher":{"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wolles-elektronikkiste.de\/en?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/wolles-elektronikkiste.de\/en#\/schema\/person\/b774e4d64b4766889a2f7c6e5ec85b46","name":"Wolfgang Ewald","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","url":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","contentUrl":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png","width":512,"height":512,"caption":"Wolfgang Ewald"},"logo":{"@id":"https:\/\/wolles-elektronikkiste.de\/wp-content\/uploads\/2019\/03\/cropped-Logo-1.png"}}]}},"_links":{"self":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/25486","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/comments?post=25486"}],"version-history":[{"count":9,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/25486\/revisions"}],"predecessor-version":[{"id":25537,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/posts\/25486\/revisions\/25537"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media\/25485"}],"wp:attachment":[{"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/media?parent=25486"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/categories?post=25486"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wolles-elektronikkiste.de\/en\/wp-json\/wp\/v2\/tags?post=25486"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}