Ta strona używa ciasteczek (plików cookies), dzięki którym może działać lepiej. Dowiedz się więcejRozumiem i akceptuję

Kurs Arduino II – #8 – cyfrowy czujnik wilgotności (DHT11)

Programowanie 22.02.2017 Damian (Treker)

Termometry (analogowe i cyfrowe), które zostały opisane podczas poprzedniego odcinka kursu, to zdecydowanie najczęściej używane sensory do pomiaru warunków atmosferycznych.

Drugim równie popularnym tematem jest pomiar wilgotności, który będzie możliwy dzięki DHT-11!

Nawigacja serii artykułów:
« poprzednia częśćnastępna część »

Kup zestaw elementów i zacznij naukę w praktyce! Przejdź do strony dystrybutora »

Czym jest pomiar wilgotności?

Bardzo często w kontekście Arduino pojawia się temat czujników wilgotności. Jednak w większości poradników pomija informacje na temat tego „co tak właściwie jest mierzone”.

Opisywany w artykule czujnik DHT-11 mierzy wilgotność względną, którą w skrócie oznacza się jako RH od angielskiego Relative Humidity. Wartość ta mieści się zawsze w zakresie od 0 do 1 i nie ma swojej jednostki. Dlatego najczęściej wilgotność względną wyraża się w %RH – czyli podaje się wartość procentową z zakresu od 0 do 100%, gdzie 0%RH oznacza powietrze suche, a 100%RH oznacza powietrze o maksymalnym stężeniu pary wodnej.

Najprościej mówiąc, wilgotność względna informuje nas o ilości wody w powietrzu.
Jeśli wartość ta osiągnie 100% woda zacznie wydzielać się w postaci kropel.

Jeśli ktoś woli definicje bardziej „akademickie”, to odsyłam do Wikipedii, gdzie znaleźć można, że: „wilgotność względna, to stosunek ciśnienia cząstkowego pary wodnej zawartej w powietrzu do ciśnienia nasycenia nad płaską powierzchnią czystej wody, określającego maksymalne ciśnienie cząstkowe pary wodnej w danej temperaturze.”


Zajmując się opisywanym zagadnieniem warto jeszcze pamiętać o tym, że ilość wody, którą jest w stanie pomieścić powietrze zależy również m.in. od jego temperatury. Wraz ze zmianą wskazań termometru zmieniać będzie się %RH. Dla przypomnienia, skroplenie wody może nastąpić, gdy: dostarczymy brakującą ilość wody do powietrza lub, gdy obniżymy jego temperaturę. Aby nie przesadzić z teorią, zainteresowane osoby odsyłam do haseł wykres Molliera (uwaga, bo wygląda strasznie) oraz punkt rosy. Teraz pora przejść do praktyki!

Zestaw elementów do przeprowadzenia wszystkich ćwiczeń

Gwarancja pomocy na forum dla osób, które kupią poniższy zestaw!

Części pozwalające wykonać ćwiczenia z kursu Arduino (poziom 2) dostępne są w formie gotowych zestawów! W komplecie m.in. diody programowalne, termometry analogowe i cyfrowe, czujnik ruchu (PIR), wyświetlacze 7-segmentowe oraz znacznie więcej!


Kup w Botland.com.pl »

Czujnik DHT-11 w praktyce

Nasze testy przeprowadzimy na popularnym, cyfrowym czujniku DHT-11. Układ ten łączy w jednej obudowie termometr oraz czujnik wilgotności. Informacje z czujnika odczytać można za pomocą interfejsu jednoprzewodowego. W wielu miejscach znaleźć można informację, że czujnik ten korzysta z 1-wire (znanego np. z omawianych czujników DS18B20) – nie jest to prawdą!

Czujniki DHT-11 korzystają ze zmodyfikowanej wersji interfejsu 1-wire,
która nie jest zgodna z tym standardem!

Z niebieskiej obudowy wystają 4 wyprowadzenia, jednak tylko 3 z nich są wykorzystane. Wyjście oznaczone jako NC (skrót od Not Connected) nie pełni żadnej istotnej funkcji i nie trzeba go nigdzie podłączać. Najważniejsze parametry czujnika:

  • Ogólne:
    • Napięcie zasilania: 3 V do 5,5 V (w naszym przypadku będzie to 5 V)
    • Pobór prądu: 0,2 mA
    • Częstotliwość próbkowania: 1Hz (nowe informacje można odczytywać co sekundę)
  • Wbudowany termometr
    • Zakres pomiarowy: 0 – 50 °C
    • Dokładność: ±2°C
  • Czujnik wilgotności:
    • Zakres pomiarowy: 20 – 95%RH
    • Dokładność  ±5%RH

