<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Nodejs on zefanjas.de - Open Source &amp; Education</title>
    <link>https://zefanjas.de/tags/nodejs/</link>
    <description>Recent content in Nodejs on zefanjas.de - Open Source &amp; Education</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>de-DE</language>
    <lastBuildDate>Fri, 20 Dec 2013 13:28:39 +0000</lastBuildDate><atom:link href="https://zefanjas.de/tags/nodejs/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Build a Robot #2 – Fernsteuerung mit dem Smartphone</title>
      <link>https://zefanjas.de/build-a-robot-2-fernsteuerung-mit-dem-smartphone/</link>
      <pubDate>Fri, 20 Dec 2013 13:28:39 +0000</pubDate>
      
      <guid>https://zefanjas.de/build-a-robot-2-fernsteuerung-mit-dem-smartphone/</guid>
      <description>&lt;p&gt;Heute soll es uns um die Steuerung des kleinen Roboters mit einem Smartphone/Tablet gehen. Dabei soll die Fernsteuerung möglichst plattform-unabhängig sein. Aus diesem Grund habe ich mich für eine einfache Website entschieden, welche die Daten des [Gyroskop][1] ausliest und entsprechende Befehle an den Roboter schickt.&lt;/p&gt;
&lt;h3 id=&#34;die-serverseite&#34;&gt;Die Serverseite&lt;/h3&gt;
&lt;p&gt;Ich habe in den letzten Jahren viel mit Javascript programmiert und aus diesem Grund habe ich mich für eine [nodejs][2] basierte Lösung entschieden. Javascript ist für die Steuerung von GPIOs eigentlich nicht wirklich geeignet (single threading, Latenzen, …), aber für das An- und Ausschalten von Motoren passt es ganz gut.&lt;/p&gt;
&lt;p&gt;Zuerst sollte man also nodejs auf dem Raspberry Pi installieren. Da die Version in den Repositories nicht gerade aktuell ist, kann man sich manuell ein compiliertes Paket direkt bei nodejs downloaden. Die Installation ist in [diesem Artikel][3] ganz gut beschrieben.&lt;/p&gt;
&lt;p style=&#34;text-align: left;&#34;&gt;
  Bei Github findet man verschiedene Pakete für die Ansteuerung der GPIOs. Ich habe mich für &lt;a href=&#34;https://github.com/brnt/node-rpio&#34;&gt;node-rpio&lt;/a&gt; entschieden, da die API der Python-API entspricht, die wir im letzten Beitrag verwendet haben. Weiterhin ist die API synchron, was in unserem Fall sinnvoll ist, da wir sonst mit vielen vielen Callbacks zu tun hätten 😉 Um node-rpio zu nutzen, muss es noch compiliert werden. Dazu gibt man einfach den Befehle
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install -g node-gyp
node-gyp rebuild
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ein, nachdem man das Github-Repo geklont hat. Nun ist alles fertig, um die Motoren über nodejs zu steuern. Da die API gleich ist, können wir im Prinzip den Quelltext aus dem letzten Beitrag nehmen und nur ein klein wenig anpassen:&lt;/p&gt;
&lt;pre class=&#34;brush:js&#34;&gt;var gpio = require(&#34;./node-rpio/lib/rpio&#34;);

//Setup GPIO Pins
gpio.setmode(gpio.BOARD);
gpio.setup(13, gpio.OUT);
gpio.setup(15, gpio.OUT);
gpio.setup(16, gpio.OUT);
gpio.setup(18, gpio.OUT);

gpio.output(13, 1);
gpio.output(15, 0);
gpio.output(16, 1);
gpio.output(18, 0);

process.on(&#39;SIGINT&#39;, function() {
    console.log(&#34;\nGracefully shutting down from SIGINT (Ctrl+C)&#34;);
    //Cleanup
    gpio.cleanup();
    process.exit();
});
```

Der letzte Teil dient dazu, dass man mit Ctrl+C das Skript abbrechen kann, denn sonst würden die Motoren ständig weiterdrehen.

Ok, jetzt können wir zwar die Motoren ansteuern, aber nur direkt am Raspberry Pi. Die Verbindung zum Smartphone fehlt noch. [Socket.io][4] ist ein großartiges Projekt, welches eine direkte Verbindung über webSockets zwischen Server und Client ermöglicht. Man kann Daten sehr einfach hin- und herschicken und eigene Ereignisse definieren, auf die dann der Server bzw. Client reagieren kann. Was wir brauchen ist nun eine HTML-Datei, welche den Gyroskop ausliest und die entsprechenden Befehle an den nodejs Server sendet, welche dieser dann verarbeitet:

&lt;noscript&gt;
  ```
