Skocz do zawartości

Kurs Arduino - #7 - Wyświetlacz tekstowy, LCD 2x16


Komentator

Pomocna odpowiedź

🙂 juz dawno sie tak dobrze nie bawilem, super elegancki pomysl z tym kursem

1 dzien "wolniejszy" w pracy i

balagan moze i dosc przecietne ale zabawa naprawde przednia 🙂 zdecydowanie polecam 🙂

balganiarski kod ponizej jesli sie zmiesci bo to raczej madrosci nie wniesie wylacznie wykorzystanie info z kursu i dostepnych bibliotek 🙂 super zabawa i bawcie sie dobrze 🙂

------------
//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
#include <TimeLib.h>

/*******************************************************

********************************************************/

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
const unsigned long DEFAULT_TIME = 1514764800;
String dnitygodnia[7]={"Niedziela","Poniedzialek","Wtorek","Sroda","Czwartek","Piatek","Sobota"};
String miesiac[12]={"Styczen","Luty","Marzec","Kwiecien","Maj","Czerwiec","Lipiec","Sierpien","Wrzesien","Pazdziernik","Listopad","Grudzien"};
String tekst1,tekst2;
int    dlugosc_tekstu;
int    pozycja=0;
int    kierunek=1;
unsigned long  czas=0;
int            tempo=450;


byte ludzik[8] = { //customChar to nazwa znaku
0b01110,
0b01110,
0b00100,
0b01110,
0b10101,
0b00100,
0b01010,
0b01010
};

byte ludzik2[8] = { //customChar to nazwa znaku
0b01110,
0b01110,
0b10101,
0b01110,
0b00100,
0b00100,
0b01010,
0b01010
};

byte ludzik3[8] = { //customChar to nazwa znaku
0b01110,
0b01110,
0b00100,
0b11111,
0b00100,
0b00100,
0b01010,
0b01010
};

byte klodka_z[8] = { //customChar to nazwa znaku
0b01110,
0b10001,
0b10001,
0b11111,
0b11011,
0b11011,
0b11111,
0b00000
};

byte klodka_o[8] = { //customChar to nazwa znaku
0b01110,
0b10000,
0b10000,
0b11111,
0b11011,
0b11011,
0b11111,
0b00000
};

byte klodka_or[8] = { //customChar to nazwa znaku
0b01110,
0b00001,
0b00001,
0b11111,
0b11011,
0b11011,
0b11111,
0b00000
};
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
#define margines  "     "

// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0);      // read the value from the sensor 
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
// we add approx 50 to those values and check to see if we are close
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
// For V1.1 us this threshold
if (adc_key_in < 50)   return btnRIGHT;
if (adc_key_in < 250)  return btnUP;
if (adc_key_in < 450)  return btnDOWN;
if (adc_key_in < 650)  return btnLEFT;
if (adc_key_in < 850)  return btnSELECT;

return btnNONE;  // when all others fail, return this...
}
void digitalClockDisplay(){

if (tekst2 == NULL) {
    tekst2=margines+dnitygodnia[weekday()-1]+", "+day()+" "+miesiac[month()-1]+" "+year()+margines;
    dlugosc_tekstu=tekst2.length();
}
tekst1=margines+dnitygodnia[weekday()-1]+", "+day()+" "+miesiac[month()-1]+" "+year()+margines;
if (tekst1 != tekst2 ) {
   tekst2=tekst1;
   dlugosc_tekstu=tekst2.length();
}
lcd.setCursor(0,0);
//lcd.print(dlugosc_tekstu);
lcd.print(tekst1.substring(pozycja));
if ( millis() - czas > tempo) {
    pozycja+=kierunek;
    czas= millis();
}
if (pozycja+16 >= dlugosc_tekstu) kierunek=-1;
if (pozycja == 0) kierunek=1;
lcd.setCursor(8,1);
printDigitsLCD(hour(),false);
printDigitsLCD(minute(),true);
printDigitsLCD(second(),true);

}


void printDigitsLCD(int digits, bool czy){
 // utility function for digital clock display: prints preceding colon and leading 0
 if ( czy ) {
    lcd.print(":");
 }
 if(digits < 10)
   lcd.print('0');
 lcd.print(digits);
}

void processSyncMessage() {
 unsigned long pctime;
    pctime = Serial.parseInt();
    if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013)
      setTime(pctime); // Sync Arduino clock to the time received on the serial port
    }

}
void setup()
{
 lcd.begin(16, 2);              // start the library
 lcd.setCursor(0,0);
 //lcd.print("Uruchamianie ..."); // print a simple message
 setTime(DEFAULT_TIME);
 Serial.begin(9600);
 //Serial.println("na przyklad: date -d \"+1 hours\" +%s > /dev/ttyUSB0");
 lcd.createChar(0, ludzik);
 lcd.createChar(1, klodka_z);  
 lcd.createChar(2, klodka_o);
 lcd.createChar(3, ludzik2);
 lcd.createChar(4, ludzik3);
 lcd.createChar(5, klodka_or);

}

void loop()
{
   if (Serial.available()) {
   processSyncMessage();
 }
 if (timeStatus()!= timeNotSet) {
   digitalClockDisplay();  
 }

 delay(50);



lcd.setCursor(0,1);            // move to the begining of the second line
lcd_key = read_LCD_buttons();  // read the buttons

switch (lcd_key)               // depending on which button was pushed, we perform an action
{
  case btnRIGHT:
    {
    lcd.print("RIGHT ");
    break;
    }
  case btnLEFT:
    {
    lcd.print("LEFT   ");
    break;
    }
  case btnUP:
    {
    lcd.print("UP    ");
    break;
    }
  case btnDOWN:
    {
    lcd.print("DOWN  ");
    break;
    }
  case btnSELECT:
    {
    lcd.print("SELECT");
    break;
    }
    case btnNONE:
    {
    //lcd.print(".:|:.  ");
    lcd.print((char)5); 
    lcd.print((char)0);
    lcd.print((char)1);
    lcd.print((char)4);
    lcd.print((char)2);
    lcd.print((char)3);
    lcd.print(" ");
    break;
    }
}

}

------------ 

[ Dodano: 15-03-2018, 21:03 ]

#define margines " " na filmie jest dlugosc 5 #define margines " " to chyba jedyna roznica, no i ten kod kurcze nie wiedzialem ze to sie przeklei bez zadnych wciec i kolorwania skladni to fatktycznie masakra 🙂 no trudno 🙂 poprawi sie pozniej 🙂

__________

Komentarz dodany przez: Treker

Kody programów należy umieszczać przez narzędzie KOD (znajdziesz je w edytorze pod ikonką "<>"). Dzięki niemu składania programów jest automatycznie kolorowana, a wtedy wszystkim znacznie łatwiej analizować wklejone programy. Proszę to poprawić - z góry dziękuję za zrozumienie i pomoc przy utrzymaniu porządku na forum.

(oh) faktycznie miales racje robi roznice .... wow teraz musze zrozumiec ze pomimio tego re kolorowanie skladni jest tak zle to wyglada 😃

dzieki za info w kazdym razie 🙂

Link do komentarza
Share on other sites

mchrzanowski, witam na forum i gratuluje projektu! Pamiętaj proszę, aby wszystkie kody programów umieszczać w tagach - ułatwia to wszystkim analizowanie programów 😉

  • Lubię! 1
Link do komentarza
Share on other sites

🙂 do projektu dlaeka droga 🙂 menu z ustawianiem czasu przede mna dopiero 🙂 to tylko 1 dzien 🙂

drogi Panie doskanly pomysl z tym kursem i doskonale wykonanie 🙂

jesli juz sie naucze wklejac kody w odpowiednim forramcie i daj bog starczy ciepliowsci na podzielenia sie ta informacja ,tej mi to raczej starczy gorzej z odbiorca 🙂

tak czy inaczej

kapitalny pomysl, niecodzinne podejscie kopletjnhie niespodziewany efekt 🙂 nie moj oczywiscie :)duzo bardzo duzy plus 🙂

Link do komentarza
Share on other sites

Stoper, filmik oraz kod w linku do Githuba

#include <LiquidCrystal.h>            //Załączenie biblioteki
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);  //Informacja o podłączeniu wyświelacza do danych pinów

#define start 13                      // Zdefiniowanie nazw przycisków
#define stop  12

int dziesiata_sekundy;    // Licznik 
int sekunda;
int minuta;

int tryb=2;               // Tryb pracy 
                         // 0 = Pomiar czasu
                         // 1 = Wynik
                         // 2 = Gotowy do pracy

int kursor_minuta;                  // Położenie kursora dla sekund, minut
int kursor_sekunda;
int przycisk_wcisniety(int przycisk); // Funkcja obsługująca naciskanie przycisków
void pomiar_wyswietlanie(int minuty, int sekundy, int dziesiate_sekundy); // Funkcja obsługująca wyświetlanie drugiego wersa wyświetlacza


unsigned long aktualny_czas  = 0;
unsigned long poprzedni_czas = 0;
unsigned long roznica_czasu  = 0;

int wynik_minuta;
int wynik_sekunda;
int wynik_dziesiata_sekundy;

void setup() 
{
 pinMode(start,INPUT_PULLUP);  // Przyciski jako wejścia
 pinMode(stop,INPUT_PULLUP);

 lcd.begin(16, 2);     // Deklaracja typu wyświetlacza
 lcd.clear();          // Czyszczenie zawartości wyświetlacza
 lcd.setCursor(0,0);   // Ustawianie kursora
 lcd.print("STOPER");  // Napis powitalny
 delay (3000);
}

void loop()
{
 if (przycisk_wcisniety(start))tryb=0;
 if (przycisk_wcisniety(stop)) tryb++;
 if (tryb>2) tryb =1;
 aktualny_czas = millis();
 roznica_czasu = aktualny_czas - poprzedni_czas;

   if (roznica_czasu>=100UL) // Jeśli różnica czasu wynosi 1/10 sekundy wykonaj wszystkie instrukcje poniżej, dzięki temu wyświetlacz nie miga!
       {
        dziesiata_sekundy ++;
        if (dziesiata_sekundy>9){sekunda++;dziesiata_sekundy=0;}
        if (sekunda>59){minuta++;sekunda=0;}
        poprzedni_czas=aktualny_czas;

             if (tryb==0) // Pomiar czasu
             {
              lcd.clear();
               lcd.setCursor(0,0);
               lcd.print("Pomiar w trakcie");
               pomiar_wyswietlanie(minuta, sekunda, dziesiata_sekundy);
               wynik_minuta=minuta;
               wynik_sekunda=sekunda;
               wynik_dziesiata_sekundy=dziesiata_sekundy;
             }

              if (tryb==1) // Wynik
             {
               lcd.clear();
               lcd.setCursor(0,0);
               lcd.print("Wynik");
               pomiar_wyswietlanie(wynik_minuta, wynik_sekunda, wynik_dziesiata_sekundy);
               poprzedni_czas=millis();               
               minuta=wynik_minuta;
               sekunda=wynik_sekunda;
               dziesiata_sekundy=wynik_dziesiata_sekundy;
             }

             if (tryb==2) //Gotowy do pracy
             { 
               minuta=sekunda=dziesiata_sekundy=0;
               lcd.clear();
               lcd.setCursor(0,0);
               lcd.print("Gotowy do pracy");
               pomiar_wyswietlanie(minuta, sekunda, dziesiata_sekundy);

             }
       }                
}