Więcej informacji na temat czujnika DHT-11
znaleźć można w jego dokumentacji.

Niestety w sprzedaży można natrafić na różne wersje tego czujnika, które mogą charakteryzować się różnymi zakresami pomiarowymi. Na szczęście, na tylnej ściance obudowy DHT-11 często producenci drukują najważniejsze informacje. W moim przypadku wyglądało to następująco:

Jeśli jesteśmy już przy obudowie, to warto zajrzeć do środka – zalecam jednak ostrożność przy jego otwieraniu. Poniżej umieszczam zdjęcia przykładowego egzemplarza więc nie ma potrzeby, aby każdy rozkładał swój sensor na czynniki pierwsze.

Istnieje wiele „różnych wersji wnętrza” – niektóre czujniki mogą wyglądać w środku zupełnie inaczej. Pozostaje wierzyć producentom, że wszystkie wersje działają poprawnie.

Wnętrze czujnika DHT-11.

Układ mierzy temperaturę w zakresie od 0 do 50°C, więc idealnie sprawdzi się podczas monitorowania pomieszczeń. Ta wersja czujnika nie nadaje się do stosowania na zewnątrz, gdzie spodziewamy się ujemnych temperatur.

Większym zakresem pomiarowym charakteryzują się
bliźniacze czujniki DHT-21 oraz DHT-22 jednak są one 3-4 razy droższe.

Podłączenie czujnika DHT-11 do Arduino

Czujnik DHT-11 korzysta z interfejsu podobnego 1-wire, więc jego podłączenie jest bardzo proste. Na początek zasilanie 5V i GND, następnie łączymy linię danych z Arduino (np. z pinem nr 2).

Tak samo jak w poprzedniej części kursu konieczne jest dodanie rezystora 4.7k,
który łączy linię danych z dodatnią szyną zasilania.

Przykładowe podłączenie widoczne jest na poniższym zdjęciu:

Komunikacja z czujnikiem DHT-11

Oczywiście w Internecie znaleźć można co najmniej kilka gotowych bibliotek, które ułatwią nam korzystanie z tego sensora. W swoich projektach najchętniej korzystam z bardzo prostej biblioteki, której autorem jest Mark Ruys. Niezbędne pliki znaleźć można na GitHubie autora.

Biblioteka potrafi również samodzielnie wykryć i obsłużyć
inne czujniki tego typu (np.: DHT22, AM2302, RHT03).

Po zainstalowaniu biblioteki (proces ten był opisywany we wcześniejszych odcinkach kursu) można przejść do napisania pierwszego programu. Zaczynamy od pustego szkieletu z dołączonym plikiem nagłówkowym biblioteki, definicją pinu oraz uruchomioną komunikacją przez UART:

W kolejnym kroku należy zadeklarować czujnik oraz poinformować bibliotekę o pinie, na którym ma odbywać się komunikacja:

Odczytanie wilgotności i temperatury z DHT-11

Teraz w pętli głównej można przejść już do odczytów. Tutaj przydadzą się dwie funkcje. Pierwsza do pobierania informacji na temat wilgotności w %RH: dht.getHumidity() oraz druga do odczytywania temperatury w °C: dht.getTemperature().

Program w najprostszej postaci będzie więc wyglądał następująco:

Działanie programu w praktyce widoczne jest na poniższej animacji. Czujnik potrzebuje stosunkowo dużo czasu na zarejestrowanie zmiany wilgotności i temperatury – może to zająć nawet od 6 do 15 sekund (typowo około 10). Więcej informacji na ten temat znaleźć można w nocie katalogowej.

Poniższa animacja przedstawia zachowanie czujnika po chuchnięciu na niego:

Zmiana odczytów czujnika DHT-11.

Niestety czasami mogą wystąpić pewne problemy z komunikacją lub inne błędy. Wtedy na ekranie zostanie wyświetlona informacja o temperaturze i wilgotności wynoszącej 0. Używana przez nas biblioteka zawiera jeszcze kilka ciekawych funkcji, które pozwolą uniknąć takich problemów.

