Arduino — Datenvisualisierung mit NodeJS

Zusammenfassung

In diesem Beitrag soll erklärt werden, wie mit einem Arduino Uno Daten erfasst werden und mittels JSON an einen WebServer übermittelt werden können. Mit Hilfe von NodeJS wird ein WebSever aufgebaut, der die vom Arduino übermittelten Daten verarbeitet und in einem Diagramm dargestellt. Ich verwende dazu das GitHub Projekt arduino-livechart, bei dem (da in der neuen Version von express.js keine Middleware mehr enthalten ist) einige Anpassungen nötig sind, damit die aktuelle Version von NodeJS verwendet werden kann.


Eine Node-WebApp um die gesendeten Daten auf einer WebSeite darzustellen

Die WebApp besteht aus drei Teil:

  • Dem Arduino Uno Sketch sendet JSON-Daten
  • Dem Backend: Ein ExpressJS-WebServer mit Datensteicherung
  • Dem Frontend: Darstellung der Daten mit Hilfe der JS-Bibliothek d3js

Download: WebServer.zip
<br /> \begin{tikzpicture}[scale=2]</p> <p>% Include tikz into local preamble<br /> [+preamble]<br />      \usepackage{tikz}<br />      \usepackage{color}<br />      \usepackage{xcolor}<br />      \tikzstyle{sensor}=[draw, fill=blue!20, text width=8em,<br />     text centered, minimum height=2.5em]<br />      \tikzstyle{webserver} = [sensor, text width=8em, fill=red!20,<br />     minimum height=8em, rounded corners]<br />      \tikzstyle{index} = [sensor, text width=8em, fill=green!20,<br />     minimum height=8em, rounded corners]<br />      \tikzstyle{arduino} = [sensor, fill=blue!20,<br />     minimum height=8em, rounded corners]<br />      \tikzstyle{d3js} = [sensor, text width=8em, fill=orange!20,<br />     minimum height=3em, rounded corners]<br />      \tikzstyle{express} = [sensor, minimum width=3em, fill=orange!20,<br />     minimum height=3em, rounded corners]<br />      \def\blockdist{2.}<br /> [/preamble]<br />   \node(webserver) [webserver] {\begin{tabular}{c} \textbf{WebServer.js}\\\scriptsize nodeJS based \\\scriptsize   \end{tabular}} ;<br />   \path (socket.west)+(-\blockdist,0) node (index) [index] {\textbf{index.html}};<br />   \path (index.south) + (0,-0.3) node (d3js) [d3js] {\textbf{d3js}};<br />   \path (index.north)+(0,0.5) node (fe) {\begin{tabular}{c} \textbf{frontend}  \\\scriptsize happens in the browser \end{tabular}};<br />   \path (webserver.east)+(\blockdist,-0) node (arduino) [arduino] {\begin{tabular}{c} \textbf{WebClient.ino}\\\scriptsize JSON  \\\scriptsize Arduino Sketch \end{tabular}};<br />   \path (arduino.north)+(0,0.5) node (fe) {\begin{tabular}{c} \textbf{sensor}  \\\scriptsize happens in the arduino uno \end{tabular}};<br />   \path (webserver.south) + (0,-0.3) node (express) [express] {\begin{tabular}{c} \textbf{express.js}\\\scriptsize WebServer \end{tabular}};<br />   \path (webserver.north)+(0,0.5) node (be) {\begin{tabular}{c}\textbf{backend} \\\scriptsize happens on the server\end{tabular}};<br />   \draw [black, fill=gray!50, fill opacity=0.3, dashed, rounded corners]($(index.north west)+(-10pt,30pt)$)  -- ($(index.north east)+(30pt,30pt)$) -- ($(index.south east)+(30pt,-50pt)$) -- ($(index.south west)+ (-10pt,-50pt)$) -- cycle;<br />   \draw [black, fill=gray!50, fill opacity=0.3, dashed, rounded corners]($(arduino.north west)+(-30pt,30pt)$)  -- ($(arduino.north east)+(10pt,30pt)$) -- ($(arduino.south east)+(10pt,-50pt)$) -- ($(arduino.south west)+ (-30pt,-50pt)$) -- cycle;</p> <p>\end{tikzpicture}<br />

Der ArduinoSketch

