Wolkenhimmel

Nextcloud auf Shared Webhosting updaten

Das Betreiben einer Nextcloud-Instanz ist bei Hostpoint eigentlich nur geduldet und der Betrieb auf einem Shared Webhosting ist von Nextcloud auch nicht supported. Für den einfachen Datenaustausch betreibe ich aber trotzdem eine Instanz auf meinem Shared Webhosting und muss diese entsprechend auch immer mal wieder updaten. Dabei treten immer wieder dieselben Probleme auf, die ich hier mit den Workarounds dokumentieren will. Die Beschreibung ist auf dem Stand von Version 25, die Probleme traten aber identisch bei den Vorgängerversionen auf und ich vermute, dass sie auch bei den nachfolgenden Releases auftreten werden.

Ich verwende in dieser Beschreibung, da meine Nextcloud-Oberfläche auf Deutsch eingestellt ist, die deutschen Bezeichnungen.

0. Backup erstellen

Eigentlich sollte es jedem klar sein, dass bei einem Update immer etwas schief gehen kann. Aber nochmals zur Sicherheit: vor jedem Update Files und Datenbank sichern!

Um umfangreiche Verzeichnisse (wie z.B. eine Nextcloud-Installation) als einzelne Datei zu Sichern habe ich ein kleines php-Tool geschrieben, das auf Knopfdruck ein Backup startet und dann das .zip-File als Download zur Verfügung stellt.

Es empfiehlt sich zusätzlich die Datei core/shipped.json einzeln herunterzuladen, da wir diese im folgenden Ablauf noch ein paar Mal benötigen werden.

1. Update starten

Als Administrator das WebUI von Nextcloud starten. Falls in den Benachrichtigungen (Glocken-Symbol) auf das Update hingewiesen wird öffnet ein Klick auf den Hinweis die Verwaltungs-Seite, von welcher aus das Update gestartet werden kann. Ansonsten kann über das Benutzer-Menü oben rechts auf Administrationseinstellungen geklickt werden und es erscheint dieselbe Seite.

Unter „Version“ wird die aktuell verwendete Version angezeigt. Wenn eine neuere Version verfügbar ist wird diese unter „Aktualisieren“ aufgeführt. Dort befindet sich auch der Knopf „Updater öffnen“, mit dem die Update-Seite geöffnet wird.

Die Update-Seite ist auf Englisch, dementsprechend kommen hier die englischen Bezeichnungen zum Zug. Es wird nochmals die Ausgangs- und die Zielversion angezeigt.

Mit „Start update“ wird das Update ausgeführt.

Es werden die verschiedenen Schritte aufgeführt. Der aktuell laufende ist mir einem drehenden Kreis markiert während die erfolgreich durchgeführten Schritte mit einem grünen Haken markiert sind.

2. Delete old files

Nach einiger Zeit schlägt der Schritt „Delete old files“ fehl und ist mit einem roten „X“ und hellroter Hintergrundfarbe markiert. Leider liefert die Update-Seite keine Informationen, was genau schief gelaufen ist. Genauere Informationen findet man in der Datei data/updater.log. Dabei sind 2 Fälle zu unterscheiden, wobei es irgendwann von Fall 1 zu Fall 2 wechselt:

  1. Message: Could not rmdir:
    Es ist ein Fehler beim Löschen des nach rmdir angegebenen Verzeichnisses aufgetreten.
    Man könnte nun das Verzeichnis von Hand löschen, dies ist aber gar nicht nötig. Auf der Update-Seite ist anstelle des Buttons „Start update“ nun der Button „Retry update“ vorhanden. Dieser führt das Update an derselben Stelle weiter und versucht entsprechend nochmals das Verzeichnis zu löschen, was dann meistens auch klappt.
    Man muss nicht nach jedem Fehler im Log nachschauen was passiert ist, man kann auch einfach mehrmals auf „Gut Glück“ auf „Retry update“ klicken.
  2. Message: core/shipped.json is not available
    Spätestens wenn der Klick auf „Retry update“ augenblicklich wieder einen Fehler meldet sollte wieder das Log konsultiert werden. Wenn die obenstehende Meldung erscheint benötigen wir das einzeln gesicherte File. Dieses wird vermutlich beim Löschen der alten Dateien ebenfalls gelöscht, wird aber für den Retry-Mechanismus wieder benötigt.
    Entsprechend kopieren wir die Datei wieder an ihre ursprüngliche Stelle und starten dann wieder mit „Retry update“. Solange nun beim Schritt „Delete old Files“ ein Fehler auftritt müssen wir immer zuerst wieder die Datei core/shipped.json hochladen und dann wieder auf „Retry update“ klicken.
    Irgendwann wird auch der Ordner core gelöscht, dann muss entsprechend auch der Ordner wieder erstellt oder kopiert werden.

3. Move new files in place

Wenn wir beim Schritt „Move new files in place“ angekommen sind gibt es wieder Fehler der Art „Message: Could not rmdir“ (diesmal aber ohne : nach rmdir). Nun kann wiederum direkt auf „Retry update“ geklickt werden bis auch diese Fehlergruppe durchgearbeitet ist und wir beim Schritt „Continue with web based updater“ landen. Dort kann nun ber Button „Disable maintaince mode and …“ angeklickt werden und man landet bei der Aktualisierung der Apps.

4. Aktualisierung der Apps

Es werden alle Apps aufgeführt, die aktualisiert werden. Zuunterst gibt es den Knopf „Aktualisierung starten“ welche den Prozess auslöst.

Dies kann ebenfalls fehlschlagen, was zur Folge hat dass der Maintenance-Mode aktiv bleibt. Dadurch kann aber der fehlgeschlagene Schritt nicht nochmals gestartet werden.

In der Datei config/config.php muss ‚maintenance‘ auf false gesetzt werden um den Maintenace-Mode auszuschalten und den Aktualisierungsprozess weiterzuführen.

5. Abschluss

Zum Schluss sollte wieder das Nextcloud-Dashboard angezeigt werden. Der Maintenance-Mode wird dabei automatisch wieder ausgeschaltet. Auf der Verwaltungs-Seite (Benutzer-Menü oben rechts, Administrationseinstellungen) sollte nun unter „Aktualisieren“ vermerkt sein dass die Version aktuell ist. Falls dies nicht der Fall ist war man vermutlich auf auf einer älteren Major-Version und man darf das ganze Spiel (inkl. Backup!) nochmals durchführen.

3dwire-frame hands typing on a blue keyboard

Dell Display Manager Ersatz unter Ubuntu 22.04

Ich habe mir einen neuen Monitor geleistet, den Dell P3421W mit eingebautem KVM-Switch. Diesen verwende ich mit DisplayPort-Anschluss an meinem Windows-Rechner und mit dem HDMI-Anschluss an meinem Ubuntu-System. Unter Windows kann mit dem Dell Display Manager eine Tastenkombination definiert werden, mit welcher auf den anderen Anschluss gewechselt werden kann. Für Linux bietet Dell diese Software aber nicht an.

Recherche

Sehr schnell bin ich bei askubuntu auf eine Frage mit Antworten gestossen, die genau diese Problematik widerspiegelte. Dabei hat sich gezeigt, dass es sich lohnt nicht nur die akzeptierte und bestbewertete Antwort zu lesen, sondern auch weniger gut bewertete, die aber möglicherweise neuer sind oder andere Aspekte beleuchten. In diesem Fall wurde als Alternative für ddccontrol ddcutil empfohlen.

Umsetzung

Als erstes habe ich ddcutil installiert:

sudo apt install ddcutil

Danach habe ich mit dem detect-Command den verwendeten I2C-bus bestimmt:

sudo ddcutil detect

Die Ausgabe in der Zeile I2C bus: /dev/i2c-4 gibt dabei die zu verwendende Bus-Nummer an, in meinem Fall 4.

Um nicht jedes Mal sudo-Rechte erlangen zu müssen habe ich meinen Benutzer der Gruppe i2c hinzugefügt und mittels einer udev-Regel die i2c-Busse der Gruppe i2c zugewiesen:

sudo usermod -G i2c -a <username>
sudo cp /usr/share/ddcutil/data/45-ddcutil-i2c.rules /etc/udev/rules.d/

Zum Schluss habe ich unter Settings->Keyboard->Keyboard Shortcuts->Custom Shortcut einen neuen Shortcut mit derselben Tastenkombination wie unter Windows und dem Command ddcutil -b 4 setvcp 0x60 0x0f erfasst.

Fazit

Mit den passenden Tools kann, mit ein wenig Aufwand, unter Linux das System mit individuellen Komfortfunktionen ergänzt werden.


Image courtesy of pixtawan at FreeDigitalPhotos.net

Zeitgeist 2020

Nachdem ich für das Jahr 2013 den letzten Zeitgeist-Artikel erstellt hatte möchte ich, auch angeregt durch das Browser-Titelthema in der c’t 02/21, für 2020 wieder die Statistiken meiner Seiten präsentieren.

Browser

Chrome ist auch auf meinen Seiten inzwischen der dominante Browser, wenn auch nicht mit 66% wie im oben verlinkten c’t-Artikel erwähnt.

Browser-Marktanteil Web 2020
Browser-Marktanteil Web 2020
Browser-Marktanteil Blog 2020
Browser-Marktanteil Blog 2020
BrowserWebseiteBlog
Chrome44.14%36.38%
Firefox30.81%27.40%
Microsoft Edge7.56%7.14%
Safari4.12%8.85%
Chrome Mobile3.19%6.14%
Mobile Safari3.06%5.80%
Andere7.11%8.41%
Marktanteile der Browser auf der Webseite und im Blog

Der Blog scheint öfters über Smartphones oder von Apple-Rechnern abgerufen zu werden als die Webseite. Chrome hat deshalb auf dem Blog einen kleineren Marktanteil, den er auch zusammen mit der mobilen Variante nicht wett machen kann. Safari legt sowohl in der Desktop als auch in der mobilen Variante zu und liegt deshalb mit der Desktop-Variante beim Blog auch vor dem Microsoft Edge.

Suchmaschinen

Bei den Suchmaschinen ist Google weiterhin dominant, nur Bing und DuckDuckGo können noch Prozentwerte grösser als eins erreichen.

SuchmaschineWebseiteBlog
Google95.4%96.6%
Bing2.5%1.5%
DuckDuckGo1.2%1.0%
Andere0.9%0.9%
Marktanteile der Suchmaschinen auf der Webseite und im Blog

Verweise

Hier noch die Liste der wichtigsten Domänen, die auf meine Webseiten verlinken:

RangWebseiteBlog
1blog.rolandbaer.chwww.rolandbaer.ch
2de.wikipedia.orgwww.startpage.com
3wordpress.orgbaidu.com
Die drei wichtigsten Verweisseiten auf die Webseite und den Blog

Die Verweise unter Webseite und Blog funktionieren, wie man an den top-platzierten Seiten sehen kann. Die von wikipedia kommenden Besucher lesen das NSIS-Tutorial und die Verweise von WordPress kommen von den Plugins. Blog-Besucher von Startpage kamen hauptsächlich aufgrund der Internet of Things (IoT) Artikel und die wenigen Besuche über Baidu kamen zur Startseite des Blogs.

Themen

Während die Zugriffszahlen in den letzten Jahren beim Blog klar tiefer waren als bei der Webseite hat der Blog im vergangenen Jahr massiv Besucher gewonnen und liegt nun etwa auf dem Level der Webseite.

Besucheszahlen des Blogs 2016 - 2020
Blog startet durch?

Die meisten Besuche des Blogs gehen dabei auf das Konto der Artikel im IoT-Bereich, sprich Arduino und Wemos D1 mini. Bei der Webseite lässt das Interesse am NSIS-Tutorial langsam aber stetig nach, mit dem neuen iperf-Tutorial konnten aber wieder neue Besucher auf die Webseite geholt werden.

Fazit

Gegenüber der letzten Statistik für das Jahr 2013 hat sich bei den Browsern einiges getan, wenn auch nicht so extrem wie in den Statistiken von den Marktforschungsunternehmen. Die Dominanz von Google bei den Suchmaschinen ist immer noch ungebrochen.

Gefreut haben mich die gestiegenen Besucherzahlen auf dem Blog, auch wenn sie (noch) nicht zu gestiegenen Interaktionen (sprich Kommentaren) mit den Besuchern geführt haben. Diese kommen hauptsächlich über das WordPress-Plugin List Last Changes auf der Webseite zustande.

HTTP-Header

Zusätzliche HTTP-Header definieren für statische Webseiten bei Webhoster

Verschiedene, teilweise sicherheitsrelevante Funktionalitäten können durch HTTP-Header aktiviert werden, so zum Beispiel die HTTP Strict Transport Security.

Wenn man eine dynamisch generierte Webseite (z.B. via php) hat kann man relativ einfach zusätzliche HTTP-Header definieren, die ausgeliefert werden sollen. Bei php kann dies z.B. mit der Funktion header() erreicht werden.

Bei statischen Webseiten gibt es diese Möglichkeit nicht. Oftmals hostet man solche Webseiten unter einem einfachen (shared) Hosting, für welches der Webhoster (in meinem Fall Hostpoint) oftmals in seiner Verwaltungsoberfläche keine Möglichkeit bietet die Header anzupassen.

Wenn die Webseiten mit dem Apache HTTP Server ausgeliefert werden und der Webhoster das Modul mod_headers aktiviert hat können über Einträge in der Datei .htaccess zusätzliche Header gesetzt werden.

Um zu überprüfen, ob der Mechanismus funktioniert kann ein Dummy-Header ausgegeben werden, der dann über die Entwicklerwerkzeuge des Browsers geprüft werden kann. Dies ist ungefährlich, da unbekannte Header vom Browser ignoriert werden. So kann z.B. folgende Zeile in der .htaccess-Datei im passenden Verzeichnis hinzugefügt werden:

Header add Test Debug

Dabei muss darauf geachtet werden, ob ein Bereich in der .htaccess-Datei für automatische Einträge durch die Verwaltungsoberfläche des Hosters reserviert ist. Falls die Datei noch nicht existiert kann sie mit der obigen Zeile als einzigem Inhalt neu erzeugt werden.

Wenn das Ganze erfolgreich war sollte im Antwort-Header eine Zeile mit folgendem Inhalt vorhanden sein:

Test: Debug

Wenn dies erfolgreich war kann der Test-Eintrag wieder gelöscht und der richtige Header definiert werden. Ansonsten sollte der Eintrag nochmals kontrolliert oder dann der Support des Hosters kontaktiert werden.

WeMos D1 mini als Temperatur- und Luftfeuchtigkeits-Webserver

Im nächsten Versuch mit dem WeMos D1 mini soll nun seine WiFi-Funktionalität zum Einsatz kommen. Der Plan ist dabei, mit dem bereits früher verwendeten Temperatur- und Luftfeuchtigkeitssensor DHT11 (Teil 1 und Teil 2) gemessene Daten über eine einfache Webseite darzustellen.

Als erstes der einfache Steckplatinen-Aufbau:

Steckplatinenaufbau mit Wemos D1 mini und DHT11
Aufbau des WeMos D1 mini mit dem Temperatur- und Luftfeuchtigkeitssensor DHT11

Der dazugehörige Code ist schon etwas komplizierter (basiert auf dem Beispiel von Bernhard Linz):

/*******************************************************************************************
 * Read data from DHT-11 sensor and present it with a web page                             *
 *                                                                                         *
 * Based on a Script by Bernhard Linz ( https://znil.net/ )                                *
 *******************************************************************************************/


// import used libraries
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "DHT.h"

// include WiFi credentials
#include "credentials.h"

// definitions
#define DHTPIN D5         // pin of the arduino where the sensor is connected to
#define DHTTYPE DHT11     // define the type of sensor (DHT11 or DHT22)

// create web server
ESP8266WebServer webServer(80);

// create instance of DHT                          
DHT dht(DHTPIN, DHTTYPE, 6);

// variables for measured values
float temperature;
float humidity;

// initialization
void setup() {
  Serial.begin(9600);
  Serial.println("DHT11 test web server");

  // initialize measuring
  pinMode(DHTPIN, INPUT);
  dht.begin();

  Serial.println("Connecting to ");
  Serial.println(ssid);

  // connecting to local wi-fi network
  WiFi.begin(ssid, password);

  // check wi-fi staus until connected
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("my IP: ");
  Serial.println(WiFi.localIP());
  uint8_t macAddr[6];
  WiFi.macAddress(macAddr);
  Serial.printf("mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);

  webServer.on("/", handle_OnConnect);
  webServer.onNotFound(handle_NotFound);

  webServer.begin();
  Serial.println("HTTP server started");
}

void loop() {
  webServer.handleClient();
}

void handle_OnConnect() {
  temperature = dht.readTemperature();
  humidity = dht.readHumidity();
  webServer.send(200, "text/html", buildHtml(temperature,humidity));
}

void handle_NotFound(){
  webServer.send(404, "text/plain", "Not found");
}

String buildHtml(float _temperature,float _humidity){
  String page = "<!DOCTYPE html> <html>\n";
  page +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\"/>\n";
  page +="<meta charset=\"UTF-8\"/>";
  page +="<meta http-equiv=\"refresh\" content=\"5\"/>";
  page +="<title>WeMos D1 mini Temperature & Humidity Report</title>\n";
  page +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  page +="body{margin-top: 50px;} h1 {color: #444444;margin: 20px auto 30px;}\n";
  page +="h2 {color: #0d4c75;margin: 50px auto 20px;}\n";
  page +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
  page +="</style>\n";
  page +="</head>\n";
  page +="<body>\n";
  page +="<div id=\"webpage\">\n";
  page +="<h2>WeMos Lolin D1 mini</h2><h1>Temperature & Humidity Report</h1>\n";
 
  page +="<p>Temperature: ";
  page +=(int)_temperature;
  page +=" °C</p>";
  page +="<p>Humidity: ";
  page +=(int)_humidity;
  page +=" %</p>";
 
  page +="</div>\n";
  page +="</body>\n";
  page +="</html>\n";
  return page;
}

Mit dem Einbinden des ESP8266 Microcontrollers und dem vorherigen Verwenden des DHT11 sind schon alle nötigen Libraries vorhanden. Die WLAN Zugangsdaten habe ich in eine separate Datei ausgelagert um zu verhindern, dass diese versehentlich publiziert werden. Deshalb ist zusätzlich eine zweite Datei mit dem Namen „credentials.h“ mit folgendem Inhalt nötig:

#ifndef __CREDENTIALS_H__
#define __CREDENTIALS_H__

// WiFi credentials:
const char* ssid = "mySSID";
const char* password = "secret";

#endif

Nach dem Uploaden und Starten des Programmes sollte im Serial Monitor eine Ausgabe ähnlich der nachfolgenden erscheinen (SSID, IP- und MAC-Adresse anonymisiert):

DHT11 test web server
Connecting to
mySSID
....
WiFi connected
my IP: 192.168.xxx.xxx
mac address: 2c:f4:32:xx:xx:xx
HTTP server started

Falls nach der SSID längere Zeit nur Punkte erscheinen sind vermutlich die WLAN Zugangdaten falsch. Ansonsten kann mit einem Browser auf die angegebene IP-Adresse zugegriffen werden und es sollte eine Webseite mit den aktuellen Messwerten erscheinen. Die Webseite aktualisiert sich alle 5 Sekunden.

Webseite mit den aktuellen Messwerten Temperatur und Luftfeuchtigkeit, ausgeliefert vom WeMos D1 mini
Die Webseite mit den aktuellen Messwerten

Es empfiehlt sich im DHCP-Server für die MAC-Adresse des WeMos D1 mini immer dieselbe IP-Adresse vergeben zu lassen damit man nicht auf die Ausgabe des Serial Monitor angewiesen ist.

Bei Last Minute Engineers ist ein Tutorial zu finden, welches auch als Basis für das Script von Bernhard Linz diente. Dort wird die Webseite auch noch schöner gestaltet und zum Schluss wird auch noch auf das Aktualisieren mittels AJAX eingegangen.

Erste Schritte mit dem Wemos D1 Mini

Nach den ersten Schritten mit dem Arduino Nano (Teil 1 und Teil 2) soll nun ein anderer Mikrocontroller zum Zug kommen, der ESP-8266EX auf dem Wemos Lolin D1 mini board.

Um dieses Board in der Arduino IDE verwenden zu können muss es zuerst im Board Manger installiert werden. Es ist unter dem Namen „esp8266“ zu finden. Falls es nicht gefunden wird muss unter File->Preferences-> Additonal Boards Manager URLs die URL http://arduino.esp8266.com/stable/package_esp8266com_index.json hinzugefügt werden. Danach kann unter Tools->Boards->Board Manager der ESP8266 gesucht und installiert werden. Dadurch werden bei den Boards diverse ESP8266-Boards aufgelistet. Für diese Versuche wird WeMos D1 R2 & mini ausgewählt.

Als erstes war das Ziel, zwei LEDs mit zwei Tastern zum Leuchten bringen. Die hier eingesetzten LEDs haben eingebaute Vorwiderstände. Falls normale LEDs zum Einsatz kommen den Vorwiderstand nicht vergessen! Also zwei Pins als Input und zwei als Output definiert, Schaltung aufgebaut und los!

void setup() {
  pinMode(D2, INPUT);
  pinMode(D3, INPUT);

  pinMode(D6, OUTPUT);
  pinMode(D7, OUTPUT);
}

void loop() {
  int left = digitalRead(D2);
  int right = digitalRead(D3);

  digitalWrite(D6, left);
  digitalWrite(D7, right);
}
Erster fehlgeschlagener Versuch mit dem Wemos D1 mini (Steckplatinenansicht)
Erster fehlgeschlagener Versuch mit dem Wemos D1 mini

Die rote LED funktionierte auch wie geplant, die grüne leuchtete aber andauernd. Nachdem die normale Fehlersuche (Verbindungen und Code kontrollieren) keinen Erfolg brachte war der nächste Schritt die Recherche: gibt es Pins bei diesem Board, die speziell geschaltet sind? Schlussendlich hat mir diese Pinout Referenz des ESP8266 (Kapitel „Wemos D1 Mini Pinout“ und „Best Pins to Use“, leider nicht direkt verlinkbar) das Problem aufgezeigt: D3 (GPIO0) ist für Input als „pulled up“ angegeben und sollte nicht verwendet werden. Also das Ganze umgebaut und nochmals versucht:

void setup() {
  pinMode(D6, INPUT);
  pinMode(D7, INPUT);

  pinMode(D1, OUTPUT);
  pinMode(D2, OUTPUT);
}

void loop() {
  int left = digitalRead(D6);
  int right = digitalRead(D7);

  digitalWrite(D1, left);
  digitalWrite(D2, right);
}
Zweiter, erfolgreicher Versuch (Steckplatinenansicht)
Zweiter, erfolgreicher Versuch

Mit diesem Umbau klappte dieser einfache Aufbau dann wie geplant.

Temperatur und Luftfeuchtigkeit messen und Anzeigen mit dem Arduino Nano

Im letzten Teil wurde der Temperatur-Sensor DHT-11 mit dem Arduino Nano ausgelesen. Nun sollen die gemessenen Werte auch ohne Computer anzeigen werden können.

Der Aufbau basiert auf der letzten Schaltung und erweitert diese um das Display, welches ebenfalls aus dem Arduino Adventskalender stammt. Damit alles Platz hat kommen zwei kleine Steckboards zum Einsatz.

Steckplatinen-Aufbau mit Arduino Nano, DHT-11 und Display
Steckplatinen-Aufbau mit Arduino Nano, DHT-11 und Display

Für die Ansteuerung des LCD wird zusätzlich die Bibliothek „LiquidCrystal“ von Arduino, Adafruit benötigt, welche in der Arduino IDE wiederum unter Tools->Manage Libraries… hinzugefügt werden kann. Bei der Erstellung des Programmes wurde die Version 1.0.7 verwendet. Dem grösseren Aufbau entsprechend ist auch der Code umfangreicher.

/*******************************************************************************************
 * Read data from DHT-11 sensor and show it on a two-line LCD with an arduino nano         *
 *                                                                                         *
 * based on a script by Philippe Keller (www.bastelgarage.ch)                              *
 *******************************************************************************************/


// import used libraries
#include "DHT.h"                
#include <LiquidCrystal.h>

// definitions
#define DHTPIN 2          // pin of the arduino where the sensor is connected to
#define DHTTYPE DHT11     // define the type of sensor (DHT11 or DHT22)
       
// create instance of DHT                          
DHT dht(DHTPIN, DHTTYPE, 6);

// create instance of LiquidCrystal
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

void setup() {
  Serial.begin(9600);
  Serial.println("DHT11 test program 2");
  dht.begin();
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("T:        C");
  lcd.setCursor(0,1);
  lcd.print("rF:       %");
}

void loop() {
  // Wait two seconds between measurements as the sensor will not measure faster
  delay(2000);
                                   
  float h = dht.readHumidity();
  float t = dht.readTemperature();
 
  // validate values
  if (isnan(h) || isnan(t)) {      
    Serial.println("Error while reading data!");
    return;
  }

  // send data via serial connection to pc
  Serial.print("Luftfeuchtigkeit: ");
  Serial.print(h);
  Serial.print("%\t");
  Serial.print("Temperatur: ");
  Serial.print(t);
  Serial.write("°");
  Serial.println("C");

  // write data to liquid crystal display
  lcd.setCursor(4,0);
  lcd.print(t);
  lcd.setCursor(4,1);
  lcd.print(h);
}

Für die Speisung der Schaltung habe ich eine USB-PowerBank verwendet. Im Einsatz sieht dann das Ganze so aus:

Arduino Nano, DHT-11 und Display im Einsatz
Arduino Nano, DHT-11 und Display im Einsatz

Temperatur und Luftfeuchtigkeit messen mit dem Arduino Nano

Für meine ersten Schritte im Mikrocontroller-Umfeld abseits der vorgetrampelten Pfade von Starter Kit oder Adventskalender wollte ich mich mit der Luftfeuchtigkeitsmessung beschäftigen. Dabei ist mir der Temperatur- und Luftfeuchtigkeits-Sensor DHT-11 über den Weg gelaufen.

Der DHT-11 ist ein einfacher und günstiger Sensor, der die Temperatur und die Luftfeuchtigkeit misst und über ein einfaches Protokoll ausgibt. Wenn eine höhere Genauigkeit gefordert ist kann der etwas grössere und teurere DHT-22 eingesetzt werden. Für die Ansteuerung der beiden Sensoren kann dabei die selbe Bibliothek verwendet werden, es muss bei der Instanzierung nur der passende Typ angegeben werden.

Der erste einfache Aufbau benötigt nur einen Arduino (in meinem Fall kam der Arduino Nano aus dem Adventskalender zum Einsatz) und den Sensor auf einem Modul. Dieses Modul beinhaltet den Pull-up-Widerstand bereits, beim Einsatz des „nackten“ Sensors muss dieser noch entsprechend hinzugefügt werden. Beim Modul muss noch beachtet werden dass es Versionen mit verschiedenen Pin-Belegungen gibt. Beim von mir eingesetzten Modul ist die Belegung VCC / Data / GND, es gibt aber auch Module mit Data / VCC / GND.

Steckplatinen-Aufbau mit Arduino Nano und DHT-11
Steckplatinen-Aufbau mit Arduino Nano und DHT-11

Das erste Programm soll dabei nur die Daten auslesen und über die Schnittstelle zum PC ausgeben. Dazu muss die Bibliothek „DHT sensor library“ von Adafruit in der Arduino IDE unter Tools->Manage Libraries… hinzugefügt werden. Beim Erstellen des Programmes war die Version 1.3.8 aktuell. Danach kann der untenstehende Code in die IDE übernommen werden:

/*******************************************************************************************
 * Read data from DHT-11 sensor via an arduino nano                                        *
 *                                                                                         *
 * based on a script by Philippe Keller (www.bastelgarage.ch)                              *
 *******************************************************************************************/


// import used library
#include "DHT.h"

// definitions
#define DHTPIN 2          // pin of the arduino where the sensor is connected to
#define DHTTYPE DHT11     // define the type of sensor (DHT11 or DHT22)
       
// create instance of DHT                          
DHT dht(DHTPIN, DHTTYPE, 6);

void setup()
{
  Serial.begin(9600);
  Serial.println("DHT11 test program");
  dht.begin();
}

void loop()
{
  // Wait two seconds between measurements as the sensor will not measure faster
  delay(2000);
                                   
  float h = dht.readHumidity();
  float t = dht.readTemperature();
 
  // validate values
  if (isnan(h) || isnan(t)) {      
    Serial.println("Error while reading data!");
    return;
  }

  // send data via serial connection to pc
  Serial.print("Luftfeuchtigkeit: ");
  Serial.print(h);
  Serial.print("%\t");
  Serial.print("Temperatur: ");
  Serial.print(t);
  Serial.println("°C");
}

Dieses Programm wird dann auf den Arduino übertragen. Dabei musste ich für meinen Arduino Nano den Prozessor auf „ATMega 328P (Old Bootlaoder)“ und den Programmer auf „AVRISP mkII“ einstellen. Nach dem Übertragen produziert das Programm dann im Serial Monitor eine Ausgabe wie folgende:

DHT11 test program
Luftfeuchtigkeit: 36.00%      Temperatur: 25.60°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.40°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.50°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.60°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.40°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.40°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.40°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.40°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.60°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.50°C
Luftfeuchtigkeit: 35.00%      Temperatur: 25.50°C
Luftfeuchtigkeit: 35.00%      Temperatur: 25.50°C
Luftfeuchtigkeit: 36.00%      Temperatur: 25.50°C

Natürlich möchte man nicht die ganze Zeit einen PC oder Laptop mitschleppen um die Teperatur und Luftfeuchtigkeit zu messen. In einem nächsten Ausbauschritt wird deshalb eine Anzeige hinzukommen.

DisplayPort HDMI Adapter und Lenco DVT-194

Wenn der Bildschirm (noch) nicht mitspielen will

Da bei mir noch ein kleinerer LCD-TV (Lenco DVT-194) herumstand kam die Idee auf, diesen als zweiten Screen am PC zu benutzen. Es war mir klar, dass dieser als Fernseher konzipiert war und daher als PC-Bildschirm nicht die Bildqualität liefern würde wie ein dafür optimierter Monitor.

Als erste Hürde erwies sich dabei der Anschluss. Der PC hatte einen freien DisplayPort-Ausgang, der TV aber nur einen HDMI-Eingang. Aber kein Problem, dass sich nicht durch ein Adapter-Kabel lösen liesse. Leider habe ich beim Bestellen des Kabels das Bild nicht genug genau angeschaut und deshalb nicht gesehen, dass auf der HDMI-Seite der Stecker relativ breit und lang ist. Der HDMI-Anschluss beim Lenco liegt direkt neben dem Eingang des Netzteils. Es ist möglich, beide Kabel einzustecken, dabei ist es aber sehr eng – aber es funktioniert.

Also habe ich den Bildschirm mit dem PC verbunden und bin zur Einrichtung geschritten. Der Bildschirm wurde von Windows 10 erkannt und mit der Auflösung 1280×720 angesprochen. Diese wurde auch als empfohlene Auflösung angegeben. Die Verwendung dieser Auflösung veranlasste den Bildschirm aber, das Bild in alle Richtungen zu vergrössern, so dass unten die Hälfte der Taskbar nicht mehr sichtbar war. Und beim Wechsel zwischen den beiden Screens landete der Mauszeiger im Nirvana.

Versuche mit den anderen angebotenen Auflösungen lieferten auch keine befriedigende Ergebnisse. Entweder war das Bild durch die Skalierung unscharf oder gestaucht, so dass Kreise zu Ovalen mutierten. Bei der Recherche im Internet bin ich dann aber auf das Datenblatt des Lenco DVT-194 gestossen und habe dort entdeckt, dass die Auflösung des TVs 1440 x 900 beträgt. Diese Auflösung wurde aber vom Nvidia-Grafiktreiber nicht angeboten!

Durch weitere Recherche im Internet bin ich dann auf das Tool Custom Resolution Utility gestossen. Mit diesem Tool können dem Nvidia-Grafiktreiber weitere Auflösungen beigebracht werden. Nachdem ich dann den Grafiktreiber überredet hatte, dem TV die Auflösung 1440 x 900 anzubieten konnte ich den Lenco als zweiten Screen einsetzen.