Przykład błędnego odczytu.

Po pierwsze, nie ma konieczności, aby wpisywać „na sztywno” czas, po którym może nastąpić kolejny odczyt. Dzięki funkcji dht.getMinimumSamplingPeriod() możliwe jest pobranie informacji o czasie, który trzeba odczekać podczas korzystania z danego czujnika.

Po drugie, za pomocą funkcji dht.getStatusString() możemy sprawdzić, czy odczytanie pomiarów przebiegło bezbłędnie. Jeśli tak będzie, to powyższa funkcja zwróci nam „OK”. W przypadku błędu otrzymamy odpowiednią informację np. „TIMEOUT”.

Dzięki powyższym funkcjom program może wyglądać następująco:

Od teraz w momencie napotkania błędu żadne informacje nie będą wyświetlane. Przykład działania tego programu widoczny jest poniżej. Uszkodzenie czujnika symulowane było odłączeniem przewodu, który łączył DHT-11 z Arduino.

Poprawne działanie programu (bez błędnych wyników).

Na sam koniec warto jeszcze wspomnieć o ostatniej funkcji zaszytej w naszej bibliotece, która przelicza temperaturę na skalę Fahrenheita: dht.toFahrenheit(). W praktyce w naszym przypadku jej wywołanie wyglądałoby następująco:

Działanie zmienionego programu:

Konwersja temperatury odczytanej z DHT-11.

Podsumowanie

Czujnik DHT-11, jak doskonale widać powyżej, jest bardzo prosty w wykorzystaniu, dlatego cały artykuł nie musiał być długi. Korzystając z wiedzy zdobytej podczas tego i poprzedniego artykułu zachęcam do zbudowania prostej stacji pogodowej. Urządzenie to może mierzyć temperaturę, wilgotność i zachmurzenie (za pomocą fotorezystora). Wyniki można prezentować przykładowo na komputerze lub na linijce diod programowalnych.

W następnym artykule zajmiemy się funkcją millis(), która pozwala na generowanie opóźnień, które nie zawieszają całego programu. Przy okazji stworzymy praktyczny projekt inteligentnego oświetlenia. Łącząc elementy z poprzednich części stworzymy układ ułatwiający poruszanie się po zmroku!

Kup zestaw elementów i zacznij naukę w praktyce! Przejdź do strony dystrybutora »

Autor kursu: Damian (Treker) Szymański
Ilustracje: Piotr Adamczyk

Powiadomienia o nowych, darmowych artykułach!

Załączniki

DHT11 (pdf, 842 KB) - Pobierz

Dokumentacja czujnika DHT-11

Komentarze

leepa79

8:59, 28.02.2017

#1

No to ja zacznę:

Lampa i pasek LED sterowany pilotem z odczytem temp i wilgotności.

Kierując się tylko informacjami z kursów (tak jak już to wcześniej wspominałem) poskładałem coś takiego. Podpatrzyłem jedynie jak podłączyć moduł przekaźnika RM0. A więc mamy tu odbiornik podczerwieni z kursu elektroniki II #7, stabilizator napięcia z kursu elektroniki #8, wyświetlacz z kursu arduino #7, tranzystor BC547 (sterowanie paskiem LED) zastosowany w lekcjach elektroniki i arduino, tak samo jak LED i przyciski, czujnik DS18B20 oraz czujnik DHT11 z ostatnich lekcji arduinoII. Część z czujnikiem DS18B20 robiłem chwilę przed lekcją w ramach przygotowania i jest trochę inaczej niż w kursie (to będę dziś poprawiał). Kod w wersji wczesnej alfa :) cały czas modyfikowany - wczoraj przypisałem do przycisków włączanie i wyłączanie led i lampy tzn. włączanie i wyłączanie na jednym przycisku. Potem chcę coś zrobić z czasowym podświetleniem wyświetlacza (void ekranLed() ). Ten delay strasznie mrozi kod :) Zabawa jest super. Chciałem wykorzystać pilot z kursu budowy robotów, ale tam do jednego przycisku przypisane są dwa kody, a to trochę mi skomplikowało myśl - więc poczekam jeszcze na stosowną lekcję.

No i kod - proszę nie krzyczeć - w wolnych chwilach poprawiam go ;)

