diff --git a/Documentation/conf.py b/Documentation/conf.py
index 7f8e4771830e44071fcd05aa864f4e7ad0bc78b4..c7a3ee6efa69b223ee9feb4d57f6dbcd1478b910 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -91,6 +91,7 @@ autodoc_mock_imports = [
     "buttons",
     "interrupt",
     "sys_bme680",
+    "sys_bhi160",
     "sys_display",
     "sys_leds",
     "sys_max30001",
diff --git a/Documentation/pycardium/bhi160.rst b/Documentation/pycardium/bhi160.rst
index b57dc77f55cb1b6ab1c283c9e9caccb2efb902fd..f50f736bd4c68605c5fc53cdab29a3b12042d5a0 100644
--- a/Documentation/pycardium/bhi160.rst
+++ b/Documentation/pycardium/bhi160.rst
@@ -2,9 +2,10 @@
 
 ``bhi160`` - Sensor Fusion
 ==========================
+
 .. versionadded:: 1.4
 
-Supports the BHI160 sensor on the card10 for accelerometer, gyroscope...
+Supports the BHI160 sensor on the card10 for accelerometer, gyroscope, magnetometer and orientation.
 
 **Example**:
 
@@ -17,114 +18,28 @@ Supports the BHI160 sensor on the card10 for accelerometer, gyroscope...
 
     while True:
         samples = bhi.read()
-        print(samples)
-        utime.sleep(0.5)
-
-
-.. class:: bhi160.BHI160Orientation(sample_rate,dynamic_range,callback,sample_buffer_len)
-
-    Orientation of the BHI160
-
-    Parameters:
-        sample_rate: int, optional
-            Sample rate (default is 4)
-        dynamic_range: int, optional
-            Dynamic range (default is 2)
-        callback: callable, optional
-            Call this callback when enough data is collected (default is None)
-
-            .. todo:: The callback functionality is untested, so do not be confused if it does not work.
-        sample_buffer_len: int, optional
-            Length of sample buffer (default is 200)
-
-   .. py:method:: read():
-
-   Read sensor values
-
-   :returns: Collected sensor values as list
-
-   .. py:method:: close():
-
-   Close the connection to the sensor
-
-
-.. class:: bhi160.BHI160Accelerometer
-
-    Accelerometer of the BHI160
-
-    Parameters:
-        sample_rate: int, optional
-            Sample rate (default is 4)
-        dynamic_range: int, optional
-            Dynamic range (default is 2)
-        callback: callable, optional
-            Call this callback when enough data is collected (default is None)
-
-            .. todo:: The callback functionality is untested, so do not be confused if it does not work.
-        sample_buffer_len: int, optional
-            Length of sample buffer (default is 200)
-
-   .. py:method:: read():
-
-   Read sensor values
-
-   :returns: Collected sensor values as list
-
-   .. py:method:: close():
-
-   Close the connection to the sensor
-
-.. class:: bhi160.BHI160Gyroscope
-
-    Gyroscope of the BHI160
-
-    Parameters:
-        sample_rate: int, optional
-            Sample rate (default is 4)
-        dynamic_range: int, optional
-            Dynamic range (default is 2)
-        callback: callable, optional
-            Call this callback when enough data is collected (default is None)
-
-            .. todo:: The callback functionality is untested, so do not be confused if it does not work.
-        sample_buffer_len: int, optional
-            Length of sample buffer (default is 200)
-
-   .. py:method:: read():
-
-   Read sensor values
-
-   :returns: Collected sensor values as list
-
-   .. py:method:: close():
-
-   Close the connection to the sensor
-
-.. class:: bhi160.BHI160Magnetometer
-
-    Magnetometer of the BHI160
-
-    Parameters:
-        sample_rate: int, optional
-            Sample rate (default is 4)
-        dynamic_range: int, optional
-            Dynamic range (default is 1)
-        callback: callable, optional
-            Call this callback when enough data is collected (default is None)
-
-            .. todo:: The callback functionality is untested, so do not be confused if it does not work.
-        sample_buffer_len: int, optional
-            Length of sample buffer (default is 200)
-
-   .. versionadded:: 1.11
+        if len(samples) == 0:
+            utime.sleep(0.25)
+            continue
+        # print the latest sample
+        print(samples[-1])
+        utime.sleep(0.25)
 
-   .. py:method:: read():
 
-   Read sensor values
+.. autoclass:: bhi160.BHI160
 
-   :returns: Collected sensor values as list
+.. autoclass:: bhi160.BHI160Orientation
+   :members:
+   :inherited-members:
 
-   .. py:method:: close():
+.. autoclass:: bhi160.BHI160Accelerometer
+  :members:
+  :inherited-members:
 
-   Close the connection to the sensor
+.. autoclass:: bhi160.BHI160Gyroscope
+  :members:
+  :inherited-members:
 
+.. autoclass:: bhi160.BHI160Magnetometer
+  :members:
+  :inherited-members:
diff --git a/pycardium/modules/py/bhi160.py b/pycardium/modules/py/bhi160.py
index 231ba75ffbeac6379d694d000c3dd30bad7a8364..430508d10f2406c39a96f6062b7a7dafb1879be5 100644
--- a/pycardium/modules/py/bhi160.py
+++ b/pycardium/modules/py/bhi160.py
@@ -37,6 +37,9 @@ class BHI160:
         self.close()
 
     def close(self):
+        """
+        Close the connection to the sensor
+        """
         if self.active:
             self.active = False
             ret = sys_bhi160.disable_sensor(self.sensor_id)
@@ -48,6 +51,18 @@ class BHI160:
             interrupt.set_callback(self.interrupt_id, None)
 
     def read(self):
+        """
+        Read sensor values
+
+        :returns: The recent collected sensor values as a list. If no data is
+            available the list contains no elements. Maximum length of the list
+            is ``sample_buffer_len``. The last element contains the most recent
+            data. The elements contains a sensor specific named tuple. See the
+            documentation of the sensor class for more information.
+
+        .. warning::
+            Weird behaviour ahead: If the internal buffer overflows, the new samples will be dropped.
+        """
         result = []
         if self.active:
             for sample in sys_bhi160.read_sensor(self.stream_id):
@@ -70,6 +85,28 @@ class BHI160:
 
 
 class BHI160Accelerometer(BHI160):
+    """
+    Accelerometer of the BHI160.
+
+    This sensors sample data named tuple contains the following fields:
+
+    - ``x``: Acceleration along the x axis
+    - ``y``: Acceleration along the y axis
+    - ``z``: Acceleration along the z axis
+    - ``status``: accuracy / "confidence" value of the sensor (0 being worst and 3 being best)
+
+    .. todo::
+        These values are not scaled correctly
+
+    :param int sample_rate: Sample rate (optional, default is 4, range is 1 - 200 in *Hz*)
+    :param int dynamic_range: Dynamic range (optional, default is 2)
+    :param callback: Call this callback when enough data is collected (optional, default is None)
+
+            .. todo::
+               The callback functionality is untested, so do not be confused if it does not work.
+    :param int sample_buffer_len: Length of sample buffer (optional, default is 200)
+    """
+
     def __init__(
         self, sample_rate=4, dynamic_range=2, callback=None, sample_buffer_len=200
     ):
@@ -90,6 +127,28 @@ class BHI160Accelerometer(BHI160):
 
 
 class BHI160Gyroscope(BHI160):
+    """
+    Gyroscope of the BHI160.
+
+    This sensors sample data named tuple contains the following fields:
+
+    - ``x``: Rotation around the x axis
+    - ``y``: Rotation around the y axis
+    - ``z``: Rotation around the z axis
+    - ``status``: accuracy / "confidence" value of the sensor (0 being worst and 3 being best)
+
+    .. todo::
+        These values are not scaled correctly
+
+    :param int sample_rate: Sample rate (optional, default is 4, range is 1 - 200 in *Hz*)
+    :param int dynamic_range: Dynamic range (optional, default is 2)
+    :param callback: Call this callback when enough data is collected (optional, default is None)
+
+            .. todo::
+               The callback functionality is untested, so do not be confused if it does not work.
+    :param int sample_buffer_len: Length of sample buffer (optional, default is 200)
+    """
+
     def __init__(
         self, sample_rate=4, dynamic_range=2, callback=None, sample_buffer_len=200
     ):
@@ -110,6 +169,30 @@ class BHI160Gyroscope(BHI160):
 
 
 class BHI160Orientation(BHI160):
+    """
+    Orientation of the BHI160. Orientation is a virtual sensor that combines
+    Accelerometer, Magnetometer and Gyroscope using the IMU Algorithm to
+    calculate an absolute orientation.
+
+    This sensors sample data named tuple contains the following fields:
+
+    - ``x``: azimuth
+    - ``y``: pitch
+    - ``z``: roll
+    - ``status``: accuracy / "confidence" value of the sensor (0 being worst and 3 being best)
+
+    .. todo::
+        These values are not scaled correctly
+
+    :param int sample_rate: Sample rate (optional, default is 4, range is 1 - 200 in *Hz*)
+    :param int dynamic_range: This parameter is unused for the Orientation.
+    :param callback: Call this callback when enough data is collected (optional, default is None)
+
+            .. todo::
+               The callback functionality is untested, so do not be confused if it does not work.
+    :param int sample_buffer_len: Length of sample buffer (optional, default is 200)
+    """
+
     def __init__(
         self, sample_rate=4, dynamic_range=2, callback=None, sample_buffer_len=200
     ):
@@ -130,6 +213,30 @@ class BHI160Orientation(BHI160):
 
 
 class BHI160Magnetometer(BHI160):
+    """
+    Magnetometer of the BHI160
+
+    This sensors sample data named tuple contains the following fields:
+
+    - ``x``: Magnetic field along the x axis
+    - ``y``: Magnetic field along the y axis
+    - ``z``: Magnetic field along the z axis
+    - ``status``: accuracy / "confidence" value of the sensor (0 being worst and 3 being best)
+
+    .. todo::
+        These values are not scaled correctly
+
+    :param int sample_rate: Sample rate (optional, default is 4, range is 1 - 200 in *Hz*)
+    :param int dynamic_range: Dynamic range (optional, default is 1)
+    :param callback: Call this callback when enough data is collected (optional, default is None)
+
+            .. todo::
+               The callback functionality is untested, so do not be confused if it does not work.
+    :param int sample_buffer_len: Length of sample buffer (optional, default is 200)
+
+   .. versionadded:: 1.11
+    """
+
     def __init__(
         self, sample_rate=4, dynamic_range=1, callback=None, sample_buffer_len=200
     ):