int przycisk_wcisniety(int przycisk)
{
 if (digitalRead(przycisk)==0)
     {
       delay(100);
       if(digitalRead(przycisk)==0)return 1;
     }
 return 0;
}

void pomiar_wyswietlanie(int minuty, int sekundy, int dziesiate_sekundy)
{
     if (minuty>9) kursor_minuta=5; // Zmiana położenia kursora dla minut w momencie gdy wartosc staje się dwucyfrowa
         else    
         {kursor_minuta=6;          // Zapewnienie wyświetlania cyfr jednosci w formacie 01, 02, 03, etc.
          lcd.setCursor(5,1);
          lcd.print(0);} 


     if (sekundy>9) kursor_sekunda=8;   // Zmiana położenia kursora dla sekund w momencie gdy wartosc staje się dwucyfrowa
         else    
         {kursor_sekunda=9;            // Zapewnienie wyświetlania cyfr jednosci w formacie 01, 02, 03, etc.
          lcd.setCursor(8,1);
          lcd.print(0);}

     lcd.setCursor(0,1);               // Czas
     lcd.print("Czas:");

     lcd.setCursor(kursor_minuta,1);   // Minuty
     lcd.print(minuty);

     lcd.setCursor(7,1);               // Dwukropek
     lcd.print(":");

     lcd.setCursor(kursor_sekunda,1);  // Sekundy
     lcd.print(sekundy);

     lcd.setCursor(10,1);               // Dwukropek
     lcd.print(":");  

     lcd.setCursor(11,1);               // Dziesiętne części sekundy 
     lcd.print(dziesiate_sekundy);
}

  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

super stoper 🙂 i ten ladny kod ehh 🙂

jak patrze na swoj balagan to kompletnie nie mam uwag 🙂 u mnie polowa kodu to definicja char'ow ludzik1 ludzik2 ... 🙂

napraawde ladnie napisany czytelny program, gratuluje ! 🙂

zacytuje kabarte moralnego niepokoju, skecz.. jerzyk dzisiaj nie pije..:

"mozna sie bawic?" 🙂

jak widac mozna 🙂 milego wieczoru 🙂

Link do komentarza
Share on other sites

Witam, pół niedzieli się męcze i nie mogę dojść do ładu z tym zadaniem, widziałem w wielu postach że jest tyle sposobów na rozwiązanie zadania ile ludzi do tego podchodzi więc mam nadzieję że mój nie będzie tragiczny. wykorzystałem czas liczony w arduino i na podstawie różnicy czasu pomiędzy wciśnięciami przycisku chciałem pokazać wynik na wyświetlaczu. Problem się pojawia gdzieś w okolicach wciśnięcia przycisku stop powyżej wartości millis równej 64000, zamiast przypisać do stopu wartości 64000 to program przypisuje jakieś śmiesznie niskie wartości. Mógł by ktoś pomóc znaleźć przyczyne?

#include <LiquidCrystal.h>        //biblioteka wyswietlacza
LiquidCrystal lcd(2,3,4,5,6,7);   //podl wyswietlacza 
unsigned int start = 0;           //zmienna start
unsigned int stopp = 0;           //zmienna stop
unsigned int roznica = 0;         //zmienna roznicy
int ss = 0;  //zmienna milisekund
int s = 0;   //zmienna sekund
int m = 0;   //zmienna minut
byte g = 0;  //zmienna godzin




void setup() {
Serial.begin(9600);        //uruchomienie uart
pinMode(8, INPUT_PULLUP);  //przycisk do startu
pinMode(9, INPUT_PULLUP);  //przycisk do stopu
lcd.begin(16,2);           //ustawienie wyswietlacza
lcd.setCursor(0,0);        //ust kursora
lcd.print("Start wcisnij1");  //wysw. napisu

}

void loop(){
lcd.setCursor(0,1);      //ust kursora
if (digitalRead(8) == LOW){    //rozp. petli
  start = millis(); //przypisanie milisekund do startu
  lcd.clear();   //wyczyszczenie lcd
  lcd.setCursor(0,0);  //ust. kursora
  lcd.print("Stop wcisnij 2"); //wysw. napisu
  delay(100);  //pauza
}
if (digitalRead(9) == LOW){ //rozp. petli
  stopp = millis();   //przypisanie milisekund do stopu
  roznica = stopp - start;   //obliczenie roznicy pomiedzy start a stop
  g = roznica/3600000;   //obliczenie godzin
  m = (roznica-g*3600000)/60000;  //obliczenie minut
  s = (roznica-g*3600000-m*60000)/1000;   //obliczenie sekund
  ss = (roznica-g*3600000-m*60000-s*1000);   //obliczenie milisekund
  lcd.clear();   //czyszczenie lcd
  lcd.setCursor(0,0);  //ustawienie kursora
  lcd.print("Czas g:m:s:ss");  //wyswietlenie napis
  lcd.setCursor(0,1);  //ust. kursora w drugiej lini
  lcd.print("     "); //odstep w drugiej lini, nie wiem dlaczego nie mogłem 
  lcd.print(g);       //ustawic poprostu (0,6) bo to nie przynosi efektu                  
  lcd.print(":");
  lcd.print(m);
  lcd.print(":");
  lcd.print(s);       //wyswietlenie obliczonych godzin, minut i sekund
  lcd.print(":");
  lcd.print(ss);
  delay(500);}   //pauza dla alepszej widocznosci w uart
  Serial.print(millis());
  Serial.print("start ");
  Serial.print(start);
  Serial.print("stop ");
  Serial.print(stopp);
  Serial.print("roznica ");   //wyswietlenie w uart
  Serial.print(roznica);
     Serial.print(" ");
  Serial.print(g);
     Serial.print(" ");
  Serial.print(m);
     Serial.print(" ");
  Serial.println(s);

 // put your main code here, to run repeatedly:

}

Na screenie z portu szeregowego widać w środkowym słupku zaznaczoną wartość 58190 co odpowiada wartości millis z momentu wciśnięcia przycisku, po kolejnym wciśnieciu stopu przy millis równym 69254 została przypisana wartość 3204 i nie mogę rozgryźć dlaczego tak się dzieje.

To mój pierwszy post, przepraszam jak coś jest nie tak.

Link do komentarza
Share on other sites

Bubu, witaj na forum 🙂

Problem się pojawia gdzieś w okolicach wciśnięcia przycisku stop powyżej wartości millis równej 64000, zamiast przypisać do stopu wartości 64000 to program przypisuje jakieś śmiesznie niskie wartości. Mógł by ktoś pomóc znaleźć przyczyne?

Zmienna stopp w Twoim programie jest typu unsigned int, który potrafi przechować maksymalnie 65535 wartości. Po przekroczeniu zakresu zmienna zaczyna przyjmować kolejne wartości od zera - stąd Twoje "niskie wartości". O pojemności zmiennych pisałem w tym artykule: Kurs Arduino – #3 – UART (komunikacja z PC), zmienne. Jeśli chcesz przechowywać bardzo duże wartości to możesz skorzystać z typu unsigned long, który potrafi przechować 4294967295 wartości.

Link do komentarza
Share on other sites

kld5, witam na forum!

Co dokładnie ma z tyłu Twój wyświetlacz? Czy masz go z naszych zestawów? Nie widzę, aby do Twojego maila przypisany był taki zestaw. Taka informacja ułatwi rozwiązanie problemu.

Link do komentarza
Share on other sites

mam pytanie dotyczące podłączenia wyświetlacza. Jak to zrobiliście? mój wyświetlacz ma od tyłu coś, co umiemożliwia wetknięcie go do płyty.

Pewnie masz wyświetlacz z dołączonym konwerterem magistrali I2C.

Takie cuś?

https://botland.com.pl/wyswietlacze-alfanumeryczne/2351-wyswietlacz-lcd-2x16-znakow-niebieski-konwerter-i2c-lcm1602.html

Link do komentarza
Share on other sites

Wielki powrót!

/*
https://forbot.pl/blog/kurs-arduino-wyswietlacz-tekstowy-lcd-id4263
Zadanie domowe 7.4
*/

#include <LiquidCrystal.h>     //Biblioteka obslugujaca wyswietlacz LCD
#define przycisk 8             //Przypisanie wejscia 8 do przycisku

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);   //Deklaracja obiektu lcd

void setup(){
  lcd.begin(16, 2);             //Iformacja o ilosci znakow i wierszy
  lcd.setCursor(0, 0);          //Ustawienie kursora
  lcd.print("Stoper Start:");   //Komenda wypisania
  lcd.setCursor(0, 1);
  lcd.print("Czas:");

  pinMode(8, INPUT_PULLUP);     //Ustawienie funkcji wejscia 8 na INPUT_PULLUP
}

double czas;                     //Deklaracja obiektu czas  

void loop(){ 
  lcd.setCursor(0, 0);          //Ustawienie kursora
  lcd.print("Stoper Start!");   //Komenda wypisania
  lcd.setCursor(0, 1);
  lcd.print("Czas: 0");

  czas=0.0;                     //Przypisanie wartosci zmiennej czas
  while(digitalRead(przycisk)==HIGH){}   //Dopoki przycisk nie zostanie nacisniety
  delay(150);                            //opznienie

  while(digitalRead(przycisk)==HIGH){
    lcd.clear();                         //wyczysc ekran
    lcd.setCursor(0, 0);       
    lcd.print("Stoper stop!");          

    czas+=0.1;                           //Dodaj do zmiennej czas 0.1
    lcd.setCursor(0,1);      
    lcd.print("Czas: ");
    lcd.print(czas);
    delay(100);
  }
  while(digitalRead(przycisk)==LOW){}    //Zatrzymaj sie dopoki przycisk bedzie wcisniety
  delay(100);
  lcd.clear();                           //wyczysc ekran
  lcd.setCursor(0, 0);
  lcd.print("Twoj czas!");
  lcd.setCursor(0, 1);
  lcd.print(czas);
  while(digitalRead(przycisk)==HIGH){}
  delay(200);
}
  • Lubię! 1
Link do komentarza
Share on other sites

2 godziny temu, kris2k napisał:

Przegladam kody rozwiazan zadnia 7,4 czyli stopera i mam pytanie dot. tego zapisu:

(To jest kawalek kodu uzytkownika Gregorio)

if (roznica_czasu>=100UL)

Co to jest to dziwne "100UL" ?

Cześć,

oznacza, że zmienna jest "unsigned long", co w przypadku Arduino oznacza 32 bity.

Pozdrawiam

Link do komentarza
Share on other sites

15 minut temu, FlyingDutch napisał:

Cześć,

oznacza, że zmienna jest "unsigned long", co w przypadku Arduino oznacza 32 bity.

Pozdrawiam

Czyli to taki trik żeby warunek IF porównał zmienna typu "unsigned long" z druga zmienna tez typu "unsigned long".

Nie próbowałem, ale pewnie bez tego dopisu "UL" IF nie zadziała?

Link do komentarza
Share on other sites

Zadziała albo nie - zależy od wartości.

Dlaczego nie chcesz poszukać sobie na forum (bo już było wyjaśniane i to nie raz) tylko czekasz, aż ktoś Ci wyośli? Może uważasz, że naszym obowiązkiem jest wyjaśnianie podstaw każdemu, kto się zgłosi i komu nie będzie się chciało szukać? Bo jeśli tak - to chyba nie to forum, spróbuj na onecie...

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.