index denní grafy grafy za dva měsíce info tvorba
   tvorba meteostanice   


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.


   zapojení Arduina a čidel   

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.

   program v Arduinu   

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>


   závěrem ...   

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