Benutzer-Werkzeuge

Webseiten-Werkzeuge


techniken:tensorflownodebluetooth

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
techniken:tensorflownodebluetooth [2021/01/27 19:56]
d.golovko [3. Lokalen Server einrichten]
techniken:tensorflownodebluetooth [2021/02/12 15:44] (aktuell)
SabidJFejzula
Zeile 8: Zeile 8:
   * [[https://​github.com/​tensorflow/​tfjs-models/​tree/​master/​facemesh|Facemesh]]:​ markante Punkte im Gesicht erkennen, ​   * [[https://​github.com/​tensorflow/​tfjs-models/​tree/​master/​facemesh|Facemesh]]:​ markante Punkte im Gesicht erkennen, ​
   * [[https://​github.com/​tensorflow/​tfjs-models/​tree/​master/​handpose|Handpose]]:​ die Handstellung erkennen usw.    * [[https://​github.com/​tensorflow/​tfjs-models/​tree/​master/​handpose|Handpose]]:​ die Handstellung erkennen usw. 
-Es gibt TensowFlow-Implementationen für verschiedene Sprachen, z.B. Python, C++, Java und JavaScript. Die JavaScript-Variante scheint einfacher für den Start zu sein. Eure TensorFlow-Code läuft dabei im Browser. ​+Es gibt TensowFlow-Implementationen für verschiedene Sprachen, z.B. Python, C++, Java und JavaScript. Die JavaScript-Variante scheint einfacher für den Start zu sein. Euer TensorFlow-Code läuft dabei im Browser. ​
  
 <note tip>​Probiert die TensorFlow-Beispiele aus, indem ihr auf die entsprechenden Links in der Liste oben klickt!</​note>​ <note tip>​Probiert die TensorFlow-Beispiele aus, indem ihr auf die entsprechenden Links in der Liste oben klickt!</​note>​
  
-TensorFlow ist rechenintensiv. Deswegen ist es (zu diesem Zeitpunkt im Januar 2021) ziemlich langwierig, es auf einem Smartphone oder Raspberry Pi zu betreiben (bzw. wir haben noch keine gute Lösung gefunden). Es gibt zwar die abgespeckte Variante [[https://​www.tensorflow.org/​lite/​api_docs|TensorFlow Lite]], jedoch scheint es momentan einfacher, TensorFlow auf einem PC zu laufen und nur die Ergebnisse bei  Bedarf ​an den Arduino ​über die serielle Kommunikation zu schicken. Bei mobilen Robotern kann die serielle Kommunikation über Bluetooth laufen. Diesem Thema (TensorFlow & Kommunikation über die serielle Schnittstelle) widmet sich dieser Artikel.+TensorFlow ist rechenintensiv. Deswegen ist es (zu diesem Zeitpunkt im Januar 2021) ziemlich langwierig, es auf einem Smartphone oder Raspberry Pi zu betreiben (bzw. wir haben noch keine gute Lösung gefunden). Es gibt zwar die abgespeckte Variante [[https://​www.tensorflow.org/​lite/​api_docs|TensorFlow Lite]], jedoch scheint es momentan einfacher, TensorFlow auf einem PC zu laufen und nur die Ergebnisse bei Bedarf über serielle Kommunikation ​an den Arduino ​zu schicken. Bei mobilen Robotern kann die serielle Kommunikation über Bluetooth laufen. Diesem Thema (TensorFlow & Kommunikation über die serielle Schnittstelle) widmet sich dieser Artikel.
  
 Bei mobilen Robotern kann man über die App [[https://​www.dev47apps.com/​|DroidCam]] die Handy-Kamera als externe kabellose Webcam nutzen. Wenn der Rechner und das Handy beide im gleichen WLAN-Netzwerk sind, kann man sie kabellos über WLAN verbinden. Die dafür erforderliche IP-Adresse wird in der App angezeigt. ​ Bei mobilen Robotern kann man über die App [[https://​www.dev47apps.com/​|DroidCam]] die Handy-Kamera als externe kabellose Webcam nutzen. Wenn der Rechner und das Handy beide im gleichen WLAN-Netzwerk sind, kann man sie kabellos über WLAN verbinden. Die dafür erforderliche IP-Adresse wird in der App angezeigt. ​
Zeile 44: Zeile 44:
  
 ==3.1. Node.js-Installation== ==3.1. Node.js-Installation==
 +[[techniken::​tensorflownodebluetooth::​windows-lokal#​Node.js auf Windows: Posenet mit lokal gehosteter p5.js Instanz]]
  
-Wir konnten schon über den p5.js-editor die Ergebnisse von einem TensorFlow-Modell bekommen, warum brauchen wir den Server? Grund ist, wir wollen auf den //seriellen Port// zugreifen, um Daten an den Arduino zu schicken, und das geht nicht von der Client-Seite (Browser). In unserem Fall wird der Server auf dem gleichen Rechner laufen wie der Client (Browser), deswegen sagen wir, dass wir einen //lokalen// Server einrichten. ​+Wir konnten schon über den p5.js-editor die Ergebnisse von einem TensorFlow-Modell bekommen, warum brauchen wir den Server? Grund ist, wir wollen auf den //seriellen Port// zugreifen, um Daten an den Arduino zu schicken, und das geht nicht von der Client-Seite (Browser). In unserem Fall wird der Server auf dem gleichen Rechner laufen wie der Client (Browser), deswegen sagen wir, dass wir einen //lokalen// Server einrichten. Eine Internetverbindung brauchen wir trotzdem, da unsere Datei ''​index.html''​ Links zu den Bibliotheken //p5.js// und //ml5.js// beinhaltet
  
 <note tip> Informiert euch darüber, was ein Server und ein Client sind.</​note>​ <note tip> Informiert euch darüber, was ein Server und ein Client sind.</​note>​
Zeile 51: Zeile 52:
 Es gibt viele Möglichkeiten,​ einen Server zu programmieren,​ z.B. mit Java, PHP oder Python. Wir werden einen [[https://​de.wikipedia.org/​wiki/​Node.js|Node.js]]-Server einrichten, u.A. weil Node.js ebenso auf JavaScript geschrieben ist.  Es gibt viele Möglichkeiten,​ einen Server zu programmieren,​ z.B. mit Java, PHP oder Python. Wir werden einen [[https://​de.wikipedia.org/​wiki/​Node.js|Node.js]]-Server einrichten, u.A. weil Node.js ebenso auf JavaScript geschrieben ist. 
  
-Node.js verfügt über den Paket-Manager ''​npm'',​ über welchen man zusätzliche Node-Module installiert. [[https://​nodejs.org/​en/​download/​|Ladt Node.js und npm herunter]] und installiert sie. Anschließend könnt ihr mit den Befehlen ''​node ​v''​ und ''​npm ​v''​ auf dem Terminal (bzw. in der Anwendung **cmd**) überprüfen,​ ob alles geklappt hat. (Die Node/​npm-Version wird angezeigt => geklappt.) ​+Node.js verfügt über den Paket-Manager ''​npm'',​ über welchen man zusätzliche Node-Module installiert. [[https://​nodejs.org/​en/​download/​|Ladet Node.js und npm herunter]] und installiert sie. Anschließend könnt ihr mit den Befehlen ''​node ​%%--%%v''​ und ''​npm ​%%--%%v''​ auf dem Terminal (bzw. in der Anwendung **cmd**) überprüfen,​ ob alles geklappt hat. (Die Node/​npm-Version wird angezeigt => geklappt.) ​
  
 ==3.2. Hallo Welt== ==3.2. Hallo Welt==
  
-Erstellt einen Ordner (ich nenne ihn ''​NodeOrdner''​ -- andere Namen möglich), wo ihr Dateien für euren Server ablegen werdet. Es hilft, wenn dieser Ordner auf dem Laufwerk ist, wo ihr Anwendungen ausführen dürft. Wechselt über die ''​cd''​-Terminal-Befehle ​zu diesem Ordner. Bei Bedarf sucht online, wie man mit ''​cd''​ zwischen Ordnern wechseln kann. Wenn ihr im richtigen Ordner seid, führt diesen Befehl aus -- er initialisiert euer Projekt:\\+Erstellt einen Ordner (ich nenne ihn ''​NodeOrdner''​ -- andere Namen möglich), wo ihr Dateien für euren Server ablegen werdet. Es hilft, wenn dieser Ordner auf dem Laufwerk ist, wo ihr Anwendungen ausführen dürft. Wechselt über den ''​cd''​-Terminal-Befehl ​zu diesem Ordner. ​(Bei Bedarf sucht online, wie man mit ''​cd''​ zwischen Ordnern wechseln kann.Wenn ihr im richtigen Ordner seid, führt diesen Befehl aus -- er initialisiert euer Projekt:\\
 <​code>​ <​code>​
 npm init npm init
 </​code>​ </​code>​
-Bestätigt mit der Enter-Taste (mehrfach) die Standard-Einstellungen. Die Datei ''​package.json''​ wird angelegt, wo diese Einstellungen gespeichert ​werden+Bestätigt mit der Enter-Taste (mehrfach) die Standard-Einstellungen. Die Datei ''​package.json''​ wird automatisch ​angelegt, wo diese Einstellungen gespeichert ​sind
  
 Installiert auch die Node-Module,​ die wir später brauchen werden: ​ Installiert auch die Node-Module,​ die wir später brauchen werden: ​
-  * //express// (minimalistische Node-Variante):​ ''​npm install express --save''​ +  * //express// (minimalistische Node-Variante):​ ''​npm install express ​%%--%%save''​ 
-  * //​body-parser//​ (analysiert HTTP-Requests):​ ''​npm install body-parser --save''​ +  * //​body-parser//​ (analysiert HTTP-Requests):​ ''​npm install body-parser ​%%--%%save''​ 
-  * //​serialport//​ (ermöglicht den Zugriff auf serielle Ports): ''​npm install serialport --save''​+  * //​serialport//​ (ermöglicht den Zugriff auf serielle Ports): ''​npm install serialport ​%%--%%save''​
  
 Erstellt im Ordner die Datei ''​server.js''​ (andere Namen möglich) mit dem folgenden Inhalt: Erstellt im Ordner die Datei ''​server.js''​ (andere Namen möglich) mit dem folgenden Inhalt:
Zeile 93: Zeile 94:
 </​code>​ </​code>​
  
-Geht im Browser auf die Seite ''​http://​localhost:​3000/​index.html''​ (oder ''​http://​127.0.0.1:​3000/​index.html'',​ was das Selbe ist). Wenn ihr "Hallo Welt" ​sieht, funktioniert alles richtig. ​+Geht im Browser auf die Seite ''​http://​localhost:​3000/​index.html''​ (oder ''​http://​127.0.0.1:​3000/​index.html'',​ was das Selbe ist). Wenn ihr "Hallo Welt" ​seht, funktioniert alles richtig. ​
  
 Was haben wir gerade gemacht? Wir haben einen Server eingerichtet,​ der in der Lage ist, Dateien (bzw. Inhalte dieser Dateien) aus dem bestimmten Ordner (in unserem Fall ''​public''​) bereitzustellen. Dann haben wir einen Browser gestartet, der die konkrete Datei ''​index.html''​ angefordert hat. Diese Datei befand sich in dem Ornder, und so wurde ihr Inhalt an den Browser bereitgestellt:​ "Hallo Welt". Das war einfacher Text, damit kann der Browser nicht viel mehr anfangen. Wenn die Datei stattdessen html-Code beinhaltet hätte, könnte der Browser diesen entsprechend verarbeiten -- das machen wir im nächsten Schritt. ​ Was haben wir gerade gemacht? Wir haben einen Server eingerichtet,​ der in der Lage ist, Dateien (bzw. Inhalte dieser Dateien) aus dem bestimmten Ordner (in unserem Fall ''​public''​) bereitzustellen. Dann haben wir einen Browser gestartet, der die konkrete Datei ''​index.html''​ angefordert hat. Diese Datei befand sich in dem Ornder, und so wurde ihr Inhalt an den Browser bereitgestellt:​ "Hallo Welt". Das war einfacher Text, damit kann der Browser nicht viel mehr anfangen. Wenn die Datei stattdessen html-Code beinhaltet hätte, könnte der Browser diesen entsprechend verarbeiten -- das machen wir im nächsten Schritt. ​
Zeile 99: Zeile 100:
 ==3.3. Eure Dateien über den Server bereitstellen== ==3.3. Eure Dateien über den Server bereitstellen==
  
-Löscht die Datei ''​index.html''​ aus dem Ordner ''​public''​ und fügt die im Punkt 2 erstellten Dateien ''​index.html''​ und ''​script.js''​ hinzu. Ruft im Browser den Link ''​http://​localhost:​3000/​index.html''​ auf. Wenn alles richtig ist, sieht ihr euer Programm mit TensorFlow/​Posenet. ​+Löscht die Datei ''​index.html''​ aus dem Ordner ''​public''​ und fügt die im Punkt 2 erstellten Dateien ''​index.html''​ und ''​script.js''​ hinzu. Ruft im Browser den Link ''​http://​localhost:​3000/​index.html''​ auf. Wenn alles richtig ist, seht ihr euer Programm mit TensorFlow/​Posenet. ​
  
  
 ====4. GET & POST Requests==== ====4. GET & POST Requests====
  
-Der Server und der Client (Browser) kommunizieren über den //Hypertext Transfer Protocol//, HTTP ([[https://​www.ionos.de/​digitalguide/​hosting/​hosting-technik/​was-ist-http/​|kurze Erklärung]]). Der Client kann an den Server bestimmte Anfragen schicken, am häufigsten kommen der GET- und der POST-Request vor ([[https://​www.ionos.de/​digitalguide/​hosting/​hosting-technik/​http-request-erklaert/​|kurze Erklärung]]). In unserem Beispiel könnten wir sowohl GET als auch POST verwenden; Im folgenden Beispiel wird ein POST-Request verschickt.+Der Server und der Client (Browser) kommunizieren über das //Hypertext Transfer Protocol//, HTTP ([[https://​www.ionos.de/​digitalguide/​hosting/​hosting-technik/​was-ist-http/​|kurze Erklärung]]). Der Client kann an den Server bestimmte Anfragen schicken, am häufigsten kommen der GET- und der POST-Request vor ([[https://​www.ionos.de/​digitalguide/​hosting/​hosting-technik/​http-request-erklaert/​|kurze Erklärung]]). In unserem Beispiel könnten wir sowohl GET als auch POST verwenden; Im folgenden Beispiel wird ein POST-Request verschickt.
  
 Der POST-Request kann im Code so aussehen (es kann auch was anderes statt "​distance"​ und "​dist"​ stehen, aber es muss der gleiche String an beiden Seiten sein): Der POST-Request kann im Code so aussehen (es kann auch was anderes statt "​distance"​ und "​dist"​ stehen, aber es muss der gleiche String an beiden Seiten sein):
 <hidden Code: POST-Request im Browser schicken>​ <hidden Code: POST-Request im Browser schicken>​
 <code javascript>​ <code javascript>​
-    var distance = 42; // The value that will be sent to the server+    var distance = 42; // der Wert, den man an den Server schickt
     var xhttp = new XMLHttpRequest();​     var xhttp = new XMLHttpRequest();​
-    xhttp.open("​POST",​ '/​dist',​ true); +    xhttp.open("​POST",​ '/​dist',​ true);  
-    //Send the proper header information along with the request+    //Den richtigen POST-Request-Header schicken:
     xhttp.setRequestHeader("​Content-Type",​ "​application/​x-www-form-urlencoded"​);​     xhttp.setRequestHeader("​Content-Type",​ "​application/​x-www-form-urlencoded"​);​
  
-    xhttp.onreadystatechange = function() { // Call a function when the state changes.+    xhttp.onreadystatechange = function() { // Diese Funktion wird aufgerufen, sobald der Zustand sich aendert
         if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {         if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
-            // Request ​finishedDo processing here. Remove this if you are not doing anything.+            // Request ​ausgefuehrtWeitere Aktionen koennen ausgefuehrt werden.
         }         }
     }     }
-    xhttp.send("​distance="​ + distance);+    xhttp.send("​distance="​ + distance); ​// den Wert als Eigenschaft distance schicken
     ​     ​
 </​code>​ </​code>​
Zeile 128: Zeile 129:
 <hidden Code: POST-Request auf dem Server verarbeiten>​ <hidden Code: POST-Request auf dem Server verarbeiten>​
 <code javascript>​ <code javascript>​
-// listen to post request: +const bodyParser = require("​body-parser"​); ​// Node-Modul body-parser einbinden
-const bodyParser = require("​body-parser"​);​+
 app.use(bodyParser.urlencoded({extended : true})); app.use(bodyParser.urlencoded({extended : true}));
  
Zeile 135: Zeile 135:
     console.log('​Got distance:',​ req.body.distance);​     console.log('​Got distance:',​ req.body.distance);​
     res.sendStatus(200);​     res.sendStatus(200);​
-    // TODO: continue with further processing+    // TODO: weitere Aktionen ​
 }); });
 </​code>​ </​code>​
Zeile 143: Zeile 143:
 ====5. Seriellen Bluetooth-Port einrichten==== ====5. Seriellen Bluetooth-Port einrichten====
  
-TODO+Überpfüft,​ dass auf eurem Rechner ein Bluetooth-Port verfügbar ist. Auf einem Linux-Rechner kann man das z.B. so überprüfen (das Sternchen * steht für eine beliebige Nummer/​Index des Ports, der Befehl wird im Terminal ausgeführt):​
  
-====6. Daten über den seriellen Port vom Server zum HC-05 schicken====+<​code>​ 
 +ls /​dev/​rfcomm* 
 +</​code>​
  
-Wenn wir den seriellen Port erstellt haben und seinen Namen kennen, können wir Daten vom Server verschicken:​+Falls Bluetooth-Ports verfügbar sind, werden ihre Namen angezeigt, z.B. ''/​dev/​rfcomm0'',​ ''/​dev/​rfcomm1''​ usw. Wenn "No such file or directory"​ zurück kommt, sind keine Bluetooth-Ports verfügbar, und wir müssen den Port extra einrichten (oder euer Rechner ist nicht Bluetooth-fähig). Um das zu tun, müssen wir schauen, welche Bluetooth-Geräte überhaupt empfangen werden, das machen wir mit dem folgenden Befehl: 
 + 
 +<​code>​ 
 +sudo bluetoothctl 
 +</​code>​  
 + 
 +Es werden Adressen (z.B. "​F4:​5E:​AB:​AA:​BB:​CC"​) und Namen (z.B. "​HC-05"​) von den verfügbaren Geräten angezeigt. Notiert euch die Adresse vom Gerät, mit welchem ihr die serielle Kommunikation aufbauen wollt. Anschließend erstellen wir den Port mit dem Namen z.B. ''/​dev/​rfcomm0'',​ über welchen wir uns mit diesem Gerät verbinden werden: 
 + 
 +<​code>​ 
 +sudo rfcomm bind 0 F4:​5E:​AB:​AA:​BB:​CC 1 
 +</​code>​ 
 + 
 +Überpfüft mit ''​ls /​dev/​rfcomm*'',​ ob das geklappt hat. Den Portnamen ''/​dev/​rfcomm0''​ werden wir im nächsten Teil im Node.js-Code benutzen. Zum Testen ist es manchmal hilfreich, wenn man direkt im Terminal die serielle Kommunikation betreiben kann. Dafür könnt ihr z.B. das Programm //picocom// nutzen (Installation:​ ''​sudo apt-get install picocom''​):​ 
 + 
 +<​code>​  
 +picocom /​dev/​rfcomm0 
 +</​code>​  
 +\\ 
 + 
 + 
 + 
 +====6. Daten über den seriellen Port vom Server zum HC-05 schicken==== 
 +  
 +Wenn wir den seriellen Port erstellt haben und seinen Namen kennen, können wir Daten vom Server verschicken ​(dieser Code gehört in die ''​server.js''​-Datei):
  
 <hidden Code: einen String über den seriellen Port schicken>​ <hidden Code: einen String über den seriellen Port schicken>​
techniken/tensorflownodebluetooth.1611773768.txt.gz · Zuletzt geändert: 2021/01/27 19:56 von d.golovko