Spisu treści:

Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej): 9 kroków
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej): 9 kroków

Wideo: Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej): 9 kroków

Wideo: Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej): 9 kroków
Wideo: Test wyświetlacza Head-Up display! #101_Gadżetów 2024, Listopad
Anonim
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej)
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej)
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej)
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej)
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej)
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej)
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej)
Prototyp inteligentnego motocykla HUD (nawigacja zakręt po zakręcie i wiele więcej)

Cześć !

Ten Instructables to opowieść o tym, jak zaprojektowałem i zbudowałem platformę HUD (Heads-Up Display) przeznaczoną do montażu na kaskach motocyklowych. Został napisany w kontekście konkursu „mapy”. Niestety nie udało mi się ukończyć tego projektu na czas przed terminem konkursu, ale nadal chciałem podzielić się moimi postępami w nim, a także udokumentować wszystkie próby i błędy, które przeszedłem podczas jego tworzenia.

Pomysł na ten projekt przyszedł mi do głowy kilka lat temu, kiedy wsiadłem w motocykle i zacząłem zastanawiać się, jaki sprzęt będę musiał kupić, aby jazda była przyjemniejsza. W tamtym czasie zdziwiło mnie, że najlepszym sposobem na uzyskanie podstawowej nawigacji GPS podczas jazdy było po prostu przymocowanie smartfona do kierownicy roweru. Pomyślałem sobie, że z pewnością może być lepszy sposób na uzyskanie tego rodzaju informacji w locie.

Właśnie wtedy do mnie dotarło: wyświetlacz heads-up może być sposobem na nawigację podczas jazdy, bez rozładowywania baterii telefonu i wystawiania jej na działanie żywiołów.

Z biegiem czasu ten pomysł dojrzewał w mojej głowie i pomyślałem, że posiadanie HUDa przed sobą przez cały czas pozwoliłoby na znacznie więcej zastosowań niż zwykła nawigacja. Dlatego planuję uczynić platformę publiczną i modułową, aby każdy mógł stworzyć moduł wyświetlający potrzebne informacje na własnym HUD

Chociaż są dostępne na rynku produkty, które spełniają to zadanie, nie ma tak modułowych jak moja platforma, a także bywają trochę drogie. W każdym razie witaj w tym projekcie.

Co działa od teraz

Jak już wspomniano, projekt ten jest nadal w bardzo zaawansowanym stanie i nad tym obecnie pracuje.

- Komunikacja między smartfonem a płytką z ESP32 (telefon wybudzony)

- Wykonano projekt optyki (na dłuższą metę może wymagać niewielkich korekt)

- Aplikacja nawigacyjna na Androida korzystająca z pakietu SDK nawigacji Mapbox:

- Potrafi obliczać i wyświetlać pozycję użytkownika na mapie, a także trasę z niej do miejsca docelowego

- Możliwość połączenia z urządzeniem Bluetooth (adres MAC urządzenia jest od teraz zakodowany na stałe)

- Możliwość nawigacji w czasie rzeczywistym, w tym wydobywania i wysyłania informacji o nadchodzącym manewrze przez szeregowy Bluetooth (na razie obsługuje tylko zakręty)

Co wymaga pracy

Ta lista zawiera przedmioty, które są absolutnie niezbędne do zamierzonego użycia HUD, ale nie są jeszcze gotowe do wdrożenia.

- Ogólna konstrukcja (mocowanie kasku, mechanizm regulacji kąta odbłyśnika,..)

- Aplikacja na Androida:

- Wdrożenie wykrywania i korekcji poza trasą

- Możliwość wprowadzenia przez użytkownika adresu docelowego

- Punkty trasy?

- Ergonomia / Estetyka

Kieszonkowe dzieci:

Niezbędniki

-Płytka rozwojowa oparta na esp32

- Jakikolwiek nowy smartfon z Androidem (włączony Bluetooth)

- SSD1306 lub inny włączony 96-calowy ekran OLED (mój miał 128x64 piksele, patrz część "Mózgi: Mikrokontroler i ekran")

- Odbłyśnik (wystarczy dowolny kawałek akrylu/szkła/pleksi)