//ODCZYT KODOW Z PILOTA

//#include <IRremote.h>

//#define irPin 11

//IRrecv irrecv(irPin);

//decode_results results;

//

//void setup() {

// Serial.begin(9600);

// irrecv.enableIRIn();

//}

//

//void loop() {

// if (irrecv.decode(&results)) {

// Serial.print("0x");

// Serial.println(results.value, HEX);

// delay(250);

// irrecv.resume();

// }

//}

// Czytnik numerów seryjnych czujników DS18B20

//

//#include <OneWire.h>

//

//// Numer pinu cyfrowego do którego podłaczyłęś czujniki

//const byte ONEWIRE_PIN = 2;

//

//OneWire onewire(ONEWIRE_PIN);

//

//void setup()

//{

// while(!Serial);

// Serial.begin(9600);

//}

//

//void loop()

//{

// byte address[8];

//

// onewire.reset_search();

// while(onewire.search(address))

// {

// if (address[0] != 0x28)

// continue;

//

// if (OneWire::crc8(address, 7) != address[7])

// {

// Serial.println(F("Błędny adres, sprawdz polaczenia"));

// break;

// }

//

// for (byte i=0; i<8; i++)

// {

// Serial.print(F("0x"));

// Serial.print(address[i], HEX);

//

// if (i < 7)

// Serial.print(F(", "));

// }

// Serial.println();

// }

//

// while(1);

//}

#include <IRremote.h> //Dolaczenie bibloteki dla scalonego odbiornika IR

//https://github.com/shirriff/Arduino-IRremote/zipball/master

#include <LiquidCrystal.h> //Dołączenie bilbioteki wyswietlacza

#include <OneWire.h> //Bibloteki dla termometru

#include <DS18B20.h>

#include "DHT.h"//Biblioteka dla czujnika wilg / temp

#define irPin 2 //pin odbiornika IR

#define diodaPin 9 //pin listwy LED

#define diodaPin1 8 //pin kontrolki odbioru z pilota

#define lampa 7 //pin sterowania lampa (przekaźnik RM0)

#define PodLed 12 //podswietlenie wyswietlacza

#define ONEWIRE_PIN 13 //pin termometru

#define przON A0

#define przOFF A1

#define DHT11_PIN A3 //Pin czujnika wilg / temp

IRrecv irrecv(irPin);

decode_results results;

DHT dht;

byte address[8] = {0x28, 0x5, 0xD2, 0x4B, 0x8, 0x0, 0x0, 0x79}; //adres termometru

OneWire onewire(ONEWIRE_PIN); //nie mam pojecia co - dla termometru

DS18B20 sensors(&onewire);

LiquidCrystal lcd(3, 4, 5, 6, 10, 11); //Informacja o podłączeniu nowego wyświetlacza

int jasnosc = 0; // zmienna dla jasnosi listwy LED

int lampaStatus = LOW;

int diodaStatus = LOW;

int lampaStatus1 = LOW;

void setup() {

Serial.begin(9600);

irrecv.enableIRIn();

pinMode(diodaPin, OUTPUT); //deklaracja pinow wyjsciowych

pinMode(diodaPin1, OUTPUT);

pinMode(lampa, OUTPUT);

pinMode (PodLed, OUTPUT);

pinMode (przON, INPUT_PULLUP);

pinMode (przOFF, INPUT_PULLUP);

sensors.begin(); //znow cos dla termometru

sensors.request(address);

dht.setup(DHT11_PIN);//Czujnik wilgotnosci

}