&lt;code class=&#34;language-html html&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta charset=&#34;UTF-8&#34;&amp;gt;
        &amp;lt;title&amp;gt;Robot Project&amp;lt;/title&amp;gt;
	    &amp;lt;script src=&#34;https://zefanjas.de/socket.io/socket.io.js&#34;&amp;gt;&amp;lt;/script&amp;gt;
	    &amp;lt;script&amp;gt;
                //Damit lesen wir den Gyroskopen aus
        	window.addEventListener(&#34;deviceorientation&#34;, handleOrientation, true);

        	function handleOrientation(inEvent) {
     	            var socket = io.connect(&amp;#039;http://192.168.1.15&amp;#039;);
	            if (inEvent.beta &amp;lt; 0 &amp;&amp; inEvent.gamma &amp;gt; -15 &amp;&amp; inEvent.gamma &amp;lt; 15)
    	                socket.emit(&amp;#039;forwards&amp;#039;);
	            else if (inEvent.beta &amp;gt;= 0 &amp;&amp; inEvent.beta &amp;lt;= 60  &amp;&amp; inEvent.gamma &amp;gt; -15 &amp;&amp; inEvent.gamma &amp;lt; 15)
       	                socket.emit(&amp;#039;stop&amp;#039;);
	            else if (inEvent.beta &amp;gt; 60  &amp;&amp; inEvent.gamma &amp;gt; -15 &amp;&amp; inEvent.gamma &amp;lt; 15)
    	                socket.emit(&amp;#039;backwards&amp;#039;);
                    else if (inEvent.gamma &amp;lt; -15)
                        socket.emit(&amp;#039;turnLeft&amp;#039;);
                    else if (inEvent.gamma &amp;gt; 15)
                        socket.emit(&amp;#039;turnRight&amp;#039;);
                    
                    //Optionale Ausgabe der Werte des Gyroskopen
		    document.getElementById(&#34;alpha&#34;).innerHTML = inEvent.alpha;
		    document.getElementById(&#34;beta&#34;).innerHTML = inEvent.beta;
		    document.getElementById(&#34;gamma&#34;).innerHTML = inEvent.gamma;
		    return true;
        	}
        &amp;lt;/script&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Robot Project&amp;lt;/h1&amp;gt;
        &amp;lt;p id=&#34;alpha&#34;&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;p id=&#34;beta&#34;&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;p id=&#34;gamma&#34;&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;
```

```
&lt;code class=&#34;language-javascript javascript&#34;&gt;var gpio = require(&#34;./node-rpio/lib/rpio&#34;);
var app = require(&amp;#039;http&amp;#039;).createServer(handler)
  , io = require(&amp;#039;socket.io&amp;#039;).listen(app)
  , fs = require(&amp;#039;fs&amp;#039;)

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + &amp;#039;/index.html&amp;#039;,
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end(&amp;#039;Error loading index.html&amp;#039;);
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.sockets.on(&amp;#039;connection&amp;#039;, function (socket) {
    socket.on(&amp;#039;forwards&amp;#039;, function () {
        forwards();
    });
    socket.on(&amp;#039;backwards&amp;#039;, function () {
        backwards();
    });
    socket.on(&amp;#039;stop&amp;#039;, function () {
        stop();
    });
    socket.on(&amp;#039;turnRight&amp;#039;, function () {
        turnRight();
    });
    socket.on(&amp;#039;turnLeft&amp;#039;, function () {
        turnLeft();
    });
});

//Setup GPIO Pins
gpio.setmode(gpio.BOARD);
gpio.setup(13, gpio.OUT);
gpio.setup(15, gpio.OUT);
gpio.setup(16, gpio.OUT);
gpio.setup(18, gpio.OUT);

function forwards() {
    gpio.output(13, 1);
    gpio.output(15, 0);
    gpio.output(16, 1);
    gpio.output(18, 0);
}

function backwards() {
    gpio.output(13, 0);
    gpio.output(15, 1);
    gpio.output(16, 0);
    gpio.output(18, 1);
}

function turnRight() {
    gpio.output(13, 0);
    gpio.output(15, 0);
    gpio.output(16, 1);
    gpio.output(18, 0);
}

function turnLeft() {
    gpio.output(13, 1);
    gpio.output(15, 0);
    gpio.output(16, 0);
    gpio.output(18, 0);
}

function stop() {
    gpio.output(13, 0);
    gpio.output(15, 0);
    gpio.output(16, 0);
    gpio.output(18, 0);
}

process.on(&amp;#039;SIGINT&amp;#039;, function() {
    console.log(&#34;\nGracefully shutting down from SIGINT (Ctrl+C)&#34;);
    //Cleanup
    gpio.cleanup();
    process.exit();
});

&lt;/code&gt;
```
&lt;/noscript&gt;

Als nächstes wird der nodejs Server mit

```
sudo node robot.js
```

gestartet. Nun muss man nur noch die Adresse: _http://IP-des-Raspberry-Pi_ aufrufen und schon kann man den Roboter mit einem Smartphone oder Tablet steuern.

### Stromversorgung und Wlan

Es gibt nur noch ein Problem. Der Rapsberry Pi hängt bisher noch an zwei Kabeln: dem Netzwerkkabel und dem USB-Kabel für die Stromversorgung. Für beiden gibt es Lösungen. Das Netzwerkkabel habe ich durch einen Wlan-USB Dongle ersetzt. Wie man diesen einrichtet und welchen man kaufen sollte, findet man in [diesem Artikel][5].

Das verbleibende USB-Kabel habe ich einfach durch ein mobiles USB-Ladegerät ersetzt, welches man für wenig Geld zu kaufen bekommt. Diese liefern die benötigen 5V. Man sollte darauf achten, dass sie neben den 5V auch mindestens 1A liefern, ansonsten wird der Raspberry Pi nicht starten.

Und so sieht das ganze jetzt aus 😉

[&lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; class=&#34;aligncenter size-medium wp-image-1926&#34; alt=&#34;mobile Stromversorgung und WLAN-Dongle&#34; src=&#34;http://zefanjas.de/wp-content/uploads/2013/12/IMG_0815.geaendert-300x225.jpg&#34; width=&#34;300&#34; height=&#34;225&#34; srcset=&#34;https://zefanjas.de/wp-content/uploads/2013/12/IMG_0815.geaendert-300x225.jpg 300w, https://zefanjas.de/wp-content/uploads/2013/12/IMG_0815.geaendert.jpg 1024w&#34; sizes=&#34;(max-width: 300px) 100vw, 300px&#34; /&gt;][6] [&lt;img loading=&#34;lazy&#34; decoding=&#34;async&#34; class=&#34;aligncenter size-medium wp-image-1927&#34; alt=&#34;mobile Stromversorgung und WLAN-Dongle&#34; src=&#34;http://zefanjas.de/wp-content/uploads/2013/12/IMG_0817.geaendert-300x225.jpg&#34; width=&#34;300&#34; height=&#34;225&#34; srcset=&#34;https://zefanjas.de/wp-content/uploads/2013/12/IMG_0817.geaendert-300x225.jpg 300w, https://zefanjas.de/wp-content/uploads/2013/12/IMG_0817.geaendert.jpg 1024w&#34; sizes=&#34;(max-width: 300px) 100vw, 300px&#34; /&gt;][7]Ich werde in den nächsten Tagen noch ein ein Video machen&amp;#8230;

Wie geht es jetzt weiter? Die Steuerung muss noch verbessert werden. Gerade das Lenken ist noch ungenau und das Fahren somit etwas schwierig. Ein weiteres Ziel ist, mit Hilfe eines Ultraschall-Sensors dem Roboter das autonome Fahren beizubringen.

Bisherige Artikel

  * [Build a Robot #0][8]
  * [Build a Robot #1][9]

&amp;nbsp;

 [1]: http://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=1&amp;cad=rja&amp;ved=0CCoQFjAA&amp;url=http%3A%2F%2Fde.wikipedia.org%2Fwiki%2FKreiselinstrument&amp;ei=_Ta0Uvj5FomQrQfdsICoAg&amp;usg=AFQjCNEHAKMqVWmSUSBdCNu9kxia2kbt6w&amp;sig2=KMKcBikD9QcDjF387qaMQg&amp;bvm=bv.58187178,d.bmk
 [2]: http://nodejs.org/
 [3]: http://thefloppydisk.wordpress.com/2013/03/08/server-side-javascript-on-a-raspberry-pi-how-to-install-node-js/
 [4]: http://socket.io
 [5]: http://www.howtogeek.com/167425/how-to-setup-wi-fi-on-your-raspberry-pi-via-the-command-line/
 [6]: http://zefanjas.de/wp-content/uploads/2013/12/IMG_0815.geaendert.jpg
 [7]: http://zefanjas.de/wp-content/uploads/2013/12/IMG_0817.geaendert.jpg
 [8]: http://zefanjas.de/2013/12/18/build-a-robot-0-ziele-und-material/
 [9]: http://zefanjas.de/2013/12/18/build-a-robot-1-motoren-ansteuern/</description>
    </item>
    
  </channel>
</rss>
