Teploměry na DomaWEBu
Pavel
6:27:31
10.12.2017
Někdy na jaře 2017 jsem došel k poznání že nutně potřebuji znát teploty doma a venku. Venkovní teploměr na okně to po čtyřech letech vzdal a přestal ukazovat, meteostanice občas chytá signál z cizího čidla a nemá podsvícený displej. Spousta důvodů proč si začít hrát s Arduinem a něco se naučit :)
Prvotní myšlenka byla že opráším Arduino UNO, připojím čidla, připojím nějaký displej a celé to umístím někde u dveří. Proběhlo pár pokusů s čidly a napadlo mě že když už mám zaplacený hosting a doménu DomaWEB.cz tak proč ty data neposílat sem a nějak hezky si je neprezentovat. A to kdekoliv na světě. Jenže Arduino UNO a jeho Ethernet shield jsou poněkud dražší. Po krátkém hledání jsem narazil na modul ESP8266 osazený na vývojové desce Wemos D1mini, spousta paměti, WiFi, ve světě Arduina úžasný výkon, programuje se to stejně jako Arduino a cena je velmi slušná.
Už jsem věděl že na Arduino-teploměr jsou ideální čidla DS18B20, komunikují po sběrnici OneWire kde v případě parazitního napájení stačí dva dráty, já raději plnohodnotné zapojení se třemi dráty, mají dosti slušnou přesnost, jsou kalibrovaná a stojí pár korun. Tím že je použita sběrnice OneWire tak je možné zapojit až 128 čidel na jedno vedení, tedy téměř libovolně rozšiřovat svojí teploměrovou síť.
Po mnoha nezdarech daných neznalostí protokolu HTTP (ne že teď bych ho opravdu znal, ale co vím to mi stačí), tápání v odesílaných datech, spoustě chyb v programu, po kýblu kafe a mnoha cigaretách jsem dosáhl toho že Wemos si povídal s naší WiFinou, posílal data na server a já měl na mobilu stránku se třemi teplotami v domě a kolem. Zajímala mě teplota na severní straně domu kde teoreticky má být nejchladněji (v létě na čidlo chvíli ráno svítí sluníčko, to vyřeší radiační kryt), na dvoře který je uzavřený a mírně pod okolním terénem - takže jsem předpokládal že tam bude tepleji než jinde, a samozřejmě doma. A nejlépe ve všech místnostech. Metodika měření teplot je poměrně složitá, ale já nestavím meteorologickou stanici, jen mě zajímají teploty, proto si to měřím tak trochu po svém - nepřesně.
Vypisování teplot v prohlížeči je sice fajn, ale pořád to není ono, já chtěl víc. Takže když už jsem nějaká data měl, tak jsem je začal ukládat do databáze. Po pár dnech mi došlo že těch dat je strašně moc, limit velikosti databází na webhostingu Wedos je 5GB, já byl schopen je do roka zaplnit protože teploty ukládám každou minutu. Začalo trápení s průměrováním, vezmu data za posledních 15 minut, smažu je z databáze a vytvořím jen jeden záznam z průměru hodnot. Hezký nápad. Při prvotním nadšení jsem si data ukládal tak špatným způsobem že tohle průměrování byl prostě průšvih. Další kýbl kafe... V současné době to celé funguje tak že Wemos každou minutu projde sběrnici OneWire, každé čidlo požádá o teplotu, sekundu počká na změření a na server odešle adresu čidla s naměřenou teplotou. Do databáze se zapíše každé čidlo a k němu teplota. Je potom sranda vzít všechny teploty z jednoho čidla a udělat graf, rozdělit která čidla budu prezentovat veřejně a která jen pro sebe nebo pro jejich majitele. DomaWEB je totiž připravený zpracovávat i měření teplot odjinud. Grafy si vytvářím pomocí SVG až v prohlížeči, chtěl jsem co nejmenší objem přenášených dat kvůli mobilu.
V současné době se projekt Teploměry a Doby navzájem hlídají, pokud některý z Wemosů přestane komunikovat tak ten druhý to na něj "práskne" a DomaWEB pošle e-mail že je něco špatně. Pokud umře připojení k internetu nebo "dojde elektrika" tak do hodiny žaluje samotný DomaWEB s pomocí CRONu. Prostě to musí běžet pořád :)
Tenhle projekt se postupně s přestávkami vyvíjel víc než rok. Teď jej považuji za připravený, stačí vytvořit krabičku, umístit někam kde to nebude rušit, zasekat kabely od čidel do zdi, celé to nějak zabudovat do domu. To je ta horší část. Do teď to bylo jen hraní.
A tady je sketch ke studiu (je to upravené aby nebylo možné zapisovat do mojí databáze)
#include <onewire.h>
#include <esp8266wifi.h>
const char* ssid = "jmenowifi";
const char* password = "heslo_k_wifi";
const char* server = "adresa_kam_posilat";
unsigned long tim=millis();
WiFiClient client;
OneWire ds(D4);
void setup() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
}
tim=millis()+2000;
}
void loop() {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
String gdata = "";
if (tim>millis()) return;
tim=millis()+60000;
ds.reset_search();
while ( ds.search(addr)) {
gdata="GET /script.php?***="; //adresa cidla
for( i = 0; i < 8; i++) {
gdata+=String(addr[i], HEX);
gdata+="_";
}
switch (addr[0]) {
case 0x10: type_s = 1; break;
case 0x28: type_s = 0; break;
case 0x22: type_s = 0; break;
default: return;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 0); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
gdata+="&***="; //hodnota teploty
gdata+=String(celsius);
gdata+=" HTTP/1.1\r\nHost: www.domaweb.cz\r\nConnection: close\r\n\r\n";//mezera před HTTP je nutná
gdata+=" ";
if (celsius>-30 && celsius <50) { // odesílám jen rozumné hodnoty, pokud čidlo má nějaký problém pošle hodnotu -127 nebo 85
if (client.connect(server,80)) {
client.print(gdata);
} else {
tim=millis()+2000;
}
}
}
}
Netajím se tím že značná část kódu je převzatá. Neřeším nastavení přesnosti čidel, předem je mám nastavená na Arduino UNO. Zásadní je na tom ten princip a to že tenhle kód chápu. Velmi dlouho jsem řešil nestabilitu, nakonec se ukázalo že nestabilní není kód, ale "Wemos" nebo spíš nepříliš vydařený klon Wemosu (další dva kousky se chovají dle očekávání, ten první zmetek se prostě zaseknul a přestal makat)
Vlastne celou dobu co merim teploty, tak mam problem s prenosem dat.
EDIT Cervenec 2018
Ta nestabilita byla dana castecne i kodem, konecne reseni pro spolehlivou komunikaci jsem pouzil v projektu Dobby ktery v brzke dobe prevezme i celou ulohu Teplomeru. V soucasne dobe bezi Teplomery prave na tom klonu a za posledni mesic mame jen jeden vypadek prestoze v kodu vubec neresim ztratu spojeni. Dobby ma vyresenou ztratu signalu WiFi, ztratu spojeni na server, a timeout pro odesilani dat.
EDIT Listopad 2018
Se učit se učit se učit. Bez znalostí to nejde, proto to nešlo mě. Teď už to běží parádně. Projekt Teploměry končí a celou úlohu přebírá Dobby který se i tak nudí. Měření teplot je jen taková brnkačka když zrovna nemá do čeho dloubnout.
EDIT Červenec 2019
Měření teplot a dalších meteorologických dat bude nadále probíhat samostatně. Momentálně se tomu věnují dva Wemosy a trochu příspívá i Dobby. Ukázkový kód běží na první verzi Teploměrů. Druhý Wemos používá jinou sběrnici, je připravený na zálohu akumulátorem, má spuštěnou vlastní WiFi jak Captive portál (nabídne naměřená data komukoliv kdo se připojí na jeho vlastní WiFi bez přístupu do naší sítě) a hlavně je to celé schované ve vytištěném radiačním krytu (testuji, takže zatím na stole).
EDIT srpen 2023
Měříme, stále měříme. Ve třech místnostech, teplotu a vlhkost. Vytvořil a vytiskl jsem si k tomu krabičky kde je umístěný samotný Wemos D1 mini + zdroj + čidlo SHT40. Čidlo SHT40 komunikuje po sběrnici I2C, je přesnější a umí měřit i vlhkost. Vytištěné krabičky mají dva oddělené prostory tak aby čidlo nebylo pod vlivem tepla ze zdroje a Wemosu, velikost krabičky je 80x80mm, tedy běžná elektrikářská krabička na omítku a čouhá z toho jen kabel se zástrčkou do 230V. Kromě naměřených dat se na server posílají i data o IP adrese, data o restartu, a jednoznačné označení automatu. Tahle data jsou součástí jednotného protokolu zpráv u všech našich automatů, jsou nutná pro snadnou identifikaci automatu v síti a možnost přístupu na jejich vlastní web server (funkční pouze v domácí síti) a v neposlední řadě i pro možnost vzdálené aktualizace. Ty aktualizace fungují tak že majitel automatu ani nemusí vědět že jsem něco vylepšil, ale jeho automat to ví a sám si stáhne nový FW.