void loop() {

if (digitalRead(przON) == LOW) { //Jeśli przycisk wciśnięty

lampaStatus = ~lampaStatus;

digitalWrite(lampa, lampaStatus); //Włącz /wyłącz lampe

delay(250);

}

if (digitalRead(przOFF) == LOW) { //Jeśli przycisk wciśnięty

diodaStatus = ~diodaStatus;

digitalWrite(diodaPin, diodaStatus); //Wyłącz /wyłącz ledy

delay(250);

}

if (sensors.available())

{

float temperature = sensors.readTemperature(address);

Serial.print(temperature);

Serial.println(F(" 'C"));

sensors.request(address);

}

if (irrecv.decode(&results)) {

switch (results.value) {

case 0x6170807F: //instrukcja dla listwy LED zwiekszanie

if(jasnosc < 255) {jasnosc = jasnosc+51;}

Serial.println(jasnosc);

analogWrite(diodaPin, jasnosc);

zamigajLED(); //funkcja kontrolki odbioru

ekranDane();

ekranLed();

break;

case 0x617040BF: //instrukcja dla listwy LED zmniejszanie

if(jasnosc > 0) {jasnosc = jasnosc-51;}

Serial.println(jasnosc);

analogWrite(diodaPin, jasnosc);

zamigajLED();

ekranDane();

ekranLed();

break;

case 0x617020DF: //instrukcja dla listwy LED pelny

analogWrite(diodaPin, 255);

zamigajLED();

break;

case 0x6170A05F: //instrukcja dla listwy LED wylaczony

analogWrite(diodaPin, 0);

zamigajLED();

break;

case 0x617048B7: //instrukcja dla lampy

lampaStatus1 = ~lampaStatus1;

digitalWrite(lampa, lampaStatus1); //Włącz lampe

zamigajLED();

break;

}

irrecv.resume();

}

}

void zamigajLED() { //kontrolka odbioru pilota

digitalWrite(diodaPin1, HIGH); //Włączenie diody

delay(200); //Odczekanie 0,2 sekundy

digitalWrite(diodaPin1, LOW); //Wyłączenie diody

delay(200); //Odczekanie 0,2 sekundy

}

void ekranDane(){//Wyswietlenie 'danych' na ekranie

delay (50);

lcd.display();

lcd.begin(16, 2); //Deklaracja typu wyswietlacza

lcd.clear(); //Wyczyszczenie wyswietlacza

lcd.setCursor(0, 0); //Ustawienie kursora

lcd.print("LED: "); //Wyświetlenie tekstu

lcd.print(jasnosc); //Wyświetlenie tekstu

if (sensors.available() || (dht.getStatusString() == "OK"))

{

//Pobranie informacji o wilgotnosci

int wilgotnosc = dht.getHumidity();

//Pobranie informacji o temperaturze

int temperatura = dht.getTemperature();

float temperature = sensors.readTemperature(address);

Serial.print(temperature);

Serial.println(F(" 'C"));

lcd.setCursor(0, 1); //Ustawienie kursora

lcd.print("T1:"); //Wyświetlenie tekstu

lcd.setCursor(3, 1); //Ustawienie kursora

lcd.print(temperature); //Wyświetlenie tekstu

lcd.setCursor(10, 0); //Ustawienie kursora

lcd.print("W: ");

lcd.setCursor(12, 0);

lcd.print(wilgotnosc);

lcd.setCursor(9, 1); //Ustawienie kursora

lcd.print("T2:");

lcd.setCursor(12, 1);

lcd.print(temperatura);

sensors.request(address);

}

//Odczekanie wymaganego czasugo

delay(dht.getMinimumSamplingPeriod());

}

void ekranLed(){ //Podswietlenie ekranu (czasowe)

digitalWrite (PodLed, HIGH);

delay (3000);

digitalWrite (PodLed, LOW);

}

Treker
Autor wpisu
Administrator

20:18, 01.03.2017

#2

leepa79, super, widzę, że potencjał płytki stykowej wykorzystujesz w 100% :)

Informacje o wykorzystaniu pilota znajdziesz w najnowszej części kursu budowy robotów:

Kurs budowy robotów – #8 – zdalne sterowanie IR (RC5)

dejmieno

14:44, 30.05.2017

#3

Czy ten kurs będzie jeszcze kontynuowany? Z tego co widzę w sklepie botland na opisie zestawu to w planach jest jeszcze chyba jeden artykuł "Inteligentne oświetlenie domowe".

Ciekawe, czy jest jeszcze potencjał na "Kurs Arduino poziom III" ;). Te dwa kursy chyba mocno wyczerpują temat :).

Treker
Autor wpisu
Administrator

15:17, 30.05.2017

#4

dejmieno, oczywiście będzie kolejna część, ale niestety ostatnio nie mogłem zajmować się tym tematem (stąd nawet moja ogólnie mniejsza aktywność przy publikacji artykułów). Mam jednak nadzieję, że jeszcze kilka dni i wszystko wróci na właściwe tory, wtedy nadrabiam zaległości i działamy dalej!

m_rat

