V této části se podíváme na samotnou realizaci meteostanice s čidly, která naměřená data odesílá na server, který data ukládá.
Kromě Arduina Mega nebo alespoň Una (i s Nano to půjde) budeme potřebovat nějaké čidla. Lze samozřejmě nějaké přidat nebo naopak ubrat.
Dále budeme potřebovat trochu programování s Arduinem, PHP, nějaký webový prostor a trochu zapojování.
Tato meteostanice by neměla vyjít dráž, než 2500 Kč, podle toho kde se díly pořídí. Nakupování v Číně cenu také sníží.
Při pořízení levnější sériově vyráběné meteostsnice bez možnosti logovat data na internet se dostaneme s cenou někde mezi 1000 až 2000 Kč. Ovšem pokud si dokážeme pohrát s daty a ukládat je k pozdějšímu zpracování, nic nám nebude bránit využívat grafy apod. V tomto příkladu se ale musíme spokojit pouze se zobrazováním aktuálních hodnot na webu.
seznam použitých modulů a čidel | |
Síťový modul pro mikrokontroléry Typ ENC28J60 (HR911105A)
10 Mb Ethernet
RJ45 port
Podpora TCP/IP protokolu s IPv4
Protokoly UDP, TCP, DHCP, ICMP, FTP a HTTP
SPI interface
Oscilátor 25 MHz
Odběr 180 mA (průměr)
napájení 3,3V (toleruje 5V)
rozměry 58 x 34 x 17 mm
Čidlo tlaku BME280
komunikace I2C (až 3.4MHz)
Teplota: -40 až +85 °C
Rel. vlhkost: 0 až 100%
Tlak: 300 až 1100 hPa
Přesnost: teplota ± 1°C, vlhkost ± 3% a tlak ±1Pa
Čidlo intenzity osvětlení BH1750
komunikace: I2C
rozsah: 0 až 54 612 lx
přesnost: 1 až 4 lx
Napětní: 3,3V až 5V
odběr: 0,2 mA
Čidlo teploty a relativní vlhkosti DHT22
Rozsah měření vlhkosti: 0 % ~ 100 % RH
Rozsah měření teploty: -40 až +80 °C
Přesnost měření vlhkosti: ± 2.0 % RH
Přesnost měření teploty: ± 0.5 °C
Senzor: AM2302
Při teplotách pod 5°C sice měří přesně teplotu, ale vlhkost neměří vůbec, signalizuje pouze 99,9%.
Čidlo teploty a relativní vlhkosti HTU21D
Rozsah měření vlhkosti: 0 % ~ 100 % RH
Rozsah měření teploty: -40 až +125 °C
Přesnost měření vlhkosti: ± 1.0 % RH
Přesnost měření teploty: ± 0.3 °C
miskový anemometr k meteostanici WH1080
výstup: Dvoudrátový, při jedné otáčce dá impuls; když je doba mezi impulsy 1s, tak je rychlost větru 2,4 km/h.
senzor směru větru k meteostanici WH1080
výstup: Dvoudrátový, směr je rozdělen na 16 částí, které jsou rozeznávány rozdílnými odpory.
úhel 0° - 33kΩ
úhel 22,5° - 6568Ω
úhel 45° - 8200Ω
úhel 67,5° - 891Ω
úhel 90° - 1kΩ
úhel 112,5° - 668Ω
úhel 135° - 2200Ω
úhel 157,5° - 1407Ω
úhel 180° - 3900Ω
úhel 202,5° - 3136Ω
úhel 225° - 16kΩ
úhel 247,5° - 14118Ω
úhel 270° - 120kΩ
úhel 292,5° - 42120Ω
úhel 315° - 64900Ω
úhel 337,5° - 21876Ω
člunkový srážkoměr k meteostanici WH1080
výstup: Dvoudrátový, při překlopení člunku vyšle impuls, 1 impuls odpovídá 0,28 mm srážkám.
Schéma zapojení je pro Arduino Mega, ale lze ho použit i pro Arduino Uno, jen je potřeba zapojit piny od ethernetu
ENC28J60 na jiné piny (SCK - 13, SO - 12, SI - 11, CS - 10) a samozřejmě využít jiné piny k napájení čidel.
Podobné by to bylo při použití jiných desek Arduino.
Po zapojení všech modulů a čidel je potřeba jenom vyřešit napájení (např. pomocí kabelu přes USB) a propojit
ethernetový kabel s modemem, routerem nebo switchem aby bylo zařízení propojeno s internetem.
Univerzální program pro anemometr, směr větru, srážkoměr, teplotu, relativní vhkost a atmosférický tlak. Dále potom obsahuje výpočet
relativního tlaku, rosného bodu a pocitové teploty. Všechny data umí odeslat na server, který je například pomocí php dále zpracuje.
V programu je třeba změnit nadmořskou výšku, webovou adresu, IP adresu a Mac adresu zařízení.
// ARDUINO PRO METEO ČIDLA A POSÍLÁNÍ DAT PŘES ETHERNET
// 2018 Fix
#include "UIPEthernet.h" // kvůli enhernetovému modulu ENC28J60
#include "SPI.h" // kominukace
#include "Wire.h" // komunikace
#include "Adafruit_Sensor.h" // čidla
#include "BH1750.h" // intenzita světla
#include "Adafruit_BME280.h" // čidlo barometrického tlaku a teploty - SDA a SCL - čidlo BME280
// jedno z těchto čidel musí být použito (řádek s nepoužitým čidlem smažte !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
#include "DHT.h" // čidlo teploty/vlhkosti DHT22 - pokud je použito
#include "SparkFunHTU21D.h"// čidlo teploty/vlhkosti HTU21D - pokud je použito
// piny pro vstupy
int smervetru=A0; // pin pro směr větru
int pincidlo=4; // pin pro čidlo teploty a vlhkosti
int res=9; // pin pro resetování arduina (pin je propojen s pinem RST přes 1000 ohmový rezistor)
int power=8; // pin pro napájení čidel
// jedno z těchto čidel musí být použito (řádek s nepoužitým čidlem smažte !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
DHT cidlo(pincidlo, DHT22); // čidlo DHT22 - pokud je použito
HTU21D cidlo
#define BME280_ADRESA (0x76) // inicializace senzoru BME z knihovny
Adafruit_BME280 bme; // čidlo tlaku, teploty a rel. vhkosti
BH1750 lightMeter(0x23); // čidlo intenzity osvětlení (adresa) - neměnit
byte mac[] = { 0xD6, 0xA5, 0xB4, 0x73, 0xF2, 0xF1 }; // Mac adresa zařízení
EthernetClient client;
int TimeOut=5000; // maximální čas internetového spojení se serverem
int resettimes=0; // hlídání kolikrát se nepřipijí k internetu, po překročení nastavené hranice resetujeme
int power_rst=0; // když resetujeme přes napájení čidla, musíme ošetřit anemometr a srážkoměr, aby reset nebrali jako vítr / déšť
// ČIDLA METEOSTANICE
// Pro směr větru je použito čidlo k meteostanici WH1080, které pomocí různých hodnot el. odporu dokáže rozlišit 8 směrů větru.
// Pro rychlost větru je použit senzor k meteostanici WH1080 (přesné označení: Wind Speed Sensor WS 120) - miskový anemometr.
// Srážky jsou měřeny pomocí člunkového srážkoměru dodávaného k meteostanici WH1080.
// Teplotu a rel. vlhkost měříme čidlem DHT22.
int nadmorska_vyska=192; // DŮLEŽITÉ !!! - HODNOTA NADMOŘSKÉ VÝŠKY METEROSTANICE - PRO VÝPOČET RELATIVNÍHO TLAKU !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
volatile float cas0=0; // cas0 anamometru
volatile float cas; // čas mezi jednotlivými impulsy anamometru
volatile float cas2; // rychlost větru v km/h
int smer; // udaj o směru větru ze šipky
String smer2="J"; String smer3; // odkud vítr fouká
volatile int rainimp=0; // celkový počet pulsů
volatile float minrain=0; // počet pulsů za minutu
volatile float minwind=0; // průměrná rychlost za minutu
volatile float minwind2=0; // průměrná rychlost za 10 minut
volatile float tenwind=0; // odesílaná hodnota - prů. rychlost za 10 minut
volatile float maxwind=0; // maximální rychlost větru
volatile int windtimes=0; // kolikrát je měřen průměr rychlosti větru - 10x pode ČMHI
float wind=0; // sčítání rychlostí pro výpočet průměru
float temp=0; // teplota z čidla
float hum=0; // rel. vlhost z čidla
float dewpoint=0; // rosný bod
float tlak=0; // absolutní tlak
float tlak_jm = 0;
float nadvys400=0;
float tlak_ct=0;
float tlak_ct2=0;
float rel_tlak=0; // relativní tlak - tj. tlak přepočítaný na hladinu moře
volatile int wind_time=0; // kolikrát byla změřena rychlost za minutu
long rainimp2=60000; // 1 minuta = 60000 čas za který se vždy pošlou data na web
long rain_last=0; // poslední měřený čas u deště
volatile bool rrr=false;
void setup()
{
Serial.begin(9600); // spuštění seriové komunikace
Serial.println("Start ..."); delay(100);
// METEOČIDLA
pinMode(2,INPUT); // přerušování z anemometru (vstup přes 10kohmový odpor na 5V jako PULL UP rezistor)
pinMode(3,INPUT); // přerušování ze srážkoměru (vstup přes 10kohmový odpor na 5V jako PULL UP rezistor)
pinMode(power,OUTPUT); // napíjení čidel meteostanice
pinMode(A0,INPUT); // analogový vstup ze šipky směru větru (vstup přes odporový dělič 10kohmový odpor na 10V)
cidlo.begin(); // teplota/vlhkost - začátek funkce čidla
lightMeter.begin(BH1750_CONTINUOUS_HIGH_RES_MODE); // inicializace venkovní intenzity osvětlení v luxech
bme.begin(BME280_ADRESA); // inicializace tlak. čidla
// ETHERNET
Ethernet.begin(mac); // inicializuje toto síťové zařízení s adresou MAC
Serial.println("Pripojuji ...");
digitalWrite(power,LOW); delay(500); digitalWrite(power,HIGH); power_rst=1; // napájení čidel meteostanice
}
void loop() {
// METEOČIDLA
attachInterrupt(digitalPinToInterrupt(2), anemometr, RISING); // detekce přerušení - rychlost větru
attachInterrupt(digitalPinToInterrupt(3), rain, RISING); // detekce přerušení - srážky - STOUPÁNÍ IMPULSU
smer=analogRead(smervetru); // směr větru
// rozklíčování úhlu směru ze kterého vítr fouká podle analogového vstupu
smer2="";
if (smer<806 && smer>665) {smer2="sever"; smer3="S";}
if (smer<911 && smer>805) {smer2="severozapad"; smer3="SZ";}
if (smer<990 && smer>910) {smer2="zapad"; smer3="Z";}
if (smer<666 && smer>550) {smer2="jihozapad"; smer3="JZ";}
if (smer<350 && smer>200) {smer2="jih"; smer3="J";}
if (smer<201 && smer>104) {smer2="jihovychod"; smer3="JV";}
if (smer<105 && smer>50) {smer2="vychod"; smer3="V";}
if (smer<550 && smer>350) {smer2="severovychod"; smer3="SV";}
// povolení pro načítání impulsů od dešťového senzoru
if (digitalRead(3)==HIGH) {rrr=false;} // když není puls od srážkoměru
if (millis()<5000) {rainimp=0; minrain=0; wind_time=0; minwind=0; maxwind=0; cas2=0;} // 5 sekund od startu ignorujeme srážky!
// když je čas menší jak minuta, tak vezmeme průměrnou hodnotu za 10 minut pouze z první minuty, abychom neodeslali nulu! - MŮŽE SE ZRUŠIT
if (millis()<60002) {minwind2=minwind; tenwind=minwind;}
if (rainimp2 < millis() ) // když je čas větší než aktuální, JEDNOU ZA MINUTU DÁME DOHROMADY DATA, KTERÁ ODEŠLEME
{
temp=cidlo.readTemperature(); // načtení teploty z čidla
hum=cidlo.readHumidity(); // načtení relatvní vlhkosti z čidla
// výpočet rosného bodu z hodnot venkovního čidla
if (isnan(temp) || isnan(hum)) {;} else {
dewpoint = log(hum/100) + (17.62 * temp) / (243.12 + temp);
dewpoint = 243.12 * dewpoint / (17.62 - dewpoint);
}
// měření atmosférického tlaku
tlak = (bme.readPressure()/100.00);
tlak_jm = tlak * 9.80655 * nadmorska_vyska;
nadvys400 = nadmorska_vyska/400;
tlak_ct2 = 273 + temp + nadvys400; // počítat s venkovní teplotou, pokud je barometr venku, lze použít teplota z něj
tlak_ct = 287 * tlak_ct2;
rel_tlak = tlak_jm / tlak_ct + tlak;
// načtení dat z čidla pro měření intenzity osvětlení
uint16_t lux = lightMeter.readLightLevel();
if (lux<5) {lux=5;} // když bude osv. menší než 5lx, zaokrouhlíme ho dolů na nulu, kvůli přesnosti čidla, aby v noci neukazoval např. 3 lx
rainimp2=60000+millis(); // ke kontrolnímu času přičteme 1 minutu
minrain=rainimp*0.28; // počet pulsů za minutu ze srážkoměru vynásobený tak, aby odpovídal srážkám v mm (přesný koeficient je 0,2795 mm na jeden pulz ze srážkoměru)
minwind=wind/wind_time; // průměrná rychlost za minutu
windtimes++; // přičteme, že máme další průměr rychlosti
if (isnan(minwind)) {minwind=0;} // když průměr za minutu není, uvažujeme 0 km/h
minwind2=minwind2+minwind; // Přičteme průměr abychom ...
if (windtimes==10) {tenwind=minwind2/10; minwind2=0; minwind=0; windtimes=0;} // ... ho po deseti minutách mohli vydělit a získat tak průměrnou rychlost větru za 10 minut!
// výpis naměřených hodnot
Serial.print("teplota: "); Serial.print(temp); Serial.println(" st.C");
Serial.print("rel. vlhkost: "); Serial.print(hum); Serial.println("%");
Serial.print("rosny bod: "); Serial.print(dewpoint); Serial.println(" st.C");
Serial.print("pocitova teplota: ");Serial.print(cidlo.computeHeatIndex(temp, hum, false)); Serial.println(" st.C");
Serial.print("absolutni tlak: "); Serial.print(tlak); Serial.println(" hPa");
Serial.print("roelativni tlak: "); Serial.print(rel_tlak); Serial.println(" hPa");
Serial.print("rychlost vetru (min. prumer): "); Serial.print(minwind); Serial.println(" km/h");
Serial.print("rychlost vetru (10min. prumer): "); Serial.print(tenwind); Serial.println(" km/h");
Serial.print("smer vetru: "); Serial.println(smer2);
Serial.print("dest: "); Serial.print(minrain); Serial.println(" mm");
Serial.print("intenzita svetla: "); Serial.print(lux); Serial.println(" lx");
// ETHERNET
// IP adresa a číslo portu na kterou se odšlou data, IP adresa musí odpovídat webové adrese! - DŮLEŽITÉ ZMĚNIT NA TVOU ADRESU !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (client.connect("90.100.100.30", 80))
{
Serial.println("connected to web");
client.print("GET http://mujweb.cz/zapis_dat.php?autorizace=1234"); // webová adresa na kterou se odešlou data - DŮLEŽITÉ !!! ZMĚNIT NA TVŮJ WEB !!!!!!!!!!!!!!!!!!!!!!!!!!
client.print("&dest="); client.print(minrain); minrain=0; // srážkoměr
client.print("&vitr="); client.print(tenwind); if (windtimes==10) {minwind2=0; windtimes=0; tenwind=0;} // rychlost větru
client.print("&smer="); client.print(smer3); // směr větru
client.print("&tep="); client.print(temp); // teplota
client.print("&vlh="); client.print(hum); // rel. vlhkost
client.print("&rosbod="); client.print(dewpoint); // osný bod
client.print("&tlak="); client.print(tlak); // absolutní tlak
client.print("&rel_tlak="); client.print(rel_tlak); // rel. tlak
client.print("&osv="); client.print(lux); // intenzita osvětlení
client.print("&cas="); client.print(millis()); // čas běhu Arduina
rainimp=0; // vynulujeme pořet pulsů ze srážkoměru
wind_time=0; wind=0; cas2=0; maxwind=0;// kolikrát byla změřena rychlost za minutu - vynulování
client.println(" HTTP/1.1"); // odešleme data protokolem HTTP
client.println("Host: 90.100.100.30"); // odešleme data na IP adresu - DŮLEŽITÉ ZMĚNIT NA TVOU ADRESU !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
client.println("Connection: close"); // uzavřeme internetovou komunikaci
client.println();
delay(50);
// čeká v limitu na odezvu
int timeout = TimeOut;
while ((!client.available()) && (timeout > 0))
{
delay(1);
timeout = timeout - 1;
}
if (timeout > 0)
{
Serial.print("Odezva serveru v case: ");
Serial.print(TimeOut - timeout);
Serial.println(" ms");
Serial.print("cas behu arduina: ");
Serial.print(millis()/1000);
Serial.print(" s");
resettimes=0; // server odpověděl, vynulujeme tuto proměnou, která je to pro případný reset
}
else
{
resettimes++; // přičteme 1 za nespojení s internetem
Serial.println("Server neodpovida ...");
}
/// příkazy ze serveru
boolean nalez = false; // připraví proměnou pro případ když nalezneme naše řídící znaky
char data;
while (client.available()) // dokud je stánka dostupná...
{
char c = client.read(); //... do proměné 'c' zapiš bajt odeslaný ze serveru - musí být 'char'
// když objevíš náš počátečný kontrolní znak tak nález bude true - pravda když konečný tak false
if (c == 'Q') {nalez = true;} // znak Q označuje začátek posílaného příkazu
if (c == 'X') {nalez = false;} // znak X označuje konec posílaného příkazu
if (nalez && c!='Q')
{data = c;} // když je nález tak ukládej znaky do proměné data protože by se nám ukládal i první řídící znak tak, jen ukládej když je znak rozdílný od 'Q'
}
Serial.println(); Serial.print("příkaz: "); // vyčtení příkazu z internetu, musí být vždy jednopísmenkový (A-Z bez Q a X, a-z, 0-9)
Serial.println(data); if (data=='z') {Serial.println("RESET"); digitalWrite(res,LOW); delay(2000);} // reset arduina (když na požadované web stránce bude formulace QzX)
}
// když nám vypadne čidlo teploty/vlhkosti, resetujeme napájení pro meteo čidla
if (isnan(temp) || isnan(hum)) {power_rst=0; delay(100); digitalWrite(power,LOW); delay(5000); digitalWrite(power,HIGH); delay(100); power_rst=1;}
}
if (resettimes>3) {digitalWrite(res,LOW);} // celkový reset Arduina Mega, protože se Arduino více než 3x po sobě nepřihlásilo k internetu
}
void anemometr() // stoupání impulsu od anemometru
{
if (millis()>cas0 && millis()>5000 && power_rst==1) // pokud je čas mezi impulsy
{
cas=millis()-cas0; // změříme časový rozdíl mezi jednotlivými impulsy z anemometru
cas0=millis(); // zadáme základní čas (nový pro další impuls)
cas2=2400/cas; // čas přepočítáme na km/h
// výpočet průměrné rychlosti větru
wind_time++; // kolikrát byla změřena rychlost za minutu
if (cas2<500) {
wind+=cas2; // průměrná rychlost za minutu, ke které přičteme tu aktuální
if (cas2>maxwind) {maxwind=cas2;} // detekce nejvyšší hodnoty - nárazový vítr
}
}
}
void rain() // stoupání impulsu od srážkoměru
{
if (rrr==false && millis()>5000 && power_rst==1 && digitalRead(3)==LOW)
{
rrr=true; rainimp++;
}
}
program v PHP - soubor 'zapis_dat.php' | |
Na serveru je potřeba vytvořit soubor, který bude přejímat aktuální data z meteostanice a ukládat je na server.
Na serveru musí být pochopitelně povoleno ukládání souborů a také musí být povoleno používání PHP.
Soubor může vypadat následovně:
<HTML>
<BODY>
<?php
// čtení dat -------------------------------------------------------
if ($_GET['autorizace']==1234) // identifikace, že se připojilo správné zařízení
{
// načtení dat z arduina pomocí metody GET -----------------------------------------------------------
$dest=html_entity_decode($_GET['dest']); // příjem dat ze srážkoměru
$vitr=html_entity_decode($_GET['vitr']); // příjem dat z anemometru - rychlost větru
$smer=html_entity_decode($_GET['smer']); // příjem dat - svěr foukání větru
$tep=html_entity_decode($_GET['tep']); // příjem dat z teploměru
$vlh=html_entity_decode($_GET['vlh']); // příjem dat relativní vlhkosti
$rosbod=html_entity_decode($_GET['rosbod']); // příjem dat rosného bodu
$tlak=html_entity_decode($_GET['tlak']); // příjem dat ze senzoru tlaku
$rel_tlak=html_entity_decode($_GET['rel_tlak']); // příjem dat o relativním tlaku
$osv=html_entity_decode($_GET['osv']); // příjem dat ze senzoru osvětlení
$cas=html_entity_decode($_GET['cas']); // čas běhu arduina v milisekundách
// načítání hodnot ze souborů ------------------------------------------------------------
// funkce načítání souboru
function nahrat($jm_souboru)
{
if (file_exists("data/".$jm_souboru.".txt")) { // ověříme zda soubor existuje
$soubor = fopen("data/".$jm_souboru.".txt", "r"); // otevřeme soubor pro čtení
$data = fread($soubor, 15); fclose($soubor); } // vyčteme data a soubor zavřeme
else
{$data="";} // když soubor neexistuje
// když bude nový den, nebudeme počítat předešlé hodnoty
if (StrFTime("%H", Time())==0 && StrFTime("%M", Time())==0) {$data="";} // v čase 0 hod a v 0 min budeme počítat s nulovými srážkami
if (StrFTime("%H", Time())==0 && StrFTime("%M", Time())==1) {$data="";} // v čase 0 hod a v 1 min budeme počítat s nulovými srážkami
// vrátíme načtená data ze souboru, vrátíme prázdné hodnoty, pokud bude nový den
return $data;
}
// načtení dat ze srážkoměru
$puv_srazky=nahrat("dest"); if ($puv_srazky=="") {$puv_srazky=0;}
// načtení dat o max. a min. hodnotách
$max_tep=nahrat("max_tep"); if ($max_tep=="") {$max_tep=-100;} // když není max. hodnota, musí být co nejmenší, aby ji každá jiná naměřená hodnota přepsala
$min_tep=nahrat("min_tep"); if ($min_tep=="") {$min_tep=100;} // když není min. hodnota, musí být co největší, aby ji každá jiná naměřená hodnota přepsala
$max_vlh=nahrat("max_vlh"); if ($max_vlh=="") {$max_vlh=-100;}
$min_vlh=nahrat("min_vlh"); if ($min_vlh=="") {$min_vlh=100;}
$max_vitr=nahrat("max_vitr"); if ($max_vitr=="") {$max_vitr=-1;}
$min_vitr=nahrat("min_vitr"); if ($min_vitr=="") {$min_vitr=1000;}
$max_rosbod=nahrat("max_rosbod"); if ($max_rosbod=="") {$max_rosbod=-100;}
$min_rosbod=nahrat("min_rosbod"); if ($min_rosbod=="") {$min_rosbod=100;}
$max_tlak=nahrat("max_tlak"); if ($max_tlak=="") {$max_tlak=100;}
$min_tlak=nahrat("min_tlak"); if ($min_tlak=="") {$min_tlak=1200;}
$max_rel_tlak=nahrat("max_rel_tlak"); if ($max_rel_tlak=="") {$max_rel_tlak=100;}
$min_rel_tlak=nahrat("min_rel_tlak"); if ($min_rel_tlak=="") {$min_rel_tlak=1200;}
$max_osv=nahrat("max_osv"); if ($max_osv=="") {$max_osv=-1;}
$min_osv=nahrat("min_osv"); if ($min_osv=="") {$min_osv=180000;}
// ukládání hodnot z meteo čidel -----------------------------------------------------------
// funkce ukládání hodnot
function ulozit($jm_souboru,$hodnota)
{
$file_name="data/".$jm_souboru.".txt"; // název souboru
$soubor_data = fopen($file_name, "w"); // ukládání hodonoty do souboru - iniciazice souboru
fwrite($soubor_data, $hodnota); // ukládání hodonoty do souboru - samotné ukládání
fclose($soubor_data); // zavření souboru s hodnotou
}
// ukládání dat ze srážkoměru
if ($dest!="" && is_numeric($dest)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
$dest=$dest+$puv_srazky; // přičtení původních denních srážek k aktuálním srážkám
ulozit("dest",$dest); // uložení hodnoty pomocí funkce
}
// ukládání dat z anemometru - rychlost větru
if ($vitr!="" && is_numeric($vitr)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
ulozit("vitr",$vitr); // uložení hodnoty pomocí funkce
if ($vitr>$max_vitr) {ulozit("max_vitr",$vitr);} // když je hodnota větší než dosavadní maximum, přepíšeme hodnotu dosavadním maxima
if ($vitr<$min_vitr) {ulozit("min_vitr",$vitr);} // když je hodnota menší než dosavadní minimum, přepíšeme hodnotu dosavadním minima
}
// ukládání dat z anemometru - směr větru
if ($smer!="") { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
ulozit("smer",$smer);} // uložení hodnoty pomocí funkce
// ukládání dat z teploměru - teplota
if ($tep!="" && is_numeric($tep)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
ulozit("tep",$tep); // uložení hodnoty pomocí funkce
if ($tep>$max_tep) {ulozit("max_tep",$tep);} // když je hodnota větší než dosavadní maximum, přepíšeme hodnotu dosavadním maxima
if ($tep<$min_tep) {ulozit("min_tep",$tep);} // když je hodnota menší než dosavadní minimum, přepíšeme hodnotu dosavadním minima
}
// ukládání dat z teploměru - rel. vlhkost
if ($vlh!="" && is_numeric($vlh)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
ulozit("vlh",$vlh); // uložení hodnoty pomocí funkce
if ($vlh>$max_vlh) {ulozit("max_vlh",$vlh);} // když je hodnota větší než dosavadní maximum, přepíšeme hodnotu dosavadním maxima
if ($vlh<$min_vlh) {ulozit("min_vlh",$vlh);} // když je hodnota menší než dosavadní minimum, přepíšeme hodnotu dosavadním minima
}
// ukládání dat - rosný bod
if ($rosbod!="" && is_numeric($rosbod)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
ulozit("rosbod",$rosbod); // uložení hodnoty pomocí funkce
if ($rosbod>$max_rosbod) {ulozit("max_rosbod",$rosbod);} // když je hodnota větší než dosavadní maximum, přepíšeme hodnotu dosavadním maxima
if ($rosbod<$min_rosbod) {ulozit("min_rosbod",$rosbod);} // když je hodnota menší než dosavadní minimum, přepíšeme hodnotu dosavadním minima
}
// ukládání dat z tlakového čidla - tlak
if ($tlak!="" && is_numeric($tlak)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
ulozit("tlak",$tlak); // uložení hodnoty pomocí funkce
if ($tlak>$max_tlak) {ulozit("max_tlak",$tlak);} // když je hodnota větší než dosavadní maximum, přepíšeme hodnotu dosavadním maxima
if ($tlak<$min_tlak) {ulozit("min_tlak",$tlak);} // když je hodnota menší než dosavadní minimum, přepíšeme hodnotu dosavadním minima
}
// ukládání dat - relativní tlak
if ($rel_tlak!="" && is_numeric($rel_tlak)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
ulozit("rel_tlak",$rel_tlak); // uložení hodnoty pomocí funkce
if ($rel_tlak>$max_rel_tlak) {ulozit("max_rel_tlak",$rel_tlak);} // když je hodnota větší než dosavadní maximum, přepíšeme hodnotu dosavadním maxima
if ($rel_tlak<$min_rel_tlak) {ulozit("min_rel_tlak",$rel_tlak);} // když je hodnota menší než dosavadní minimum, přepíšeme hodnotu dosavadním minima
}
// ukládání dat - intenzita osvětlení
if ($osv!="" && is_numeric($osv)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
ulozit("osv",$osv); // uložení hodnoty pomocí funkce
if ($osv>$max_osv) {ulozit("max_osv",$osv);} // když je hodnota větší než dosavadní maximum, přepíšeme hodnotu dosavadním maxima
if ($osv<$min_osv) {ulozit("min_osv",$osv);} // když je hodnota menší než dosavadní minimum, přepíšeme hodnotu dosavadním minima
}
// ukládání dat - čas běhu arduina v milisekundách
if ($cas!="" && is_numeric($cas)) { // kontrola jestli je hodota číslo a jestli hodnota není prázdný údaj
$cas=$cas/1000;
ulozit("cas",$cas);} // uložení hodnoty pomocí funkce
// záspis posledního času zápisu
$actual_time=StrFTime("%H:%M - %d.%m.%Y", Time()); // zadáme čas, abychom vědeli, kdy se naposledy uložity data z meteostanice
ulozit("akt_cas",$actual_time); // uložení hodnoty pomocí funkce
// příkazy pro reset arduina ----------------------------------------------------------------------
// když soubor bude existovat, pošleme příkaz pro reset Arduina, poté ho hned smažeme, aby se reset provedl pouze jednou
if (file_exists("data/prikaz_reset.txt")) {$ovl_meteo="z"; unlink("data/prikaz_reset.txt");} // reset Arduina
// zápis ovádacího příkazu pro ovládání (dá se využít na spínání relátek aj. doplňků Arduina)
echo "Q".$ovl_meteo."X"; // poslání příkazu pro Arduino, musí být ohraničeno písmeny Q a X, aby se náhodou nenačetl nějaký nechtěný znak z HTML
echo ("<BR>data zapsána! <BR><BR>");
}
else
{ echo ("nepřihlášeno! <BR><BR>");}
?>
</BODY>
</HTML>
Dále pak ještě vytvoříme složku 'data', protože samotné PHP ho nevytvoří. Do ní vložíme soubor '.htaccess'. Vytvořit soubor takového jmnéna není normální a windows to neumí. Stačí ale otevřít poznámkový blok, dát 'Uložit jako ...' a typ souboru zvolit 'všechny soubory (*.*)' a jako název souboru dát '.htaccess' i s uvozovkami a soubor se uloží. Do tohoto souboru uložíme:
deny from all
Tento soubor zamení přístupu z venčí, k souborům bude mít přístup pouze PHP a proto nebude možné tyto soubory nějak ovlivnit.
program v PHP - soubor 'meteo.php' | |
Soubor 'meteo.php' bude zobrazovat právě aktuální hodnoty z meteostanice. Pokud bychom chtěli, můžeme soubor klidně pojmenovat 'index.php', aby se na našich stránkách objevovaly rovnou data z meteostanice.
<HTML>
<HEAD>
<meta http-equiv="Content-Language" content="cs">
<meta http-equiv="refresh" content="240"> <!-- Tato stránka bude obnovovat načtená data po 240s, pokud tato funkce není požadována, stačí smazat tento řádek. -->
<title>METEO STANICE - meřená data</title>
<STYLE type=text/css>
A:link, A:visited {font-size: 12pt; text-decoration : none; color : #FF0000; }
A:active {font-size: 12pt; text-decoration : none; color : #800000; }
A:hover {font-size: 12pt; text-decoration : none; color : #4060FF; }
P, TD { font-size: 12pt; font-family: Arial; color : #0A0A0A;}
BODY {font-size: 14pt; font-family: Arial; }
</style>
</head>
<BODY>
<BR><B STYLE='color:red;'>DATA Z METEOSTANICE:</B><BR>
<?php
// funkce pro čtení dat z meteostanice
function nahrat($jm_souboru)
{
if (file_exists("data/".$jm_souboru.".txt")) { // ověříme zda soubor existuje
$soubor = fopen("data/".$jm_souboru.".txt", "r"); // otevřeme soubor pro čtení
$data = fread($soubor, 20); fclose($soubor); } // vyčteme data a soubor zavřeme
else
{$data="";} // když soubor neexistuje
return $data;
}
// funkce výpočtu wind chillu
function windchill($tep,$wind) { // teplota ve °C a rychlost v km/h
$windchill=$tep;
if ($tep<=10)
{
if ($wind<0) {$wind=0;}
$A=0.6215*$tep;
$B=11.37*pow($wind,0.16);
$C=0.3965*$tep*pow($wind,0.16);
$windchill=13.12+$A-$B+$C;
}
return $windchill; // vrátí hodnotu Windchill ve °C
}
// funkce výpočtu heat indexu
function heatindex($tepT,$vlhV) { // teplota ve °C a rel. vlhkost v %
$teppocit_hi = $tepT; // teplota pocitová heat indexu
if ($tepT>26.9 && $vlhV>39.9) {
$tepTpocit=(5/9)* (-42.379+(2.04901523*$tepTF)+(10.14333127*$vlhV)+(-0.22475541*$tepTF*$vlhV)+(-0.00683783*$tepTF*$tepTF)+(-0.0548717*$vlhV*$vlhV)+(0.00122874*$tepTF*$tepTF*$vlhV)+(0.00085282*$tepTF*$vlhV*$vlhV)+(-0.00000199*$tepTF*$tepTF*$vlhV*$vlhV) - 32);
if ($tepT > $tteppocit_hi) { $teppocit_hi = $tepT;}
}
return $teppocit_hi; // vrátí hodnotu heat indexu
}
// čtení dat ze souboru
$tep=nahrat("tep");
$vlh=nahrat("vlh");
$rosbod=nahrat("rosbod");
$tlak=nahrat("tlak");
$rel_tlak=nahrat("rel_tlak");
$vitr=nahrat("vitr");
$smer=nahrat("smer");
$dest=nahrat("dest");
$osv=nahrat("osv");
$akt_cas=nahrat("akt_cas");
$max_tep=nahrat("max_tep");
$min_tep=nahrat("min_tep");
$max_vlh=nahrat("max_vlh");
$min_vlh=nahrat("min_vlh");
$max_vitr=nahrat("max_vitr");
$min_vitr=nahrat("min_vitr");
$max_rosbod=nahrat("max_rosbod");
$min_rosbod=nahrat("min_rosbod");
$max_tlak=nahrat("max_tlak");
$min_tlak=nahrat("min_tlak");
$max_rel_tlak=nahrat("max_rel_tlak");
$min_rel_tlak=nahrat("min_rel_tlak");
$max_osv=nahrat("max_osv");
// zobrazení výsledků
echo "<BR>aktuální data byla změřena v: ".$akt_cas." \n";
if ($tep!="") {echo "<BR><B>teplota:</B> ".number_format($tep,1,","," ")."°C \n";}
if ($max_tep!="") {echo "<BR> max: ".number_format($max_tep,1,","," ")."°C \n";}
if ($min_tep!="") {echo "<BR> min: ".number_format($min_tep,1,","," ")."°C \n";}
if ($vlh!="") {echo "<BR><B>rel. vlhkost:</B> ".number_format($vlh,0,","," ")."% \n";}
if ($max_vlh!="") {echo "<BR> max: ".number_format($max_vlh,0,","," ")."% \n";}
if ($min_vlh!="") {echo "<BR> min: ".number_format($min_vlh,0,","," ")."% \n";}
if ($rosbod!="") {echo "<BR><B>rosný bod:</B> ".number_format($rosbod,1,","," ")."°C \n";}
if ($max_rosbod!="") {echo "<BR> max: ".number_format($max_rosbod,1,","," ")."°C \n";}
if ($min_rosbod!="") {echo "<BR> min: ".number_format($min_rosbod,1,","," ")."°C \n";}
if ($tep!="" && $vlh!="" && $tep>26) {echo "<BR><B>heat index:</B> ".number_format(heatindex($tep,$vlh),1,","," ")."°C (pocitová teplota při vyšších teplotách) \n";} // výpočet heat indexu
if ($tep!="" && $vitr!="" && $tep<11) {echo "<BR><B>wind chill:</B> ".number_format(windchill($tep,$vitr),1,","," ")."°C (pocitová teplota při nižších teplotách) \n";} // výpočet windchillu
if ($tlak!="") {echo "<BR><B>absloutní tlak:</B> ".number_format($tlak,1,","," ")." hPa \n";}
if ($max_tlak!="") {echo "<BR> max: ".number_format($max_tlak,1,","," ")." hPa \n";}
if ($min_tlak!="") {echo "<BR> min: ".number_format($min_tlak,1,","," ")." hPa \n";}
if ($rel_tlak!="") {echo "<BR><B>relativní tlak:</B> ".number_format($rel_tlak,1,","," ")." hPa \n";}
if ($max_rel_tlak!="") {echo "<BR> max: ".number_format($max_rel_tlak,1,","," ")." hPa \n";}
if ($min_rel_tlak!="") {echo "<BR> min: ".number_format($min_rel_tlak,1,","," ")." hPa \n";}
if ($smer!="") {echo "<BR><B>směr větru:</B> ".$smer." \n";}
if ($vitr!="") {echo "<BR><B>rychlost větru:</B> ".number_format($vitr,1,","," ")." km/h = ".number_format(($vitr/3.6),1,","," ")." m/s \n";}
if ($max_vitr!="") {echo "<BR> max: ".number_format($max_vitr,1,","," ")." km/h = ".number_format(($max_vitr/3.6),1,","," ")." m/s \n";}
if ($min_vitr!="") {echo "<BR> min: ".number_format($min_vitr,1,","," ")." km/h = ".number_format(($min_vitr/3.6),1,","," ")." m/s \n";}
if ($dest!="") {echo "<BR><B>denní úhrn srážek:</B> ".number_format($dest,2,","," ")." mm \n";}
if ($osv!="") {echo "<BR><B>intenzita osvětlení:</B> ".number_format($osv,0,","," ")." lx \n";}
if ($max_osv!="") {echo "<BR> max: ".number_format($max_osv,0,","," ")." lx \n";}
?>
</BODY>
</HTML>
Co napsat závěrem. Doufám, že jsem vám poskytl spoustu informací k realizaci své meteostanici. Software, který jsem zde uveřejnil je 'open source', tzn. že jej můžete šířit dál, upravovat, dolaďovat, zjednodušovat apod. Tak přeji mnoho zdaru a naměřených hodnot.
© 2019 Fix