{"id":29010,"date":"2021-12-23T10:39:00","date_gmt":"2021-12-23T09:39:00","guid":{"rendered":"https:\/\/pi3g.com\/?p=29010"},"modified":"2021-12-23T16:24:28","modified_gmt":"2021-12-23T15:24:28","slug":"integrating-the-bsec-in-circuitpython-a-work-in-progress","status":"publish","type":"post","link":"https:\/\/pi3g.com\/de\/integrating-the-bsec-in-circuitpython-a-work-in-progress\/","title":{"rendered":"Integration des BSEC in CircuitPython (Eine laufende Arbeit)"},"content":{"rendered":"<h2 class=\"wp-block-heading\">Einige Hinweise zur Verwendung des Build-Flags USER_C_MODULES<\/h2>\n\n\n\n<p>Dieser Blog-Beitrag wird zwei verschiedene Themen behandeln. Einerseits werde ich \u00fcber den allgemeinen Ansatz zum Einbinden und Testen Ihres eigenen C-Codes in Ihrem benutzerdefinierten Build von <a href=\"https:\/\/github.com\/adafruit\/circuitpython\" target=\"_blank\" rel=\"noreferrer noopener\">SchaltkreisPython<\/a> . Andererseits werde ich \u00fcber spezifische Herausforderungen bei der Nutzung der <a href=\"http:\/\/pi3g.com\/de\/bme688\/\" target=\"_blank\" rel=\"noreferrer noopener\">BME688 Breakout Board<\/a>basierend auf dem BME688-Sensor von Bosch, wobei das spezifische Breakout-Board von uns entwickelt wurde, und deren BSEC-Bibliothek auf dem RP2040. Diese Bibliothek erm\u00f6glicht eine erweiterte Analyse der vom BME688 bereitgestellten Sensordaten und Berechnungen auf der Grundlage dieser Sensordaten.<\/p>\n\n\n\n<p>Die Vorteile, entweder eigenen C-Code oder statische Bibliotheken in CircuitPython zu verpacken, liegen auf der Hand. Viele Mikrocontroller-Boards, in diesem Fall der Raspberry Pi Pico, der auf dem RP2040 basiert, erlauben die Ausf\u00fchrung von C-Code. Reines C zu schreiben kann entmutigend sein, besonders f\u00fcr Programmierer, die noch nicht viel Zeit mit dieser Sprache verbracht haben. CircuitPython hingegen bietet einen einfachen Zugang \u00fcber die Python-Syntax, eine Menge gut geschriebener Bibliotheken und eine gro\u00dfartige Community, die Ihnen hilft.<\/p>\n\n\n\n<p>Unser Ziel war es, zu testen, ob es theoretisch m\u00f6glich ist, die BSEC-Bibliothek zu umh\u00fcllen. Diese Bibliothek wird f\u00fcr eine Vielzahl von Plattformen und Compilern angeboten, darunter der Cortex M0+ und der <a href=\"https:\/\/www.bosch-sensortec.com\/software-tools\/software\/bme688-software\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">arm-none-eabi-gcc-Compiler<\/a>.<\/p>\n\n\n\n<p>W\u00e4hrend die Umgehung des BSEC f\u00fcr unseren Fall spezifisch sein k\u00f6nnte, werde ich einige allgemeinere Hinweise geben, wie man ein selbst geschriebenes C-Modul in CircuitPython einbindet, um seine Funktionalit\u00e4t schnell zu testen, wie man eine zus\u00e4tzliche Bin\u00e4rbibliothek bindet und wie man CircuitPython so baut, dass sowohl das C-Modul als auch die Bibliothek eingebunden sind. Auf dem Weg dorthin gibt es einige kleinere Fallstricke, die dieser Blogbeitrag hoffentlich abdeckt.<\/p>\n\n\n\n<p>Wenn Sie Ihr eigenes CircuitPython C-Modul schreiben wollen, gibt es derzeit zwei verschiedene Ans\u00e4tze. \u00dcber den ersten k\u00f6nnen Sie in den offiziellen Richtlinien auf der <a href=\"https:\/\/learn.adafruit.com\/extending-circuitpython\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Adafruit Website<\/a> die derzeit veraltet sind, aber immer noch eine Menge n\u00fctzlicher Informationen enthalten. Daher wird empfohlen, sich den Quellcode von CircuitPython anzusehen und ihm als Beispiel zu folgen. Ohne zu sehr ins Detail zu gehen, geht es darum, Ihre Header- und Quellcodedateien in den Verzeichnissen \"shared-bindings\" bzw. \"shared-module\" abzulegen und dabei die bereitgestellten Wrapper-Methoden zu verwenden.<\/p>\n\n\n\n<p>Wenn Ihr Ziel die langfristige Nutzung oder die Mitarbeit an der offiziellen Version ist, sollten Sie diese Richtlinien befolgen. Wenn Sie zun\u00e4chst sehen wollen, ob der Code auf einer bestimmten Plattform l\u00e4uft oder einige schnelle Tests durchf\u00fchren wollen, ist der hier beschriebene Ansatz etwas einfacher und weniger arbeitsintensiv.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wie verwendet man USER_C_MODULES?<\/h2>\n\n\n\n<p>Zuerst gehen wir den Prozess der Erstellung von CircuitPython durch, indem wir die offizielle Anleitung verwenden, die Sie hier finden k\u00f6nnen <a href=\"https:\/\/learn.adafruit.com\/building-circuitpython\/introduction\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">hier<\/a>. Nachdem wir uns vergewissert haben, dass alles wie vorgesehen funktioniert, CircuitPython gebaut wird und auf der Zielplattform l\u00e4uft, k\u00f6nnen wir damit beginnen, unseren eigenen Code einzubinden. Dies geschieht \u00fcber das Build-Flag USER_C_MODULES. Diese Funktionalit\u00e4t ist von MicroPython geerbt. Wenn Sie daran interessiert sind, k\u00f6nnen Sie einen Blick auf die offizielle <a href=\"https:\/\/docs.micropython.org\/en\/latest\/develop\/cmodules.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">MicroPython-Dokumentation<\/a> was auch auf CircuitPython anwendbar zu sein scheint.<\/p>\n\n\n\n<p>Zuerst erstellen wir einen neuen Ordner im CircuitPython-Verzeichnis und f\u00fcllen ihn mit den notwendigen Dateien:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">circuitpython\n\u251c\u2500\u2500circuitpython\/\n| \u251c\u2500\u2500\u2500data\/\n| \u251c\u2500\u2500\u2500Ger\u00e4te\/\n| \u251c\u2500\u2500\u2500docs\/\n... ...\n|\n\u2514\u2500\u2500\u2500externeC-Module\/\n        \u2514\u2500\u2500BSEC_Test\n                \u251c\u2500\u2500\u2500 bsec_datatypes.h\n                \u251c\u2500\u2500\u2500 bsec_interface.h\n                \u251c\u2500\u2500\u2500 libalgobsec.a\n                \u251c\u2500\u2500\u2500 micropython.mk\n                \u2514\u2500\u2500 testingBSEC.c<\/pre>\n\n\n\n<p>In diesem Fall werden 'bsec_datatypes.h', 'bsec_interface.h' und 'libalgobsec.a' von Bosh bereitgestellt. Wir m\u00fcssen uns nur um mircopython.mk und testingBSEC.c k\u00fcmmern.<\/p>\n\n\n\n<p>Wie sich herausstellt, enth\u00e4lt CircuitPython bereits ein C (und C++) Beispiel und das dazugeh\u00f6rige Makefile im Quellcode. Sie k\u00f6nnen es finden unter:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>circuitpython\/examples\/usercmodule\/cexample\/<\/code><\/pre>\n\n\n\n<p>Wir k\u00f6nnen den Code einfach kopieren und f\u00fcr unseren eigenen Gebrauch bearbeiten. Dazu binden wir die Header-Dateien der Bibliothek ein, die wir verwenden wollen (in unserem Fall #include \"bsec_interface.h\") und passen den Code darin an. Die Datei \"examplemodule.c\" ist ein gut gew\u00e4hltes Beispiel, da sie eine sehr einfache Funktion enth\u00e4lt, die Integer-Eingaben entgegennimmt und Integer-Ausgaben erzeugt. Die Anpassung an unsere Anforderungen bestand haupts\u00e4chlich darin, die Anzahl der Eingabevariablen zu \u00e4ndern und einige Funktionen umzubenennen. Wenn Ihr Ziel nur darin besteht, die Durchf\u00fchrbarkeit einer gro\u00df angelegten Integration zu testen, sollte dies wahrscheinlich ausreichend sein. Dies kann leicht erreicht werden, indem man Fehlercodes und einige Beispielausgaben zur\u00fcckgibt und pr\u00fcft, ob sie wie erwartet aussehen. Ansonsten ist das Hinzuf\u00fcgen neuer Funktionen oder das Vornehmen grundlegenderer \u00c4nderungen an bestehenden Funktionen nicht sehr schwierig und in der MicroPython-Dokumentation gut beschrieben.<\/p>\n\n\n\n<p>Sie k\u00f6nnen es bereits dabei belassen. Je nach Komplexit\u00e4t Ihres Testfalls kann es notwendig sein, weitere Funktionen hinzuzuf\u00fcgen, aber in unserem Fall war das Hauptziel einfach zu sehen, ob der Code l\u00e4uft.<\/p>\n\n\n\n<p>Zus\u00e4tzlich \u00e4ndern wir das Makefile - micropython.mk - so, dass es etwa so aussieht:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>BSEC_TEST_DIR := $(USERMOD_DIR)\n# F\u00fcgen Sie unsere C-Datei zu SRC_USERMOD hinzu.\nSRC_USERMOD += $(BSEC_TEST_DIR)\/testingBSEC.c\n# Hinzuf\u00fcgen der vorkompilierten Bibliothek zu SRC_USERMOD.\nSRC_USERMOD += $(BSEC_TEST_DIR)\/libalgobsec.a<\/code><\/pre>\n\n\n\n<p>Wir machen dann einfach weiter und bauen CircuitPython wie in der offiziellen Dokumentation beschrieben:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>1. Gehen Sie in das Verzeichnis des Ports, f\u00fcr den Sie bauen wollen (in unserem Fall circuitpython\/ports\/raspberrypi)<\/li><li>2. make BOARD=raspberry_pi_pico USER_C_MODULES=..\/..\/..\/externalCmodules<\/li><\/ul>\n\n\n\n<p>Das Build-Flag verweist auf das Verzeichnis, in das wir unseren Code und unsere Bibliotheken stellen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Probleme w\u00e4hrend des Erstellungsprozesses<\/h2>\n\n\n\n<p>Wenn Sie die Anweisungen bis hierher genau befolgt haben, werden Sie auf das erste Problem sto\u00dfen. Das Build-System findet die Bibliothek (libalgobsec.a) nicht.<\/p>\n\n\n\n<p>Es scheint, dass das Build-System an zwei verschiedenen Stellen w\u00e4hrend des Build-Prozesses danach sucht. In unserem Fall an den folgenden zwei Stellen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>circuitpython\n\u251c\u2500\u2500circuitpython\/\n| \u251c\u2500\u2500\u2500data\/\n| \u251c\u2500\u2500\u2500Ger\u00e4te\/\n| \u251c\u2500\u2500\u2500docs\/\n| \u2514\u2500\u2500BSEC_Test\n<span class=\"has-inline-color has-luminous-vivid-amber-color\">| \u2514\u2500\u2500 libalgobsec.a<\/span>\n...\n|\n\u2514\u2500\u2500externeC-Module\/\n        \u2514\u2500\u2500BSEC_Test\n                \u251c\u2500\u2500\u2500 bsec_datatypes.h\n                \u251c\u2500\u2500\u2500 bsec_interface.h\n<span class=\"has-inline-color has-luminous-vivid-amber-color\">                \u251c\u2500\u2500 libalgobsec.a<\/span>\n                \u251c\u2500\u2500 micropython.mk\n                \u2514\u2500\u2500 testingBSEC.c<\/code><\/pre>\n\n\n\n<p>Dieses Hindernis hat offenbar seinen Ursprung in der Art und Weise, wie das Build-System mit dem USER_C_MODULE-Buildflag interagiert. Selbst nachdem ich einige Zeit damit verbracht habe, mich damit zu befassen, war jede L\u00f6sung, die ich ausprobiert habe, in irgendeiner Weise unzureichend oder f\u00fchrte zu weiterer Komplexit\u00e4t. Sollte jemand dies lesen und eine sauberere L\u00f6sung finden, w\u00fcrde ich mich freuen, wenn Sie diese mit mir teilen w\u00fcrden! In diesem Fall werde ich den Text entsprechend \u00e4ndern.<\/p>\n\n\n\n<p>Zum Gl\u00fcck l\u00e4sst sich das Problem leicht vermeiden, indem man die Bibliothek dupliziert und ebenfalls am zweiten Speicherort ablegt. Dies ist zwar nicht die sauberste L\u00f6sung, aber es gibt keinen Gr\u00f6\u00dfenunterschied im endg\u00fcltigen Build.<\/p>\n\n\n\n<p>Wenn Sie versuchen, Ihren eigenen Code zum Laufen zu bringen, sollte dies alles sein, was Sie brauchen, um weitere Tests durchf\u00fchren zu k\u00f6nnen. Durch die Umgehung dieses kleinen Problems sollten Ihr eigener Code und Ihre Bibliotheken bereits kompiliert, korrekt gelinkt, gebaut und aufrufbar sein.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Aber was ist mit unserem Testfall, dem BSEC?<\/h2>\n\n\n\n<p>Wenn Sie diesen Weg einschlagen, werden Sie schnell entt\u00e4uscht sein. Sie werden sich mit Fehlermeldungen \u00fcber undefinierte Funktionen konfrontiert sehen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/hanno\/System\/bin\/ARM_GCC\/gcc-arm-none-eabi-10-2020-q4-major\/bin\/..\/lib\/gcc\/arm-none-eabi\/10.2.1\/..\/..\/..\/..\/arm-none-eabi\/bin\/ld: IaqEstimator.c:(.text+0xea): undefinierte Referenz auf `fminf'\n\/home\/hanno\/System\/bin\/ARM_GCC\/gcc-arm-none-eabi-10-2020-q4-major\/bin\/..\/lib\/gcc\/arm-none-eabi\/10.2.1\/..\/..\/..\/..\/arm-none-eabi\/bin\/ld: IaqEstimator.c:(.text+0x112): undefinierte Referenz auf `fmaxf'\n\/home\/hanno\/System\/bin\/ARM_GCC\/gcc-arm-none-eabi-10-2020-q4-major\/bin\/..\/lib\/gcc\/arm-none-eabi\/10.2.1\/..\/..\/..\/..\/arm-none-eabi\/bin\/ld: IaqEstimator.c:(.text+0x162): undefinierte Referenz auf `fmaxf'\n\/home\/hanno\/System\/bin\/ARM_GCC\/gcc-arm-none-eabi-10-2020-q4-major\/bin\/..\/lib\/gcc\/arm-none-eabi\/10.2.1\/..\/..\/..\/..\/arm-none-eabi\/bin\/ld: IaqEstimator.c:(.text+0x190): undefinierte Referenz auf `fmaxf'\n\/home\/hanno\/System\/bin\/ARM_GCC\/gcc-arm-none-eabi-10-2020-q4-major\/bin\/..\/lib\/gcc\/arm-none-eabi\/10.2.1\/..\/..\/..\/..\/arm-none-eabi\/bin\/ld: IaqEstimator.c:(.text+0x198): undefinierte Referenz auf `fminf'\n........\n<\/code><\/pre>\n\n\n\n<p>Nun, wie sich herausstellt, gibt es derzeit ein gro\u00dfes Hindernis. Da CircuitPython f\u00fcr den Einsatz auf Mikrocontrollern gedacht ist und der Speicher auf diesen oft sehr begrenzt ist, haben die Entwickler ihre eigene Mathematikbibliothek geschrieben und verwenden diese. W\u00e4hrend dies je nach pers\u00f6nlichem Anwendungsfall kein Problem sein mag, verwendet BSEC die Funktionalit\u00e4t der Standard-C-Mathe-Bibliothek. Und obwohl es ein Buildflag gibt, um CircuitPython mit der Standard-C-Mathe-Bibliothek zu bauen (circuitpython\/ports\/raspberrypi\/mpconfigport.mk \u2192 INTERNAL_LIBM), scheint es derzeit nicht mehr zu funktionieren. Es wieder zum Laufen zu bringen, w\u00fcrde zus\u00e4tzliche Zeit und eine gute Kenntnis des Build-Systems erfordern und ging f\u00fcr unseren kleinen Testfall etwas zu weit.<\/p>\n\n\n\n<p>Aber es gibt eine (etwas 'hacky') L\u00f6sung, um das BSEC zumindest dazu zu bringen, sich zu initialisieren und einige grundlegende Informationen auszugeben, was beweist, dass es wahrscheinlich m\u00f6glich ist, es in der Theorie zu integrieren. Wir wickeln die fehlenden Funktionen in unseren C-Code ein oder implementieren sie neu, indem wir die eingebauten mathematischen Funktionen verwenden, die die internal_libm bereitstellt. Dies kann etwa wie folgt aussehen:<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>float fminf ( float x, float y ) {\n    if (isnan(x))\n\t\ty zur\u00fcckgeben;\n\tif (isnan(y))\n\t\treturn x;\n\t\/\/ Behandlung von Nullen mit Vorzeichen, siehe C99 Anhang F.9.9.2\n\tif (signbit(x) != signbit(y))\n\t\treturn signbit(x) ? x : y;\n\treturn x &lt; y ? x : y;\n}<\/code><\/pre>\n\n\n\n<p>In den meisten F\u00e4llen wurde der Code aus dem <a href=\"https:\/\/developer.arm.com\/tools-and-software\/open-source-software\/developer-tools\/gnu-toolchain\/gnu-rm\/downloads\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">arm-none-eabi-gcc-Compiler<\/a> die quelloffen ist und ohne Probleme eingesehen werden kann.<\/p>\n\n\n\n<p>Jetzt wird CircuitPython gebaut, das BSEC ist aufrufbar und gibt die entsprechenden Werte zur\u00fcck. Trotzdem bleiben einige Probleme bestehen, wenn man versucht, bestimmte Funktionen zu nutzen. Es scheint wahrscheinlich, dass diese das Ergebnis des CircuitPython-Build-Prozesses sind, da sie verschwinden, wenn die BSEC nativ mit C verwendet wird. Um das BSEC in seiner Gesamtheit zum Laufen zu bringen und es einfach von CircuitPython aus aufrufen zu k\u00f6nnen, ist zus\u00e4tzliche Arbeit und wahrscheinlich auch eine gewisse Koordination notwendig, um Zugang zu einer korrekten Version des BSEC zu bekommen (das derzeit mit der Version 9-2019-q4-major der ARM GNU Tool Chain gebaut wird, w\u00e4hrend CircuitPython die Version 10-2020-q4-major verwendet) und um den Build-Prozess von CircuitPython leicht zu modifizieren und anzupassen. Ob dies in Zukunft von uns gemacht wird, bleibt abzuwarten, aber ich hoffe, dass dieser Blogbeitrag Entwicklern, die ihren eigenen Code mit dem USER_C_MODULES-Buildflag testen und dabei einige Fallstricke vermeiden wollen, eine Orientierung geben kann.<\/p>\n\n\n\n<p>Sollte es eine Aktualisierung unserer Fortschritte geben, wird diese Seite entsprechend aktualisiert.<\/p>\n\n\n\n<p>Wenn Sie weitere Fragen haben, die ich nicht ausf\u00fchrlich genug (oder gar nicht) behandelt habe, k\u00f6nnen Sie entweder einen Kommentar hinterlassen oder sich per E-Mail an mich wenden! Ich werde gerne antworten.<\/p>","protected":false},"excerpt":{"rendered":"<p>Ein kurzer Beitrag \u00fcber die Verwendung einer statischen C-Bibliothek in CircuitPython und ein Fortschrittsbericht \u00fcber das Wrapping der BSEC-Bibliothek im Besonderen.<\/p>","protected":false},"author":860,"featured_media":28281,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[402,610,1,400,939,452],"tags":[986,985,984],"class_list":["post-29010","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","category-python","category-raspberrypi-blog","category-raspberry-pi-embedded-development","category-raspberry-pi-embedded-hardware","category-tips-tricks","tag-bme688","tag-bsec","tag-circuitpython"],"_links":{"self":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/29010","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/users\/860"}],"replies":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/comments?post=29010"}],"version-history":[{"count":15,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/29010\/revisions"}],"predecessor-version":[{"id":29028,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/29010\/revisions\/29028"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/media\/28281"}],"wp:attachment":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/media?parent=29010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/categories?post=29010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/tags?post=29010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}