- Soczewka Fresnela (moja miała długość F około 13 cm, patrz część "Wybór soczewki")

Narzędzia

-Lutownica

- Deska do krojenia chleba

- Kilka kabli rozruchowych

- drukarka 3d / usługa drukowania 3d

Krok 1: Jak to wszystko działa: Wyjaśnienie wyborów projektowych

Jak to wszystko działa: wyjaśnienie wyborów projektowych
Jak to wszystko działa: wyjaśnienie wyborów projektowych
Jak to wszystko działa: wyjaśnienie wyborów projektowych
Jak to wszystko działa: wyjaśnienie wyborów projektowych
Jak to wszystko działa: wyjaśnienie wyborów projektowych
Jak to wszystko działa: wyjaśnienie wyborów projektowych

Podstawową ideą wyświetlacza Heads Up jest wyświetlanie obrazu przed czyjąś wizją, dzięki czemu nie muszą odwracać wzroku od tego, co robią (czy to pilotowanie samolotu, czy prowadzenie motocykla, który będzie naszym przykładowy przypadek).

Optyka

Technicznie można to osiągnąć, ustawiając ekran przed oczami użytkownika. Jednak ekran nie jest przezroczysty, przez co utrudniałby użytkownikowi widzenie. Następnie można umieścić ekran przed odblaskową powierzchnią, która odzwierciedlałaby zawartość ekranu, a jednocześnie byłaby wystarczająco przejrzysta, aby użytkownik mógł zobaczyć, co znajduje się przed nim.

Takie podejście ma jednak ogromną wadę: rzeczywisty ekran jest zwykle bliżej oczu użytkownika niż to, na czym użytkownik faktycznie musi się skupić (np. droga przed nim). Oznacza to, że aby odczytać to, co znajduje się na powierzchni odbijającej, oczy użytkownika musiałyby dostosować się do odległości wyświetlacza od jego oczu (powiedzmy 20 cm), a następnie musiałyby się ponownie dostosować, aby skupić się na drodze przed nimi (~2/5 metrów). Czas, jaki zajmuje ta cała operacja, to cenny czas, który należy poświęcić na patrzenie na drogę, a częsta adaptacja może być niewygodna dla użytkownika już po kilku minutach.

Dlatego postanowiłem dodać soczewkę między ekranem a reflektorem. Soczewka ta, jeśli zostanie wybrana starannie, powinna pozwolić na stworzenie wirtualnego obrazu ekranu (patrz schemat powyżej), który następnie wydawałby się być dalej od oczu użytkownika, tak jak jest w rzeczywistości, przez co wymaga mniej gwałtownych adaptacji (lub wcale, w idealnym scenariuszu). Taka konstrukcja umożliwia użytkownikowi szybkie spojrzenie na reflektor, uzyskanie potrzebnych informacji i natychmiastowe spojrzenie na drogę.

Rola smartfona

Ponieważ próba wdrożenia całej aplikacji nawigacyjnej na samym ESP32 była nierealistyczna, postanowiłem zrobić aplikację na Androida, która by się tym zajęła. Aplikacja musiałaby wtedy tylko powiedzieć ESP32, co użytkownik musi zrobić, aby dotrzeć do celu, a ESP32 przekazuje te informacje przez HUD (patrz rysunek „Jak działa moduł”).

Krok 2: Części – mózgi: mikrokontroler i ekran

Części - mózgi: mikrokontroler i ekran
Części - mózgi: mikrokontroler i ekran
Części - mózgi: mikrokontroler i ekran
Części - mózgi: mikrokontroler i ekran

Jak wspomniano powyżej, planowałem, aby mój moduł wyświetlał informacje nawigacyjne, podczas gdy w rzeczywistości nie musiał obliczać rzeczywistego pozycjonowania, śledzenia i nawigacji w czasie rzeczywistym. zamiast tego telefon użytkownika komunikowałby się z modułem i wysyłał mu informacje, które następnie byłyby wyświetlane na HUD.