13:17, 06.07.2017

#5

Świetny kurs.

Mam nadzieję, że jak najszybciej ukaże się następny rozdział :)!

marekmarecki

15:35, 17.07.2017

#6

mam mały problem z tak funkcją define DHTTYPE DHT11

po napisaniu programu wyskakuje błąd przy wgrywaniu nie wiem jak to naprawić

Treker
Autor wpisu
Administrator

15:46, 17.07.2017

#7

marekmarecki, witam na forum :) Pokaż proszę kod, który kompilujesz (wklej dokładnie, to co próbujesz wgrać u siebie).

marekmarecki

9:44, 18.07.2017

#8

taki wyświetla błąd po wgraniu programu z funkcją define DHTTYPE DHT11

a tak wygląda napisany program

Treker
Autor wpisu
Administrator

10:00, 18.07.2017

#9

marekmarecki, ciężko powiedzieć, ponieważ nic takiego w kursie nie występuje. Nie wiem jakiej biblioteki używasz i skąd ten program i błąd. Zwróć uwagę, że w kursie korzystamy z biblioteki przyjmującej tylko 1 argument, a Ty do swojej podajesz dwa. Jeśli masz pytania nie związane z kursem, czyli np. z inną biblioteką to załóż osobny temat, w którym opiszesz dokładnie swój problem i podlinkujesz używane biblioteki. Dzięki temu nie będziemy mieszać w głowach osobom, które korzystają z tego kursu - z góry dziękuję za pomoc w utrzymaniu porządku na forum :)

Drugie rozwiązanie: skorzystaj z bibliotek i programów opisanych w kursie, nie powinieneś mieć wtedy żadnych problemów :)

yacca

21:53, 27.09.2017

#10

A czy można by uzupełnić ten kod o obsługę prostego LCD - tak, aby dane na temat temperatury i wilgotności wyświetlać bezpośrednio na wyświetlaczu?

Pozdrawiam, y.

Treker
Autor wpisu
Administrator

22:50, 27.09.2017

#11

yacca, witam na forum - oczywiście, że tak :)

Informacje o korzystaniu z LCD znajdziesz w pierwszym poziomie kursu Arduino: Kurs Arduino – #7 – Wyświetlacz tekstowy, LCD 2×16

marekmarecki

16:55, 28.09.2017

#12

Cytat:

program był zrobiony z normalnym LCD 16x2 i działał u mnie bez problemu teraz jest przerobiony pod konwerter lcd i też nie ma problemów

olmekowie

22:08, 11.10.2017

#13

Witam kiedy się spodziewać Kurs Arduino II – #9 – inteligentne oświetlenie domowe ??

Treker
Autor wpisu
Administrator

22:25, 11.10.2017

#14

olmekowie, witam na forum :) Niestety w przypadku tej części coś ewidentnie mi nie idzie i za każdym razem, pojawia się przeszkoda. Przez co artykuł jest odkładany w nieskończoność. Mam teraz plan, aby napisać go raz jeszcze, zupełnie inaczej niż planowałem - postaram się, aby pojawił się w tym miesiącu :)

Edit: Sporo się tego ostatnio nazbierało (kurs FPGA, kurs Raspberry Pi)... Nie miałem kiedy opublikować tego odcinka. Niedługo nadrobię jednak zaległość - obiecuję!

SiaQ

21:16, 18.10.2017

#15

Witam, mam pytanie - czy będzie (ewentualnie jest już) jakiś artykuł, w którym opisane jest jak można rozszerzyć ilość wejść/wyjść Arduino przy pomocy ekspandera np.

https://botland.com.pl/ekspandery-wyprowadzen/4455-modul-pcf8574-ekspander-wyprowadzen-mikrokontrolera.html?search_query=+PCF8574&results=19

Proszę o informacje, ponieważ bardzo mi się to przyda :)

Pozdrawiam!

Treker
Autor wpisu
Administrator

10:05, 19.10.2017

#16

SiaQ, witam na forum :)

Z ekspandera pinów korzystamy w kursie budowy robotów, konkretnie tutaj: Kurs budowy robotów – #9 – ekspander I/O, serwo

Zobacz wszystkie komentarze (41) na forum

FORBOT Damian Szymański © 2006 - 2018 Zakaz kopiowania treści oraz grafik bez zgody autora. vPRsLH.