Přeskočit na obsah

Programování pro Arduino Uno

Z Wikiknih

Arduino Uno je programovatelný mikropočítač, který s příslušným programem dokáže obstarávat jednoduché úlohy, jako je blikání LED diodou nebo melodie hraná z piezo reproduktoru. Programy píšeme v jazyce Wiring, který navazuje na C. Užíváme k tomu vývojové prostředí Arduino IDE, pomocí kterého potom napsaný program nahrajeme do Arduina.

Samotné Arduino

Arduino IDE a jeho použití

[editovat | editovat zdroj]
Arduino IDE verze 1.6.0 a úspěšně zkompilovaný návrh

Arduino IDE je vývojové prostředí vytvořené pro Arduino. Obsahuje jednoduché ovládací prvky, takže naprogramovat Arduino v něm dokáže i začátečník.

Často si vystačíme s pěti hlavními tlačítky nad názvem našeho návrhu. První dvě slouží k ověření správnosti kódu(kompilaci) a následnému nahrátí do mikropočítače, další tři potom k vytvoření, otevření nebo uložení návrhu.

Jako první musíme vytvořit návrh (sketch). Do bílého textového pole následně můžeme začít psát program.

Když máme hotovo, zmáčkneme tlačítko pro kompilaci a dole v černém poli se ukáže její výsledek.

Pokud jsme udělali chybu v návrhu tak to ihned zjistíme. Jakmile je kompilace úspěšná, tak program nahrajeme a měli bychom vidět žádanou činnost.

Základní příkazy

[editovat | editovat zdroj]

Jazyk Wiring má dvě hlavní funkce:

setup() - Funkce setup() je zavolána po každém spuštění nebo stisknutí tlačítka reset.

- Užíváme ji k nastavení pinů, proměnných nebo různých knihoven.

loop() - Funkce loop() má za úkol opakovat se stále dokola.

- Umožnuje také schopnost reagovat na různé podněty.

Pro správné pochopení našeho programu je dobré si ho okomentovat vlastními poznámkami.

K tomu nám poslouží dvě lomítka (//), jak můžete vidět na obrázku.

Jak funkce setup() tak loop() musejí být započaty a zakončeny závorkami { }.

Bez nich program nebude funkční!

První program - blikání

[editovat | editovat zdroj]
Ukázka Arduino IDE verze 1.6.0 a našeho prvního programu
K tomuto programu potřebujeme pouze Arduino

Tento příklad ukáže, jak je možné rozsvítit LED diodu vestavěnou v Arduinu.

V této ukázce se nacházejí čtyři nové příkazy:

int -- vybírá piny které budeme užívat

--v tomto programu zvolíme pin 13, který je běžně spojen s LED diodou integrovanou v Arduinu

pinMode -- určuje, zda jsou piny vstupní nebo výstupní (INPUT/OUTPUT)

digitalWrite -- nastavuje napětí na vybraném pinu - HIGH = zapnuto / LOW = vypnuto

delay -- nastavuje dobu, po kterou se nebude nic měnit (1000=1s)

Budeme potřebovat:

  • Arduino
  • Vodiče

Kód programu:

int ledPin = 13; //vybere pin pro připojené LED diody

void setup(){ 
  pinMode(ledPin, OUTPUT);  //nastaví ledPin jako výstupní
}

void loop() {
  digitalWrite(13, HIGH);   // rozsvítí LED diodu, HIGH nastavuje výstupní napětí
  delay(1000);              // nastaví dobu svícení na 1000ms(1s)
  digitalWrite(13, LOW);    // vypne LED diodu, LOW nastaví výstupní napětí na 0V
  delay(1000);              // nastaví dobu svícení
}

Pokud jste nahráli program správně, LED dioda na Arduinu by měla blikat v intervalu 1 vteřiny.

Blikání LED diodou připojenou k digitálnímu výstupu

[editovat | editovat zdroj]

V tomto příkladu se dozvíte, jak je možné rozsvítit LED diodu, kterou máme připojenou k digitálnímu

pinu 11. Náš obvod musí obsahovat také rezistor, postačí 220Ω nebo 330Ω. Bez něj by mohlo dojít ke spálení

LED diody, takže ho budeme používat ve všech našich zapojeních obsahujících LEDky. K výpočtu odporu

využijeme vzorec z Ohmova zákona:

R=U/I

Blikání LED diodou připojenou k digitálnímu výstupu

Budeme potřebovat:

  • 1x LED dioda
  • Rezistor 220Ω nebo 330Ω
  • Vodiče

Kód programu:

int ledPin = 11; //vybere pin pro připojené LED diody

void setup(){ 

 pinMode(ledPin, OUTPUT);  //nastaví ledPin jako výstupní

}

void loop() {

 digitalWrite(11, HIGH);   // rozsvítí LED diodu, HIGH nastavuje výstupní napětí

 delay(1000);              // nastaví dobu svícení na 1000ms(1s)

 digitalWrite(11, LOW);    // vypne LED diodu, LOW nastaví výstupní napětí na 0V

 delay(1000);              // nastaví dobu svícení

}

Teď se naučíme sestrojit náš vlastní semafor. Tento úkol nás naučí lépe užívat příkaz delay

a uvidíme smysl funkce loop v našich kódech.

Budeme potřebovat:

  • 3x barevné LED diody
  • 3x rezistor 220Ω nebo 330Ω
  • Nepájivé pole
  • Arduino
  • Vodiče
    Schéma zapojení semaforu

Tento úkol nás naučí lépe užívat příkaz delay a uvidíme smysl funkce loop v našich kódech.

Kód programu:

//Nastavíme piny připojených LED diod

int cervenaled = 9;

int oranzovaled = 10;

int zelenaled = 11;


void setup() {  

//Nastavíme zapojené piny jako výstupní  

pinMode (cervenaled, OUTPUT);  

pinMode (oranzovaled, OUTPUT);  

pinMode (zelenaled, OUTPUT);

}

void loop() {     

//Zde nastavujeme v jakém pořadí      

//a po jakou dobu budou LED diody svítit       

digitalWrite (cervenaled, 1);     

delay(9000);     

digitalWrite (oranzovaled, 1);     

delay (1000);     

digitalWrite (cervenaled, 0);     

digitalWrite (oranzovaled, 0);          

digitalWrite (zelenaled, 1);     

delay (9000);     

digitalWrite (zelenaled, 0);     

digitalWrite (oranzovaled, 1);     

delay (3000);     

digitalWrite (oranzovaled, 0);

}

Čtení analogového vstupu s potenciometrem

[editovat | editovat zdroj]

Program je určený pro čtení analogového vstupu na pinu 2 a zobrazení výsledků na sériovém monitoru

Použité součástky:

  •   Potenciometr 10KΩ
  •   Arduino
  •   Vodiče
  •   Nepájivé pole
    Čtení analogového vstupu - schéma zapojení
Sériový monitor obrázek

Kód programu:

void setup() {  

// nastaví sériovou komunikaci na 9600 bitů za sekundu:  

Serial.begin(9600);

}

// funkce loop se bude opakovat navždy:

void loop() {  

// čte vstup na analogovém pinu 2:  

int hodnotaNaPotenciometru = analogRead(A2);  

// ukáže výsledek na sériovém monitoru:  

Serial.println(hodnotaNaPotenciometru);  

delay(1);        // pauza mezi čteními pro stabilitu

}

Po nahrátí programu do Arduina ho necháme připojené k PC. V Arduino IDE zvolíme

nástroje a následně sériový monitor. Ten by nám měl ukázat měnící se hodnoty,

způsobené otáčením potenciometru.

Čtení hodnot z digitálního vstupu

[editovat | editovat zdroj]

Program pro čtení digitálního pinu 2, ke kterému je jako vstup připojeno tlačítko. Použijeme rezistor s velkým odporem,

v tomto příkladu 10KΩ, aby se správně ukazovaly změny na vstupu.

Výsledek mačkání tlačítka se nám zobrazí na sériovém monitoru.

Použité komponenty:

  • Tlačítko
  • Odpor 10KΩ
Čtení digitálního vstupu - schéma zapojení

Užitý program:

// na digitální pin 2 je připojeno tlačítko

int tlacitko = 2; //název si volíme, pin také

// funkce setup proběhne jednou, když zmáčknete reset

void setup() { 

//nastaví sériovou komunikaci na 2400 bitů za vteřinu: 

Serial.begin(2400); 

// nastaví tlačítko jako vstup: 

pinMode(tlacitko, INPUT);

}

// funkce loop se bude opakovat navždy

void loop() { 

// přečte vstupní pin: 

int stavtlacitka = digitalRead(tlacitko); 

// ukáže, v jakém stavu se tlačítko nachází: 

Serial.println(stavtlacitka); 

delay(1);        // pauza mezi čteními pro stabilitu   

    Po nahrátí programu do Arduina ho necháme připojené k PC. V Arduino IDE zvolíme

nástroje a následně sériový monitor. Ten by nám měl ukázat měnící se hodnoty,

způsobené mačkáním tlačítka.

Semafory s tlačítkem

[editovat | editovat zdroj]

Tato úloha spojuje minulý příklad semaforu s tlačítkem. Přidáme i semafor k přechodu pro chodce.

Důležité je hlavně správné načasování, které můžeme porovnávat s nastavením skutečné dopravní signalizace.

Princip programu je jednoduchý. Auta mají zelenou, po 10 vteřinách od stisknutí tlačítka naskočí oranžová a červená. Následuje 2 vteřiny prodleva a po ní mají chodci zelenou na dobu 9 vteřin. Poté 5 vteřin červená na obou semaforech a následně je opět zelená pro auta dokud znova nezmáčkneme tlačítko.

Opět použijeme příkaz digitalRead ke čtení hodnot z tlačítka.

Nově použijeme také příkazy if(pokud) a else(ostatní možnosti). Jsou to podmínky, když neplatí if, tak platí else a naopak. Pokud chcete v programování mikroprocesorů pokračovat, je nutné pochopit jejich funkci. V mém kódu platí if, pouze když zmáčkneme tlačítko, jinak platí else. Nikdy nemohou platit zároveň!

Schéma zapojení semaforu s tlačítkem

Budeme potřebovat:

  • 2x zelená LED dioda
  • 2x červená LED dioda
  • 1x oranžová LED dioda
  • 5x rezistor 220Ω
  • 1x rezistor 10KΩ
  • Tlačítko
  • Vodiče
  • Arduino
  • Nepájivé pole

Kód programu:

//Semafor s tlačítkem

//Nastavení pinů LED diod a tlačítka
//CL = červená LED,OL = oranžová LED, atd..
int CL = 9;
int OL = 10;
int ZL = 11;
int prechodC = 5; //semafor pro chodce má pouze 2 LED diody
int prechodZ = 6;
int tlacitko = 2;
int stavTlacitka = 0; //proměnná pro změnu stavu tlačítka

void setup() {
//nastavení pinů LED diod jako výstupní a tlačítka vstupní:
pinMode (CL, OUTPUT);
pinMode (OL, OUTPUT);
pinMode (ZL, OUTPUT);
pinMode (prechodC, OUTPUT);
pinMode (prechodZ, OUTPUT);
pinMode (tlacitko, INPUT);

}

void loop() {
//Tento příkaz čte změnu stavu tlačítka:
stavTlacitka = digitalRead(tlacitko);
//Používáme podmínku if(pokud) a else(ostatní možnosti):
   if (stavTlacitka == HIGH){ //Když zmáčkneme tlačítko,
                              //stanou se následující akce
       delay(10000);
       digitalWrite(ZL, LOW);
       digitalWrite(OL, HIGH);
       delay(2000);
       
       digitalWrite(OL, LOW);
       digitalWrite(CL, HIGH);
       delay(2000);
       
       digitalWrite(prechodC, LOW);
       digitalWrite(prechodZ, HIGH);
       delay(9000);
       
       digitalWrite(prechodZ, LOW);
       digitalWrite(prechodC, HIGH);
       delay(5000) ;
         
       digitalWrite(OL, HIGH);
       delay(2000);
       digitalWrite(OL, LOW);
       }
   else {  //Pokud nedojde ke stisknutí tlačítka,
           //platí nasledující příkazy
     digitalWrite(CL, LOW);
     digitalWrite(ZL, HIGH);
     digitalWrite(prechodC, HIGH);
  }

Rozsvěcování a zhasínání LED diody

[editovat | editovat zdroj]

V tomto příkladu si ukážeme, jak postupně zhasínat a rozsvěcovat LED diodu pomoci příkazu analogWrite().

Budeme potřebovat:

  • 1x LED dioda
  • Rezistor 220Ω nebo 330Ω
  • Vodiče
  • Arduino
  • Nepájivé pole

Kód programu:

int led = 6;           // pin, ke kterému je připojena LED dioda

int jas = 0;    // nastavuje jas LED diody

int hodnotaZhasinani = 5;    // udává o kolik má LED zhasínat

void setup()  { 

// nastaví pin 6 jako výstupní: 

pinMode(led, OUTPUT);

}

void loop()  { 

// nastaví jas na pinu 6: 

analogWrite(led, jas);    

// změní jas při dalším průběhu funkce loop: 

jas = jas + hodnotaZhasinani;

// po úplném zhasnutí se LED dioda začne opět rozsvěcovat 

  if (jas == 0

Výsledek by měl být dobře viděť. Pozměněním hodnot docílíme různé doby zhasnutí.           

Melodie hraná z piezo reproduktoru

[editovat | editovat zdroj]

V tomto příkladu si ukážeme, jak používat příkaz tone() a také jak k programu připojit soubor pitches.h, což je soupis hodnot výšek tónů, díky kterému tóny znějí tak, jak mají. Vytvořil ho Brett Hagman, kvůli kterému vznikl příkaz tone().

Použité součástky:

  • Piezo reproduktor
  • Arduino
  • Nepájivé pole
  • Vodiče
Schéma zapojení piezo reproduktoru

Kód programu:

# include "pitches.h" //přidá k programu potřebný soubor, který udává hodnotu daného tónu

//noty, které melodie obsahuje

int melodie[] = { 

NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};

// udává časování not: 4 je nota čtvrťová, 8 pak nota osminová

int casovaniNot[] = { 

4, 8, 8, 4,4,4,4,4 };

void setup() { 

for (int Nota = 0; Nota < 8; Nota++) {   

//výpočet délky zvuku jedné noty vypočítáme tak, že vydělíme 1000/noteDurations   

//např.1000/4 nebo 1000/8        

int casovaniNoty = 1000/casovaniNot[Nota];   

//první číslem v závorce určujeme digitální pin pro výstup    

tone(7, melodie[Nota],casovaniNoty);   

//pro rozlišení not nastavte pauzyMeziNotami * 1.30    

int pauzyMeziNotami = casovaniNoty * 1.30;   

delay(pauzyMeziNotami);   

//zastaví melodii   

noTone(8); 

}

}

void loop() { 

//pokud nechcete melodii opakovat, tak funkci loop nechte prázdnou

}

Když jste program úspěšně nahráli, měli byste slyšet melodii vycházející z reproduktoru.

Sledování teploty a vlhkostí v časech a tvorba grafů

[editovat | editovat zdroj]

Cílem této úlohy je sledování teploty a vlhkosti venku a uvnitř pomocí dvou DHT11, Arduina Uno a Ethernet shieldu.

Schéma zapojení DHT11 k Arduinu

Zapojení:

[editovat | editovat zdroj]

Ke správné funkčnosti našeho zařízení potřebujeme tyto součásti:

·       Arduino Uno

·       Ethernet shield

·       2x DHT11

·       1x rezistor 10kOhm

·       Vodiče

·       Ethernet kabel

·       Router

·       Počítač připojený k síti

·       (Volitelně nepájivé pole)

Výše můžete vidět schéma připojení součástek k Arduinu. Dále je nutné zasunout Ethernet shield do Arduina,

zapojit do něj a do sítě ethernet kabel a připojit k napájení.

Poté již stačí jen nahrát a sputit potřebné programy a můžeme vidět výsledek naší práce. 

Stačí spustit prohlížeč a zadat námi zvolenou IP adresu.

Program pro Arduino:

[editovat | editovat zdroj]
# include "DHT.h" //Přidáme používané knihovny
# include <SPI.h>
# include <Ethernet.h>

# define DHTPIN0 2 //definuje použité piny
# define DHTPIN1 3
# define DHTTYPE DHT11 //definuje použitý typ DHT

DHT dht0(DHTPIN0, DHTTYPE);
//určuje jaké DHT užíváme a kde je připojeno

DHT dht1(DHTPIN1, DHTTYPE);

byte mac[] = { //sem napište MAC adresu vašeho ethernet
                     //shieldu, většinou se shoduje

0x90, 0xA2, 0xDA, 0x00, 0x23, 0x36 };

IPAddress ip(192,168,199,102); //nastavuje IP adresu, ze //které budeme číst data

EthernetServer server(80); //nastavuje port

void setup() { //tato funkce se volá vždy jednou na začátku
 Serial.begin(9600); //spouští sériovou komunikaci
 dht0.begin(); //spouští komunikaci s DHT
 dht1.begin();
  Ethernet.begin(mac, ip); //spouští komunikaci přes ethernet
  server.begin();
  Serial.print("IP je ");
  Serial.println(Ethernet.localIP());} //vypíše lokalní IP adresu
void loop() { //opakuje se stále dokola

int h0 = dht0.readHumidity(); //vytvoří proměnnou z přečtené
                                          //vlhkosti

int t0 = dht0.readTemperature();

int h1 = dht1.readHumidity();

int t1 = dht1.readTemperature();
 Serial.print(h0); //do sériového monitoru vypíše h0
 Serial.print("\t");
 Serial.print(t0);
 Serial.print("\t");
 Serial.print(h1);
 Serial.print("\t") ;
 Serial.print(t1);
 Serial.print("\n"); 
 delay(500); //vytvoří zpoždění 500ms
  EthernetClient client = server.available();
  if (client) {
    Serial.println("nový");
    boolean currentLineIsBlank = true;   
    while (client.connected()) { 
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n' && currentLineIsBlank) {       
          // Výstupní hodnoty z DHT odešle na IP adresu
           client.print(h0);
           client.print(",");
           client.print(t0);
           client.print(",");
           client.print(h1);
           client.print(",") ;
           client.print(t1);
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
    Serial.println("Klient odpojen");
  }

Python je vysokoúrovňový programovací jazyk, který v roce 1991 navrhnul Guido Van Rossum.

Je to open-source projekt, který je dostupný na většinu platforem, od Linuxu, přes Windows až po OSX.

Existuje mnoho knihoven vytvořeným pro Python. Zde se zaměřím na Matplotlib, Psycopg2 a Flask.

K programování v jazyce Python užívám grafické rozhraní Spyder.

K nejdůležitějším vlastnostem  tohoto editoru patří zvýrazňování syntaxí a možnost spustit více programů najednou.

V této části uvidíte dva potřebné programy v jazyce Python , které nám budou ukládat hodnoty do databáze a vykreslovat grafy.

Musíte mít také vytvořenou databázi, do které se nám budou ukládat data.

Je důležité, aby jste měli všechny použité moduly nainstalované a funkční, jinak program nebude správně fungovat.

Flask je microframework pro Python určený k spravování a tvorbě webových stránek.

K  instalaci tohoto modulu je třeba stáhnout si instalační soubor pip z těchto stránek https://bootstrap.pypa.io/get-pip.py

a spustit ho v příkazové řádce příkazem python get-pip.py

Teď je třeba nainstalovat moduly, aby Flask fungoval,

příkazy v řádce:

·       pip install Jinja2

·       pip install Flask

V Pythonu poté připojíme HTML soubor, který zajistí vzhled našich stránek. 

Matplotlib
[editovat | editovat zdroj]

Matplotlib je knihovna pro Python, užívaná k vytváření grafů

(sloupcových, bodových, atd.) a dále například histogramů. K tomu nám stačí jen pár řádků kódu.

Já knihovnu užívám k tvorbě grafu, ve kterém se zobrazuje vnitřní a venkovní teplota a vlhkost.

Data se získávají z databáze, do které se ukládají opět přes Python. 

Psycopg2 je nejpoužívanější  knihovna užívaná k práci s databázovým systémem PostgreSQL.

Umožňuje nám do databáze přistupovat, číst z ní data a také do ní zapisovat.

Níže můžete vidět, jaký kód jsem použil pro přihlášení do databáze a následný zápis dat,

které jsou čteny z použité IP adresy, na kterou se odesílají naměřené hodnoty. 

SQL (Structured Query Language) je dotazovací jazyk, který je používán v dotazovací databázi. Je nástupcem jazyka SEQUEL.

  Přenositelnost SQL dotazů je omezená, jelikož každý databázový systém obsahuje prvky a konstrukce, které nejsou ve standardech obsaženy.

  Existuje mnoho databázových systémů, např:

·       PostgreSQL

·       MySQL

·       Oracle

·       SQLite 

V této práci používám databázový systém PostgreSQL, do kterého přistupuji jak z Pythonu, tak přes webové rozhraní Adminer.

Je to open-source software, takže je zdarma a volně dostupný všem uživatelům.

# -*- coding: utf-8 -*-
import psycopg2 #naimportujeme potřebné moduly, tento je pro komunikaci s databází
from datetime import datetime #datetime je pro používání času
import time #time pro používání času
import httplib #pro síťovou komunikaci
web = httplib.HTTPConnection("192.168.199.102:80") #IP adresa ze které budeme číst data
web.request("GET", "/") #data budeme sbírat metodou GET
r1 =web.getresponse() 
data1=r1.read() #přečte příchozí data

conn = psycopg2.connect(host='localhost', #zde zadáte adresu uložené databáze, uživ. jméno, heslo a název databáze
                        user='ham32291',
                        password='vo2OG9hu',
                        database='ham32291')
curs=conn.cursor() #vytvoří cursor

while True:
    try:
            data=data1.split(",") #oddělí příchozí data čárkou

            print data #vypíše do console příchozí data
            print int(data[0])
            print int(data[1])
            print int(data[2])
            print int(data[3])            
            try:                
                curs.execute("INSERT INTO arduino (vlhkost,teplota, teplotavenku, vlhkostvenku, cas) VALUES (%i,%i, %i, %i,CURRENT_TIMESTAMP)" % (int(data[0]), int(data[1]), int(data[3]), int(data[2])))
                #tímto příkazem odesíláme přečtená data do databáze                
                conn.commit() 
                time.sleep(300) #vytvoří zpoždění 300s
            except conn.IntegrityError:  
                print "Zápis dat selhal" #pokud selže zápis dat do databáze vypíše se chybová hláška
                curs.close() #ukončí se komunikace s databází
    except conn.IntegrityError: 
            print "Selhalo načítání !" #pokud se nepodařilo přečist data, vypíše chybovou hlášku

Zde můžete viděť verzi, která data nesbírá z IP adresy, ale přímo z Arduino přes USB sériovou komunikací:

#!/usr/bin/python
# -*- coding: utf8 -*-
############################################D################################## 

from flask import Flask, url_for, request, render_template
import psycopg2
import serial
from datetime import datetime
com = serial.Serial('COM4', baudrate=9600)
arduinoString = com.readline() #Přečte text ze seriového vstupu 
conn = psycopg2.connect(host='zadejadresu', #zde zadáte adresu uložené databáze, uživ. jméno, heslo a název databáze
                        user='zadejuzivatelskejmeno',
                        password='zadej heslo',
                        database='zadejnazevdatabaze')
curs=conn.cursor()


while True:
    try:    
            arduinoString = com.readline() #Přečte text ze seriového vstupu 
            print arduinoString            
            data= arduinoString.split("\t") #Rozdělí data ze sériového vstupu na dvě části
    
    #        Vlh = float( data[0])
    #        temp = float( data[1])
    #        print temp
    #        print Vlh
            print data
            print int(data[0])
            print int(data[1])
            print int(data[2])
            print int(data[3])            
            try:                
                curs.execute("INSERT INTO arduino (vlhkost,teplota, teplotavenku, vlhkostvenku, cas) VALUES (%i,%i, %i, %i,CURRENT_TIMESTAMP)" % (int(data[0]), int(data[1]), int(data[2]), int(data[3])))
                conn.commit()
            except conn.IntegrityError:
                print "Zápis dat selhal"
                curs.close()
    except conn.IntegrityError:
            print "Selhalo načítání !"

Čtení dat a vykreslování grafů na serveru

[editovat | editovat zdroj]
# -*- coding: utf-8 -*-
from __future__ import division, print_function, unicode_literals #naimportujeme všechny potřebné knihovny
from datetime import datetime
import StringIO
import base64
from time import mktime

from flask import Flask, render_template, send_from_directory, request
from matplotlib.pyplot import figure, title, xlabel, ylabel, plot, legend, axis, savefig
import os
import matplotlib
from scipy import arange

matplotlib.use('Agg') #určuje, že se z grafu vytvoří PNG obrázek, který se poté bude zobrazovat na webu
import psycopg2

PWD = os.path.dirname(__file__)
app = Flask(__name__)
######################################################################################
conn = psycopg2.connect(host='****', #připojíme se k databázi
                        user='****',
                        password='****',
                        database='****')
curs = conn.cursor() #vytvoří cursor pomocí kterého budeme přistupovat do databáze 

@app.route('/')
def index():
    od, do = -1, -1
    if "od" in request.args and request.args["od"]: 
        od = odtext = request.args["od"]
        odtext = od
        od = datetime.strptime(od, "%Y-%m-%d") #převede vložený řetězec na datum 
        od = mktime(od.timetuple())
    else:
        odtext = ""

    if "do" in request.args and request.args["do"]:
        do = request.args["do"]
        dotext = do
        do = datetime.strptime(do, "%Y-%m-%d")
        do = mktime(do.timetuple())
    else:
        dotext = ""

    return render_template('base1.html', img=image_gen(od, do), od=odtext, do=dotext)

def image_gen(od=-1, do=-1):
    conn = psycopg2.connect(host='****', #připojíme se k databázi
                        user='****',
                        password='****',
                        database='****')
    curs = conn.cursor()    
    
    
    if od < 0 and do < 0:
        curs.execute(
            #vybere z tabulky arduino data ze všech níže uvedených sloupců a seřadí je vzestupně podle času
            "SELECT teplota, vlhkost, cas, vlhkostvenku, teplotavenku FROM arduino ORDER BY cas ASC")
    elif od > 0 and do > 0:
        od = datetime.fromtimestamp(od)
        do = datetime.fromtimestamp(do)
        curs.execute(
            "SELECT teplota, vlhkost, cas, vlhkostvenku, teplotavenku FROM arduino WHERE cas > '{}' AND cas < '{}' ORDER BY cas ASC".format(
                str(od.year) + "-" + str(od.month) + "-" + str(od.day),
                str(do.year) + "-" + str(do.month) + "-" + str(do.day))) #převede datum z databáze do potřebné podoby 
    elif od > 0:
        od = datetime.fromtimestamp(od)
        curs.execute(
            "SELECT teplota, vlhkost, cas, vlhkostvenku, teplotavenku FROM arduino WHERE cas > '{}' ORDER BY cas ASC".format(
                str(od.year) + "-" + str(od.month) + "-" + str(od.day)))
    elif do > 0:
        do = datetime.fromtimestamp(do)
        curs.execute(
            "SELECT teplota, vlhkost, cas, vlhkostvenku, teplotavenku FROM arduino WHERE cas > '{}' ORDER BY cas ASC".format(
                str(do.year) + "-" + str(do.month) + "-" + str(do.day)))


    data = curs.fetchall()
    t = arange(0, len(data), 1)

    tep = list() #Vytvoří seznam 
    vlh = list()
    teplotavenku = list()
    vlhkostvenku = list()
    for d in data: 
        tep.append(d[0]) #přiřadí jednotlivé hodnoty k d[0], d[1], atd.
        vlh.append(d[1])
        teplotavenku.append(d[4])
        vlhkostvenku.append(d[3])

    fig = figure()
    graf = fig.add_subplot(111)

    graf.grid(True) #Vytvoří mřížku za grafem
    title("Teplota a vlhkost v čase") #Vytvoří nadpis

    xlabel("Čas[Počet dní]") #Vytvoří popisek osy x
    ylabel("Teplota[°C], Vlhkost[%], Teplota venku[°C], Vlhkost venku[%]") #Vytvoří popisek osy y

    plot(t, tep, label="Teplota", linewidth=2) #Vytvoří křivku teploty
    plot(t, vlh, label="Vlhkost", linewidth=2) #Vytvoří křivku vlhkosti
    plot(t, teplotavenku, label="Teplota venku", linewidth=2)
    plot(t, vlhkostvenku, label="Vlhkost venku", linewidth=2)
    if data:
        axis([0, len(data), min(min(tep), min(vlh), min(teplotavenku), min(vlhkostvenku)) - 5, 
              max(max(tep), max(vlh), max(teplotavenku), max(vlhkostvenku)) + 20]) #
    legend()
    output = StringIO.StringIO()
    savefig(output)
    r = base64.b64encode(output.getvalue())
    output.close()
    return r

@app.route('/tmp/<path:filename>')
def static_data(filename):
    return send_from_directory('tmp', filename)

############################################################################

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8080, debug=True)

Webové rozhraní a HTML

[editovat | editovat zdroj]
Graf sledovaného počasí v čase

HTML (HyperText MarkUp Language) je název značkovacího

jazyka užívaného pro tvorbu webových stránek, jenž jsou propojeny hypertextovými odkazy.

Je jedním z hlavních jazyků pro vytváření webových stránek. Osobně jsem pro editaci zvolil Notepad++.

Poslední verzí je HTML5. Níže uvidíte kód, který jsem použil.

Je poměrné jednoduchý, jelikož stránka neobsahuje moc prvků, ale pro funkčnost plně dostačující a přehledný.

<!doctype html>
<html lang="cs">
<head> <!začíná a končí hlavičku, která se sice nezobrazuje, ale obsahuje některé důležité údaje>
    <title>Teplota a vlhkost v čase</title> <!vymezuje název dokumentu (může se lišit od jména souboru)>
    <meta charset="utf-8"> <!určuje kódování na utf-8>
    <meta name="description"
          content="Teplota a vlhkost v čase"> <!Název obsahu>
    <meta name="author" content="Radek Hampl"><!Podpis autora souboru>
</head>

<body> <!část body se bude zobrazovat>
<header role="banner">
    <h1>Teplota a vlhkost v čase</h1> <!vytvoří nadpis 1. úrovně, nejmenší je h6>
</header>

<main role="main">
    <form method="get" action="{{ url_for('index') }}">
        <p>Teplota a vlhkost v čase <!párový tag p použijeme pro vložení textu a inputy>
            <input type="date" size="10" name="od" value="{{ od }}" class="date" placeholder="2016-12-31"/> <!vytvoří pole, do kterého píšeme datum nebo si ho vybereme z kalendáře.>
            <input type="date" size="10" name="do" value="{{ do }}" class="date" placeholder="2016-12-31"/>
		</p>
        <p>(Zadej období, za které se mají vykreslit hodnoty ve formátu RR-MM-DD)
		
		<input type="submit" /> 
    </form>
    <p><img src="data:image/png;base64,{{ img }}"
            alt="Teplota a vlhkost v čase"></p> <!vloží obrázek vykresleného grafu na stránku>
</main>

</body>
</html>

Použité zdroje

[editovat | editovat zdroj]

[1]Funkce tone()[2]Flask[3]PostgreSQL[4]Matplotlib[5]Html[6]PostgreSQL anglicky[7]Flask anglicky[8]Podobná problematika[9]Tvorba stránek v Html