Aby ułatwić komunikację między telefonem użytkownika a modułem, wybrałem do tego projektu płytkę opartą na ESP32. Wybór ten był spowodowany tym, że ten konkretny moduł miał zintegrowane funkcje Bluetooth, a także kilka innych interesujących specyfikacji (łatwa w użyciu nieulotna pamięć masowa, dwurdzeniowy procesor, wystarczająca ilość pamięci RAM do obsługi wyświetlacza OLED przez I2C, …). Zaprojektowanie płytek PCB opartych na ESP32 jest stosunkowo proste, co wziąłem pod uwagę. Mam też doświadczenie zawodowe w obsłudze i projektowaniu układów z ESP32, co zdecydowanie wpłynęło na mój wybór.

Wybór ekranu sprowadzał się w zasadzie do tego, co mogłem znaleźć, że byłby wystarczająco jasny do użytku, a jednocześnie był tak mały, jak to tylko możliwe. Nie martwiłem się zbytnio liczbą pikseli ekranu, ponieważ moim celem było posiadanie bardzo minimalistycznego i prostego interfejsu użytkownika.

Należy zauważyć, że sterownik ekranu powinien być obsługiwany przez bibliotekę umożliwiającą dublowanie obrazu. Dzieje się tak dlatego, że wyświetlany obraz jest odwracany, gdy przechodzi przez obiektyw i pojawia się w reflektorze, a brak konieczności ręcznego odwracania tego, co jest wyświetlane, jest ogromnym ciężarem z naszych ramion jako budowniczych.

Krok 3: Części - Optyka: Znalezienie kompromisu

Części - Optyka: znalezienie kompromisu
Części - Optyka: znalezienie kompromisu
Części - Optyka: znalezienie kompromisu
Części - Optyka: znalezienie kompromisu
Części - Optyka: znalezienie kompromisu
Części - Optyka: znalezienie kompromisu

Optyka do tego projektu była dość trudna, ponieważ nie miałem pojęcia, czego szukam, kiedy zaczynałem ten projekt. Po kilku badaniach zrozumiałem, że chciałem stworzyć „wirtualny obraz” mojego ekranu OLED, który wydawałby się być dalej od oka, niż jest w rzeczywistości. Idealna odległość do utworzenia tego wirtualnego obrazu wynosiłaby około 2-5 metrów przed kierowcą, a wydaje się, że jest to odległość do obiektów, na których skupiamy się podczas jazdy (inne samochody, wyboje na drodze itp.).

Aby osiągnąć ten cel, zdecydowałem się na użycie soczewek Fresnela, ponieważ są one dość duże, tanie, wydawały się oferować wystarczająco dobrą ogniskową dla mojego projektu i można je ciąć prostymi nożyczkami (co nie jest w przypadku bardziej wyrafinowane okrągłe szklane soczewki). Soczewki Fresnela można znaleźć pod nazwami takimi jak „lupa kieszonkowa” lub „lupa do czytania”, ponieważ są bardzo odpowiednie, aby pomóc osobom ze słabym wzrokiem czytać.

Zasadniczo trik polegał na znalezieniu właściwego kompromisu między:

- Posiadanie rozsądnej odległości obrazu wirtualnego (to znaczy, jak daleko HUD będzie się wydawał użytkownikowi lub jak daleko użytkownik będzie musiał dostosować swoje oczy, aby zobaczyć, co jest na HUD)

- Aby tekst na ekranie nie był zbytnio powiększony przez obiektyw (który w zasadzie jest lupą)

- Posiadanie rozsądnej odległości między ekranem OLED a obiektywem, co w przeciwnym razie prowadziłoby do bardzo nieporęcznego modułu

Osobiście zamówiłem kilka różnych obiektywów na amazon i określiłem ich odpowiednie ogniskowe, zanim wybrałem jeden o długości F około 13 cm. Znalazłem tę długość F, z odległością obiektywu OLED wynoszącą 9 cm, co dało mi satysfakcjonujący obraz na moim odbłyśniku (patrz kilka ostatnich zdjęć powyżej).

Jak widać na moich ilustracjach, aby właściwie zogniskować wyświetlany tekst, aparat używany do robienia tych zdjęć musi wyregulować się tak, jakby skupiał się na odległym obiekcie, przez co wszystko na tej samej płaszczyźnie co reflektor wydaje się nieostre. Dokładnie tego chcemy dla naszego HUDa.

