<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ESP32 &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<atom:link href="https://www.smarthomeng.de/tag/esp32/feed" rel="self" type="application/rss+xml" />
	<link>https://www.smarthomeng.de</link>
	<description>Die Device Integrations-Plattform für Dein Smart Home</description>
	<lastBuildDate>Sat, 28 Jul 2018 11:21:56 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.5.5</generator>

<image>
	<url>https://www.smarthomeng.de/wp-content/uploads/global/logo_small_152x152-150x150.png</url>
	<title>ESP32 &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<link>https://www.smarthomeng.de</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>E-Paper Wetterstation mit Daten aus SmartHomeNG</title>
		<link>https://www.smarthomeng.de/epaper-wetterstation-mit-daten-aus-smarthomeng</link>
					<comments>https://www.smarthomeng.de/epaper-wetterstation-mit-daten-aus-smarthomeng#comments</comments>
		
		<dc:creator><![CDATA[Marc René Frieß]]></dc:creator>
		<pubDate>Sun, 22 Jul 2018 09:28:47 +0000</pubDate>
				<category><![CDATA[Beispiel-Implementierungen]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Arduino IDE]]></category>
		<category><![CDATA[EPaper]]></category>
		<category><![CDATA[ESP32]]></category>
		<category><![CDATA[Waveshare]]></category>
		<category><![CDATA[Wetterstation]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=1929</guid>

					<description><![CDATA[E-Paper Displays, wie sie etwa im Amazon Kindle zum Einsatz kommen, stellen eine hervoragende und energiesparende Möglichkeit dar, Daten von SmartHomeNG zu visualisieren. Im folgenden Artikel soll als Beispiel eine Wetterstation auf Basis eines ESP32 und eines Waveshare 4.2 Zoll E-Paper Display mit 400 x 300 Pixel Auflösung erstellt werden.<a class="moretag" href="https://www.smarthomeng.de/epaper-wetterstation-mit-daten-aus-smarthomeng"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>E-Paper Displays, wie sie etwa im Amazon Kindle zum Einsatz kommen, stellen eine hervoragende und energiesparende Möglichkeit dar, Daten von SmartHomeNG zu visualisieren.</p>
<p>Im folgenden Artikel soll als Beispiel eine Wetterstation auf Basis eines ESP32 und eines Waveshare 4.2 Zoll E-Paper Display mit 400 x 300 Pixel Auflösung erstellt werden.</p>
<p>Das Display kann bspw. via <a href="https://www.amazon.de/Module-Resolution-Electronic-Controller-Communicating/dp/B074NR1SW2" target="_blank" rel="noopener">Amazon</a> bezogen werden. Der verwendete ESP32 kann <a href="https://www.amazon.de/Espressif-ESP32-DEVKITC-Genuine-ESP-WROOM-32-Marked/dp/B07DZP27TH/ref=sr_1_5?s=computers&amp;ie=UTF8&amp;qid=1532247493&amp;sr=1-5&amp;keywords=espressif+esp32" target="_blank" rel="noopener">hier</a> gefunden werden. Als Bibliothek zum Rendern des Bildes kommt <a href="https://github.com/ZinggJM/GxEPD2" target="_blank" rel="noopener">GxEPD2</a> zum Einsatz.  Vorab muss allerdings gesagt werden, dass die Fonts der Bibliothek nur Standard ASCII Zeichen könne, also weder ein Grad Zeichen (°) noch deutsche Sonderzeichen. Als Icons wurden Teile aus <a href="http://adamwhitcroft.com/climacons/" target="_blank" rel="noopener">http://adamwhitcroft.com/climacons/</a> und den SmartVISU Icons verwendet, die via <a href="http://www.digole.com/tools/PicturetoC_Hex_converter.php" target="_blank" rel="noopener">http://www.digole.com/tools/PicturetoC_Hex_converter.php</a> von einem PNG in C-Arrays konvertiert wurden.</p>
<p>Der Artikel erhebt keinen Anspruch auf vollständige Korrektheit und Schönheit des C Codes und dient lediglich als Proof of Concept. Auch sind die Icons derzeit noch nicht vollständig. Der Artikel wird dazu sukzessive aktualisiert.</p>
<p>Für die Items wurden sowohl Systemdaten aus SHNG direkt, dem KNX Plugin, dem ETA PU Plugin, dem SMA EM, als auch des DarkSky Plugins verwendet, die via Webservices Plugin (siehe Tutorial <a href="https://www.smarthomeng.de/das-smarthomeng-webservices-plugin" target="_blank" rel="noopener">https://www.smarthomeng.de/das-smarthomeng-webservices-plugin</a>) verfügbar gemacht wurden. Teilweise wurden die Rohdaten der Plugins über Child-Items noch formatiert oder in Strings (bspw. beim UV Wert) umgerechnet.</p>
<h1>Verkabelung</h1>
<p>Dem Display ist ein Kabel beigelegt, das wie folgt an den ESP32 angeschlossen wird:</p>
<p><img fetchpriority="high" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/07/Kabel_Waveshare.jpg" alt="" width="733" height="638" class="alignnone size-full wp-image-1935" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/07/Kabel_Waveshare.jpg 733w, https://www.smarthomeng.de/wp-content/uploads/2018/07/Kabel_Waveshare-300x261.jpg 300w" sizes="(max-width: 733px) 100vw, 733px" /></p>
<table border="1" style="border-collapse: collapse; width: 100%;">
<tbody>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><strong>Farbe</strong></td>
<td style="width: 50%; height: 29px;"><strong>Anschluß</strong></td>
</tr>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><strong><span style="color: #ff0000;">rot</span></strong></td>
<td style="width: 50%; height: 29px;">3v3</td>
</tr>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><strong>schwarz</strong></td>
<td style="width: 50%; height: 29px;">GND</td>
</tr>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><strong><span style="color: #0000ff;">blau</span></strong></td>
<td style="width: 50%; height: 29px;">IO23</td>
</tr>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><span style="color: #e3eb15;"><strong>gelb</strong></span></td>
<td style="width: 50%; height: 29px;">IO18</td>
</tr>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><span style="color: #ff9900;"><strong>orange</strong></span></td>
<td style="width: 50%; height: 29px;">IO17</td>
</tr>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><span style="color: #339966;"><strong>grün</strong></span></td>
<td style="width: 50%; height: 29px;">IO16</td>
</tr>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><span style="color: #d6d6d6;"><strong>weiß</strong></span></td>
<td style="width: 50%; height: 29px;">IO5</td>
</tr>
<tr style="height: 29px;">
<td style="width: 50%; height: 29px;"><span style="color: #800080;"><strong>lila</strong></span></td>
<td style="width: 50%; height: 29px;">IO19</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<h1>Items (via Webservices Plugin)</h1>
<p>Folgende Items werden als Itemset vom Webservices Plugin als JSON bereitgestellt:</p>
<p><img decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/07/epaper_json.jpg" alt="" width="685" height="786" class="alignnone size-full wp-image-1936" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/07/epaper_json.jpg 685w, https://www.smarthomeng.de/wp-content/uploads/2018/07/epaper_json-261x300.jpg 261w" sizes="(max-width: 685px) 100vw, 685px" /></p>
<h1>Code</h1>
<p>Das Programm wurde mit der Arduino IDE geschrieben und auf den ESP32 übertragen. Wie oben bereits erwähnt, müssen dazu die notwendigen Bibliotheken vorhanden sein. Wie der ESP32 in der Arduino IDE eingerichtet werden kann, kann <a href="https://www.smarthomeng.de/entfernungsmessung-auf-basis-eines-esp32-und-smarthomeng" target="_blank" rel="noopener">https://www.smarthomeng.de/entfernungsmessung-auf-basis-eines-esp32-und-smarthomeng</a> entnommen werden.</p>
<p>In der Methode <code>void setup(void)</code> werden zunächst das Display und die WLAN Verbindung initialisiert.<br />
In <code>void loop()</code> findet dann der Datenzugriff und das Rendering statt. Nach erfolgreicher Verbindung zu SmartHomeNG wird zuerst der HTTP Header herausgefiltert. Sobald in der Response eine geschweifte Klammer erkannt wird, werden die JSON Daten in ein Char Array (<code>inData</code>) eingelesen. Ist dies vollendet, wird die Verbindung getrennt und der JSON Datensatz geparsed (<code>JsonObject&amp; root = jsonBuffer.parseObject(inData);</code>). Bei Erfolg, werden die Daten mit <code>printJsonData(JsonObject&amp; root)</code> auf dem Display ausgegeben. Dafür werden sie aus den JSON Daten extrahiert und ggf. noch formatiert.</p>
<p>Im &#8222;do &#8230; while&#8220; Block findet die konkrete Ausgabe statt. <code>display.setCursor</code> setzt den Textcursor an bestimmte Positionen. Danach wird Text ausgegeben. Die Methode <code>void display_icon(int x, int y, String icon_name)</code> gibt an entsprechenden Positionen das Icon aus.<br />
Die Methoden <code>void dashedRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)</code> und <code>void drawDashedHLine(int16_t x, int16_t y, int16_t w, uint16_t color)</code> wurden von <a href="https://forum.arduino.cc/index.php?topic=487007.225" target="_blank" rel="noopener">https://forum.arduino.cc/index.php?topic=487007.225</a> übernommen und zeichnen Linien oder Rechtecke.</p>
<pre><code class="language-c">
#include &lt;WiFi.h&gt;
#include &lt;WiFiServer.h&gt;
#include &lt;WiFiClient.h&gt;
#include &lt;WiFiUdp.h&gt;
#include &lt;JsonParser.h&gt;
#include &lt;ArduinoJson.h&gt;
#include &lt;GxEPD2_BW.h&gt;
#include &lt;GxEPD2_3C.h&gt;
#define EPD_CS 17 //SS
#include &lt;Fonts/FreeMonoBold9pt7b.h&gt;
#include &lt;Fonts/FreeMonoBold12pt7b.h&gt;
#include &lt;Fonts/FreeMonoBold18pt7b.h&gt;

// Define each of the *icons for display
const unsigned char gate_open[] PROGMEM = {
0x00,0x00,0x1f,0xff,0xff,0xe0,0x00,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x00,0x70,0x00,0x00,0x38,0x00
,0x00,0x00,0x60,0x00,0x00,0x18,0x00,0x00,0x00,0x60,0x00,0x00,0x18,0x00,0x00,0x00,0xe0,0x00,0x00,0x1c,0x00,0x00,0x00,0xe0,0x00,0x00,0x1c,0x00
,0x00,0x00,0xe0,0x00,0x00,0x1c,0x00,0x00,0x00,0xff,0xff,0xff,0xfc,0x00,0x00,0x03,0xff,0xff,0xff,0xfe,0x00,0x00,0x03,0x03,0xc0,0x0f,0x03,0x00
,0x00,0x02,0x03,0xff,0xff,0x01,0x00,0x00,0x02,0x03,0xff,0xff,0x01,0x00,0x00,0x03,0x07,0x80,0x07,0x83,0x00,0x00,0x03,0xff,0xff,0xff,0xff,0x00
,0x00,0x03,0xff,0xff,0xff,0xff,0x00,0x00,0x03,0xff,0xff,0xff,0xff,0x00,0x00,0x01,0xff,0xff,0xff,0xfe,0x00,0x00,0x01,0xf8,0x00,0x00,0x7c,0x00
,0x00,0x01,0xf8,0x00,0x00,0x7c,0x00,0x00,0x01,0xf8,0x00,0x00,0x7c,0x00,0x00,0x00,0xf0,0x00,0x00,0x7c,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00
,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xf8,0x00,0x00,0x00,0x00,0x80,0xff,0xf8,0x00,0x00,0x00,0x00,0xc0
,0xff,0x38,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0
,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0
,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0
,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0
,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xdf,0x18,0x00,0x00,0x00,0x00,0xc0,0xff,0xf8,0x00,0x00,0x00,0x00,0xc0,0xff,0xf8,0x00,0x00,0x00,0x00,0xc0
,0xff,0xf8,0x00,0x00,0x00,0x00,0xc0,0x1f,0xff,0xff,0xff,0xff,0xff,0xc0
};

const unsigned char gate_closed[] PROGMEM = {
0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x01,0xff,0xff,0xff,0x80,0x00,0x03,0x80,0x00,0x01,0xc0,0x00,0x03,0x80,0x00,0x01,0xc0
,0x00,0x03,0x00,0x00,0x00,0xc0,0x00,0x03,0x00,0x00,0x00,0xc0,0x00,0x07,0x00,0x00,0x00,0xe0,0x00,0x07,0x00,0x00,0x00,0xe0
,0x00,0x07,0x00,0x00,0x00,0xe0,0x00,0x07,0xff,0xff,0xff,0xe0,0x00,0x0f,0xff,0xff,0xff,0xf0,0x00,0x18,0x1e,0x00,0x78,0x18
,0x00,0x10,0x1f,0xff,0xf8,0x08,0x00,0x10,0x1f,0xff,0xf8,0x08,0x00,0x18,0x3c,0x00,0x3c,0x18,0x00,0x1f,0xff,0xff,0xff,0xf8
,0x00,0x1f,0xff,0xff,0xff,0xf8,0x00,0x1f,0xff,0xff,0xff,0xf8,0x00,0x0f,0xff,0xff,0xff,0xf0,0x00,0x0f,0xc0,0x00,0x03,0xe0
,0x00,0x0f,0xc0,0x00,0x03,0xe0,0x00,0x0f,0xc0,0x00,0x03,0xe0,0x00,0x07,0x80,0x00,0x03,0xe0,0x60,0x00,0x00,0x00,0x00,0x00
,0xe0,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0xe7,0xff,0xff,0xff,0xff,0xf4,0xef,0xff,0xff,0xff,0xff,0xf6
,0xee,0x71,0xce,0x71,0xce,0x76,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36
,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36
,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36
,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36
,0xec,0x31,0x8e,0x31,0x8e,0x36,0xec,0x31,0x8e,0x31,0x8e,0x36,0xef,0xff,0xff,0xff,0xff,0xf6,0xef,0xff,0xff,0xff,0xff,0xf6
,0xe7,0xff,0xff,0xff,0xff,0xf6,0x7f,0xff,0xff,0xff,0xff,0xfe
};

const unsigned char light_off[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x00,0x00,0x00
,0x00,0x00,0x7e,0x1f,0x80,0x00,0x00,0x00,0x00,0xf0,0x03,0xc0,0x00,0x00,0x00,0x01,0xe0,0x01,0xe0,0x00,0x00,0x00,0x03,0xc0,0x00,0xf0,0x00,0x00
,0x00,0x03,0x80,0x00,0x70,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00
,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00
,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x03,0x80,0x00,0x70,0x00,0x00,0x00,0x03,0x80,0x00,0x70,0x00,0x00
,0x00,0x01,0xc0,0x00,0xe0,0x00,0x00,0x00,0x01,0xc0,0x00,0xe0,0x00,0x00,0x00,0x00,0xe0,0x01,0xc0,0x00,0x00,0x00,0x00,0xf0,0x03,0xc0,0x00,0x00
,0x00,0x00,0x70,0x03,0x80,0x00,0x00,0x00,0x00,0x38,0x07,0x00,0x00,0x00,0x00,0x00,0x38,0x07,0x00,0x00,0x00,0x00,0x00,0x38,0x07,0x00,0x00,0x00
,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xf0,0x00,0x00,0x00
,0x00,0x00,0x03,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00
};

const unsigned char light_on[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x03,0x00,0xe0,0x30,0x00,0x00
,0x00,0x03,0x80,0xe0,0x70,0x00,0x00,0x00,0x03,0x80,0xe0,0x70,0x00,0x00,0x00,0x01,0xc0,0x00,0xe0,0x00,0x00,0x00,0x01,0xc0,0x00,0xe0,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x20,0x00,0x03,0xc0,0x0f,0xfc,0x00,0xf0,0x00,0x03,0xe0,0x3f,0xff,0x01,0xf0,0x00
,0x01,0xf0,0xff,0x3f,0xc3,0xe0,0x00,0x00,0x61,0xf0,0x03,0xe1,0x80,0x00,0x00,0x01,0xe0,0x01,0xe0,0x00,0x00,0x00,0x03,0xc0,0x00,0xf0,0x00,0x00
,0x00,0x03,0x80,0x00,0x70,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x08,0x87,0x00,0x00,0x38,0x44,0x00
,0x1f,0x87,0x00,0x00,0x38,0x7e,0x00,0x1f,0x87,0x00,0x00,0x38,0x7e,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00
,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0x00,0x38,0x00,0x00,0x00,0x03,0x80,0x00,0x70,0x00,0x00,0x00,0x03,0x80,0x00,0x70,0x00,0x00
,0x00,0xe1,0xc0,0x00,0xe1,0x80,0x00,0x03,0xe1,0xe0,0x01,0xe1,0xf0,0x00,0x07,0xe0,0xe0,0x01,0xc1,0xf8,0x00,0x03,0x80,0xf0,0x03,0xc0,0x70,0x00
,0x00,0x00,0x70,0x03,0x80,0x00,0x00,0x00,0x00,0x78,0x07,0x80,0x00,0x00,0x00,0x00,0x38,0x07,0x00,0x00,0x00,0x00,0x00,0x38,0x07,0x00,0x00,0x00
,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,0x00,0x00,0x18,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x0f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xf0,0x00,0x00,0x00
,0x00,0x00,0x03,0xf0,0x00,0x00,0x00,0x00,0x00,0x01,0xc0,0x00,0x00,0x00
};

const unsigned char moon_0_8[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0xff,0xf8,0x3f,0xff,0xfc,0x3f,0xff,0xfc,0x7f,0xff,0xfe
,0x7f,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xfe
,0x7f,0xff,0xfe,0x3f,0xff,0xfc,0x3f,0xff,0xfc,0x1f,0xff,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char moon_1[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0xe1,0xf8,0x3f,0xf0,0x7c,0x3f,0xfc,0x3c,0x7f,0xfc,0x1e
,0x7f,0xfe,0x1e,0xff,0xfe,0x0f,0xff,0xff,0x0f,0xff,0xff,0x0f,0xff,0xff,0x0f,0xff,0xff,0x0f,0xff,0xfe,0x0f,0x7f,0xfe,0x1e
,0x7f,0xfc,0x1e,0x3f,0xfc,0x3c,0x3f,0xf0,0x7c,0x1f,0xe1,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char moon_2[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0xe1,0xf8,0x3f,0xf0,0x7c,0x3f,0xfc,0x3c,0x7f,0xfc,0x1e
,0x7f,0xfe,0x1e,0xff,0xfe,0x0f,0xff,0xff,0x0f,0xff,0xff,0x0f,0xff,0xff,0x0f,0xff,0xff,0x0f,0xff,0xfe,0x0f,0x7f,0xfe,0x1e
,0x7f,0xfc,0x1e,0x3f,0xfc,0x3c,0x3f,0xf0,0x7c,0x1f,0xe1,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char moon_3[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0xf1,0xf8,0x3f,0xf0,0x7c,0x3f,0xf0,0x3c,0x7f,0xf0,0x1e
,0x7f,0xf0,0x1e,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0x7f,0xf0,0x1e
,0x7f,0xf0,0x1e,0x3f,0xf0,0x3c,0x3f,0xf0,0x7c,0x1f,0xf1,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char moon_4[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0xc1,0xf8,0x3f,0xc0,0x7c,0x3f,0x80,0x3c,0x7f,0x00,0x1e
,0x7f,0x00,0x1e,0xff,0x00,0x0f,0xff,0x00,0x0f,0xff,0x00,0x0f,0xff,0x00,0x0f,0xff,0x00,0x0f,0xff,0x00,0x0f,0x7f,0x00,0x1e
,0x7f,0x00,0x1e,0x3f,0x80,0x3c,0x3f,0xc0,0x7c,0x1f,0xc1,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char moon_5[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0x81,0xf8,0x3e,0x00,0x7c,0x3c,0x00,0x3c,0x78,0x00,0x1e
,0x78,0x00,0x1e,0xf0,0x00,0x0f,0xf0,0x00,0x0f,0xf0,0x00,0x0f,0xf0,0x00,0x0f,0xf0,0x00,0x0f,0xf0,0x00,0x0f,0x78,0x00,0x1e
,0x78,0x00,0x1e,0x3c,0x00,0x3c,0x3e,0x00,0x7c,0x1f,0x81,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char moon_6[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0x8f,0xf8,0x3e,0x0f,0xfc,0x3c,0x0f,0xfc,0x78,0x0f,0xfe
,0x78,0x0f,0xfe,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0xf0,0x0f,0xff,0x78,0x0f,0xfe
,0x78,0x0f,0xfe,0x3c,0x0f,0xfc,0x3e,0x0f,0xfc,0x1f,0x8f,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char moon_7[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0x87,0xf8,0x3e,0x0f,0xfc,0x3c,0x3f,0xfc,0x78,0x3f,0xfe
,0x78,0x7f,0xfe,0xf0,0x7f,0xff,0xf0,0xff,0xff,0xf0,0xff,0xff,0xf0,0xff,0xff,0xf0,0xff,0xff,0xf0,0x7f,0xff,0x78,0x7f,0xfe
,0x78,0x3f,0xfe,0x3c,0x3f,0xfc,0x3e,0x0f,0xfc,0x1f,0x87,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char moon_8[] PROGMEM = {
0x00,0x3c,0x00,0x01,0xff,0x80,0x07,0xff,0xe0,0x0f,0xff,0xf0,0x1f,0x87,0xf8,0x3e,0x0f,0xfc,0x3c,0x3f,0xfc,0x78,0x3f,0xfe
,0x78,0x7f,0xfe,0xf0,0x7f,0xff,0xf0,0xff,0xff,0xf0,0xff,0xff,0xf0,0xff,0xff,0xf0,0xff,0xff,0xf0,0x7f,0xff,0x78,0x7f,0xfe
,0x78,0x3f,0xfe,0x3c,0x3f,0xfc,0x3e,0x0f,0xfc,0x1f,0x87,0xf8,0x0f,0xff,0xf0,0x07,0xff,0xe0,0x01,0xff,0x80,0x00,0x3c,0x00
};

const unsigned char pressure[] PROGMEM = {
0x00, 0x00, 0x84, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x84, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x4c, 0x88, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x40, 0x00, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x11, 0x08, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x30, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x80, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x04, 0x18, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x00
, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc0, 0x00, 0x18, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, 0x01, 0x80
, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x80, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x61, 0x80, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x80, 0x00, 0x03, 0xc0
, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x80
, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00
, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00
, 0x00, 0x08, 0x00, 0x00, 0x03, 0x80, 0x3f, 0x80, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x80, 0x3f, 0xe0, 0x00
, 0x00, 0x20, 0x00, 0x00, 0x03, 0x80, 0x30, 0xe0, 0x00, 0x3c, 0xc0, 0x00, 0x00, 0x03, 0xfc, 0x30, 0xe7, 0xf0
, 0xff, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x30, 0xe3, 0xf0, 0xe3, 0x80, 0x00, 0x00, 0x03, 0x8e, 0x3b, 0xe0, 0x38
, 0x01, 0x80, 0x00, 0x00, 0x03, 0x8e, 0x3f, 0xc1, 0xf8, 0x01, 0x80, 0x00, 0x00, 0x03, 0x8e, 0x3f, 0x07, 0xf8
, 0x01, 0x80, 0x00, 0x00, 0x03, 0x8e, 0x30, 0x0e, 0x38, 0x01, 0x80, 0x00, 0x00, 0x03, 0x8e, 0x30, 0x0e, 0x38
, 0x03, 0x80, 0x00, 0x00, 0x03, 0x8e, 0x30, 0x07, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x30, 0x03, 0xf0
};

const unsigned char sunrise_sunset[] PROGMEM = {
0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x03,0xc0,0x00,0x00,0x00,0x00,0x03,0xc0,0x00,0x00,0x00,0x00,0x03,0xc0,0x00,0x00
,0x00,0x00,0x03,0xc0,0x00,0x00,0x00,0x00,0x03,0xc0,0x00,0x00,0x00,0x00,0x03,0xc0,0x00,0x00,0x01,0xc0,0x01,0x80,0x03,0x80
,0x01,0xe0,0x00,0x00,0x07,0x80,0x01,0xf0,0x00,0x00,0x0f,0x80,0x00,0xf8,0x00,0x00,0x1f,0x00,0x00,0x78,0x00,0x00,0x1e,0x00
,0x00,0x38,0x03,0xc0,0x1c,0x00,0x00,0x00,0x1f,0xf8,0x00,0x00,0x00,0x00,0x7f,0xfe,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00
,0x00,0x01,0xf8,0x1f,0x80,0x00,0x00,0x03,0xe0,0x07,0xc0,0x00,0x00,0x03,0xc0,0x03,0xc0,0x00,0x00,0x07,0x80,0x01,0xe0,0x00
,0x00,0x07,0x80,0x01,0xe0,0x00,0x00,0x0f,0x00,0x00,0xf0,0x00,0x7e,0x0f,0x00,0x00,0xf0,0x7e,0xff,0x0f,0x00,0x00,0xf0,0xff
,0xff,0x0f,0x00,0x00,0xf0,0xff,0x7e,0x0f,0x00,0x00,0xf0,0x7e,0x00,0x07,0x00,0x00,0xe0,0x00,0x00,0x07,0x80,0x01,0xe0,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x07,0xff,0xff,0xe0,0x00,0x00,0x0f,0xff,0xff,0xf0,0x00,0x00,0x0f,0xff,0xff,0xf0,0x00,0x00,0x07,0xff,0xff,0xe0,0x00
};

const unsigned char clear_day[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
, 0x00, 0x38, 0x00, 0x30, 0x00, 0x70, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0xf0, 0x00
, 0x00, 0x3e, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x03, 0xe0, 0x00
, 0x00, 0x0f, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x07, 0x00, 0x78, 0x03, 0x80, 0x00
, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x00, 0x00
, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x03, 0xf0, 0x00, 0x00
, 0x00, 0x00, 0x7c, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x00
, 0x00, 0x00, 0xf0, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x3c, 0x00, 0x00
, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00, 0x0f, 0xc1, 0xe0, 0x00, 0x1e, 0x0f, 0xc0
, 0x1f, 0xe1, 0xe0, 0x00, 0x1e, 0x1f, 0xe0, 0x1f, 0xe1, 0xe0, 0x00, 0x1e, 0x1f, 0xe0
, 0x0f, 0xc1, 0xe0, 0x00, 0x1e, 0x0f, 0xc0, 0x00, 0x01, 0xe0, 0x00, 0x1e, 0x00, 0x00
, 0x00, 0x00, 0xf0, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x3c, 0x00, 0x00
, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xf8, 0x00, 0x00
, 0x00, 0x00, 0x3f, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00
, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00
, 0x00, 0x07, 0x00, 0x78, 0x03, 0x80, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x03, 0xc0, 0x00
, 0x00, 0x1f, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0xf0, 0x00
, 0x00, 0x3c, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x38, 0x00, 0x30, 0x00, 0x70, 0x00
, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const unsigned char temperature[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xcf, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x87, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x07, 0xb7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xb7, 0xc0, 0x00, 0x00
, 0x00, 0x00, 0x0f, 0x33, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x79, 0xe0, 0x00, 0x00
, 0x00, 0x00, 0x1e, 0xfd, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xfd, 0xe0, 0x00, 0x00
, 0x00, 0x00, 0x1e, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x33, 0xc0, 0x00, 0x00
, 0x00, 0x00, 0x0f, 0x87, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00
, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const unsigned char prob_rain[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0xc0,0x00,0x00
,0x00,0x00,0x3f,0xff,0xf0,0x00,0x00,0x00,0x00,0x7f,0xff,0xfc,0x00,0x00,0x00,0x01,0xff,0xff,0xfe,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0x00,0x00
,0x00,0x07,0xff,0xff,0xff,0x80,0x00,0x00,0x07,0xff,0xff,0xff,0xc0,0x00,0x00,0x0f,0xff,0xff,0xff,0xe0,0x00,0x00,0x0f,0xff,0xff,0xff,0xe0,0x00
,0x00,0x00,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00
,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00
,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x00,0x00,0x00,0x00,0x00,0x38,0xe0,0x00,0x00,0x00,0x00,0x00,0x38,0xe0,0x00,0x00
,0x00,0x00,0x00,0x1f,0xc0,0x00,0x00,0x00,0x00,0x00,0x1f,0x80,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

const unsigned char barometer[] PROGMEM = {
0x00,0x1f,0xe0,0x00,0x00,0x7f,0xf8,0x00,0x01,0xff,0xfe,0x00,0x03,0xf0,0x3f,0x00,0x0f,0x80,0x07,0xc0,0x0f,0x00,0x03,0xc0,0x1e,0x00,0x01,0xe0,0x3c,0x00,0x00,0xf0
,0x38,0x00,0x3c,0x70,0x70,0x00,0x3c,0x38,0x70,0x00,0x7c,0x38,0xf0,0x00,0xfc,0x3c,0xe0,0x07,0xf0,0x1c,0xe0,0x0f,0xe0,0x1c,0xe0,0x0f,0xc0,0x1c,0xe0,0x0f,0xc0,0x1c
,0xe0,0x1f,0x80,0x1c,0xe0,0x3f,0x80,0x1c,0xf3,0xfc,0x00,0x3c,0x71,0xf8,0x00,0x38,0x70,0xf0,0x00,0x38,0x38,0x70,0x00,0x70,0x3c,0x30,0x00,0xf0,0x1e,0x10,0x01,0xe0
,0x0f,0x00,0x03,0xc0,0x0f,0x80,0x07,0xc0,0x03,0xf0,0x3f,0x00,0x01,0xff,0xfe,0x00,0x00,0x7f,0xf8,0x00,0x00,0x1f,0xe0,0x00
};

const unsigned char wind_speed[] PROGMEM = {
0x00,0x00,0x00,0x00,0x01,0xfc,0x00,0x00,0x03,0x3f,0xf0,0x00,0x85,0x3e,0x1f,0x80,0xd9,0x3e,0x1f,0x38,0xf1,0x3e,0x0f,0x0c,0xc1,0x3e,0x0f,0x0c,0xc1,0x3e,0x0f,0x0c
,0xf1,0x3e,0x0f,0x0c,0xd9,0x3e,0x0f,0x18,0xc5,0x3e,0x1f,0xc0,0xc3,0x3f,0xf0,0x00,0xc1,0xfe,0x00,0x00,0xc0,0x80,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00
,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00
,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

const unsigned char rain[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00
,0x00,0x01,0xff,0xe0,0x00,0x00,0x00,0x00,0x07,0xff,0xf8,0x00,0x00,0x00,0x00,0x0f,0xff,0xfc,0x00,0x00,0x00,0x00,0x3f,0x80,0x7f,0x00,0x00,0x00
,0x00,0x7e,0x00,0x1f,0x80,0x00,0x00,0x00,0x78,0x00,0x07,0x80,0x00,0x00,0x00,0xf0,0x00,0x03,0xc0,0x00,0x00,0x01,0xe0,0x00,0x01,0xec,0x00,0x00
,0x01,0xe0,0x00,0x01,0xff,0xc0,0x00,0x03,0xc0,0x00,0x00,0xff,0xf0,0x00,0x03,0xc0,0x00,0x00,0xff,0xf8,0x00,0x03,0x80,0x00,0x00,0x40,0x7c,0x00
,0x03,0x80,0x00,0x00,0x00,0x3e,0x00,0x07,0x80,0x00,0x00,0x00,0x1e,0x00,0x07,0x80,0x00,0x00,0x00,0x0f,0x00,0x07,0x80,0x00,0x00,0x00,0x07,0x00
,0x07,0x80,0x00,0x00,0x00,0x07,0x00,0x03,0x80,0x00,0x00,0x00,0x07,0x80,0x03,0x80,0x00,0x00,0x00,0x07,0x80,0x03,0xc0,0x00,0x00,0x00,0x07,0x80
,0x03,0xc0,0x78,0x00,0x78,0x07,0x80,0x01,0xe0,0x78,0x00,0x78,0x07,0x00,0x01,0xe0,0x78,0x00,0x78,0x0f,0x00,0x00,0xf0,0x78,0x00,0x78,0x0f,0x00
,0x00,0x78,0x78,0x78,0x78,0x1e,0x00,0x00,0x78,0x78,0x78,0x78,0x3e,0x00,0x00,0x38,0x30,0x78,0x30,0x7c,0x00,0x00,0x08,0x00,0x78,0x00,0x78,0x00
,0x00,0x00,0x00,0x78,0x00,0x70,0x00,0x00,0x00,0x00,0x78,0x00,0x40,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x78,0x00,0x78,0x00,0x00,0x00,0x00,0x78,0x00,0x78,0x00,0x00,0x00,0x00,0x78,0x00,0x78,0x00,0x00,0x00,0x00,0x78,0x00,0x78,0x00,0x00
,0x00,0x00,0x78,0x78,0x78,0x00,0x00,0x00,0x00,0x78,0x78,0x78,0x00,0x00,0x00,0x00,0x30,0x78,0x30,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00
,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

const unsigned char partly_cloudy_day[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 0x0e, 0x00
, 0x00, 0x07, 0x80, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x3e, 0x00
, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x78, 0x00
, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00
, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x00
, 0x00, 0x07, 0xe7, 0xe0, 0x7e, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x80, 0x1f, 0x00, 0x00
, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x07, 0x80, 0x00
, 0x07, 0xf0, 0x0f, 0xe0, 0x07, 0x80, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x03, 0xc0, 0x00
, 0x1f, 0x00, 0x00, 0xf8, 0x03, 0xc1, 0xf8, 0x1e, 0x00, 0x00, 0x78, 0x03, 0xc3, 0xfc
, 0x3c, 0x00, 0x00, 0x3f, 0xc3, 0xc3, 0xfc, 0x3c, 0x00, 0x00, 0x3f, 0xfb, 0xc1, 0xf8
, 0x78, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x78, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00
, 0x70, 0x00, 0x00, 0x08, 0x1f, 0x80, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00
, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00
, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00
, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00
, 0x78, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00
, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00
, 0x1e, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00
, 0x0f, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x1f, 0x80, 0x00
, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00
, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00
};

GxEPD2_BW&lt;GxEPD2_420, GxEPD2_420::HEIGHT&gt; display(GxEPD2_420(/*CS=D8*/ EPD_CS, /*DC=D3*/ 16, /*RST=D4*/ 5, /*BUSY=D2*/ 19));

char ssid[] = "xxxxxx"; // Your network SSID (name)
char password[] = "xxxxxxxx"; // Your network key
char host[] = "192.168.178.100"; // IP of SmartHomeNG
int port = 4321;

WiFiClient client;
JsonParser&lt;32&gt; parser;
String currentLine = "";
String currRates = "";
boolean readingJson = false;
#define BUFFERSIZE 5800
static char inData[BUFFERSIZE + 1]; // string + terminator

void setup(void) {
  Serial.begin(115200);
  initialise_wifi();
  display.init(115200);
}

void loop() {
  connect_to_server();
  Serial.println("new loop");
  if (client.connected())
  {
    Serial.println("[isConnected]");
    int index = 0;
    while (!client.available()) {}
    while (client.available()) {
      char inChar = client.read();
      if (inChar == '{') {
        readingJson = true;
      }
      if (readingJson) {
        if (index &lt; BUFFERSIZE - 1)
        {
          inData[index] = inChar; // Store it
          index++;
        }
        if (inChar == '}') {
          readingJson = false;
          inData[index] = '\0';
        }
      }
    }
    client.stop();
    Serial.println("[Disconnected]");
     
    // JSON Daten parsen
    StaticJsonBuffer&lt;5800&gt; jsonBuffer;
    JsonObject&amp; root = jsonBuffer.parseObject(inData);
    if (!root.success())
    {
      Serial.print("parseObject(");
      Serial.print(inData);
      Serial.println(") failed");
    } else {
      Serial.println("[Parse Success]");
      printJsonData(root);
    }
  }
  delay(1000 * 60 * 10); // 10 Minuten warten
}

void printJsonData(JsonObject&amp; root)
{
  int dateSubstringStart = 11;
  int dateSubstringEnd = 16;
  double ozone = root["weather.darksky.home.currently.ozone"];
  String uvIndex = root["weather.darksky.home.currently.uvIndex"];
  String uvIndexStr = root["weather.darksky.home.currently.uvIndex.string"];
  uvIndexStr.replace("u00e4", "ae");
  uvIndexStr.replace("u00df", "ss");
  String curTime = root["weather.darksky.home.currently.time.timeStr"];
  String curDate = root["weather.darksky.home.currently.time.dateStr"];
  double outsideHumidity = root["weather.darksky.home.currently.humidity"];
  double surplus = root["sma.smaem.surplus.kw"];
  double regard = root["sma.smaem.regard.kw"];
  double precipProb = root["weather.darksky.home.currently.precipProbability"];
  double pressure = root["weather.darksky.home.currently.pressure"];
  String currentIcon = root["weather.darksky.home.currently.icon"];
  String moonLight = root["env.location.moonlight"];
  String knx_light_status = root["knx.light_status"];
  String gate_state = root["knx.outside.gate.driveway.state"];
  String moonRise = root["env.location.moonrise"];
  moonRise = moonRise.substring(dateSubstringStart, dateSubstringEnd);
  String moonSet = root["env.location.moonset"];
  moonSet = moonSet.substring(dateSubstringStart, dateSubstringEnd);
  String moonPhase = root["env.location.moonphase"];
  String sunSet = root["env.location.sunset"];
  sunSet = sunSet.substring(dateSubstringStart, dateSubstringEnd);;
  String sunRise = root["env.location.sunrise"];
  sunRise = sunRise.substring(dateSubstringStart, dateSubstringEnd);
  String temperature = root["eta_unit.temperature_outside.value"];
  String temperatureMin = root["eta_unit.temperature_outside.value.min_24"];
  String temperatureMax = root["eta_unit.temperature_outside.value.max_24"];
  String currentlySummary = root["weather.darksky.home.currently.summary"];
  String dailySummary = root["weather.darksky.home.daily.summary"];
  double windSpeed = root["weather.darksky.home.currently.windSpeed"];
  dailySummary.replace("u00b0C", " Grad");
  dailySummary.replace("u00e4", "ae");
  display.setRotation(2);
  display.setFont(&amp;FreeMonoBold18pt7b);
  display.setTextColor(GxEPD_BLACK);
  display.setFullWindow();
  display.firstPage();

  do
  {
    display.fillScreen(GxEPD_WHITE);
    display.setFont(&amp;FreeMonoBold9pt7b);

    display.setCursor(0, 11); display.println(curTime);
    display.setCursor(150, 11); display.println("Mein Ort");
    display.setCursor(290, 11); display.println(curDate);
    drawDashedHLine(0, 20, 420, GxEPD_BLACK);

    display_icon(330, 25, currentIcon);
    display.setCursor(270, 42);
    if (surplus &gt; 0) {
      display.println(surplus);
    } else {
      display.println((-1)*regard);
    }
    display.setCursor(270, 62); display.println("kW");
    display.setCursor(270, 100); display.println("UV: "+uvIndex);
    display.setCursor(270, 115); display.println(uvIndexStr);
    display.setCursor(270, 140); display.print("Ozon: "); display.println((int)ozone, DEC);

    display.setFont(&amp;FreeMonoBold12pt7b);
    dashedRect(0,25,260,125, GxEPD_BLACK);
    display_icon(2, 25, "temperature");
    display.setCursor(50, 47); display.println(temperature+" Grad");
    display.setCursor(50, 67); display.print(outsideHumidity*100,0); display.println("%");
    display_icon(2, 65, "prob_rain");
    display.setCursor(50, 98); display.print(precipProb*100,0); display.println("%");
    display_icon(100, 76, "wind_speed");
    display.setCursor(140, 98); display.print((int)windSpeed, DEC); display.println("km/h");

    //display.setFont(&amp;FreeMonoBold9pt7b);
    display_icon(15, 113, "barometer");
    display.setCursor(50, 135); display.print((int)pressure, DEC); display.println("hPa");

    display.setFont(&amp;FreeMonoBold9pt7b);
    drawDashedHLine(0, 155, 420, GxEPD_BLACK);
    display.setCursor(0, 170); display.println(dailySummary);
    drawDashedHLine(0, 220, 420, GxEPD_BLACK);
    display.setFont(&amp;FreeMonoBold9pt7b);
    display_icon(0, 255, "sunrise_sunset");
    display.setCursor(60, 275); display.println(sunRise);
    display.setCursor(60, 289); display.println(sunSet);
    display.setFont(&amp;FreeMonoBold18pt7b);
    display_icon(137, 265, "moon_"+moonPhase);
    display.setFont(&amp;FreeMonoBold9pt7b);
    display.setCursor(170, 275); display.println(moonRise);
    display.setCursor(170, 289); display.println(moonSet);
    display.setCursor(260, 242); display.println("Tor:");
    
    if (gate_state.equals("false")) {
      display_icon(257, 249, "gate_closed");
    } else {
      display_icon(257, 249, "gate_open");
    }
    display.setCursor(325, 242); display.println("Licht:");
    if (knx_light_status.equals("false")) {
      display_icon(330, 247, "light_off");
    } else {
      display_icon(330, 247, "light_on");
    }
  }
  while (display.nextPage());
}

void drawDashedHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
  display.startWrite();
  writeDashedLine(x, y, x + w - 1, y, color);
  display.endWrite();
}

#ifndef _swap_int16_t
#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; }
#endif

void writeDashedLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) {
  int16_t steep = abs(y1 - y0) &gt; abs(x1 - x0);
  bool hole = false; //make it dash by using a hole every second pixel
  if (steep) {
    _swap_int16_t(x0, y0);
    _swap_int16_t(x1, y1);
  }

  if (x0 &gt; x1) {
    _swap_int16_t(x0, x1);
    _swap_int16_t(y0, y1);
  }

  int16_t dx, dy;
  dx = x1 - x0;
  dy = abs(y1 - y0);

  int16_t err = dx / 2;
  int16_t ystep;

  if (y0 &lt; y1) {
    ystep = 1;
  }
  else {
    ystep = -1;
  }

  for (; x0 &lt;= x1; x0++) {
    if (steep) {
      if (!hole) display.writePixel(y0, x0, color);
      hole = !hole;
    } else {
      if (!hole) display.writePixel(x0, y0, color);
      hole = !hole;
    }
    err -= dy;
    if (err &lt; 0) {
      y0 += ystep;
      err += dx;
    }
  }
}

void dashedRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
  display.startWrite();
  writeDashedLine(x, y, x + w - 1, y, color);
  writeDashedLine(x, y, x, y + h - 1, color);
  writeDashedLine(x + w - 1, y, x + w - 1, y + h - 1, color);
  writeDashedLine(x, y + h - 1, x + w - 1, y + h - 1, color);
  display.endWrite();
}

void display_icon(int x, int y, String icon_name) {
  int scale = 10; // Adjust size as necessary
  if (icon_name == "partly-cloudy-day")
    display.drawBitmap(x, y, partly_cloudy_day, 54, 50, GxEPD_BLACK);
  else if (icon_name == "clear-day")
    display.drawBitmap(x, y, clear_day, 54, 50, GxEPD_BLACK);
  else if (icon_name == "rain")
    display.drawBitmap(x, y, rain, 54, 50, GxEPD_BLACK);
  else if (icon_name == "sunrise_sunset")
    display.drawBitmap(x, y, sunrise_sunset, 48, 36, GxEPD_BLACK);
  else if (icon_name == "prob_rain")
    display.drawBitmap(x, y, prob_rain, 54, 50, GxEPD_BLACK);
  else if (icon_name == "temperature")
    display.drawBitmap(x, y, temperature, 54, 50, GxEPD_BLACK);
  else if (icon_name == "pressure")
    display.drawBitmap(x, y, pressure, 69, 64, GxEPD_BLACK);
  else if (icon_name == "moon_0")
    display.drawBitmap(x, y, moon_0_8, 24, 24, GxEPD_BLACK);
  else if (icon_name == "moon_1")
    display.drawBitmap(x, y, moon_2, 24, 24, GxEPD_BLACK);
  else if (icon_name == "moon_2")
    display.drawBitmap(x, y, moon_3, 24, 24, GxEPD_BLACK);
  else if (icon_name == "moon_3")
    display.drawBitmap(x, y, moon_4, 24, 24, GxEPD_BLACK);
  else if (icon_name == "moon_4")
    display.drawBitmap(x, y, moon_5, 24, 24, GxEPD_BLACK);
  else if (icon_name == "moon_5")
    display.drawBitmap(x, y, moon_6, 24, 24, GxEPD_BLACK);
  else if (icon_name == "moon_6")
    display.drawBitmap(x, y, moon_7, 24, 24, GxEPD_BLACK);
  else if (icon_name == "moon_7")
    display.drawBitmap(x, y, moon_8, 24, 24, GxEPD_BLACK);
  else if (icon_name == "moon_8")
    display.drawBitmap(x, y, moon_0_8, 24, 24, GxEPD_BLACK);
  else if (icon_name == "barometer")
    display.drawBitmap(x, y, barometer, 30, 30, GxEPD_BLACK);
  else if (icon_name == "wind_speed")
    display.drawBitmap(x, y, wind_speed, 30, 30, GxEPD_BLACK);
  else if (icon_name == "light_on")
    display.drawBitmap(x, y, light_on, 50, 50, GxEPD_BLACK);
  else if (icon_name == "light_off")
    display.drawBitmap(x, y, light_off, 50, 50, GxEPD_BLACK);
  else if (icon_name == "gate_open")
    display.drawBitmap(x, y, gate_open, 50, 50, GxEPD_BLACK);
  else if (icon_name == "gate_closed")
    display.drawBitmap(x, y, gate_closed, 47, 50, GxEPD_BLACK);
}

// NETWORK STUFF

void connect_to_server() {
  if (client.connect(host, port)) {
    Serial.println("[Connected to server]");
    // HTTP Request gegen SmartHomeNG / das Webservices-Plugin durchführen
    client.println("GET /rest/itemset/weather/ HTTP/1.0");
    //client.println("Host: 192.168.178.100");
    client.println();
  }
  else
  {
    Serial.println("[Connection Failed!]");
    client.stop();
  }
}

static void initialise_wifi(void)
{
  // Versuche ins WiFi Netzwerk zu verbinden
  int connAttempts = 0;
  Serial.print(F("\r\nConnecting to: "));
  Serial.println(String(ssid));
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000); Serial.print(".");
  if (connAttempts &gt; 30) return;
    connAttempts++;
  }
  Serial.println("Connected to wifi");
  print_wifi_status();
}

void print_wifi_status() {
  // SSID des WiFi Netzwerkes ausgeben:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // WiFi IP Adresse des ESP32 ausgeben:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // WiFi Signalstärke ausgeben:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
</code></pre>
<p>Lädt man das Programm nun auf den verkabelten ESP32 hoch, erscheint nach kurzer Zeit folgende Ausgabe. Nach 10 Minuten erfolgt ein automatischer Refresh:</p>
<p><img decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/07/result_epaper.jpg" alt="" width="1082" height="770" class="alignnone size-full wp-image-1944" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/07/result_epaper.jpg 1082w, https://www.smarthomeng.de/wp-content/uploads/2018/07/result_epaper-300x213.jpg 300w, https://www.smarthomeng.de/wp-content/uploads/2018/07/result_epaper-768x547.jpg 768w, https://www.smarthomeng.de/wp-content/uploads/2018/07/result_epaper-1024x729.jpg 1024w" sizes="(max-width: 1082px) 100vw, 1082px" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/epaper-wetterstation-mit-daten-aus-smarthomeng/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Entfernungsmessung mit ESP32 und SmartHomeNG &#8211; Teil 2: Anbindung eines SSD1306 OLED Displays</title>
		<link>https://www.smarthomeng.de/entfernungsmessung-mit-esp32-und-smarthomeng-teil-2-anbindung-eines-ssd1306-oled-displays</link>
					<comments>https://www.smarthomeng.de/entfernungsmessung-mit-esp32-und-smarthomeng-teil-2-anbindung-eines-ssd1306-oled-displays#respond</comments>
		
		<dc:creator><![CDATA[Marc René Frieß]]></dc:creator>
		<pubDate>Sat, 19 May 2018 17:46:32 +0000</pubDate>
				<category><![CDATA[Beispiel-Implementierungen]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[ESP32]]></category>
		<category><![CDATA[OLED Display]]></category>
		<category><![CDATA[SSD1306]]></category>
		<category><![CDATA[Wasserstand]]></category>
		<category><![CDATA[Webservices]]></category>
		<category><![CDATA[Zisterne]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=1671</guid>

					<description><![CDATA[Als nächsten Schritt meines Projekts zur Überwachung des Wasserstands meiner Zisterne, habe ich ein SSD1306 OLED Display ergänzt, das in meiner Garage in der Nähe der Pumpe installiert werden soll. Hier möchte ich die Wasserhöhe und &#8211; eines Tages &#8211; den Wasserstand anzeigen. Als Vorarbeiten wird im Wesentlichen der Artikel<a class="moretag" href="https://www.smarthomeng.de/entfernungsmessung-mit-esp32-und-smarthomeng-teil-2-anbindung-eines-ssd1306-oled-displays"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>Als nächsten Schritt meines Projekts zur Überwachung des Wasserstands meiner Zisterne, habe ich ein SSD1306 OLED Display ergänzt, das in meiner Garage in der Nähe der Pumpe installiert werden soll. Hier möchte ich die Wasserhöhe und &#8211; eines Tages &#8211; den Wasserstand anzeigen.</p>
<p>Als Vorarbeiten wird im Wesentlichen der Artikel &#8222;<a href="https://www.smarthomeng.de/entfernungsmessung-auf-basis-eines-esp32-und-smarthomeng" target="_blank" rel="noopener">Entfernungsmessung auf Basis eines ESP32 und SmartHomeNG</a>&#8220; vorausgesetzt.<a href="https://www.smarthomeng.de/entfernungsmessung-auf-basis-eines-esp32-und-smarthomeng"></a></p>
<p>Mittlerweile bin ich bei der Messung des Ultraschallsignales des HR-SR04 allerdings auf die Arduino Bibliothek <a href="https://playground.arduino.cc/Code/NewPing" target="_blank" rel="noopener">NewPing</a> umgestiegen, die die Messung übernimmt:<img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/05/newping_lib.jpg" alt="" width="726" height="96" class="alignnone size-full wp-image-1710" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/05/newping_lib.jpg 726w, https://www.smarthomeng.de/wp-content/uploads/2018/05/newping_lib-300x40.jpg 300w" sizes="(max-width: 726px) 100vw, 726px" />Als Display kommt ein kleines OLED Display mit SSD 1306 Controller zum Einsatz (<a href="https://www.az-delivery.de/products/0-96zolldisplay" target="_blank" rel="noopener">https://www.az-delivery.de/products/0-96zolldisplay</a>, ca. 7 Euro).</p>
<p>Das Display wird wie folgt zusätzlich zum HC-SR04 angeschlossen:</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/05/Untitled-Sketch-2_Steckplatine.png" alt="" width="529" height="460" class="alignnone wp-image-1673" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/05/Untitled-Sketch-2_Steckplatine.png 1098w, https://www.smarthomeng.de/wp-content/uploads/2018/05/Untitled-Sketch-2_Steckplatine-300x261.png 300w, https://www.smarthomeng.de/wp-content/uploads/2018/05/Untitled-Sketch-2_Steckplatine-768x667.png 768w, https://www.smarthomeng.de/wp-content/uploads/2018/05/Untitled-Sketch-2_Steckplatine-1024x890.png 1024w" sizes="(max-width: 529px) 100vw, 529px" /></p>
<p>Als Bibliothek kommt die &#8222;<a href="https://github.com/ThingPulse/esp8266-oled-ssd1306" target="_blank" rel="noopener">ESP8266 and ESP32 Oled Driver for SSD1306 display</a>&#8220; von Daniel Eichhorn und Fabrice Weinberg in Version 4.0.0 zum Einsatz:</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/05/display_lib.jpg" alt="" width="734" height="90" class="alignnone size-full wp-image-1685" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/05/display_lib.jpg 734w, https://www.smarthomeng.de/wp-content/uploads/2018/05/display_lib-300x37.jpg 300w" sizes="(max-width: 734px) 100vw, 734px" /></p>
<p>Der angepasst Sourcecode sieht nun wie folgt aus. Es ist dabei zu beachten, dass das Webservices- Plugin inzwischen über die REST Schnittstelle angesteuert wird. Weiterhin sind alle Log-Outputs für den Seriellen Monitor entfernt worden. Sämtliche relevanten Outputs werden jetzt auf dem Display ausgegeben.</p>
<pre><code class="language-c">
#include &lt;HTTPClient.h&gt;
#include &lt;NewPing.h&gt;
#include &lt;WiFi.h&gt;
#include &lt;WiFiClient.h&gt;
#include &lt;WiFiServer.h&gt;
#include &lt;WiFiUdp.h&gt;
#include &lt;Wire.h&gt;
#include "SSD1306.h"

const int triggerPin = 15;   // HC-SR04: Trigger Pin
const int echoPin = 4;       // HC-SR04: Echo Pin
const int sdaPin = 21;       // Display: SDA Pin
const int sclPin = 22;       // Display: SCL Pin
const int sensorRange = 280; // Reichweite (&lt; maximale Reichweite)

// HC-SR04
NewPing sonar(triggerPin, echoPin, sensorRange); // create NewPing instance

// Wifi
char ssid[] = "&lt;wlan_ssid&gt;";     // your network SSID (name)
char pass[] = "&lt;wlan_password&gt;"; // your network password
char host[] = "192.168.178.100"; // ip of service interface in SmartHomeNG
int port = 4321;                 // port of service interface in SmartHomeNG
char cm_item[] = "test.numeric";
int status = WL_IDLE_STATUS;
WiFiClient client;

// Display
SSD1306Wire display(0x3c, sdaPin, sclPin);

void setup() {
  Serial.begin(19200);
  // Init Display
  display.init();
  display.flipScreenVertically();
  // Init Wifi
  initialise_wifi();
}

void loop() {
  delay(50);
  unsigned int result = sonar.ping();
  float cm = sonar.convert_cm(result); //(result/2)/29.1; //

  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  if (cm &gt; 0) {
    if (client.connect(host, port)) {
      HTTPClient http;
      char portStr[12];
      sprintf(portStr, "%d", port);
      char url[128];
      sprintf(url, "http://%s:%s/rest/items/%s", host, portStr, cm_item);
      http.begin(url);
      http.addHeader("Content-Type", "application/json");
      char cmStr[12];
      char cmStrFull[24];
      sprintf(cmStr, "%f", cm);
      sprintf(cmStrFull, "%i cm", (int)cm);
      int httpCode = http.PUT(cmStr);
      String payload = http.getString();
      http.end();

      display.clear();
      display.setFont(ArialMT_Plain_16);
      display.drawString(0, 0, "Wasserstand:");
      display.setFont(ArialMT_Plain_24);
      display.drawString(0, 17, cmStrFull);
      display.display();
    }
  }
  // Wait 5 seconds and do next measurement
  delay(5000);
}

static void initialise_wifi(void) {
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, 0, "Setting up wifi...");
  display.display();

  while (status != WL_CONNECTED) {
    display.drawString(0, 11, "Attempting to connect...");
    display.display();
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  display.drawString(0, 22, "Connected to wifi!");
  display.display();
  printWifiStatus();
}

void printWifiStatus() {
  IPAddress ip = WiFi.localIP();
  String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
  display.drawString(0, 33, "IP: "+ipStr);
  display.display();
  long rssi = WiFi.RSSI();
  char rssiStr[255];
  sprintf(rssiStr, "RSSI: %d dBm", rssi);
  display.drawString(0, 44, rssiStr);
  display.display();
}</code></pre>
<p>Nach der Initialisierung des Displays in der Methode <code>setup</code>, kann mittels <code>display.drawString(...)</code> Text auf das Display gesendet werden. Der erste Parameter ist dabei die X-, der zweite die Y-Koordinate. Im dritten Parameter wird der String gesetzt. Mit <code>display.display();</code> werden alle zuvor eingesteuerten Operationen dann wirklich auf dem Display ausgegeben. Ein <code>display.clear();</code> leert die auf dem Display ausgegebenen Werte, damit neuer Text dargestellt werden kann. Wird kein <code>display.display();</code> aufgerufen, so wird immer mehr auf das Display geschrieben. Dies kann soweit führen, dass Text über bestehenden Text geschrieben wird.</p>
<p>Dies kann am Beispiel der WLAN-Initialisierung gut gesehen werden. Das Gehäuse ist dabei wieder von Thingiverse bezogen und via 3D Drucker gedruckt worden (<a href="https://www.thingiverse.com/thing:2176764" target="_blank" rel="noopener">https://www.thingiverse.com/thing:2176764</a>):</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/05/IMAG0778-1.jpg" alt="" width="546" height="418" class="alignnone wp-image-1699" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/05/IMAG0778-1.jpg 730w, https://www.smarthomeng.de/wp-content/uploads/2018/05/IMAG0778-1-300x230.jpg 300w" sizes="(max-width: 546px) 100vw, 546px" /><br />
Nach der Initialisierung wird nun auf dem Display der Abstand angezeigt:</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/05/IMAG0776.jpg" alt="" width="516" height="556" class="alignnone wp-image-1690" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/05/IMAG0776.jpg 3024w, https://www.smarthomeng.de/wp-content/uploads/2018/05/IMAG0776-278x300.jpg 278w, https://www.smarthomeng.de/wp-content/uploads/2018/05/IMAG0776-768x827.jpg 768w, https://www.smarthomeng.de/wp-content/uploads/2018/05/IMAG0776-950x1024.jpg 950w" sizes="(max-width: 516px) 100vw, 516px" /></p>
<p>In Teil 3 folgt nun in Kürze noch ein Update zu meiner tatsächlichen Installation in der Zisterne und der Garage. Die Arbeiten sind bereits vollendet und die Werte werden via Kabel in die Garage auf den ESP32 übertragen. Mehr dazu aber in der nächsten Zeit&#8230;</p>
<p><em>(Die in diesem Artikel verwendeten Screenshots und Fotos wurden selber erstellt. Für den Schaltplan wurde das Tool<span> </span><a href="http://fritzing.org/home/" target="_blank" rel="noopener">Fritzing</a><span> </span>verwendet.)</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/entfernungsmessung-mit-esp32-und-smarthomeng-teil-2-anbindung-eines-ssd1306-oled-displays/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Entfernungsmessung auf Basis eines ESP32 und SmartHomeNG</title>
		<link>https://www.smarthomeng.de/entfernungsmessung-auf-basis-eines-esp32-und-smarthomeng</link>
					<comments>https://www.smarthomeng.de/entfernungsmessung-auf-basis-eines-esp32-und-smarthomeng#comments</comments>
		
		<dc:creator><![CDATA[Marc René Frieß]]></dc:creator>
		<pubDate>Tue, 03 Apr 2018 17:01:26 +0000</pubDate>
				<category><![CDATA[Beispiel-Implementierungen]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Entfernungsmessung]]></category>
		<category><![CDATA[ESP32]]></category>
		<category><![CDATA[HC-SR04]]></category>
		<category><![CDATA[Internet of Things]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Ultraschall]]></category>
		<category><![CDATA[Webservices]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=1198</guid>

					<description><![CDATA[ESP32 Mikrocontroller stellen eine günstige, relativ performante, WLAN- und Bluetooth-fähige Basis für Internet of Things (IoT) &#8211; Implementierungen bereit. Sie lassen sich zudem relativ einfach mit SmartHomeNG nutzen. Das hier vorgestellte Beispiel, das u.a. für die Überwachung des Füllstands einer Zisterne verwendet werden kann, ist auf Basis eines Espressif ESP32<a class="moretag" href="https://www.smarthomeng.de/entfernungsmessung-auf-basis-eines-esp32-und-smarthomeng"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>ESP32 Mikrocontroller stellen eine günstige, relativ performante, WLAN- und Bluetooth-fähige Basis für Internet of Things (IoT) &#8211; Implementierungen bereit. Sie lassen sich zudem relativ einfach mit SmartHomeNG nutzen.</p>
<p>Das hier vorgestellte Beispiel, das u.a. für die Überwachung des Füllstands einer Zisterne verwendet werden kann, ist auf Basis eines <a href="https://www.espressif.com/en/products/hardware/esp32/overview" target="_blank" rel="noopener">Espressif ESP32</a> entwickelt worden, der zum Zeitpunkt dieses Artikels für ca. 15 Euro zu haben ist. Dazu wird für die Entfernungsmessung ein <a href="http://www.mikrocontroller-elektronik.de/ultraschallsensor-hc-sr04/" target="_blank" rel="noopener">HC-SR04 Ultraschallsensor</a> verwendet, der für knapp 2 Euro erhältlich ist.</p>
<p>Die Daten werden dabei an ein Item übermittelt, das via Webservices-Plugin erreichbar ist. Mehr zu diesem Plugin ist unter <a href="https://www.smarthomeng.de/das-smarthomeng-webservices-plugin" target="_blank" rel="noopener">https://www.smarthomeng.de/das-smarthomeng-webservices-plugin</a> zu finden. Die korrekte Konfiguration des Items wird in diesem Artikel als Voraussetzung angenommen.</p>
<p><strong>Update:</strong> Inzwischen ist der zweite Teil zum Thema erschienen, bei dem ich erläutere, wie man die Entfernungsdaten auf ein OLED Display bringt. Direkteinstieg unter <a href="https://www.smarthomeng.de/entfernungsmessung-mit-esp32-und-smarthomeng-teil-2-anbindung-eines-ssd1306-oled-displays" target="_blank" rel="noopener">Entfernungsmessung mit ESP32 und SmartHomeNG Teil 2: Anbindung eines SSD1306 OLED Displays</a>.</p>
<h1>Installation des Espressif ESP32 unter Windows</h1>
<p>Als erstes muss der ESP32 als USB Gerät erkannt werden. Dazu kann die Anleitung unter <a href="https://dl.espressif.com/doc/esp-idf/latest/get-started/establish-serial-connection.html" target="_blank" rel="noopener">https://dl.espressif.com/doc/esp-idf/latest/get-started/establish-serial-connection.html</a> befolgt werden. Eine alternative Anleitung für MacOS und Linux ist dort ebenfalls zu finden.</p>
<p>Zusammengefasst muss der Treiber für das ESP32 Core Board von <a href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers" target="_blank" rel="noopener">https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers</a> installiert werden. Danach sollte das Gerät als COM3 auftauchen, wie in untenstehendem Bild zu sehen ist. In meinen Tests klappte dies nicht mit jedem Micro-USB-Kabel. Daher sind ggf. Kabel durchzuprobieren.</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/system_esp32.png" alt="" class="alignnone size-full wp-image-1201" width="644" height="348" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/system_esp32.png 644w, https://www.smarthomeng.de/wp-content/uploads/2018/04/system_esp32-300x162.png 300w" sizes="(max-width: 644px) 100vw, 644px" /></p>
<h1>Einrichtung der Arduino IDE</h1>
<p>Als nächstes muss die Arduino IDE installiert werden. Diese kann kostenlos über <a href="https://www.arduino.cc/en/main/software" target="_blank" rel="noopener">https://www.arduino.cc/en/main/software</a> oder bei Windows 10 den <a href="https://www.microsoft.com/de-de/store/p/arduino-ide/9nblggh4rsd8">Microsoft Store</a> bezogen werden.</p>
<p>Über &#8222;Werkzeuge&#8220; → &#8222;Board&#8220; muss dort nun das &#8222;ESP32 Dev Module&#8220; ausgewählt werden. Die weiteren Einstellungen sind ebenfalls im folgenden Bild zu sehen:</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_board.png" alt="" class="alignnone size-full wp-image-1202" width="1320" height="1276" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_board.png 1320w, https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_board-300x290.png 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_board-768x742.png 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_board-1024x990.png 1024w" sizes="(max-width: 1320px) 100vw, 1320px" /></p>
<p>Wird rechts unten noch ein &#8222;None auf COM3&#8220; angezeigt, so ist das nicht weiter dramatisch, sofern der ESP32 bereits im Geräte-Manager auf COM3 sichtbar ist.</p>
<h1>Versuchsaufbau: Espressif ESP32 mit HC-SR04 Ultraschallsensor</h1>
<p>Die Funktionsweise des <a href="http://www.mikrocontroller-elektronik.de/ultraschallsensor-hc-sr04/" target="_blank" rel="noopener">HC-SR04 Ultraschallsensors</a> ist schnell erklärt:</p>
<p>Der HC-SR04 hat einen Lautsprecher und ein Mikrofon verbaut. Über den Lautsprecher wird ein Ultraschall-Ton ausgegeben. Dieser wird von einem Objekt reflektiert und über das direkt neben dem Lautsprecher platzierte Mikrofon erfasst. Die Zeitdauer zwischen dem Senden des Signals und dem Empfang des Echos wird gemessen. Über die Schallgeschwindigkeit von 343,2 m/s bei 20° Celsius kann nun die Distanz zu demjenigen Objekt berechnet werden, an dem das Signal relektiert wird.</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/HC-SR04.png" alt="" class="alignnone size-full wp-image-1284" width="300" height="330" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/HC-SR04.png 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/HC-SR04-273x300.png 273w" sizes="(max-width: 300px) 100vw, 300px" /><br />
Da der Sensor in Mikrosekunden misst, muss zur Bestimmung der Distanz der gemessene Wert erst halbiert (einfache Strecke) und dann mit 0,03432 multipliziert bzw. grob überschlagen durch 29.1 geteilt werden (1/29.1 = 0,03436).</p>
<p>Für den Versuchsaufbau muss der HC-SR04 an den ESP angeschlossen werden. Der HC-SR04 besitzt dabei die Anschlüsse &#8222;Gnd&#8220;, &#8222;Echo&#8220;, &#8222;Trig&#8220; und &#8222;Vcc&#8220;.</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0706.jpg" alt="" class="alignnone size-full wp-image-1219" width="2284" height="1320" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0706.jpg 2284w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0706-300x173.jpg 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0706-768x444.jpg 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0706-1024x592.jpg 1024w" sizes="(max-width: 2284px) 100vw, 2284px" /></p>
<p>&#8222;Gnd&#8220; wird am ESP ebenfalls an &#8222;Gnd&#8220; angeschlossen. &#8222;Vcc&#8220; kommt an den &#8222;5V&#8220; Anschluss für die Stromversorgung. &#8222;Echo&#8220; und &#8222;Trig&#8220; werden an die jeweiligen GPIOs angeschlossen. Im Beispiel wird &#8222;Echo&#8220; auf &#8222;IO4&#8220; und &#8222;Trig&#8220; auf &#8222;IO15&#8220; gelegt. Diese sind später im Programmcode zu referenzieren.</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/ESP32_GPIO.png" alt="" class="alignnone size-full wp-image-1273" width="1362" height="813" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/ESP32_GPIO.png 1362w, https://www.smarthomeng.de/wp-content/uploads/2018/04/ESP32_GPIO-300x179.png 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/ESP32_GPIO-768x458.png 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/ESP32_GPIO-1024x611.png 1024w" sizes="(max-width: 1362px) 100vw, 1362px" /></p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/ultraschall_Steckplatine.png" alt="" class="alignnone size-full wp-image-1309" width="1755" height="1239" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/ultraschall_Steckplatine.png 1755w, https://www.smarthomeng.de/wp-content/uploads/2018/04/ultraschall_Steckplatine-300x212.png 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/ultraschall_Steckplatine-768x542.png 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/ultraschall_Steckplatine-1024x723.png 1024w" sizes="(max-width: 1755px) 100vw, 1755px" /><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0704.jpg" alt="" class="alignnone size-full wp-image-1218" width="2904" height="2740" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0704.jpg 2904w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0704-300x283.jpg 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0704-768x725.jpg 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0704-1024x966.jpg 1024w" sizes="(max-width: 2904px) 100vw, 2904px" /></p>
<h1>Programmierung des ESP32 via Arduino IDE und C-Code</h1>
<p>Als letztes ist nun der ESP32 via Arduino IDE zu programmieren.</p>
<p>Als Bibliotheken werden via &#8222;Sketch&#8220; → &#8222;Bibliothek einbinden&#8220; → &#8222;Bibliotheken verwalten&#8220; die &#8222;WiFi&#8220; Bibliothek (1.2.7) und die &#8222;Wire&#8220; Bibliothek (1.0.0) installiert. Erstere ist für den WiFi-Zugriff, zweitere für den Zugriff auf die GPIO&#8217;s.</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/arduino_libs.png" alt="" class="alignnone size-full wp-image-1263" width="1993" height="847" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/arduino_libs.png 1993w, https://www.smarthomeng.de/wp-content/uploads/2018/04/arduino_libs-300x127.png 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/arduino_libs-768x326.png 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/arduino_libs-1024x435.png 1024w" sizes="(max-width: 1993px) 100vw, 1993px" /></p>
<p>Als Nächstes ist der Quellcode zu erstellen. Dabei sind im Wesentlichen die PINs für den Trigger (&#8222;Trig&#8220; → <code>triggerPin</code>) und den Echo-Anschluss (&#8222;Echo&#8220; → <code>echoPin</code>) des HC-SR04 Ultraschallsensors, die WiFi-SSID (<code>ssid[]</code>), das WiFi-Passwort (<code>pass[]</code>), die IP von SmartHomeNG (<code>host[]</code>) und der Port des Webservices Interfaces in SmartHomeNG (<code>port</code>) zu setzen. Weiterhin ist der Itempfad desjenigen Items zu setzen, dass die Entfernung in Zentimeter aufnehmen soll (<code>cm_item[]</code>). Im Beispiel hat dieses Item den Pfad <code>test.numeric</code>.</p>
<p>Das zugehörige Item ist bei aktiviertem Webservices-Plugin wie folgt konfiguriert:</p>
<pre><code class="language-yaml">
%YAML 1.1
---
test:

    numeric:
        type: num
        visu_acl: rw
        webservices_set: outside
        webservices_data: 'val'
</code></pre>
<p>Die Initialisierung der WiFi-Verbindung wird in der Methode <code>setup</code> aufgerufen. Des Weiteren werden dort die Input- und Output GPIO PINs gesetzt.</p>
<p>Die Methode <code>initialise_wifi</code> sorgt dafür, dass die WiFi Verbindung aufgebaut wird. Am Ende der Methode werden via <code>print_wifi_status</code> die Daten der Verbindung ausgegeben:</p>
<pre>Attempting to connect to SSID: 
&lt;wifi-name&gt;
Connected to wifi
SSID: &lt;wifi-name&gt;
IP Address: 192.168.178.23
signal strength (RSSI):-77 dBm
</pre>
<pre data-line="8-9, 12, 15-19, 34-35, 65, 69-76, 78, 82, 91-93" class="line-numbers"><code class="language-c">
#include &lt;WiFi.h&gt;
#include &lt;WiFiClient.h&gt;
#include &lt;WiFiServer.h&gt;
#include &lt;WiFiUdp.h&gt;
#include &lt;Wire.h&gt;

// PINs
const int triggerPin = 15;
const int echoPin = 4;

// VARs
const int runs = 3;

// Wifi
char ssid[] = "&lt;wlan_id&gt;";          // your network SSID (name)
char pass[] = "&lt;wlan_password&gt;";    // your network password
char host[] = "192.168.178.100";    // ip of service interface in SmartHomeNG
int port = 4321;                    // port of service interface in SmartHomeNG
char cm_item[] = "test.numeric";
int status = WL_IDLE_STATUS;
WiFiClient client;

void setup() {
  Serial.begin(19200);
  initialise_wifi();
 
  // PIN-Modes
  pinMode(triggerPin, OUTPUT);
  pinMode(echoPin, INPUT);
  digitalWrite(triggerPin, HIGH);
}

void loop() {
  float distance = get_distance();
  float avg_distance = get_distance_avg();
 
  Serial.write("distance: ");
  Serial.print(distance) ;
  Serial.write(" , avg. distance: ");
  Serial.print(avg_distance) ;
  Serial.write(" cm\n");
 
  Serial.println("\nStarting connection to server...");
  // Wenn die Verbindung möglich ist, Verbindungsdaten an Serial zurückgeben.
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  if (client.connect(host, port)) {
    Serial.println("\nconnected to server");
    // HTTP Request gegen SmartHomeNG / das Webservices-Plugin durchführen
    char buffer[64];
    int ret = snprintf(buffer, sizeof buffer, "GET /ws/items/%s/%f HTTP/1.1", cm_item, avg_distance);
    Serial.println(buffer);
    client.println(buffer);
    client.println("Host: ");
    client.println();
  } 
  Serial.print("\n");
  // 1 Sekunde Warten
  delay(1000);
}

float get_distance() {
  float duration=0;
  float distance=0;
 
  digitalWrite(triggerPin, LOW);
  delayMicroseconds(2); 
  noInterrupts();
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW); 
  duration = pulseIn(echoPin, HIGH); // Erfassung - Dauer in Mikrosekunden 
  interrupts();

  distance = (duration / 2) / 29.1; // Distanz in CM
  return(distance);
}

float get_distance_avg() {
  float alt = 0;
  float avg;
  float dist;
  int i;

  delay(10);
  alt = get_distance();
  delay(10);
  for (i=0; i&lt;runs; i++) {
    dist = get_distance();
    avg = (0.8*alt) + (0.2*dist);
    alt = avg;
    delay(10);
  }
  return (avg);
}

static void initialise_wifi(void)
{
  // Versuche ins WiFi Netzwerk zu verbinden
  while (status != WL_CONNECTED) {
    Serial.println("");
    Serial.println("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Ins WPA/WPA2 Netzwerk verbinden. 
    status = WiFi.begin(ssid, pass);
    // 10 Sekunden auf die Verbindung warten:
    delay(10000); 
  }
  Serial.println("Connected to wifi");
  print_wifi_status();
}

void print_wifi_status() {
  // SSID des WiFi Netzwerkes ausgeben:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID()); 

  // WiFi IP Adresse des ESP32 ausgeben:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // WiFi Signalstärke ausgeben:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
</code></pre>
<p>In der Methode <code>loop</code> findet nun die konkrete Ermittlung des Abstands statt. In der dort aufgerufenen Methode <code>get_distance_avg()</code> werden mehrere Messungen (<code>runs</code>) durchgeführt, um Messfehler zu minimieren. <code>get_distance()</code> wird zum Vergleich ebenfalls einzeln aufgerufen.</p>
<p>In jedem <code>run</code> wird in der Methode <code>get_distance_avg()</code> nun ebenfalls <code>get_distance()</code> aufgerufen. Dort findet der technische Teil des Messung statt: Zuerst wird der Trigger auf LOW gesetzt: <code>digitalWrite(triggerPin, LOW);</code>. Danach wird 2 Mikrosekunden gewartet und der Trigger auf HIGH gesetzt (<code>digitalWrite(triggerPin, HIGH);</code>). Nach erneutem Warten von 10 Mikrosekunden (erst nach dieser Zeit sendet der Sensor Ultraschallwellen) wird der Trigger wieder auf LOW gesetzt (<code>digitalWrite(triggerPin, LOW);</code>) und via <code>duration = pulseIn(echoPin, HIGH);</code> die Dauer zwischen Puls und Empfang des Echos gemessen. Während der Zeitmessung sollten Interrupts zudem abgeschaltet werden (<code>noInterrupts();</code>).<br />
Zuletzt wird die Entfernung in Zentimetern, wie oben bereits erklärt, mit <code>distance = (duration / 2) / 29.1;</code> berechnet und zurückgegeben.</p>
<p>In <code>get_distance_avg()</code> wird dies nun mehrfach wiederholt und ein gleitender gewichteter Durchschnittswert (<code>avg = (0.8*alt) + (0.2*dist);</code>) gebildet. Werden dort trotzdem noch starke Abweichungen festgestellt, können bspw. die Anzahl der <code>runs</code> erhöht oder die Gewichtung verändert werden.</p>
<p>Das Ergebnis von <code>get_distance_avg()</code> wird dann via HTTP Get Request an das Webservices-Plugin (Simple Interface) und das konfigurierte Item übertragen. Auch diese Vorgänge werden im Code ausgegeben:</p>
<pre>distance: 17.41 , avg. distance: 17.42 cm

Starting connection to server...
HTTP/1.1 200 OK
Content-Length: 65
Server: CherryPy/14.0.1
Content-Type: application/json
Date: Tue, 03 Apr 2018 19:31:48 GMT

{"Success": "Item with item path test.numeric set to 17.419243."}
connected to server
GET /ws/items/test.numeric/17.419930 HTTP/1.1</pre>
<p>Wir das REST-Interface des Webservices-Plugins verwendet, so sieht der Codeblock zum Senden der Daten wie folgt aus:</p>
<pre><code class="language-c">#include &lt;HTTPClient.h&gt;<httpclient.h>
[...]
if (client.connect(host, port)) {
     HTTPClient http;    //Declare object of class HTTPClient
     char portStr[12];
     sprintf(portStr, "%d", port);
     char url[128];
     sprintf(url, "http://%s:%s/rest/items/%s", host, portStr, cm_item);
     http.begin(url);  //Specify request destination
     Serial.println(url);
     http.addHeader("Content-Type", "application/json");                //Specify content-type header
     char cmStr[12];
     sprintf(cmStr, "%f", cm);
     int httpCode = http.PUT(cmStr);                                    //Send the request
     String payload = http.getString();                                 //Get the response payload
     http.end();                                                        //Close connection
} 
</httpclient.h></code></pre>
<h1>Erster Programmstart und Test</h1>
<p>Ist der ESP32 via USB verbunden, so kann das Programm über das &#8222;Haken&#8220;-Icon links oben auf Syntaxfehler geprüft und kompiliert und mittels des &#8222;Pfeil&#8220;-Icons daneben auf den ESP32 übertragen werden.</p>
<p>Gleichzeitig sollte vor einer Übertragung (und damit dem Programmstart) über &#8222;Werkzeuge&#8220; → &#8222;Serieller Monitor&#8220; der Monitor für die Testausgaben geöffnet werden.</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_debug.png" alt="" class="alignnone size-full wp-image-1223" width="1184" height="862" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_debug.png 1184w, https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_debug-300x218.png 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_debug-768x559.png 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/esp32_debug-1024x746.png 1024w" sizes="(max-width: 1184px) 100vw, 1184px" /></p>
<p><strong>Tipp:</strong> Plausible Distanzen kommen nur heraus, wenn der Sensor etwas erhöht, bspw. auf einer Kaffeetasse platziert wird. Anstonsten stören Reflektionen am Boden die Messwerte. Bei der Messung sollte daher generell beachtet werden, dass sich das Ultraschallsignal kegelförmig ausbreitet. Auf große Distanzen (&gt; 1m) muss der Sensor so genau wie möglich auf das Zielobjekt ausgerichtet werden. Man sollte zudem Acht geben, dass das emittierte Signal auf einer möglichst parallelen Fläche reflektiert wird. Als Oberfläche für den Abprall der Impulse kann testweise bspw. ein Buch platziert werden. Die im Beispiel gemessenen 12,6 cm sind dabei bis auf ca. 5 mm genau.</p>
<p><img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0707.jpg" alt="" class="alignnone size-full wp-image-1224" width="3420" height="2616" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0707.jpg 3420w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0707-300x229.jpg 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0707-768x587.jpg 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0707-1024x783.jpg 1024w" sizes="(max-width: 3420px) 100vw, 3420px" /></p>
<h1>Fazit</h1>
<p>Mit dem ESP32 und einem HC-SR04 lässt sich für unter 20 Euro eine relativ genaue Abstandsmessung implementieren, die sehr simpel via WLAN an SmartHomeNG Daten sendet. Als Anwendungsfall wird die Installation im Sommer in meiner Zisterne installiert werden. Dazu folgt ein separater Bericht in diesem Blog.</p>
<p>Als Gehäuse für den HC-SR04 dient eine Vorlage von <a href="https://www.thingiverse.com/thing:1708627" target="_blank" rel="noopener">Thingiverse</a>, die mittels 3D Drucker &#8222;gedruckt&#8220; wurde:<br />
<img loading="lazy" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0708.jpg" alt="" class="alignnone wp-image-1226" width="376" height="258" srcset="https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0708.jpg 1880w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0708-300x206.jpg 300w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0708-768x528.jpg 768w, https://www.smarthomeng.de/wp-content/uploads/2018/04/IMAG0708-1024x704.jpg 1024w" sizes="(max-width: 376px) 100vw, 376px" /></p>
<p>Aber auch andere Sensoren lassen sich auf ähnliche Art und Weise kostengünstig und schnell verbauen und mit SmartHomeNG verbinden.</p>
<p>Für weniger versierte Programmierer bietet sich hier <a href="https://www.letscontrolit.com/wiki/index.php/ESPEasy" target="_blank" rel="noopener">ESPEasy</a> an, das Thema eines <a href="https://www.smarthomeng.de/einbindung-von-sensoren-ueber-wlan-mit-esp8266-unter-verwendung-von-espeasy" target="_blank" rel="noopener">anderen Artikels</a> ist.</p>
<p>Im zweiten Teil zum Thema wird erläutert, wie man die Entfernungsdaten auf ein OLED Display bringt. Direkteinstieg unter <a href="https://www.smarthomeng.de/entfernungsmessung-mit-esp32-und-smarthomeng-teil-2-anbindung-eines-ssd1306-oled-displays" target="_blank" rel="noopener">Entfernungsmessung mit ESP32 und SmartHomeNG Teil 2: Anbindung eines SSD1306 OLED Displays</a>.</p>
<p><em>(Die in diesem Artikel verwendeten Screenshots und Fotos wurden selber erstellt. Für den Schaltplan wurde das Tool <a href="http://fritzing.org/home/" target="_blank" rel="noopener">Fritzing</a> verwendet.)</em></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/entfernungsmessung-auf-basis-eines-esp32-und-smarthomeng/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