Der ArduinoSketch hat die Aufgabe eine Serielle Verbindung zum WebServer aufzubauen und
die (gemessenen) Daten im JSON-Format: {„time“: time,“a0″:a0,“a1″,a1, … } zu übermitteln. Dabei ist das Feld „time“ unverzichtbar. „a0“, „a1“ und … sind dann die jeweiligen Messdaten.

[js_markieren]

/*
  JSON ubs client

 This sketch sends Data in JSON-Format to a NodeJS WebServer 
 over usb-link.

 
 SensorPins:
 * Not implemented jet
 
 
 created 01 Jun 2014
 by Wolfgang Wolff
 
*/
 

// the time is important 
int time = 0;

// two variables to hold the sensor data
double a0 = 0.0; 
double a1 = 3.0;

void setup(void) {
  pinMode(ledPin, OUTPUT);  //1
  Serial.begin(9600);
  
  digitalWrite(ledPin, LOW);
 
}
 
void loop(void) {     
  // JSON-Format: {"time": time,"a0":a0,"a1",a1, ... } 
  // important: the filed "time" is necessary
  Serial.print("{\"time\":");
  Serial.print(time);
  Serial.print(",\"a0\":");
  Serial.print(a0);
  Serial.print(",\"a1\":");
  Serial.print(a1);   
  Serial.print("}");
  Serial.println();
  
  // time to wait before the next dataset is taken:
  delay(5000);
  // readout sensor data 
  // here using a sin and cos-function to simulate real data
  time = time + 5;
  a0 = 3*sin(time);
  a1 = 2*cos(time); 
}


Der WebServer

Als Basis für den WebServer dient das GitHub Projekt arduino-livechart. Damit arduino-livechart auf mit der Aktuellen NodeJS Version funktioniert müssen im ExpressJS-Code ein paar Änderungen vorgenommen werden. Diese Änderungen sind nötig, da in der neueren Version von Express Middleware in eigenen Module ausgelagert wurde.

  • Das Module body-phraser ist der Ersatz für die ExpressJS-Funktion: express.bodyParser().
  • Das Module morgan ist der Ersatz für die ExpressJS-Funktion: express.logger()

Konkret muss in der WebServer.js (in der original Quelle ist das die Datei index.js) der Code

 
var util = require('util');
var express = require('express');
var app = express();

app.configure(function () {
	app.use(express.logger());
	app.use(express.bodyParser());
});

durch

var util = require('util');
var express = require('express');
var app = express();
var bodyParser = require('body-parser');


var env = process.env.NODE_ENV || 'development';
if ('development' == env) {
   app.use(require('morgan')('dev'));
	 app.use(bodyParser());
}

ersetzt werden. Damit alle Abhängigkeiten installiert werden können muss noch die Datei package.json um die fehlenden Module ergänzt werden:

{
	"name": "arduino-livechart",
	"version": "0.0.1",
	"private": true,
	"author": "Bill Roy ",
	"description": "Collects data from a USB- or network-connected Arduino and displays it as a D3 graph",
	"dependencies": {
		"optimist": ">=0.3.5",
		"express": ">=3.0.3",
		"shelljs": ">=0.0.8",
		"serialport": ">=1.1.0",
		"body-parser": ">=1.3.0",
		"morgan": ">=1.0.0"
	},
	"engines": {
		"node": ">=0.10.1",
		"npm": "1.1.x"
	}
}



Der Befehl
npm install
installiert alle Module im Ordner node_modules. Jetzt ist der WebServer bereit für den Einsatz.

Das Frontend: index.html

Am Frontend habe ich bisher keine Veränderungen vorgenommen.

Das Starten der App

  1. Zuerst solle der Arduino-Sketch auf den Arduino Uno aufgespielt werden. Der Arduino sollte mit USB-Kabel mit dem PC verbunden ein und zusätzlich mit dem lokalen Netzwerk per EthernetShield verbunden sein.
  2. Dann sollte der Node-WebServer gestartet werde:

    node WebServer.js
  3. Jetzt kann über die URL http://localhost:8080 auf den WebServer zugegriffen werden. Wenn alles funktioniert sieht der Inhalt der WebSeite wie folgt aus:

Was noch zu tun ist

Viel, aber zuerst muss ich erst einmal noch etwas besser d3js lernen.
Denkbar wäre dieses Projekt mit Hilfe eines Wetter-Sensoren (Temperatur,Druck,Feuchte) zu einer Wetterstation auszubauen. Dazu muss aber der ArduinoSketch und das Frontend entsprechend erweitert werden.

Quellen:

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert