{"id":135845,"date":"2018-08-24T11:11:00","date_gmt":"2018-08-24T08:11:00","guid":{"rendered":"https:\/\/ruuvi.com\/ruuvi-firmware-teil-5-umweltsensorik\/"},"modified":"2026-06-11T08:48:58","modified_gmt":"2026-06-11T05:48:58","slug":"ruuvi-firmware-teil-5-umweltsensorik","status":"publish","type":"post","link":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/","title":{"rendered":"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"536\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing-1024x536.jpeg\" alt=\"Introbild zur Ruuvi-Firmware-Serie, Teil 5\" class=\"wp-image-3610\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing-1024x536.jpeg 1024w, https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing-450x236.jpeg 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing-768x402.jpeg 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing-600x314.jpeg 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing.jpeg 1400w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">In diesem Teil des Tutorials entwickeln wir eine Sensorschnittstelle, die jedes Backend zum Auslesen von Sensordaten nutzen kann, und implementieren das Backend mit dem integrierten Temperatursensor des nRF52. Danach schreiben wir SPI-Treiber zum Auslesen externer Sensoren und implementieren das Sensor-Backend mit dem Bosch BME280. Den finalen Code findest du auf <a href=\"https:\/\/github.com\/ruuvi\/ruuvi.firmware.c\">Ruuvi GitHub<\/a> im <em>ruuviblog<\/em>-Branch, Tag<em> 3.5.0-alpha<\/em>. Bitte folge <a href=\"https:\/\/ruuvi.com\/ruuvi-firmware-part-1-sleep\/\">Teil 1 der Serie<\/a> f\u00fcr Details dazu, wie du das Repository klonst und den Code kompilierst. Das finale Hex dieses Tutorials kannst du von <a href=\"http:\/\/jenkins.ruuvi.com:8080\/job\/ruuvi.firmware.c\/19\/\">Ruuvi Jenkins<\/a> herunterladen.    <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"681\" height=\"689\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-firmware-architecture-3-5-0.png\" alt=\"Die Ruuvi-Firmware-Architektur 3.5.0\" class=\"wp-image-3611\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-firmware-architecture-3-5-0.png 681w, https:\/\/ruuvi.com\/i\/u\/ruuvi-firmware-architecture-3-5-0-445x450.png 445w, https:\/\/ruuvi.com\/i\/u\/ruuvi-firmware-architecture-3-5-0-600x607.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-firmware-architecture-3-5-0-100x100.png 100w\" sizes=\"auto, (max-width: 681px) 100vw, 681px\" \/><\/figure><\/div>\n\n<h2 class=\"wp-block-heading\">Sensorschnittstelle<\/h2>\n\n<p class=\"wp-block-paragraph\">Im Allgemeinen hat jeder Sensor, den wir verwenden, einige gemeinsame Parameter, wie Aufl\u00f6sung, Abtastrate, Skalierung, Digital-Signal-Processing-(DSP)-Funktion und Parameter f\u00fcr das DSP. Au\u00dferdem k\u00f6nnten wir daran interessiert sein, den Sensor zu starten, zu stoppen oder eine Single-Shot-Messung durchzuf\u00fchren. <\/p>\n\n<p class=\"wp-block-paragraph\">Wir wollen au\u00dferdem ein paar feste Bedeutungen f\u00fcr unsere Sensoren definieren, wie <strong>RESOLUTION_MAX<\/strong> oder <strong>SCALE_MIN.<\/strong> So k\u00f6nnen wir eine Vielzahl von Sensoren einrichten, ohne die genauen F\u00e4higkeiten des zugrunde liegenden Ger\u00e4ts zu kennen. Au\u00dferdem verwenden wir <strong>0<\/strong> als <em>sinnvollen Standard<\/em>-Wert. Dadurch k\u00f6nnen wir die Konfiguration per <em>memset<\/em> auf lauter Nullen setzen und erhalten am Ende sinnvolle Werte, ohne Parameter explizit setzen zu m\u00fcssen, die uns eigentlich nicht interessieren.  <\/p>\n\n<p class=\"wp-block-paragraph\">Da wir die Konfiguration sp\u00e4ter per BLE \u00fcbertragen wollen, sparen wir in unserer Schnittstelle Platz. Wir verwenden <em>uint8_t<\/em>-Werte, um die Sensoren zu konfigurieren. DSP-Funktionen sind Bit-Flags, damit sich mehrere Optionen kombinieren lassen.  <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"416\" src=\"https:\/\/ruuvi.com\/i\/u\/sensor-configuration-constants-1024x416.png\" alt=\"Konstanten f&#xFC;r die Sensorkonfiguration\" class=\"wp-image-3612\" srcset=\"https:\/\/ruuvi.com\/i\/u\/sensor-configuration-constants-1024x416.png 1024w, https:\/\/ruuvi.com\/i\/u\/sensor-configuration-constants-450x183.png 450w, https:\/\/ruuvi.com\/i\/u\/sensor-configuration-constants-768x312.png 768w, https:\/\/ruuvi.com\/i\/u\/sensor-configuration-constants-600x244.png 600w, https:\/\/ruuvi.com\/i\/u\/sensor-configuration-constants.png 1358w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Konstanten f\u00fcr die Sensorkonfiguration<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Da wir jeden verf\u00fcgbaren Sensor nutzen wollen, definieren wir eine gemeinsame Schnittstelle zum zugrunde liegenden Sensor \u00fcber Funktionszeiger. So k\u00f6nnen wir denselben Code mit dem <a href=\"https:\/\/www.nordicsemi.com\/eng\/Products\/Bluetooth-low-energy\/nRF52832\"><strong>nRF52<\/strong><\/a>-Temperatursensor und dem <a href=\"https:\/\/www.bosch-sensortec.com\/bst\/products\/all_products\/bme280\"><strong>BME280<\/strong><\/a>-Umweltsensor verwenden, um Umweltdaten zu erhalten; <strong>nRF52<\/strong> liefert bei Druck und Luftfeuchtigkeit einfach \u201eung\u00fcltige\u201c Werte zur\u00fcck. Man k\u00f6nnte argumentieren, dass C++ die bessere Wahl f\u00fcr Schnittstellen w\u00e4re, allerdings werden wir die beiden nicht mischen, au\u00dfer es ist aus irgendeinem Grund unbedingt n\u00f6tig.  <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"863\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-driver-sensor-h-interface-functions-1024x863.png\" alt=\"ruuvi_driver_sensor.h, Schnittstellenfunktionen\" class=\"wp-image-3613\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-driver-sensor-h-interface-functions-1024x863.png 1024w, https:\/\/ruuvi.com\/i\/u\/ruuvi-driver-sensor-h-interface-functions-450x379.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-driver-sensor-h-interface-functions-768x647.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-driver-sensor-h-interface-functions-1536x1295.png 1536w, https:\/\/ruuvi.com\/i\/u\/ruuvi-driver-sensor-h-interface-functions-600x506.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-driver-sensor-h-interface-functions.png 1794w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>ruuvi_driver_sensor.h \u2014 Schnittstellenfunktionen<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Unsere Initialisierung erlaubt es, den <em>Bus<\/em> zu definieren; damit k\u00f6nnen wir unterst\u00fctzen, ob der Sensortreiber mit dem jeweiligen Sensor <strong>I2C<\/strong> oder <strong>SPI<\/strong> verwenden soll. Au\u00dferdem \u00fcbergeben wir ein <em>uint8_t handle<\/em>, das dem Programm hilft, den richtigen Sensor auszuw\u00e4hlen. Bei <strong>I2C<\/strong> ist dieses Handle die Adresse des Sensors, bei <strong>SPI<\/strong> ist es der <strong>GPIO<\/strong>-Pin, der zum Ausw\u00e4hlen des Sensors verwendet wird.  <\/p>\n\n<p class=\"wp-block-paragraph\">Wir versuchen, unsere Schnittstelle einfach zu halten. Die Abtastrate ist in <em>Hz<\/em> und die Aufl\u00f6sung in Bits. Werte von 1 \u2026 200 sind erlaubt, wobei 0 die besondere Bedeutung <em>Standard<\/em> hat und Werte \u00fcber 200 f\u00fcr Konstanten mit spezieller Bedeutung reserviert sind. Wenn unser Sensor den exakt angegebenen Wert nicht unterst\u00fctzt, interpretieren wir den Wert als <em>mindestens<\/em>. Wenn zum Beispiel eine Aufl\u00f6sung von 9 Bit angefordert wird, aber 8 und 10 Bit unterst\u00fctzt werden, w\u00e4hlen wir 10 Bit Aufl\u00f6sung.   <\/p>\n\n<p class=\"wp-block-paragraph\">Eine schwierigere Frage ist, was Aufl\u00f6sung und Skalierung darstellen sollen, wenn sie nicht <strong>MIN<\/strong>, <strong>MAX<\/strong> oder <strong>DEFAULT<\/strong> sind. Skalierung ist mit <em>uint8_t<\/em> als Typ schwerer darzustellen als Aufl\u00f6sung. F\u00fcr etwas wie die Beschleunigungssensor-Skalierung funktioniert es gut, weil wir problemlos 2, 4, 8, 16 <em>G<\/em> haben k\u00f6nnen. Einheiten wie <em>Pascal<\/em> sind anspruchsvoller: Wir k\u00f6nnten so etwas wie 100 000 <em>Pa<\/em> haben, das durch die Skalierungszahl repr\u00e4sentiert werden sollte.   <\/p>\n\n<p class=\"wp-block-paragraph\">Um unsere Schnittstelle einfach zu halten, wenden wir dasselbe Prinzip an wie bei Abtastrate und Aufl\u00f6sung. Die Skalierung ist in einer sinnvollen physikalischen Einheit wie <em>G<\/em>. Gleiches gilt f\u00fcr die Abtastrate: Ein Beschleunigungssensor k\u00f6nnte im Low-Resolution-Modus 5 kHz erreichen, aber jeder Wert au\u00dferhalb des Bereichs wird mit <strong>MAX<\/strong> dargestellt. Das schr\u00e4nkt zwar einige Sonderf\u00e4lle ein, aber wir akzeptieren, dass jeder spezielle Use Case mehr Arbeit erfordert, und versuchen, die allgemeinen Bed\u00fcrfnisse zu erf\u00fcllen.   <\/p>\n\n<p class=\"wp-block-paragraph\">Digital-Signal-Processing-Funktionen sind ein noch gemischteres Feld, da es unterschiedliche gew\u00fcnschte Funktionskombinationen geben kann, die komplett andere Parameter erfordern. Um beim Prinzip \u201eeinfach halten\u201c zu bleiben, erlauben wir ein Bit-Flag der hardwareunterst\u00fctzten DSP-Funktionen und \u00fcbergeben einen einzelnen, gemeinsamen Parameter daf\u00fcr. <\/p>\n\n<p class=\"wp-block-paragraph\">Die Sensorschnittstelle definiert Funktionszeiger zum Setzen und Auslesen jedes Parameters. Die Schnittstelle passt die \u00fcbergebenen Werte an den tats\u00e4chlich geschriebenen Wert an oder an <em>default <\/em>, wenn der Sensor den angegebenen Parameter nicht unterst\u00fctzt. Der R\u00fcckgabecode ist <strong>SUCCESS<\/strong>, wenn eine sinnvolle Aktion m\u00f6glich war, oder ein Fehlercode wie <strong>NOT_SUPPORTED<\/strong>, wenn es keine M\u00f6glichkeit gibt, die angeforderte Einstellung zu erf\u00fcllen.  <\/p>\n\n<h2 class=\"wp-block-heading\">Umweltsensor<\/h2>\n\n<h3 class=\"wp-block-heading\">Schnittstelle f\u00fcr Umweltsensordaten<\/h3>\n\n<p class=\"wp-block-paragraph\">Wir verwenden Floats in unserem Sensordatenformat, da wir damit gen\u00fcgend Skalierung in sinnvollen SI-Einheiten haben. Au\u00dferdem f\u00fcgen wir den Daten einen Zeitstempel in Millisekunden hinzu, auch wenn wir noch kein <strong>RTC<\/strong> implementiert haben. <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"940\" height=\"448\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-environmental-h.png\" alt=\"ruuvi_interface_environmental.h\" class=\"wp-image-3619\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-environmental-h.png 940w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-environmental-h-450x214.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-environmental-h-768x366.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-environmental-h-600x286.png 600w\" sizes=\"auto, (max-width: 940px) 100vw, 940px\" \/><figcaption>ruuvi_interface_environmental.h<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Variablen bekommen als Suffix den Namen der Einheit, um jede Mehrdeutigkeit dar\u00fcber zu vermeiden, um welche Art von Werten es im Code geht.<\/p>\n\n<h3 class=\"wp-block-heading\">Implementierung des nRF52-Umweltsensors<\/h3>\n\n<p class=\"wp-block-paragraph\">Die Umgebungs-Implementierung ist beim <strong>nRF52<\/strong> einfach, da wir dort nur eine einfache, einzelne synchrone <em>data_get<\/em>-Funktion in <strong>nRF52<\/strong> zur Verf\u00fcgung haben. Unsere Initialisierungsfunktion richtet das Offset-Kompensationsregister des <strong>nRF52<\/strong> und die Funktionszeiger ein. Die Definitionen von <em>Bus<\/em> und <em>handle<\/em> k\u00f6nnen hier ignoriert werden. Die Deinitialisierung setzt die Funktionszeiger auf <strong>NULL<\/strong>, weitere Aktionen sind nicht n\u00f6tig.  <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"478\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-initialization-1024x478.png\" alt=\"ruuvi_platform_environmental_mcu.c &#x2014; Initialisierung\" class=\"wp-image-3620\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-initialization-1024x478.png 1024w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-initialization-450x210.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-initialization-768x358.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-initialization-1536x717.png 1536w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-initialization-600x280.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-initialization.png 1800w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>ruuvi_platform_environmental_mcu.c \u2014 Initialisierung<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Die Set-Funktionen geben <strong>RUUVI_DRIVER_ERROR_NOT_SUPPORTED<\/strong> zur\u00fcck, au\u00dfer der Nutzer gibt zuf\u00e4llig den Standardwert der Einstellung ein, z. B. eine Aufl\u00f6sung von 10 Bit. Au\u00dferdem erlauben wir <strong>DEFAULT<\/strong>, <strong>MIN<\/strong>, <strong>MAX<\/strong> und <strong>NO_CHANGE<\/strong>. Getter markieren den Wert, auf den gezeigt wird, als <em>default <\/em> und geben <strong>RUUVI_DRIVER_SUCCESS<\/strong> zur\u00fcck.  <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"380\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-resolution-setter-and-getter-1024x380.png\" alt=\"ruuvi_platform_environmental_mcu.c &#x2014; Setter und Getter f&#xFC;r Aufl&#xF6;sung\" class=\"wp-image-3621\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-resolution-setter-and-getter-1024x380.png 1024w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-resolution-setter-and-getter-450x167.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-resolution-setter-and-getter-768x285.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-resolution-setter-and-getter-600x223.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-resolution-setter-and-getter.png 1510w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>ruuvi_platform_environmental_mcu.c \u2014 Setter und Getter f\u00fcr Aufl\u00f6sung<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Wir ahmen die kontinuierliche Sampling-Funktionalit\u00e4t nach, indem wir ein Flag setzen, um die Daten bei <em>data_get.<\/em> zu aktualisieren. So k\u00f6nnen Programme, die beim Umweltsensor auf den Continuous Mode angewiesen sind, auch mit dem <strong>nRF52<\/strong>-Temperatursensor sinnvoll arbeiten.<\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"933\" height=\"1024\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-mode-setter-933x1024.png\" alt=\"Mode-Setter und -Getter, Datenlesefunktion\" class=\"wp-image-3622\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-mode-setter-933x1024.png 933w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-mode-setter-410x450.png 410w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-mode-setter-768x843.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-mode-setter-600x658.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-platform-environmental-mcu-c-mode-setter.png 1272w\" sizes=\"auto, (max-width: 933px) 100vw, 933px\" \/><figcaption>ruuvi_platform_environmental_mcu.c \u2014 Mode-Setter und -Getter, Datenlesefunktion<\/figcaption><\/figure><\/div>\n\n<h3 class=\"wp-block-heading\">Implementierung des BME280-Umweltsensors<\/h3>\n\n<p class=\"wp-block-paragraph\">Die <strong>BME280<\/strong>-Implementierung ist deutlich komplexer, weil wir \u00fcber den <strong>SPI<\/strong>-Bus mit einem externen Sensor kommunizieren m\u00fcssen. Zum Gl\u00fcck stellt Bosch einen plattformunabh\u00e4ngigen C-Treiber f\u00fcr den <strong>BME280<\/strong> bereit, und wir m\u00fcssen nur ein paar grundlegende Funktionen bereitstellen, um ihn zu nutzen. <\/p>\n\n<p class=\"wp-block-paragraph\">Die Initialisierung ist \u00e4hnlich wie bei der <strong>nRF52 <\/strong>-Implementierung. Wir pr\u00fcfen, ob der ausgew\u00e4hlte Bus <strong>SPI<\/strong> war, richten das Handle sowie die <em>read<\/em>\/<em>write<\/em>\/<em>delay <\/em>-Funktionen ein, rufen den Bosch-Treiber zur Initialisierung des <strong>BME280<\/strong> auf, f\u00fchren einen <em>Self-Test<\/em> aus und machen einen <em>Soft Reset<\/em>. Zum Schluss setzen wir das Oversampling f\u00fcr jedes Sensorelement auf 1, um den Stolperstein zu vermeiden, dass der<strong> BME280<\/strong> nicht sampelt, wenn das Oversampling nicht mindestens 1 ist. Wenn keine Fehler aufgetreten sind, richten wir die Funktionszeiger ein und geben <strong>SUCCESS<\/strong> zur\u00fcck.   <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"929\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-c-initialization-1024x929.png\" alt=\"ruuvi_interface_bme280.c &#x2014; Initialisierung\" class=\"wp-image-3623\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-c-initialization-1024x929.png 1024w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-c-initialization-450x408.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-c-initialization-768x697.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-c-initialization-1536x1393.png 1536w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-c-initialization-600x544.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-c-initialization.png 1698w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>ruuvi_interface_bme280.c \u2014 Initialisierung<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Der <strong>BME280<\/strong> hat nat\u00fcrlich deutlich mehr Umweltsensor-Features als der <strong>nRF52<\/strong>, aber die meisten davon zu nutzen ist ziemlich geradlinig \u00fcber Switch-Cases zur Auswahl der passenden Optionen. Die einzigen Stolpersteine sind: Das Oversampling jeder Sensorkomponente muss mindestens 1 sein, es gibt keine feste Abtastrate, sondern eine Verz\u00f6gerung zwischen Samples, und die Sampling-Zeit h\u00e4ngt von der Oversampling-Einstellung ab. Wir akzeptieren eine gewisse Ungenauigkeit bei der Abtastrate und nehmen einfach an, dass wir die gew\u00fcnschte Rate erreichen, indem wir die Verz\u00f6gerung w\u00e4hlen, die die gew\u00fcnschte Abtastrate ergibt.  <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"679\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-h-sample-rate-1024x679.png\" alt=\"ruuvi_interface_bme280.h &#x2014; Setter und Getter f&#xFC;r Abtastrate.\" class=\"wp-image-3624\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-h-sample-rate-1024x679.png 1024w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-h-sample-rate-450x298.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-h-sample-rate-768x509.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-h-sample-rate-600x398.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-bme280-h-sample-rate.png 1524w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>ruuvi_interface_bme280.h \u2014 Setter und Getter f\u00fcr Abtastrate.<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Aufl\u00f6sung und Skalierung sind schwer als einzelne Zahl zu definieren, da wir es mit drei verschiedenen Ma\u00dfeinheiten zu tun haben. Daher geben wir <em>default<\/em> als Parameterwert zur\u00fcck und liefern einen Fehler, wenn der Setter etwas anderes als <strong>MIN<\/strong><em>, <\/em><strong>MAX<\/strong><em>, <\/em><strong>DEFAULT<\/strong><em> oder <\/em><strong>NO_CHANGE.<\/strong> erhalten hat. <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"932\" height=\"446\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi.interface-bme280-h-scale-setter-and-getter.png\" alt=\"ruuvi_interface_bme280.h &#x2014; Setter und Getter f&#xFC;r Skalierung.\" class=\"wp-image-3625\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi.interface-bme280-h-scale-setter-and-getter.png 932w, https:\/\/ruuvi.com\/i\/u\/ruuvi.interface-bme280-h-scale-setter-and-getter-450x215.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi.interface-bme280-h-scale-setter-and-getter-768x368.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi.interface-bme280-h-scale-setter-and-getter-600x287.png 600w\" sizes=\"auto, (max-width: 932px) 100vw, 932px\" \/><figcaption>ruuvi_interface_bme280.h \u2014 Setter und Getter f\u00fcr Skalierung.<\/figcaption><\/figure><\/div>\n\n<h2 class=\"wp-block-heading\">SPI-Treiber<\/h2>\n\n<h3 class=\"wp-block-heading\">Schnittstelle<\/h3>\n\n<p class=\"wp-block-paragraph\">Unsere Schnittstelle hat zwei Funktionen: <em>Initialization<\/em> und einen blockierenden Full-Duplex-<em>transfer<\/em>. Unsere anderen Treiber f\u00fcr Peripherie implementieren Wrapper, die die Transfer-Funktion verwenden. <\/p>\n\n<p class=\"wp-block-paragraph\">Die Schnittstelle definiert <strong>SPI<\/strong>-Mode- und Frequenz-Enumerationen sowie eine Initialisierungsstruktur. So vermeiden wir, den Treiber an die Board-Definitionen zu binden, aber die Anwendung muss die Board-Einstellungen passend zum Treiber konfigurieren. <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"772\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-h-1024x772.png\" alt=\"ruuvi_interface_spi.h\" class=\"wp-image-3626\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-h-1024x772.png 1024w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-h-450x339.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-h-768x579.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-h-1536x1158.png 1536w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-h-600x452.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-h.png 1800w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>ruuvi_interface_spi.h<\/figcaption><\/figure><\/div>\n\n<h3 class=\"wp-block-heading\">Implementierung<\/h3>\n\n<p class=\"wp-block-paragraph\">Die Implementierung selbst enth\u00e4lt nichts, was wir nicht schon gesehen h\u00e4tten: Wir pr\u00fcfen die Eingabeparameter, reichen sie an das <a href=\"https:\/\/infocenter.nordicsemi.com\/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.0.0%2Findex.html\">Nordic SDK<\/a> weiter und geben eventuelle Fehlercodes zur\u00fcck. Das Nordic SDK w\u00fcrde viel Feinschliff mit Direct Memory Access (<strong>DMA<\/strong>) und Peripheral-Peripheral Interconnect (<strong>PPI<\/strong>) unterst\u00fctzen, aber wir entscheiden uns vorerst f\u00fcr einfache blockierende Transfer-Funktionen. Vielleicht schauen wir uns die Implementierungen sp\u00e4ter noch einmal an, wenn das Power-Profiling zeigt, dass die funktionale Firmware bei den <strong>SPI<\/strong>-Reads viel Strom verbraucht \u2013 aber im Moment w\u00e4re das verfr\u00fchte Optimierung.  <\/p>\n\n<h3 class=\"wp-block-heading\">BME280-Wrapper<\/h3>\n\n<p class=\"wp-block-paragraph\">Der Bosch-<strong>BME280<\/strong>-Treiber erwartet <em>read<\/em>-, <em>write<\/em>&#8211; und <em>delay<\/em>-Funktionen mit den folgenden Signaturen:<\/p>\n\n<pre class=\"wp-block-code\"><code>int8_t ruuvi_interface_spi_bme280_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);int8_t ruuvi_interface_spi_bme280_read (uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);void bosch_delay_ms(uint32_t time_ms);<\/code><\/pre>\n\n<p class=\"wp-block-paragraph\"><em>Delay<\/em> ist einfach: Wir reichen den Aufruf an <em>ruuvi_platform_delay_ms<\/em> weiter und ignorieren den R\u00fcckgabewert. <em>Read<\/em> und <em>write<\/em> erfordern etwas mehr Arbeit: Unsere <strong>SPI<\/strong>-Transfer-Funktion ist Full-Duplex mit zwei Buffern, w\u00e4hrend die Bosch-Funktion Adresse + R\/W-Daten verwendet.<\/p>\n\n<p class=\"wp-block-paragraph\">Wir implementieren die <strong>BME280<\/strong>&#8211;<strong>SPI<\/strong>-Funktionen in der <em>Schnittstelle<\/em>, also als <em>plattform<\/em>unabh\u00e4ngig. Im Wrapper rufen wir die vom <em>Platform<\/em> bereitgestellten <strong>GPIO<\/strong>-Steuerfunktionen und die <strong>SPI<\/strong>-Transfer-Funktion auf. <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"749\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-bme280-c-1024x749.png\" alt=\"ruuvi_interface_spi_bme280.c\" class=\"wp-image-3627\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-bme280-c-1024x749.png 1024w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-bme280-c-450x329.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-bme280-c-768x561.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-bme280-c-600x439.png 600w, https:\/\/ruuvi.com\/i\/u\/ruuvi-interface-spi-bme280-c.png 1376w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>ruuvi_interface_spi_bme280.c<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Im Wesentlichen teilen wir hier einen Funktionsaufruf aus dem Bosch-Treiber in vier Aufrufe auf:<\/p>\n\n<ul class=\"wp-block-list\"><li>Das angegebene <strong>SPI<\/strong>-Ger\u00e4t ausw\u00e4hlen, indem die <strong>GPIO<\/strong>-Leitung auf <em>low<\/em> gesetzt wird<\/li><li>Zielregister schreiben<\/li><li>Daten aus dem Register lesen\/schreiben<\/li><li>Das <strong>SPI<\/strong>-Ger\u00e4t abw\u00e4hlen, indem die <strong>GPIO<\/strong>-Leitung auf <em>high<\/em> gesetzt wird<\/li><\/ul>\n\n<h3 class=\"wp-block-heading\">SPI-Treiber initialisieren<\/h3>\n\n<p class=\"wp-block-paragraph\">Die Initialisierung von <strong>SPI<\/strong> erfordert etwas mehr Arbeit als die bisherigen <strong>GPIO<\/strong>&#8211; oder <em>log<\/em>-Implementierungen, da unsere Boards unterschiedliche Pinbelegungen oder maximale SPI-Geschwindigkeiten haben k\u00f6nnen. Wir erstellen eine dedizierte <em>Task<\/em> f\u00fcr <strong>SPI<\/strong>, die die Board-Definitionen liest und an den Treiber weitergibt. <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"804\" src=\"https:\/\/ruuvi.com\/i\/u\/task-spi-c-1024x804.png\" alt=\"task_spi.c\" class=\"wp-image-3628\" srcset=\"https:\/\/ruuvi.com\/i\/u\/task-spi-c-1024x804.png 1024w, https:\/\/ruuvi.com\/i\/u\/task-spi-c-450x353.png 450w, https:\/\/ruuvi.com\/i\/u\/task-spi-c-768x603.png 768w, https:\/\/ruuvi.com\/i\/u\/task-spi-c-600x471.png 600w, https:\/\/ruuvi.com\/i\/u\/task-spi-c.png 1276w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>task_spi.c<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Wir nehmen hier eine Abk\u00fcrzung und gehen davon aus, dass wir den <strong>SPI<\/strong>-Mode 0 verwenden. Die <em>Frequenz<\/em> wird per Switch-Case behandelt, und die <em>Pinbelegung<\/em> wird unver\u00e4ndert \u00fcbernommen.<\/p>\n\n<h2 class=\"wp-block-heading\">Den Umweltsensor beim Boot ausw\u00e4hlen<\/h2>\n\n<p class=\"wp-block-paragraph\">Idealerweise m\u00fcssten wir nur eine einzelne Zeile <strong>new_environmental_sensor_present 1<\/strong> zu unserer Board-Definition hinzuf\u00fcgen, und unsere <em>Schnittstelle<\/em> w\u00fcrde versuchen, den neuen Sensor zu initialisieren, wenn der Treiber implementiert wurde. Das w\u00fcrde jedoch eine Abh\u00e4ngigkeit zwischen Treibern und Boards einf\u00fchren, und solche Abh\u00e4ngigkeiten vermeiden wir so weit wie m\u00f6glich. Daher m\u00fcssen wir die m\u00f6glichen Sensoren in unserer Initialisierungs-Task f\u00fcr den Umweltsensor hinzuf\u00fcgen. Das bedeutet zwar etwas mehr Arbeit beim Portieren der Anwendung auf ein neues Board mit einem neuen Umweltsensor, aber wir akzeptieren das und machen die zus\u00e4tzliche Arbeit bei Bedarf f\u00fcr ein neues Ziel-Board.   <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"849\" src=\"https:\/\/ruuvi.com\/i\/u\/task-environmental-c-initialization-1024x849.png\" alt=\"task_environmental.c &#x2014; Initialisierung\" class=\"wp-image-3629\" srcset=\"https:\/\/ruuvi.com\/i\/u\/task-environmental-c-initialization-1024x849.png 1024w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-initialization-450x373.png 450w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-initialization-768x637.png 768w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-initialization-600x498.png 600w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-initialization.png 1172w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>task_environmental.c \u2014 Initialisierung<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Die Definitionen <strong>RUUVI_BOARD_ENVIRONMENTAL_BME280_PRESENT<\/strong> und <strong>RUUVI_BOARD_ENVIRONMENTAL_MCU_PRESENT<\/strong> sind in der Board-Datei definiert. Wenn das Board beide Sensoren haben k\u00f6nnte, kompilieren wir den Code zum Testen beider mit. Beim <strong>BME280<\/strong> erlauben wir den Fehler <strong>NOT_FOUND<\/strong>, weil wir diesen Code auf einem <strong>RuuviTag B Basic<\/strong> ohne Sensoren ausf\u00fchren k\u00f6nnten. Wenn der <strong>BME280<\/strong> gefunden wird, kehren wir zur\u00fcck und der Umweltsensor ist initialisiert und konfiguriert. Wenn der <strong>BME280<\/strong> nicht gefunden wird, versuchen wir, den <strong>nRF52<\/strong>-Temperatursensor als Umweltsensor zu initialisieren. Unsere Konfigurationsfunktion \u00fcbernimmt Konstanten aus der <em>application_config.h<\/em>     <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"489\" src=\"https:\/\/ruuvi.com\/i\/u\/application-config-h-environmental-sensor-settings-1024x489.png\" alt=\"application_config.h &#x2014; Einstellungen f&#xFC;r den Umweltsensor\" class=\"wp-image-3630\" srcset=\"https:\/\/ruuvi.com\/i\/u\/application-config-h-environmental-sensor-settings-1024x489.png 1024w, https:\/\/ruuvi.com\/i\/u\/application-config-h-environmental-sensor-settings-450x215.png 450w, https:\/\/ruuvi.com\/i\/u\/application-config-h-environmental-sensor-settings-768x367.png 768w, https:\/\/ruuvi.com\/i\/u\/application-config-h-environmental-sensor-settings-600x286.png 600w, https:\/\/ruuvi.com\/i\/u\/application-config-h-environmental-sensor-settings.png 1454w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>application_config.h \u2014 Einstellungen f\u00fcr den Umweltsensor<\/figcaption><\/figure><\/div>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"326\" src=\"https:\/\/ruuvi.com\/i\/u\/task-environmental-c-configuration-1024x326.png\" alt=\"task_environmental.c &#x2014; Konfiguration\" class=\"wp-image-3631\" srcset=\"https:\/\/ruuvi.com\/i\/u\/task-environmental-c-configuration-1024x326.png 1024w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-configuration-450x143.png 450w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-configuration-768x244.png 768w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-configuration-600x191.png 600w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-configuration.png 1126w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>task_environmental.c \u2014 Konfiguration<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Unsere Konfiguration verwendet standardm\u00e4\u00dfig den <em>Single-Shot<\/em>-Modus, da wir die Umgebungs-Messung per Tastendruck ausl\u00f6sen wollen. Weil wir davon ausgehen, dass Tastendr\u00fccke relativ selten sind, oversamplen wir so stark, wie es die Hardware erlaubt, um m\u00f6glichst wenig Rauschen in der Messung zu haben. <\/p>\n\n<h3 class=\"wp-block-heading\">Den Umweltsensor verwenden<\/h3>\n\n<p class=\"wp-block-paragraph\">Jetzt k\u00f6nnen wir mit unserem Board etwas Interessanteres machen, als nur <strong>LED<\/strong>s blinken zu lassen. Lass uns eine <em>on_button<\/em>-Funktion erstellen, die ein Umgebungs-Sample nimmt, die Sensordaten ausliest und ausgibt. <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"647\" src=\"https:\/\/ruuvi.com\/i\/u\/task-environmental-c-reading-the-sensor-1024x647.png\" alt=\"task_environmental.c &#x2014; Sensor auslesen und Daten ausgeben\" class=\"wp-image-3632\" srcset=\"https:\/\/ruuvi.com\/i\/u\/task-environmental-c-reading-the-sensor-1024x647.png 1024w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-reading-the-sensor-450x284.png 450w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-reading-the-sensor-768x485.png 768w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-reading-the-sensor-600x379.png 600w, https:\/\/ruuvi.com\/i\/u\/task-environmental-c-reading-the-sensor.png 1184w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>task_environmental.c \u2014 Sensor auslesen und Daten ausgeben<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Ein bemerkenswerter Punkt ist, dass das Ausgeben von <em>uint64_t<\/em> und <em>float<\/em> in Bezug auf die Codegr\u00f6\u00dfe ziemlich teuer ist. Nach dem Aktivieren der Compiler-Flags ist unser Code um 3,3 kB gewachsen! Es gibt noch ein weiteres ernstes Problem mit den Compiler-Flags: <strong>Unser Jenkins-Build wird sich anders verhalten, da der Code mit einem anderen Makefile und anderen Compiler-Flags kompiliert wird. <\/strong>Wir werden den Jenkins-Build in einem sp\u00e4teren Tutorial fixen, denn dieser Teil ist ohnehin schon lang genug.  <\/p>\n\n<p class=\"wp-block-paragraph\">Wir fangen an, die RuuviFW-Funktionalit\u00e4t nachzuahmen, indem wir die <strong>ROTE LED <\/strong>w\u00e4hrend der Aktivit\u00e4t einschalten. Ersetzen wir die bisherige <em>task_led_cycle<\/em>-Task durch <em>task_environmental_on_button<\/em> <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"905\" height=\"1024\" src=\"https:\/\/ruuvi.com\/i\/u\/main-c-main-905x1024.png\" alt=\"main.c &#x2014; main\" class=\"wp-image-3633\" srcset=\"https:\/\/ruuvi.com\/i\/u\/main-c-main-905x1024.png 905w, https:\/\/ruuvi.com\/i\/u\/main-c-main-398x450.png 398w, https:\/\/ruuvi.com\/i\/u\/main-c-main-768x869.png 768w, https:\/\/ruuvi.com\/i\/u\/main-c-main-600x679.png 600w, https:\/\/ruuvi.com\/i\/u\/main-c-main.png 1198w\" sizes=\"auto, (max-width: 905px) 100vw, 905px\" \/><figcaption>main.c \u2014 main<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Wir implementieren hier au\u00dferdem ein weiteres RuuviFW-Feature: <strong>nRF52<\/strong> gibt <strong>ERROR_NOT_SUPPORTED<\/strong> zur\u00fcck, wenn wir versuchen, das Oversampling zu konfigurieren. Der Status wird am Ende der Initialisierung nicht <strong>RUUVI_DRIVER_SUCCESS<\/strong> sein, und wir werden die <strong>GR\u00dcNE LED <\/strong>nicht einschalten. Das ist an dieser Stelle ziemlich hacky, weil eine andere Konfiguration in application_config.h keinen solchen Fehler ausgeben w\u00fcrde. Im n\u00e4chsten Teil, wenn der Beschleunigungssensor hinzugef\u00fcgt wird, haben wir beim Basic-Modell jedoch immer <strong>ERROR_NOT_FOUND<\/strong>, und die <strong>GR\u00dcNE LED <\/strong>funktioniert wie vorgesehen.   <\/p>\n\n<h2 class=\"wp-block-heading\">Testen<\/h2>\n\n<h3 class=\"wp-block-heading\">Funktionalit\u00e4t<\/h3>\n\n<p class=\"wp-block-paragraph\">Wenn alles wie vorgesehen funktioniert, haben wir ein Programm, das die Sensoren initialisiert und intelligent zwischen <strong>BME280<\/strong> und <strong>nRF52<\/strong> ausw\u00e4hlt \u2013 je nachdem, was verf\u00fcgbar ist. Bei Tastendruck werden die Daten im Terminal ausgegeben. <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"279\" height=\"163\" src=\"https:\/\/ruuvi.com\/i\/u\/output-on-ruuvi-tag-B-model-plus.png\" alt=\"Ausgabe auf RuuviTag B Modell +\" class=\"wp-image-3634\"\/><figcaption>Ausgabe auf RuuviTag B Modell +<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Die Sensorwerte sehen beim Modell + plausibel aus, der Zeitstempel ist <strong>UINT64_MAX<\/strong>, also der ung\u00fcltige Wert, weil wir noch kein <strong>RTC<\/strong> implementiert haben. Schauen wir, wie es beim Basic-Modell ohne <strong>BME280<\/strong> aussieht. <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"215\" src=\"https:\/\/ruuvi.com\/i\/u\/output-on-ruuvi-tag-B-model-basic-1024x215.png\" alt=\"Ausgabe auf RuuviTag B Modell Basic\" class=\"wp-image-3635\" srcset=\"https:\/\/ruuvi.com\/i\/u\/output-on-ruuvi-tag-B-model-basic-1024x215.png 1024w, https:\/\/ruuvi.com\/i\/u\/output-on-ruuvi-tag-B-model-basic-450x95.png 450w, https:\/\/ruuvi.com\/i\/u\/output-on-ruuvi-tag-B-model-basic-768x161.png 768w, https:\/\/ruuvi.com\/i\/u\/output-on-ruuvi-tag-B-model-basic-600x126.png 600w, https:\/\/ruuvi.com\/i\/u\/output-on-ruuvi-tag-B-model-basic.png 1294w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Ausgabe auf RuuviTag B Modell Basic<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Beim Basic-Modell bekommen wir Warnungen, weil der <strong>nRF52<\/strong> kein integriertes Hardware-Oversampling hat. Die Temperaturmessungen unterscheiden sich stark zwischen den Ger\u00e4ten; eine m\u00f6gliche Erkl\u00e4rung ist, dass das <strong>nRF52-DK<\/strong> unter meinem Modell Plus das Board aufheizt. Das Basic-Modell liefert ung\u00fcltige Druck- und Luftfeuchtigkeitswerte, weil der <strong>nRF52<\/strong> diese nicht messen kann. Unsere Treiber scheinen wie vorgesehen zu funktionieren.   <\/p>\n\n<h3 class=\"wp-block-heading\">Stromverbrauch<\/h3>\n\n<p class=\"wp-block-paragraph\">Wie immer ist ein niedriger Stromverbrauch f\u00fcr uns entscheidend. Wenn unser Code \u201efunktioniert\u201c, aber die Batterie innerhalb weniger Wochen leer saugt, m\u00fcssen wir zur\u00fcck ans Rei\u00dfbrett und die Probleme beheben, bevor wir weitermachen. Schauen wir, wie der Verbrauch beim RuuviTag+ aussieht.  <\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1025\" height=\"802\" src=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-plus-idling.png\" alt=\"RuuviTag+ im Idle\" class=\"wp-image-3638\" srcset=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-plus-idling.png 1025w, https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-plus-idling-450x352.png 450w, https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-plus-idling-768x601.png 768w, https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-plus-idling-600x469.png 600w\" sizes=\"auto, (max-width: 1025px) 100vw, 1025px\" \/><figcaption>RuuviTag+ im Idle<\/figcaption><\/figure><\/div>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1025\" height=\"800\" src=\"https:\/\/ruuvi.com\/i\/u\/bme280-sampling.png\" alt=\"BME280-Sampling\" class=\"wp-image-3639\" srcset=\"https:\/\/ruuvi.com\/i\/u\/bme280-sampling.png 1025w, https:\/\/ruuvi.com\/i\/u\/bme280-sampling-450x351.png 450w, https:\/\/ruuvi.com\/i\/u\/bme280-sampling-768x599.png 768w, https:\/\/ruuvi.com\/i\/u\/bme280-sampling-600x468.png 600w\" sizes=\"auto, (max-width: 1025px) 100vw, 1025px\" \/><figcaption>BME280-Sampling<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Diesmal scheint unser Sleep-Strom bei <strong>3,4 \u03bcA<\/strong> zu liegen, runter von <strong>4,1 \u03bcA<\/strong> im letzten Teil der Serie. Das k\u00f6nnte mit der anhaltenden Hitzewelle in Europa zusammenh\u00e4ngen \u2013 letzte Woche war es deutlich hei\u00dfer als jetzt. Oder es ist einfach Messungenauigkeit. Wie auch immer: Im Moment m\u00fcssen wir uns keine Sorgen machen.   <\/p>\n\n<p class=\"wp-block-paragraph\">Schauen wir, wie es bei einem RuuviTag Basic ohne Sensoren aussieht.<\/p>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"803\" src=\"https:\/\/ruuvi.com\/i\/u\/nrf52-sampling.png\" alt=\"nRF52-Sampling\" class=\"wp-image-3640\" srcset=\"https:\/\/ruuvi.com\/i\/u\/nrf52-sampling.png 1024w, https:\/\/ruuvi.com\/i\/u\/nrf52-sampling-450x353.png 450w, https:\/\/ruuvi.com\/i\/u\/nrf52-sampling-768x602.png 768w, https:\/\/ruuvi.com\/i\/u\/nrf52-sampling-600x471.png 600w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>nRF52-Sampling<\/figcaption><\/figure><\/div>\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1023\" height=\"798\" src=\"https:\/\/ruuvi.com\/i\/u\/nrf52-idling.png\" alt=\"nRF52 im Idle\" class=\"wp-image-3641\" srcset=\"https:\/\/ruuvi.com\/i\/u\/nrf52-idling.png 1023w, https:\/\/ruuvi.com\/i\/u\/nrf52-idling-450x351.png 450w, https:\/\/ruuvi.com\/i\/u\/nrf52-idling-768x599.png 768w, https:\/\/ruuvi.com\/i\/u\/nrf52-idling-600x468.png 600w\" sizes=\"auto, (max-width: 1023px) 100vw, 1023px\" \/><figcaption>nRF52 im Idle<\/figcaption><\/figure><\/div>\n\n<p class=\"wp-block-paragraph\">Beim RuuviTag Basic liegen wir bei <strong>1,4 \u03bcA<\/strong>, da wir uns nicht um den Standby-Strom der Sensoren k\u00fcmmern m\u00fcssen. Praktisch macht das keinen Unterschied, da beide Tags so wenig verbrauchen, dass die Batterie lange vorher abl\u00e4uft, bevor der Verbrauch sie leerzieht.  Bis hierhin sieht\u2019s gut aus.<\/p>\n\n<h2 class=\"wp-block-heading\">Fazit<\/h2>\n\n<p class=\"wp-block-paragraph\">Das war der bisher l\u00e4ngste Beitrag, und wir sind weit vorangekommen. Jetzt haben wir: <\/p>\n\n<ul class=\"wp-block-list\"><li>Eine generische Schnittstelle f\u00fcr Sensoren<\/li><li>Intelligente Auswahl des Sensor-Backends f\u00fcr unsere Anwendung<\/li><li>Einen generischen <strong>SPI<\/strong>-Treiber f\u00fcr externe Sensoren und <strong>BME280<\/strong>-spezifische Wrapper daf\u00fcr<\/li><li>Integration des Bosch-<strong>BME280<\/strong>-Treibers<\/li><li><strong>nRF52<\/strong> als Fallback f\u00fcr <strong>BME280<\/strong><\/li><\/ul>\n\n<p class=\"wp-block-paragraph\">Die n\u00e4chsten Tutorial-Teile werden einfacher, da wir auf dieser Grundlage aufbauen und der Firmware Beschleunigungssensor, <strong>RTC<\/strong> und <strong>ADC<\/strong>-Batteriemessungen hinzuf\u00fcgen.<\/p>\n\n<p class=\"wp-block-paragraph\"><strong>Bleib dran und folge <\/strong><a href=\"https:\/\/twitter.com\/ojousima\"><strong>@ojousima<\/strong><\/a><strong> und <\/strong><a href=\"https:\/\/twitter.com\/ruuvicom\"><strong>@ruuvicom<\/strong><\/a><strong> auf Twitter f\u00fcr #FirmwareFriday-Beitr\u00e4ge!<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In diesem Teil des Tutorials entwickeln wir eine Sensorschnittstelle, die jedes Backend zum Auslesen von Sensordaten nutzen kann, und implementieren das Backend mit dem integrierten Temperatursensor des nRF52. Danach schreiben wir SPI-Treiber zum Auslesen externer Sensoren und implementieren das Sensor-Backend mit dem Bosch BME280. Den finalen Code findest du auf Ruuvi GitHub im ruuviblog-Branch, Tag [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":135847,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[324],"tags":[],"class_list":["post-135845","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ruuvi-software-artikel"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ruuvi Firmware \u2013 Teil 5: Umweltsensorik \u2013 Ruuvi<\/title>\n<meta name=\"description\" content=\"Entwicklung einer Sensorschnittstelle f\u00fcr den integrierten nRF52-Chip, bevor das Sensor-Backend mit dem eigentlichen Sensor umgesetzt wird.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik \u2013 Ruuvi\" \/>\n<meta property=\"og:description\" content=\"Entwicklung einer Sensorschnittstelle f\u00fcr den integrierten nRF52-Chip, bevor das Sensor-Backend mit dem eigentlichen Sensor umgesetzt wird.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/\" \/>\n<meta property=\"og:site_name\" content=\"Ruuvi\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/ruuvi.cc\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-24T08:11:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-11T05:48:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"1400\" \/>\n\t<meta property=\"og:image:height\" content=\"733\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Otso Jousimaa\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ruuvicom\" \/>\n<meta name=\"twitter:site\" content=\"@ruuvicom\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Otso Jousimaa\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"13\u00a0Minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/\"},\"author\":{\"name\":\"Otso Jousimaa\",\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/#\\\/schema\\\/person\\\/143b8e2a095f1e6484b9186673c9ec00\"},\"headline\":\"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik\",\"datePublished\":\"2018-08-24T08:11:00+00:00\",\"dateModified\":\"2026-06-11T05:48:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/\"},\"wordCount\":2563,\"image\":{\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/ruuvi.com\\\/i\\\/u\\\/ruuvi-tag-firmware-environmental-sensing.jpeg\",\"articleSection\":[\"Ruuvi-Software-Artikel\"],\"inLanguage\":\"de\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/\",\"url\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/\",\"name\":\"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik \u2013 Ruuvi\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/ruuvi.com\\\/i\\\/u\\\/ruuvi-tag-firmware-environmental-sensing.jpeg\",\"datePublished\":\"2018-08-24T08:11:00+00:00\",\"dateModified\":\"2026-06-11T05:48:58+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/#\\\/schema\\\/person\\\/143b8e2a095f1e6484b9186673c9ec00\"},\"description\":\"Entwicklung einer Sensorschnittstelle f\u00fcr den integrierten nRF52-Chip, bevor das Sensor-Backend mit dem eigentlichen Sensor umgesetzt wird.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/#primaryimage\",\"url\":\"https:\\\/\\\/ruuvi.com\\\/i\\\/u\\\/ruuvi-tag-firmware-environmental-sensing.jpeg\",\"contentUrl\":\"https:\\\/\\\/ruuvi.com\\\/i\\\/u\\\/ruuvi-tag-firmware-environmental-sensing.jpeg\",\"width\":1400,\"height\":733,\"caption\":\"Introbild zur Ruuvi-Firmware-Serie, Teil 5\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/ruuvi-firmware-teil-5-umweltsensorik\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/front\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/\",\"name\":\"Ruuvi\",\"description\":\"Measure Your World\",\"potentialAction\":[],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/#\\\/schema\\\/person\\\/143b8e2a095f1e6484b9186673c9ec00\",\"name\":\"Otso Jousimaa\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fd52303e35b8b23c01cfeec7bb2636768de567cd33604f794ae86dd971e61645?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fd52303e35b8b23c01cfeec7bb2636768de567cd33604f794ae86dd971e61645?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fd52303e35b8b23c01cfeec7bb2636768de567cd33604f794ae86dd971e61645?s=96&d=mm&r=g\",\"caption\":\"Otso Jousimaa\"},\"url\":\"https:\\\/\\\/ruuvi.com\\\/de\\\/author\\\/ojousima\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik \u2013 Ruuvi","description":"Entwicklung einer Sensorschnittstelle f\u00fcr den integrierten nRF52-Chip, bevor das Sensor-Backend mit dem eigentlichen Sensor umgesetzt wird.","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:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/","og_locale":"de_DE","og_type":"article","og_title":"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik \u2013 Ruuvi","og_description":"Entwicklung einer Sensorschnittstelle f\u00fcr den integrierten nRF52-Chip, bevor das Sensor-Backend mit dem eigentlichen Sensor umgesetzt wird.","og_url":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/","og_site_name":"Ruuvi","article_publisher":"https:\/\/www.facebook.com\/ruuvi.cc","article_published_time":"2018-08-24T08:11:00+00:00","article_modified_time":"2026-06-11T05:48:58+00:00","og_image":[{"width":1400,"height":733,"url":"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing.jpeg","type":"image\/jpeg"}],"author":"Otso Jousimaa","twitter_card":"summary_large_image","twitter_creator":"@ruuvicom","twitter_site":"@ruuvicom","twitter_misc":{"Verfasst von":"Otso Jousimaa","Gesch\u00e4tzte Lesezeit":"13\u00a0Minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/#article","isPartOf":{"@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/"},"author":{"name":"Otso Jousimaa","@id":"https:\/\/ruuvi.com\/de\/#\/schema\/person\/143b8e2a095f1e6484b9186673c9ec00"},"headline":"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik","datePublished":"2018-08-24T08:11:00+00:00","dateModified":"2026-06-11T05:48:58+00:00","mainEntityOfPage":{"@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/"},"wordCount":2563,"image":{"@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/#primaryimage"},"thumbnailUrl":"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing.jpeg","articleSection":["Ruuvi-Software-Artikel"],"inLanguage":"de"},{"@type":"WebPage","@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/","url":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/","name":"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik \u2013 Ruuvi","isPartOf":{"@id":"https:\/\/ruuvi.com\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/#primaryimage"},"image":{"@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/#primaryimage"},"thumbnailUrl":"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing.jpeg","datePublished":"2018-08-24T08:11:00+00:00","dateModified":"2026-06-11T05:48:58+00:00","author":{"@id":"https:\/\/ruuvi.com\/de\/#\/schema\/person\/143b8e2a095f1e6484b9186673c9ec00"},"description":"Entwicklung einer Sensorschnittstelle f\u00fcr den integrierten nRF52-Chip, bevor das Sensor-Backend mit dem eigentlichen Sensor umgesetzt wird.","breadcrumb":{"@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/#primaryimage","url":"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing.jpeg","contentUrl":"https:\/\/ruuvi.com\/i\/u\/ruuvi-tag-firmware-environmental-sensing.jpeg","width":1400,"height":733,"caption":"Introbild zur Ruuvi-Firmware-Serie, Teil 5"},{"@type":"BreadcrumbList","@id":"https:\/\/ruuvi.com\/de\/ruuvi-firmware-teil-5-umweltsensorik\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ruuvi.com\/de\/front\/"},{"@type":"ListItem","position":2,"name":"Ruuvi Firmware \u2013 Teil 5: Umweltsensorik"}]},{"@type":"WebSite","@id":"https:\/\/ruuvi.com\/de\/#website","url":"https:\/\/ruuvi.com\/de\/","name":"Ruuvi","description":"Measure Your World","potentialAction":[],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/ruuvi.com\/de\/#\/schema\/person\/143b8e2a095f1e6484b9186673c9ec00","name":"Otso Jousimaa","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/fd52303e35b8b23c01cfeec7bb2636768de567cd33604f794ae86dd971e61645?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/fd52303e35b8b23c01cfeec7bb2636768de567cd33604f794ae86dd971e61645?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/fd52303e35b8b23c01cfeec7bb2636768de567cd33604f794ae86dd971e61645?s=96&d=mm&r=g","caption":"Otso Jousimaa"},"url":"https:\/\/ruuvi.com\/de\/author\/ojousima\/"}]}},"_links":{"self":[{"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/posts\/135845","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/comments?post=135845"}],"version-history":[{"count":1,"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/posts\/135845\/revisions"}],"predecessor-version":[{"id":135871,"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/posts\/135845\/revisions\/135871"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/media\/135847"}],"wp:attachment":[{"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/media?parent=135845"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/categories?post=135845"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ruuvi.com\/de\/wp-json\/wp\/v2\/tags?post=135845"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}