Pliki 3d do uchwytu obiektywu można znaleźć tutaj.

Krok 4: Części - pojemnik do ich wszystkich

Części - pojemnik do ich wszystkich
Części - pojemnik do ich wszystkich
Części - pojemnik do ich wszystkich
Części - pojemnik do ich wszystkich

Kiedy piszę te instrukcje, rzeczywisty pojemnik, który pomieści każdy element wyświetlacza przeziernego, nie jest do końca zaprojektowany. Mam jednak kilka pomysłów na temat jego ogólnego kształtu i tego, jak podejść do niektórych problemów (np. Jak utrzymać reflektor nieruchomo i sprawić, by wytrzymał wiatr o prędkości 100 km/h). Jest to wciąż bardzo w toku.

Krok 5: Tworzenie protokołu dla naszego modułu

Aby przesłać instrukcje nawigacji z telefonu na płytkę rozwojową, musiałem wymyślić własny protokół komunikacyjny, który pozwoli mi w łatwy sposób przesłać wymagane dane z telefonu, a jednocześnie ułatwi ich przetwarzanie po otrzymaniu.

W momencie pisania tej instrukcji informacje, które musiały zostać przesłane z telefonu, aby nawigować z modułem, były następujące:

- Rodzaj nadchodzącego manewru (prosty skręt, rondo, wjazd na inną drogę,…)

- Dokładne instrukcje dotyczące zbliżającego się manewru (w zależności od typu manewru: prawo/lewo do skrętu; który zjazd wybrać na rondo, …)

- Dystans pozostały do zbliżającego się manewru (na razie w metrach)

Postanowiłem uporządkować te dane przy użyciu następującej struktury ramek:

:typ.instrukcje, odległość;

Choć nie jest pięknym rozwiązaniem, to pozwala na łatwe oddzielenie i rozróżnienie każdego pola naszego protokołu, co ułatwiło kodowanie po stronie ESP32.

Należy pamiętać, że w przypadku przyszłych funkcji może być konieczne dodanie do tego protokołu innych informacji (takich jak dokładny dzień i godzina lub muzyka odtwarzana na telefonie użytkownika), co byłoby łatwo wykonalne przy użyciu tego samego budowanie logiki jak teraz.

Krok 6: Kod: strona ESP32

Kod: strona ESP32
Kod: strona ESP32
Kod: strona ESP32
Kod: strona ESP32

Kod dla ESP32 jest obecnie dość prosty. Wykorzystuje bibliotekę U8g2lib, która umożliwia łatwe sterowanie ekranem OLED (przy jednoczesnym umożliwieniu dublowania wyświetlanego obrazu).

Zasadniczo wszystko, co robi ESP32, to odbieranie danych szeregowych przez Bluetooth, gdy aplikacja je wysyła, parsowanie i wyświetlanie tych danych lub zdjęć na podstawie tych danych (tj. wyświetlanie strzałki zamiast zdania „skręć w lewo/w prawo”). Oto kod:

/*Program do sterowania HUD z aplikacji na Androida przez port szeregowy Bluetooth*/#include "BluetoothSerial.h" //Plik nagłówka dla portu szeregowego Bluetooth zostanie domyślnie dodany do Arduino#include #include #ifdef U8X8_HAVE_HW_SPI#include #endif# ifdef U8X8_HAVE_HW_I2C#include #endif//OLED konstruktor biblioteki, należy zmienić zgodnie z twoim screenU8G2_SSD1306_128X64_ALT0_F_HW_I2C u8g2(U8G2_MIRROR, /* reset=*/ U8X8_PIN_NONE); // maszyna stanu wartości wykryte_pola + zmienna#definiuj pole manewru 1#definiuj instrukcjePole 2#definiuj dystansPole 3#definiuj endOfFrame 4int wykryte_pole = endOfFrame;BluetoothSerial serialBT; // Obiekt dla Bluetoothcharchodzący_char;manewr znaku[10];instrukcje znaku[10];odległość znaku[10];char tempManeuver[10];char tempInstructions[10];char tempDistance[10];int nbr_char_maneuver = 0;int nbr_char_instructions = 0;int nbr_char_distance = 0;boolean fullsentence = false;unieważnij ustawienia() { Serial.begin(9600); // Uruchom monitor szeregowy z prędkością 9600 bodów u8g2.begin(); // Rozpocznij sterowanie OLED serialBT.begin("ESP32_BT"); // Nazwa opóźnienia sygnału Bluetooth(20); Serial.println("Urządzenie Bluetooth jest gotowe do sparowania");}void loop() { if (serialBT.available() && !fullentence) // Znaki odbierane przez port szeregowy Bluetooth {chodzący_char = serialBT.read(); Serial.print("Otrzymano:"); Serial.println(znak_przychodzący); } switch (detected_field) { case manewrField: Serial.println("Wykryte pole: manewr"); if (incoming_char == '.') // Wykryto następne pole { wykryte_pole = InstructionsField; } else { // Wypełnij tablicę informacji o typie manewru manewr[nbr_char_maneuver] = przychodzący_char; nbr_char_maneuver ++; } przerwa; case instructionsField: Serial.println("Wykryte pole: instrukcje"); if (incoming_char == ', ') // Wykryto następne pole { wykryte_pole = distanceField; } else { // Wypełnij tablicę informacji o instrukcjach instrukcje[nbr_char_instructions] = przychodzący_char; nbr_char_instrukcje ++; } przerwa; case distanceField: Serial.println("Wykryte pole: odległość"); if (incoming_char == ';') // Wykryto koniec ramki { wykryte_field = endOfFrame; Serial.print("manewr:"); Serial.println(manewr); Serial.print("instrukcje:"); Serial.println(instrukcje); Serial.print("odległość:"); Serial.println(odległość); pełne zdanie = prawda; update_Display(); // Odebrano pełną ramkę, przeanalizuj ją i wyświetl dane z odbiornika } else { // Wypełnij tablicę informacji o odległości distance[nbr_char_distance] = initial_char; nbr_char_distance ++; } przerwa; case endOfFrame: if (incoming_char == ':') wykryte_pole = pole manewru; // Wykryto przerwanie nowej ramki; default: // Nic nie przerywaj; } delay(20);}void update_Display(){ // Buforuj każdą tablicę znaków, aby uniknąć możliwych konfliktów memcpy(tempManeuver, manewr, nbr_char_maneuver); memcpy(tempInstrukcje, instrukcje, nbr_char_instructions); memcpy(tempDistance, odległość, nbr_char_distance); parseCache(); // Przetwarzaj i przetwarzaj tablice znaków fullsentence = false; // Zdanie przetworzone, gotowe na następne}void parseCache(){ u8g2.clearBuffer(); // wyczyść pamięć wewnętrzną u8g2.setFont(u8g2_font_ncenB10_tr); // wybierz odpowiednią czcionkę // tablice znaków -> ciąg znaków wymagany do użycia funkcji substring() String manewrString = tempManeuver; Instrukcje stringString = tempInstructions; //Implementacja protokołu tutaj. Na razie obsługuje tylko skręty. if (maneuverString.substring(0, 4) == "turn") { // Sprawdź typ manewru Serial.print("ZWROT WYKRYTY"); if (instructionsString.substring(0, 5) == "right") { // Sprawdź konkretne instrukcje i wyświetl odpowiednio u8g2.drawStr(5, 15, "-"); } else if (instructionsString.substring(0, 4) == "left") { // Sprawdź konkretne instrukcje i wyświetl odpowiednio u8g2.drawStr(5, 15, "<---"); } else u8g2.drawStr(5, 15, "Błąd."); // Nieprawidłowe pole instrukcji } /* Zaimplementuj inne typy manewrów (rondy itp.) * else if (tempManeuver == "rdbt"){ * *] */ u8g2.drawStr(5, 30, tempDistance); // Wyświetl pozostałą odległość u8g2.sendBuffer(); // przenieś pamięć wewnętrzną na wyświetlacz // Zresetuj wszystkie tablice znaków przed następnym odczytem memset(maneuver, 0, 10); memset(instrukcje, 0, 10); memset(odległość, 0, 10); memset(tempManeuver, 0, 10); memset(tempInstrukcje, 0, 10); memset(tempDistance, 0, 10); // Zresetuj liczbę elementów w tablicach nbr_char_distance = 0; nbr_char_instrukcje = 0; nbr_char_maneuver = 0;}

Krok 7: Kod: strona Androida

Kod: strona Androida
Kod: strona Androida
Kod: strona Androida
Kod: strona Androida
Kod: strona Androida
Kod: strona Androida

W przypadku aplikacji na smartfony zdecydowałem się użyć SDK nawigacji Mapbox, ponieważ oferuje wiele przydatnych funkcji, jeśli chodzi o budowanie mapy nawigacyjnej od podstaw. Pozwala również na korzystanie z wielu przydatnych słuchaczy, które zdecydowanie pomagają w działaniu tego modułu. Użyłem również biblioteki android-bluetooth-serial harry1453 dla Androida, ponieważ znacznie ułatwiła ona komunikację szeregową Bluetooth.

Jeśli chcesz zbudować tę aplikację w domu, musisz uzyskać token dostępu do Mapbox, który jest bezpłatny do określonej liczby żądań miesięcznie. Będziesz musiał umieścić ten token w kodzie i zbudować aplikację po swojej stronie. Będziesz także musiał zakodować swój własny adres MAC Bluetooth ESP32.

W obecnej formie aplikacja może poprowadzić Cię z Twojej bieżącej lokalizacji do dowolnej lokalizacji, którą możesz kliknąć na mapie. Jak wspomniano we wstępie, nie obsługuje on żadnych innych manewrów niż skręty i nie obsługuje jeszcze zjazdów z trasy.

Cały kod źródłowy można znaleźć na moim githubie.

Krok 8: Co dalej?

Teraz, gdy aplikacja jest na tyle funkcjonalna, że faktycznie prowadzi użytkownika po wyznaczonej trasie (jeśli nie ma żadnych odchyleń od wyznaczonej trasy), moim głównym celem będzie ulepszenie aplikacji na smartfony i zaimplementowanie kilku możliwości, które sprawią, że moduł stanie się realne urządzenie nawigacyjne. Obejmuje to włączanie komunikacji Bluetooth z telefonu, nawet gdy ekran jest wyłączony, a także obsługę innych rodzajów manewrów (rondy, łączenie się itp.). Zaimplementuję również funkcję przekierowania, jeśli użytkownik zboczy z oryginalnej trasy.

Kiedy to wszystko zrobię, poprawię pojemnik i jego mechanizm mocowania, wydrukuję go w 3d i spróbuję wziąć moduł do pierwszego uruchomienia.

Jeśli wszystko pójdzie dobrze, moim długoterminowym celem jest zaprojektowanie niestandardowej płytki drukowanej dla wbudowanej elektroniki tego projektu, co pozwoliłoby zaoszczędzić dużo miejsca na produkcie końcowym.

Mogę w przyszłości dodać do tego modułu kilka innych funkcji, w tym wyświetlanie czasu, a także alarm powiadomienia telefonu, który może wyświetlać ikonę, gdy użytkownik otrzyma wiadomość tekstową lub połączenie. Na koniec chciałbym dodać do tego modułu możliwości Spotify, jako wielki fan muzyki. Jednak w tej chwili jest to tylko miłe.

Krok 9: Wnioski i specjalne podziękowania

Wnioski i specjalne podziękowania!
Wnioski i specjalne podziękowania!

Jak wspomniano we wstępie, chociaż ten projekt jest daleki od ukończenia, naprawdę chciałem podzielić się nim ze światem, w nadziei, że zainspiruje kogoś innego. Chciałem również udokumentować moje badania na ten temat, ponieważ nie ma tak naprawdę zainteresowania hobbystów AR i HUD, co moim zdaniem jest wstydem.

Chciałbym bardzo podziękować Awall99 i Danelowi Quintanie, których projekt rozszerzonej rzeczywistości bardzo mnie zainspirował przy tworzeniu tego modułu.

Dziękuję wszystkim za uwagę, na pewno opublikuję aktualizację, gdy ten projekt zostanie ulepszony w najbliższej przyszłości. Tymczasem do zobaczenia później!

Zalecana: