{"id":170,"date":"2015-08-27T17:25:08","date_gmt":"2015-08-27T15:25:08","guid":{"rendered":"http:\/\/cetmita.tk\/?p=170"},"modified":"2015-08-27T17:25:08","modified_gmt":"2015-08-27T15:25:08","slug":"toen-was-er-data","status":"publish","type":"post","link":"https:\/\/catmita.duckdns.org\/?p=170","title":{"rendered":"Toen was er data"},"content":{"rendered":"<p>In de verschillende projecten heb ik gemerkt dat het belangrijk is om te meten en te monitoren. Als hij dan stuk gaat of iets onverwachts optreed kan je je met data achter halen wat er verkeerd is gegaan en daar op in spelen. Het is daarbij niet alleen belangrijk om te meten maar ook deze meetresultaten op te slaan en daarbij te presenteren.<\/p>\n<p>In het verleden hebben wij (als team)  wel eens log-files gehad van een systeem dat binnen 40 minuten meer dan 60 Mb aan data had verzameld, in de\u00a0vorm van een txt file. Hiermee konden we dus ook de locatie aanwijzen (via gps) waar het verkeerd ging met ons systeem.\u00a0Mijn idee is\u00a0daarom ook maak een meet systeem met daarbij een verwerkingssysteem er achter. Het verwerkingssysteem is\u00a0niet alleen voor het opslaan van de data maar ook om de data te presenteren, het liefst live. Een txt file van 60 Mb is leuk maar als een live grafiek of kaart voor je getekend wordt kan je sneller conclusies trekken.<\/p>\n<p>Ik wil een systeem maken waar ik gemakkelijk, wat voor data dan ook, kan opslaan en presenteren. Met de data bedoel ik dan ook Heel Veel Data, een paar\u00a0gigabyte zou mogelijk moeten zijn. Dat zou ook een beetje snel moeten kunnen. Het systeem moet geschikt zijn om 24&#215;7 data van sensoren uit te lezen en op te slaan en dan ook energie zuinig(de sensoren dan). He dit klink als The-Internet-of-things, dat is het ook. Ik wil het ontwikkelen als\u00a0bouwblok of Tool, zodat ik het ook in andere projecten kan gebruiken of aansluiten. Zodat ik bijvoorbeeld mijn <a href=\"https:\/\/catmita.duckdns.org\/?p=41\">MPPT<\/a>\u00a0de\u00a0logs opslaat en overal waar ik ben uit kan lezen. Maar begin vooral simpel en bouw het dan uit. Hou het daarbij goedkoop hierdoor\u00a0kan de hoeveelheid sensoren makkelijk toenemen.<\/p>\n<p><!--more--><\/p>\n<h1>Onderzoek<\/h1>\n<p>Als je onderzoek gaat doen naar The-Internet-of-Things, kom je al snel op de Raspberry Pi uit, die dan sensoren uit leest en dan op<a href=\"https:\/\/thingspeak.com\/\" target=\"_blank\" rel=\"noopener\"> standaard systemen opslaat<\/a>. Ik ben zelf een grote fan van de raspberry pi, maar ik vind dit een overkill. Een keer per seconden de temperatuur meten en dan op thingspeak wegschrijven, de Rasperry Pi kan een complete programmeer omgeving draaien. Dit kan beter en zuiniger, dat betekent niet dat ik de Raspberry Pi buiten beschouwing hou. Ik zie hem dan meer als server kant, hij kan de data opslaan en een website hosten. Thingspeak is een leuk systeem maar limiteert snel het aantal punten, een eigen systeem wordt dat gelimiteerd door de schijfruimte.<\/p>\n<p>Het meten van temperatuur is wel een goed begin, wat simpel is en nuttig. Het is wel leuk om te weten hoeveel het &#8217;s nachts heeft gevroren. De Pi\u00a0niet\u00a0als sensor kant; wat dan wel, het is niet dat er een ethernet controller in de Atmega8A zit gebouwd. Je hebt wel externe ethernet controllers die je via SPI kan aansluiten, zo als de bekende\u00a0<a href=\"http:\/\/ww1.microchip.com\/downloads\/en\/DeviceDoc\/39662e.pdf\" target=\"_blank\" rel=\"noopener\">ENC28J60<\/a>. Dan mag ik door het hele huis kabels gaan trekken. Er is nu een enorme trend gaande met de\u00a0<a href=\"https:\/\/nurdspace.nl\/ESP8266\" target=\"_blank\" rel=\"noopener\">ESP8266<\/a>. Toen ik begon met onderzoek kwam ik ze tegen voor<a href=\"http:\/\/www.cnx-software.com\/2014\/08\/28\/esp8266-wifi-serial-module-costs-just-5\/\" target=\"_blank\" rel=\"noopener\"> 5 euro<\/a>. Toen dacht ik al dat is goedkoop voor een wifi module die je via uart kan aansloten. Ik had er toen gelijk een gekocht, ik had alleen nog geen tijd voor om er mee te werken. Nu zijn ze zelf goedkoper geworden, 2 euro 30.<\/p>\n<div id=\"attachment_181\" style=\"width: 201px\" class=\"wp-caption alignright\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-181\" class=\"wp-image-181 size-medium\" src=\"https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/wpid-wp-1440420974355-e1440436844744-191x300.jpeg\" alt=\"wpid-wp-1440420974355.jpeg\" width=\"191\" height=\"300\" srcset=\"https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/wpid-wp-1440420974355-e1440436844744-191x300.jpeg 191w, https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/wpid-wp-1440420974355-e1440436844744-651x1024.jpeg 651w, https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/wpid-wp-1440420974355-e1440436844744-768x1207.jpeg 768w, https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/wpid-wp-1440420974355-e1440436844744-977x1536.jpeg 977w, https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/wpid-wp-1440420974355-e1440436844744-1303x2048.jpeg 1303w, https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/wpid-wp-1440420974355-e1440436844744.jpeg 1371w\" sizes=\"auto, (max-width: 191px) 100vw, 191px\" \/><p id=\"caption-attachment-181\" class=\"wp-caption-text\">Arduino-mini-pro<\/p><\/div>\n<p>De gebrekkige informatie over de ESP8266 module of chip\u00a0heb ik eerst een module besteld en daarbij een microcontroller die in een breadboard past. Standaard gebruik in de Atmega8A in SMD, deze past niet in een breadboard, dus is ging ik opzoek naar goedkope ontwikkel printjes en ben uiteindelijk uitgekomen op een met de Atmega328p. Of anders gezegd de Arduino-mini-pro. Dat betekent niet dat ik gelijk in Arduino moet programeren, het blijft gewoon een atmega dus kan gewoon in C blijven programmeren. Het belangrijkste om deze te kiezen is omdat hij pin compatible is, dat betekent dat ik een PCB voor de een kan ontwerpen en de andere er later toch op solderen. (bron: <a href=\"http:\/\/www.atmel.com\/images\/doc2553.pdf\" target=\"_blank\" rel=\"noopener\">AVR094<\/a>, weet het is de 88 maar dat is alleen het kleine flash versie van de 328)<\/p>\n<p>Om wat te proberen had ik gelijk een paar verschillende temperatuur sensoren gekocht.\u00a0De sensoren kunnen vaak naast temperature (temperatuur) ook\u00a0humidity (luchtvochtigheid in RH) of Pressure (luchtdruk) meten.<\/p>\n<ul>\n<li><a href=\"http:\/\/akizukidenshi.com\/download\/ds\/aosong\/DHT11.pdf\" target=\"_blank\" rel=\"noopener\">DHT11<\/a>, Resolutie; 1\u00b0C , 1%RH, Communicatie; One-Wire*<\/li>\n<li><a href=\"http:\/\/www.adafruit.com\/datasheets\/DHT22.pdf\" target=\"_blank\" rel=\"noopener\">DTH22<\/a>,\u00a0Resolutie; 0.1\u00b0C , 0.1%RH,\u00a0Communicatie\u00a0One-Wire*<\/li>\n<li><a href=\"http:\/\/datasheets.maximintegrated.com\/en\/ds\/DS18B20.pdf\" target=\"_blank\" rel=\"noopener\">DS18B20<\/a>, Resolutie; 0.0625\u00b0C, Communicatie One-Wire**<\/li>\n<li><a href=\"https:\/\/www.adafruit.com\/datasheets\/1899_HTU21D.pdf\" target=\"_blank\" rel=\"noopener\">HTU21D<\/a>***, Resolutie;\u00a00.01\u00b0C , 0.1%RH,\u00a0Communicatie I\u00b2c<\/li>\n<li><a href=\"https:\/\/www.adafruit.com\/datasheets\/BST-BMP180-DS000-09.pdf\" target=\"_blank\" rel=\"noopener\">BMP180<\/a>, Resolutie;\u00a00.1\u00b0C , 0.01 hPa of 0.01 <a href=\"http:\/\/www.knmi.nl\/cms\/content\/35969\/millibar\" target=\"_blank\" rel=\"noopener\">mbar<\/a>,\u00a0Communicatie I\u00b2c<\/li>\n<\/ul>\n<p>* Maken gebruik van een eigen versie en kan dus niet zo als bij de originele one-wire in een lus worden aangesloten.<br \/>\n** Sensor is gekozen omdat hij in een lus aangesloten en deze waterdicht verkrijgbaar is.<br \/>\n*** lijkt compatibele met de\u00a0<a href=\"http:\/\/www.sensirion.com\/fileadmin\/user_upload\/customers\/sensirion\/Dokumente\/Humidity\/Sensirion_Humidity_SHT21_Datasheet_V4.pdf\" target=\"_blank\" rel=\"noopener\">SHT21<\/a>, inc. het\u00a0I\u00b2c adres.<\/p>\n<h1>Experimenteren<\/h1>\n<p>Temperatuur sensoren genoeg om mee te experimenteren. Liep gelijk al tegen een hobbel aan\u00a0de ESP8266 heeft 3.3V min 250 mA nodig (dat vond ik ook al veel) en\u00a0de DHT11 en DTH22 3.5 t\/m 5 V dus die vielen al af voor het eindontwerp. Ik had geen zin om ook nog een 5 V voeding te bouwen.<\/p>\n<p>Voor het schrijven van de microcontroller software is het lastig te debug-en zonder uart, de uart wordt namelijk gebruikt voor de ESP8266 module. Dus had ik een sw-uart bij gebouwd op basis van de application note van atmel, de <a href=\"http:\/\/www.atmel.com\/Images\/doc0941.pdf\" target=\"_blank\" rel=\"noopener\">AVR304<\/a>. Deze werkt redelijk en was zeer nuttig bij het schrijven van de library voor de ESP8266 module.<\/p>\n<p>Voor de server kant op de computer maak ik gebruik van Python (op ubuntu, linux), door middel van een simpel TCP socket kan ik de waardes om mijn computer opslaan. Over de socket wordt (zo als ik ander met uart ook doe) <a href=\"https:\/\/nl.wikipedia.org\/wiki\/Kommagescheiden_bestand\" target=\"_blank\" rel=\"noopener\">CSV<\/a>\u00a0of komma gescheiden waardes verstuurt. Simpel en zo min mogelijk overige informatie. Om deze data dan in een database op te slaan was simpel, door gebruik te maken van sqlite.<\/p>\n<pre class=\"height-set:true lang:python decode:true\" title=\"Code voor het wegschrijven van een CSV naar een sqlite database\">#!\/usr\/bin\/python\nimport socket\nimport datetime\nimport time\nimport sqlite3\nimport sys\n\nTCP_IP = \"0.0.0.0\"\nTCP_PORT = 8080\n\ntry:\n    #connectie sqlite database\n    database = sqlite3.connect('test.db', check_same_thread=False)\n    d = database.cursor()\n    #timezone correctie\n    offset = datetime.datetime.now() - datetime.datetime.utcnow()\n    #starten van tcp\/ip socket\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    sock.bind((TCP_IP, TCP_PORT))\n    sock.listen(1)\n    #wachten op een inkomende verbinding\n    conn, addr = sock.accept()\n    databaseName = \"db\" + str(datetime.datetime.now()).translate(None, \" -,!.:;\")\n    print 'Connection address:', addr, 'database', databaseName\n    d.execute(\"CREATE TABLE '%s'(ID INT PRIMARY KEY NOT NULL, var1 TEXT, var2 TEXT, var3 REAL, var4 REAL)\" % databaseName)\n    id = 0\n    conn.setblocking(False)\n    conn.settimeout(10)\n    \n    while True:\n        try:\n            data = \"\"\n            data = conn.recv(1024)\n            print str(datetime.datetime.now().time()), \"@\", addr, \":\", data.rstrip('\\r\\n')\n            #Controlleer of het een voledige zin is, door de commas te tellen.\n            if data.count(',') == 2:\n                id=id+1\n                #uncomment deze line voor meer debug info\n                #print \"\"\"INSERT INTO %s VALUES(%d,\"%s\",%s)\"\"\" % (databaseName, id, str(datetime.datetime.now()).translate(None, \" ,!.:;\"), data.rstrip('\\r\\n'))                \n                d.execute(\"\"\"INSERT INTO %s VALUES(%d,\"%s\",%s)\"\"\" % (databaseName, id, str(datetime.datetime.now()), data.rstrip('\\r\\n')))\n                \n        except socket.error, socket.timeout:\n            #als er een probleem is met de verbinding of timeout wacht op nieuwe connectie\n            print 'Connection close:', addr\n            if conn:\n                conn.close()\n            conn, addr = sock.accept()\n            print 'Connection address:', addr\n            conn.setblocking(False)\n            conn.settimeout(10)\n            \n        except sqlite3.OperationalError, sqlite3.IntegrityError:\n            #bij fouten in het schrijven in de database\n            print \"database ERROR\"\n            pass\nexcept (KeyboardInterrupt, SystemExit):\n    print 'except exit'\n    conn.close()\n    sock.close()\n    database.commit()\nfinally:\n    print 'closing socket'\n    conn.close()\n    sock.close()\n    database.commit()<\/pre>\n<p>Iedere keer dat dit python script op start maakt hij een data base aan. De velden die hij aan maakt zijn:<\/p>\n<ol>\n<li>ID, nummer dan de data<\/li>\n<li>Var1,\u00a0is de datum en tijd.<\/li>\n<li>Var2, Hex waarde van een andere status.<\/li>\n<li>Var3, Temperature in REAL<\/li>\n<li>Var4, Humidity in REAL<\/li>\n<\/ol>\n<p>Sqlite heeft niet veel <a href=\"https:\/\/www.sqlite.org\/datatype3.html\" target=\"_blank\" rel=\"noopener\">datatypes<\/a>, ik was daarom genoodzaakt om text voor hex en REAL voor een FLOAT\u00a0of DOUBLE te gebruiken. In het Filmpje hieronder is te zien de microcontroller de data verzend. De zwarte terminal is aangesloten op de TX van de ESP8266. De paarse (ubuntu) terminal is het draaien van het python script.<\/p>\n<p>https:\/\/youtu.be\/bhTNZVhVB0g<\/p>\n<p>Dat werk en was niet zo moeilijk, alleen als je uit dezelfde database wil lezen als je aan het schrijven ben werkt niet makkelijk met Sqlite. Daarom heb ik het aangepast aan MySQL, zodat de database bijvoorbeeld uitgelezen kan worden met PHP. Ik heb het script nu aangepast dat als er meerdere zinnen in \u00e9\u00e9n keer binnen komen (kan gebeuren als het wegschrijven langer duurt dan verwacht) er per zin wordt weggeschreven. Per keer dat er een zin wordt geschreven print hij een &#8220;.&#8221;. Ook heb ik hem geschikt gemaakt om met dezelfde database verder te gaan en meerdere waardes (dit geval te Pressure en tweede temperatuur)<\/p>\n<pre class=\"lang:c decode:true\" title=\"Mijn regel voor het versturen van de data\">\t\tsprintf_P(buffer, PSTR(\"%02x,%3d.%02d,%3d.%02d,%3d.%01d,%4d.%02d\\r\\n\"), temp, Temperature_H, Temperature_L, Humidity_H, Humidity_L, Temperature_bmp180_H, Temperature_bmp180_L, Pressure_H, Pressure_L);\n\t\tESP8266_send_data(1, buffer, false);<\/pre>\n<pre class=\"height-set:true lang:default decode:true\" title=\"Code voor het wegschrijven van een CSV naar een Mysql database\">#!\/usr\/bin\/python\nimport threading\nimport socket\nimport datetime\nimport time\nimport MySQLdb\nimport sys\n\nTCP_IP = \"0.0.0.0\"\nTCP_PORT = 8080\n\ndatabase = MySQLdb.connect('localhost', 'username', 'passdatiknietgavertellen', 'testdb')\nd = database.cursor()\ntry:    \n    #Deze weg halen voor het maken van een andere database    \n    #databaseName = \"db\" + str(datetime.datetime.now()).translate(None, \" -,!.:;\")\n    #deze latenstaan voor de zelfde database\n    databaseName = \"Weather\"\n    \n    offset = datetime.datetime.now() - datetime.datetime.utcnow()\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    sock.bind((TCP_IP, TCP_PORT))\n    \n    sock.listen(1)\n    \n    conn, addr = sock.accept()\n    print 'Connection address:', addr, 'database', databaseName\n    #Voor het maken van een database\n    d.execute(\"CREATE TABLE %s (ID INT PRIMARY KEY AUTO_INCREMENT, var1 TEXT, var2 TEXT, var3 FLOAT, var4 FLOAT, var5 FLOAT, var6 FLOAT)\" % databaseName)\n    id = 0\n    conn.setblocking(False)\n    conn.settimeout(10)\n    while True:\n        try:\n            data = \"\"\n            data = conn.recv(1024)\n            print str(datetime.datetime.now().time()), \"@\", addr, \":\", data.rstrip('\\r\\n')\n            for datasplit in data.splitlines():\n                #het aantal commas aanpassan als het nodig is, dit is mijn check op geldige data\n                if datasplit.count(',') == 4:\n                    #een punt voor iedere zin dat hij wegschrijft,\n                    print \".\",\n                    #nieuwe waardes in een tabel, de tijd wordt de lokaale tijd beruikt om dat er geen rtc op mijn uc draait\n                    d.execute(\"\"\"INSERT INTO %s(var1,var2,var3,var4,var5,var6) VALUES(\"%s\",%s)\"\"\" % (databaseName, str(datetime.datetime.now()), datasplit.rstrip('\\r\\n')))\n                    database.commit()\n        except socket.error, socket.timeout:\n            print 'Connection close:', addr\n            if conn:\n                conn.close()\n            conn, addr = sock.accept()\n            print 'Connection address:', addr\n            conn.setblocking(False)\n            conn.settimeout(10)\n        except  (MySQLdb.ProgrammingError, MySQLdb.OperationalError, MySQLdb.IntegrityError):\n            print \"database ERROR\"\n            pass\nexcept (KeyboardInterrupt, SystemExit):\n    print 'except exit'\n    conn.close()\n    sock.close()\n    database.commit()\nfinally:\n    print 'closing socket'\n    conn.close()\n    sock.close()\n    database.commit()\n<\/pre>\n<p>Met dank aan <a href=\"http:\/\/www.highcharts.com\/stock\/demo\/dynamic-update\" target=\"_blank\" rel=\"noopener\">highcharts<\/a>\u00a0demo\u00a0kan ik eenvoudig een grafiek tekenen dat live is. Een php pagina leest de data uit de database. De webpagina wheater.html haalt highcharts de data en zorgt dat hij dat blijft doen.<\/p>\n<p><a href=\"https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/Schermafdruk-van-2015-05-25-175651.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-large wp-image-197 aligncenter\" src=\"https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/Schermafdruk-van-2015-05-25-175651-1024x785.png\" alt=\"Schermafdruk van 2015-05-25 17:56:51\" width=\"640\" height=\"491\" srcset=\"https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/Schermafdruk-van-2015-05-25-175651-1024x785.png 1024w, https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/Schermafdruk-van-2015-05-25-175651-300x230.png 300w, https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/Schermafdruk-van-2015-05-25-175651-768x589.png 768w, https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/Schermafdruk-van-2015-05-25-175651.png 1220w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p><strong>Toen had ik data<\/strong>,\u00a0668266 data punten over de temperatuur van mijn kamer, dat niet meer dan 2\u00a0\u00b0C verschilt. Zucht&#8230;. Nu nog een print maken dat moet gaan zorgen voor zinnige data. Zoals constant de temperatuur buiten gaat meten.<\/p>\n<p><a href=\"https:\/\/catmita.duckdns.org\/wp-content\/uploads\/2015\/08\/websitefiles.zip\">Hier<\/a> zijn de files voor de webpagina.\u00a0Het is wel belangrijk om de juiste python 2.7 modules te installeren en mysql en apache te draaien, voor het draaien van het mysql script moet de &#8220;testdb&#8221; zijn aangemaakt. De ESP8266\u00a0library komt nog op github.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In de verschillende projecten heb ik gemerkt dat het belangrijk is om te meten en te monitoren. Als hij dan stuk gaat of iets onverwachts optreed kan je je met data achter halen wat er verkeerd is gegaan en daar &hellip; <a href=\"https:\/\/catmita.duckdns.org\/?p=170\">Lees verder <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[2,3,4,6,8],"class_list":["post-170","post","type-post","status-publish","format-standard","hentry","category-geen-categorie","tag-atmega","tag-esp8266","tag-highcharts","tag-live-data-loggen","tag-mysql"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=\/wp\/v2\/posts\/170","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=170"}],"version-history":[{"count":0,"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=\/wp\/v2\/posts\/170\/revisions"}],"wp:attachment":[{"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=170"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=170"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/catmita.duckdns.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=170"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}