diff --git a/Documentation/conf.py b/Documentation/conf.py
index bb211aa0cf679dd8486cc21ed5bcbc56418a3d7f..7f8e4771830e44071fcd05aa864f4e7ad0bc78b4 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -90,6 +90,7 @@ html_context = {
 autodoc_mock_imports = [
     "buttons",
     "interrupt",
+    "sys_bme680",
     "sys_display",
     "sys_leds",
     "sys_max30001",
diff --git a/Documentation/pycardium/bme680.rst b/Documentation/pycardium/bme680.rst
index e657d49bf35988652dd015e6ea42ec731b6499c9..812173a625593f879580e196acff741cfcae13cf 100644
--- a/Documentation/pycardium/bme680.rst
+++ b/Documentation/pycardium/bme680.rst
@@ -2,6 +2,7 @@
 
 ``bme680`` - Environmental Sensor
 =================================
+Allows access to environmental data of card10's surroundings.
 
 **Example**:
 
@@ -9,17 +10,28 @@
 
    import bme680, utime
 
-   bme680.init()
+   with bme680.Bme680() as environment:
+       while True:
+           d = environment.get_data()
 
-   while True:
-       temperature, humidity, pressure, resistance = bme680.get_data()
+           print("Temperature:    {:10.2f} °C".format(d.temperature))
+           print("Humidity:       {:10.2f} % r.h.".format(d.humidity))
+           print("Pressure:       {:10.2f} hPa".format(d.pressure))
+           print("Gas Resistance: {:10.2f} Ω".format(d.resistance))
 
-       print("Temperature:    {:10.2f} °C".format(temperature))
-       print("Humidity:       {:10.2f} % r.h.".format(humidity))
-       print("Pressure:       {:10.2f} hPa".format(pressure))
-       print("Gas Resistance: {:10.2f} Ω".format(resistance))
+           utime.sleep(1)
 
-       utime.sleep(1)
+Sensor Class
+------------
+
+.. autoclass:: bme680.Bme680
+   :members:
+
+Deprecated Interface
+--------------------
+The following functions should no longer be used directly.  The only exist for
+compatibility as they were the old BME680 interface in previous firmware
+versions.
 
 .. py:function:: init()
 
@@ -29,6 +41,8 @@
    :py:func:`bme680.init`.
 
    .. versionadded:: 1.4
+   .. deprecated:: 1.10
+      Use the :py:class:`bme680.Bme680` class instead.
 
 .. py:function:: get_data()
 
@@ -38,9 +52,13 @@
       ``pressure`` (hPa) and ``gas resistance`` (Ohm).
 
    .. versionadded:: 1.4
+   .. deprecated:: 1.10
+      Use the :py:class:`bme680.Bme680` class instead.
 
 .. py:function:: deinit()
 
    Deinitialize the sensor.
 
    .. versionadded:: 1.4
+   .. deprecated:: 1.10
+      Use the :py:class:`bme680.Bme680` class instead.
diff --git a/pycardium/meson.build b/pycardium/meson.build
index 1d45e9704351cc8450275bdc66a9263ce7316cfc..bc2337002098e032da67976adc7120f25d67db2d 100644
--- a/pycardium/meson.build
+++ b/pycardium/meson.build
@@ -16,7 +16,7 @@ modsrc = files(
   'modules/sys_display.c',
   'modules/utime.c',
   'modules/vibra.c',
-  'modules/bme680.c',
+  'modules/sys_bme680.c',
   'modules/ws2812.c'
 )
 
diff --git a/pycardium/modules/py/bme680.py b/pycardium/modules/py/bme680.py
new file mode 100644
index 0000000000000000000000000000000000000000..bbb6481de9bb0cf780fce35ca161cea8ccaf077b
--- /dev/null
+++ b/pycardium/modules/py/bme680.py
@@ -0,0 +1,134 @@
+import sys_bme680
+import ucollections
+
+# Import old module for compatibility
+from sys_bme680 import *  # noqa
+
+Bme680Data = ucollections.namedtuple(
+    "Bme680Data", ["temperature", "humidity", "pressure", "gas_resistance"]
+)
+
+
+class Bme680:
+    """
+    BME680 4-in-1 environmental sensor.
+
+    **Example**:
+
+    .. code-block:: python
+
+        import bme680
+
+        environment = bme680.Bme680()
+        print("Current temperature: {:4.1f} °C".format(environment.temperature()))
+
+    This class can also be used as a context-manager which will automatically
+    deactivate the sensor on exit:
+
+    .. code-block:: python
+
+        import bme680
+
+        with bme680.Bme680() as environment:
+            print("H: {:4.1f}%".format(environment.humidity()))
+
+        # Sensor is off again, saving power
+
+    .. versionadded:: 1.10
+    """
+
+    def __init__(self):
+        sys_bme680.init()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args):
+        self.close()
+
+    def get_data(self):
+        """
+        Get all sensor data at once.
+
+        :py:meth:`~bme680.Bme680.get_data` returns a namedtuple with the
+        following fields:
+
+        - ``temperature``: Temperature in *°C*
+        - ``humidity``: Relative humidity
+        - ``pressure``: Barometric pressure in *hPa*
+        - ``gas_resistance``: Gas resistance in *Ω*
+
+        **Example**:
+
+        .. code-block:: python
+
+            import bme680
+
+            with bme680.Bme680() as environment:
+                data = environment.get_data()
+
+                print("T: {}".format(data.temperature))
+                print("H: {}".format(data.humidity))
+        """
+        return Bme680Data(*sys_bme680.get_data())
+
+    def close(self):
+        """
+        Stop/deinit the BME680.
+
+        If you no longer need measurements, you should call this function to
+        save power.
+        """
+        sys_bme680.deinit()
+
+    def temperature(self):
+        """
+        Measure current temperature in *°C*.
+
+        **Example**:
+
+        .. code-block:: python
+
+            environment = bme680.Bme680()
+            print(str(environment.temperature()))
+        """
+        return self.get_data().temperature
+
+    def humidity(self):
+        """
+        Measure current relative humidity.
+
+        **Example**:
+
+        .. code-block:: python
+
+            environment = bme680.Bme680()
+            print(str(environment.humidity()))
+        """
+        return self.get_data().humidity
+
+    def pressure(self):
+        """
+        Measure current barometric pressure in *hPa*.
+
+        **Example**:
+
+        .. code-block:: python
+
+            environment = bme680.Bme680()
+            print(str(environment.pressure()))
+        """
+        return self.get_data().pressure
+
+    def gas_resistance(self):
+        """
+        Measure current gas resistance in *Ω*.
+
+        **Example**:
+
+        .. code-block:: python
+
+            environment = bme680.Bme680()
+            print(str(environment.gas_resistance()))
+        """
+        return self.get_data().gas_resistance
diff --git a/pycardium/modules/py/meson.build b/pycardium/modules/py/meson.build
index 75bf937c7b2d394d0834542e333bb050328c0823..ade56b1404c0b00eec07a70716ac96d75c8d802a 100644
--- a/pycardium/modules/py/meson.build
+++ b/pycardium/modules/py/meson.build
@@ -1,5 +1,6 @@
 python_modules = files(
   'bhi160.py',
+  'bme680.py',
   'color.py',
   'htmlcolor.py',
   'display.py',
diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h
index 1c48037060bb14ded87839d4bdb2ff63a83c31cf..0ff0a8caac12fff03bcdb18b781a091a5784e98e 100644
--- a/pycardium/modules/qstrdefs.h
+++ b/pycardium/modules/qstrdefs.h
@@ -104,7 +104,7 @@ Q(stop)
 Q(read)
 
 /* bme680 */
-Q(bme680)
+Q(sys_bme680)
 Q(init)
 Q(deinit)
 Q(get_data)
diff --git a/pycardium/modules/bme680.c b/pycardium/modules/sys_bme680.c
similarity index 91%
rename from pycardium/modules/bme680.c
rename to pycardium/modules/sys_bme680.c
index ca4aca6d1dcb5d4f06c81ba20458f01bdafdb316..f6899c77c187c4d0d536fb41c14428d449bf62be 100644
--- a/pycardium/modules/bme680.c
+++ b/pycardium/modules/sys_bme680.c
@@ -46,7 +46,7 @@ static mp_obj_t mp_bme680_get_data()
 static MP_DEFINE_CONST_FUN_OBJ_0(bme680_get_data_obj, mp_bme680_get_data);
 
 static const mp_rom_map_elem_t bme680_module_globals_table[] = {
-	{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bme680) },
+	{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys_bme680) },
 	{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&bme680_init_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bme680_deinit_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_get_data), MP_ROM_PTR(&bme680_get_data_obj) },
@@ -59,4 +59,4 @@ const mp_obj_module_t bme680_module = {
 };
 
 /* Register the module to make it available in Python */
-MP_REGISTER_MODULE(MP_QSTR_bme680, bme680_module, MODULE_BME680_ENABLED);
+MP_REGISTER_MODULE(MP_QSTR_sys_bme680, bme680_module, MODULE_BME680_ENABLED);