Przeszukaj forum
Pokazywanie wyników dla tagów 'Programownie'.
Znaleziono 10 wyników
-
Sztuczna inteligencja jest jednym z najbardziej dynamicznie rozwijających się obszarów współczesnej technologii. Od momentu jej powstania, AI (ang. Artificial intelligence) nieustannie ewoluuje, przekształcając sposób, w jaki żyjemy i pracujemy. W dzisiejszym świecie AI jest obecna niemal wszędzie - od inteligentnych asystentów w naszych telefonach, przez systemy rekomendujące treści w mediach społecznościowych, aż po zaawansowane algorytmy wykorzystywane w analizie danych. W dobie rozwijających się algorytmów sztucznej inteligencji warto wiedzieć, czym ona tak właściwie jest i jak działa. W tym artykule przedstawię Ci: Czym jest sztuczna inteligencja. Problemy sztucznej inteligencji. Zastosowania sztucznej inteligencji. Wstęp do algorytmów uczenia maszynowego: Podział algorytmów. Regresja liniowa. Algorytm genetyczny. Sztuczne sieci neuronowe. Algorytmy i modele sztucznej inteligencji mogą być fascynujące i bardzo efektywne. Źródło zdjęcia. Czym jest sztuczna inteligencja Frazę sztuczna inteligencja należy rozdzielić na sztuczna oraz inteligencja. Przyjrzyjmy się drugiemu rzeczownikowi. Inteligencja - zdolność rozumienia, uczenia się oraz wykorzystywania posiadanej wiedzy i umiejętności w sytuacjach nowych ~ sjp.pwn.pl. Jest to abstrakcyjne pojęcie, któremu filozofowie, psycholodzy i inni uczeni przypisywali różne definicje, takie jak: Ogólna zdolność jednostki do świadomego dostosowywania swojego myślenia do nowych wymagań. ~ William Stern. Źródło definicji. [...] Wszystkie asymilacyjne i akomodacyjne interakcje między organizmem a środowiskiem. ~ Jean Piaget. Źródło definicji. Zdolność osoby do przenoszenia swojej wiedzy i zgromadzonego doświadczenia z jednej sytuacji do drugiej. ~ George Ferguson. Źródło definicji. Max Tegmark, profesor fizyki w MIT w swojej książce Życie 3.0 przyjmuje bardzo szeroką definicję, tj. Inteligencja = zdolność do osiągania złożonych celów. Wszystkie te definicje obejmują słowa kluczowe, jakimi są dostosowywanie, akomodacja i przenoszenie. Zatem za inteligencję możemy przyjąć zdolność do nauki, zrozumienia i adaptacji do nowych warunków. Sztuczna inteligencja - dział informatyki badający reguły rządzące zachowaniami umysłowymi człowieka i tworzący programy lub systemy komputerowe symulujące ludzkie myślenie. ~ sjp.pwn.pl. Zatem sztuczną inteligencją są modele, które starają się naśladować ludzkie myślenie. Mając na uwadze szeroko pojętą definicję inteligencji, możemy też powiedzieć, że sztuczną inteligencją jest rozwiązanie technologiczne/program komputerowy, który potrafi uczyć się i dostosowywać do nowych sytuacji, znajdując rozwiązania na zadany problem. Istnieje wiele rodzajów ludzkiej inteligencji: emocjonalna, społeczna i twórcza. Źródło zdjęcia. Problemy sztucznej inteligencji Algorytmy AI (szczególnie uczenia maszynowego) opierają się na danych, co oznacza, że jakość ich działania w dużej mierze zależy od jakości i kompletności danych, którymi są trenowane i weryfikowane. Jeśli dane uczące są niepełne lub zawierają błędy, sztuczna inteligencja może powielać te same niedoskonałości. Może to prowadzić do niepoprawnych rozwiązań. Przykładem może być ChatGPT i generowanie obrazu kieliszka wypełnionego w pełni winem. Istnieje względnie mało zdjęć, obrazów i innych źródeł, które przedstawiają kieliszek wypełniony po brzegi winem, dlatego prawdopodobnie brakuje takich źródeł w danych, którymi był trenowany ChatGPT. Skutkuje to tym, że model językowy nie potrafi generować takich obrazów. Oczywiście pojawia się tutaj problem z interpretacją samego polecenia. Chociaż pojawiają się głosy, że sztuczna inteligencja już potrafi to robić… Zapytanie o wygenerowanie obrazu. Wniosek jest jeden. Sztuczna inteligencja może się mylić. Nie bez powodu algorytmy te ocenia się i poddaje się testom i innym zabiegom, żeby były jak najdoskonalsze. O błędach informują twórcy modeli językowych w krótkich komunikatach, zazwyczaj w obrębie pola do wpisywania poleceń. Komunikat na stronie ChatGPT. Komunikat na stronie MS Copilot. Błędy, które popełniają modele językowe, nie zmieniają faktu, że sztuczna inteligencja to bardzo obiecująca i efektywna dziedzina, która znajduje zastosowanie w wielu branżach. Zastosowania sztucznej inteligencji 1. LLM i tłumaczenie tekstów Tematem na topie od ostatnich kilku lat są duże modele językowe (ang. Large Language Models), które zrewolucjonizowały sposób, w jaki korzystamy z internetu. Potrafią analizować, rozumieć i generować tekst w sposób zbliżony do ludzkiego. Oczywistymi przykładami, których chyba nie muszę wyjaśniać są ChatGPT oraz DeepSeek. Warto przedstawić polski model językowy: Bielik. W 2017 roku powstało narzędzie DeepL – start-up, który założył Polak dr Jarosław Kutyłowski. Według strony DeepL tłumacz korzysta po części z Transformer Model. DeepL wykorzystuje algorytmy sztucznej inteligencji do tłumaczenia tekstów. Źródło zdjęcia. 2. Rozpoznawanie obrazów i elementów na obrazach Dzięki zastosowaniu sieci neuronowych algorytmy wykorzystujące sztuczną inteligencję potrafią identyfikować twarze, przedmioty, znaki drogowe, a nawet emocje na ludzkich twarzach. Rozpoznawanie elementów na obrazie to nie tylko identyfikowanie, co znajduje się na zdjęciu, ale też gdzie dokładnie dany obiekt się znajduje oraz jakie relacje zachodzą między różnymi elementami sceny. Sztuczna inteligencja jest w stanie rozpoznać twarz, oko, a nawet źrenicę oka. Źródło zdjęcia. 3. Pomoc przy diagnozowaniu chorób Sztuczna inteligencja może znajdować zastosowanie w medycynie, szczególnie w obszarze diagnozowania chorób. Jednym z najbardziej obiecujących obszarów jest onkologia. Algorytmy sztucznej inteligencji coraz skuteczniej analizują obrazy i wykrywają zmiany nowotworowe. Naukowcy z Harvard Medical School opracowali innowacyjne narzędzie o nazwie CHIEF, które wykorzystuje sztuczną inteligencję do diagnozowania nowotworów. Model ten analizuje cyfrowe obrazy tkanek nowotworowych, identyfikując komórki rakowe i przewidując profil molekularny guza na podstawie cech widocznych na obrazach. CHIEF został przetestowany na 19 różnych typach nowotworów, osiągając dokładność wykrywania raka na poziomie niemal 94%. Miejmy nadzieję, że w przyszłości sztuczna inteligencja będzie służyła do ratowania życia. Źródło zdjęcia. 4. Sztuczna inteligencja w elektronice Implementację algorytmów sztucznej inteligencji umożliwiają coraz bardziej wydajne platformy sprzętowe, takie jak rozwiązania NVIDIA Jetson, które umożliwiają uruchamianie aplikacji korzystających z uczenia maszynowego. Warto zwrócić uwagę na projekty, takie jak reComputer lub reCamera, które stanowią wygodną bazę do pracy z AI w praktyce. Takie urządzenia umożliwiają tworzenie autonomicznych systemów wizyjnych, robotów czy inteligentnych czujników. Rozwój technologiczny przyczynił się do konstrukcji takiego sprzętu jak Nvidia Jetson. Na zdjęciu widać Nvidia Jetson Nano developer kit. Źródło zdjęcia. Wstęp do algorytmów uczenia maszynowego Sercem każdego z tych zastosowań są konkretne algorytmy, które przetwarzają dane, uczą się na ich podstawie i podejmują decyzje. Przybliżę Ci zasadę działania kilku algorytmów uczenia maszynowego. Skoncentrujemy się na aspektach formalnych, tworząc bazę pod dalszą analizę tych metod. Podział algorytmów Pojęcie sztuczna inteligencja dzieli się na różne kategorie: Klasyfikacja sztucznej inteligencji. Źródło zdjęcia. Powyżej wyróżniono uczenie maszynowe (ang. Machine Learning), czyli dziedzinę sztucznej inteligencji zajmującą się algorytmami, które samodzielnie doskonalą swoje działanie na podstawie zebranych doświadczeń. Najpopularniejszym podziałem tych algorytmów jest podział na: Uczenie nienadzorowane - algorytmy samodzielnie odkrywają wzorce w zbiorze danych. Uczenie nadzorowane - człowiek przedstawia algorytmowi, jakie wyjście powinno pojawić się przy odpowiednim wejściu. Uczenie przez wzmacnianie - algorytm uczy się na podstawie własnych doświadczeń w pewnym środowisku. Podział algorytmów uczenia maszynowego. Źródło zdjęcia. Przykłady algorytmów uczenia maszynowego 1. Regresja liniowa Jeden z podstawowych algorytmów uczenia maszynowego i statystyki, używany do modelowania zależności między zmiennymi. Jego głównym celem jest przewidywanie wartości zmiennej na podstawie jednej lub wielu zmiennych wejściowych. Celem regresji jest dopasowanie takiej prostej, która najlepiej opisuje dane, czyli minimalizuje różnice (błędy) między przewidywanymi a rzeczywistymi wartościami. Przykład rozwiązania zadania regresji liniowej. Niebieskie punkty to zbiór danych, dla którego należy znaleźć prostą najlepiej opisującą te dane. W tym przypadku jest to czerwona prosta. Źródło zdjęcia. Szczegóły matematyczne zostawiam dla ciekawskich. W tym przypadku przedstawiamy algorytmowi, jakie jest wejście (oś x) i wyjście (oś y). Algorytm na tej podstawie uczy się co może być pomiędzy jedną, a drugą wartością. Jest to zatem uczenie nadzorowane. 2. Algorytm genetyczny Algorytmy genetyczne (ang. Genetic Algorithms, GA) to techniki optymalizacyjne oparte na zasadach ewolucji biologicznej, takich jak selekcja naturalna, krzyżowanie i mutacja. Algorytm minimalizuje zdefiniowaną funkcję celu, krzyżując i modyfikując osobniki z populacji. Natura jest inspiracją do różnych rozwiązań technicznych. W tym wypadku inspiracją do stworzenia algorytmu genetycznego była ewolucja. Źródło zdjęcia. Algorytm genetyczny działa następująco: Definicja funkcji celu: należy matematycznie określić, co algorytm będzie minimalizował w celu ulepszenia populacji osobników. Generacja populacji początkowej: jako populację rozumiemy zbiór osobników posiadających cechy, które w każdej iteracji będziemy poddawali ocenie funkcją celu. Obliczenie wartości funkcji celu dla każdego osobnika: każdemu osobnikowi przypisujemy ocenę, która wskazuje na to, jak silny jest osobnik. Ocena, czy algorytm powinien zostać zakończony: jest to uzależnione od czynników, które zdefiniujemy. Algorytm może zakończyć się po konkretnej liczbie iteracji lub, gdy stworzymy osobnika o satysfakcjonującej wartości funkcji celu. Generacja populacji potomnej: w tym kroku może (nie musi) dziać się wiele rzeczy. Głównym celem tego kroku jest stworzenie kolejnej populacji osobników, które będą lepsze od poprzednich. Stosuje się tu kilka metod: Selekcja: spośród osobników wybieramy tylko te, które są dla nas satysfakcjonujące. Istnieje kilka metod, które pozwalają na selekcję, w tym metoda progowa bądź ruletki. Krzyżowanie: łączenie ze sobą najsilniejszych osobników, które przeszły selekcję. Jeżeli cechy osobników definiujemy liczbowo, to możemy analizować ich wartość binarną. Krzyżowanie polega na mieszaniu cech osobników. Np. binarną wartość osobnika dzieli się na pół. Powstają dwie połówki. Te połówki łączy się z połówkami drugiego osobnika. Tak powstają kolejne dwa osobniki. Mutacja: polega na odwróceniu pojedynczego bitu osobnika. Inwersja: odwrócenie ciągu bitów osobnika. Schemat blokowy algorytmu genetycznego. Algorytm genetyczny wykonuje zadanie optymalizacji. 3. Sztuczne sieci neuronowe Sztuczne sieci neuronowe to modele matematyczne inspirowane strukturą i działaniem ludzkiego mózgu. Budowa neuronu. Źródło zdjęcia. W 1943 Warren McCulloch oraz Walter Pitts zaproponowali model matematyczny neuronu, zwany Neuronem McCullocha-Pittsa. Model ma wejścia i wyjście binarne. Model McCulloch Pittsa. Źródło zdjęcia. W powyższym modelu wejścia ‘x’ są mnożone przez wagę, a następnie sumowane ze sobą. Ta wartość przechodzi przez funkcję aktywacji, której wyjście daje odpowiedź w postaci 0 lub 1. Ewolucją powyższego modelu jest perceptron sformułowany przez Rosenblatta. Jego główną innowacją było wprowadzenie możliwości uczenia się na podstawie danych - perceptron potrafi dostosowywać swoje wagi w taki sposób, by lepiej dopasowywać się do zadania klasyfikacyjnego. W perceptronie dane wejściowe mogą być wartościami rzeczywistymi, a każdemu wejściu przypisana jest waga, czyli liczba, która określa znaczenie danego sygnału. Perceptron oblicza ważoną sumę wejść i dodaje do niej tzw. bias (wartość przesuwająca próg aktywacji). Następnie ta suma przechodzi przez funkcję aktywacji. Podstawą działania perceptronu jest reguła uczenia. Wagi są aktualizowane na podstawie różnicy między oczekiwanym wynikiem a wynikiem uzyskanym. Jeśli perceptron popełnia błąd, modyfikuje swoje wagi, by w przyszłości lepiej klasyfikować dane. Perceptron. Źródło zdjęcia. Pojedynczy perceptron ma ograniczone możliwości. Jest w stanie rozwiązywać jedynie problemy liniowo separowalne, czyli takie, w których dane można oddzielić prostą linią (lub hiperpowierzchnią w przestrzeni wielowymiarowej). Aby poradzić sobie z bardziej złożonymi zależnościami, wiele takich neuronów łączy się w sieć. Sztuczna sieć neuronowa składa się z warstw: Warstwa wejściowa – przyjmuje dane wejściowe. Warstwa (lub warstwy) ukryta – zawiera wiele perceptronów, które przetwarzają dane na coraz wyższym poziomie abstrakcji. Warstwa wyjściowa – generuje końcową decyzję, np. klasyfikację lub wartość liczbową. Przykład sieci neuronowej. Źródło zdjęcia. Przykładem uczenia sieci neuronowej jest algorytm propagacji wstecznej. Oprócz klasycznej sieci feedforward przedstawionej powyżej istnieje jeszcze wiele innych np. sieć rekurencyjna lub rozszerzenie sztucznej sieci neuronowej - splotowa sieć neuronowa. Gorąco zachęcam do rozszerzenia tematu. Podsumowanie Sztuczna inteligencja przestała być futurystycznym pojęciem rodem z filmów science fiction, a stała się realnym narzędziem zmieniającym sposób, w jaki postrzegamy technologię, biznes i codzienne życie. To fascynująca dziedzina, która nie tylko stawia przed nami nowe możliwości, ale również wyzwania, ucząc nas pokory wobec potęgi danych i algorytmów. AI nieustannie się rozwija – zarówno w zakresie prostych rozwiązań wspomagających naszą codzienność, jak i w obszarach wymagających głębokiej analizy i precyzji, jak medycyna czy analiza obrazu. Dodajmy też kontekst: dlaczego właśnie teraz sztuczna inteligencja zyskała taką popularność i realną wartość użytkową? Kluczowy przełom nastąpił dzięki połączeniu kilku czynników: potężnych modeli językowych trenowanych na ogromnych zbiorach danych, rosnącej mocy obliczeniowej (szczególnie dzięki GPU), oraz rozwoju technik uczenia głębokiego (deep learning). To one sprawiły, że AI zaczęła nie tylko rozumieć i generować język na poziomie zbliżonym do ludzkiego, ale również przetwarzać obrazy, kod, dźwięk czy nawet rozumowanie w zupełnie nowej jakości. Warto jednak podchodzić do tematu z rozsądkiem. Na fali popularności łatwo wpaść w pułapkę marketingowego nadużywania pojęcia „sztuczna inteligencja”, które często wykorzystywane jest tylko jako chwytliwe hasło – nawet wtedy, gdy rzeczywistość technologiczna danego rozwiązania nie ma z AI zbyt wiele wspólnego. I na koniec ważne zastrzeżenie: wyłącznie to podsumowanie zostało napisane przeze mnie - ChatGPT. Pozdrawiam czytelników Forbota!
-
- 5
-
-
- informatyka
- Programownie
- (i 1 więcej)
-
Początkujący Programowanie w Python. Podstawy dla początkujących
mcsw_02 opublikował temat w Artykuły użytkowników
Języki programowania przechodziły i nadal przechodzą ewolucję – od asemblerowych instrukcji, aż po złożone systemy abstrakcji pozwalające pisać kod bliższy ludzkiemu myśleniu niż mechanicznej logice procesora. Każdy etap tego rozwoju był ukierunkowany na zwiększenie intuicyjności i efektywności procesu programowania. Wraz z rozwojem technologii zaczęto też dążyć do tworzenia języków wysokopoziomowych, w których programista mógł skupić się na rozwiązywaniu problemów zamiast na szczegółach technicznych działania sprzętu. W tym kontekście narodził się Python - język, który łączy prostotę składni z potężnymi możliwościami, zyskując popularność wśród programistów na całym świecie. W tym artykule przedstawię Ci: Historię Pythona. Zastosowanie. Filozofię i Zen Pythona. Podstawową składnię i słowa kluczowe. Czy wiedziałeś, że nazwa języka nie nawiązuje do zwierzęcia, lecz do brytyjskiego serialu komediowego Monty Python’s Flying Circus? Źródło zdjęcia. Historia języka Python Historia sięga końca lat 80., kiedy Guido van Rossum, holenderski programista, rozpoczął prace nad nowym językiem, który miał być łatwiejszy w użyciu niż dostępne wówczas alternatywy. Van Rossum czerpał inspirację z języka ABC, ale chciał stworzyć narzędzie bardziej elastyczne i wszechstronne. W 1991 roku opublikował pierwszą wersję Pythona (0.9.0), który zawierał takie elementy jak obsługa wyjątków, funkcje i podstawowe typy danych: lista, słownik, łańcuchy znaków i inne. Python 2 (wydany w 2000 roku) oraz Python 3 (w 2008 roku) – przynosiły nowe funkcje i usprawnienia. Choć Python 2 przez wiele lat był szeroko stosowany, jego wsparcie zakończyło się w 2020 roku na rzecz Pythona 3. Python został stworzony, aby ułatwić programowanie i uczynić je bardziej intuicyjnym. Źródło zdjęcia. Zastosowanie języka Python Obecnie Python znajduje zastosowanie w różnych dziedzinach – od analizy danych i sztucznej inteligencji po tworzenie stron internetowych i automatyzację. Bogaty ekosystem bibliotek i funkcjonalności języka sprawiają, że Python dynamicznie się rozwija, pozostając jednym z kluczowych języków współczesnej informatyki. 1. MicroPython i CircuitPython Python, jako język o szerokim zastosowaniu, doczekał się licznych wersji i wariantów dostosowanych do różnych platform i urządzeń. Jednym z takich przykładów są MicroPython i CircuitPython – lekkie implementacje Pythona, przeznaczone do działania na mikrokontrolerach, takich jak ESP32 czy Raspberry Pi. Dzięki współczesnym technologiom możliwe jest programowanie mikrokontrolerów prostymi językami, takimi jak MicroPython. Źródło zdjęcia. 2. Sztuczna inteligencja Jednym z najważniejszych powodów, dla których Python zyskał tak dużą popularność w środowisku algorytmów sztucznej inteligencji, jest jego przejrzystość i prostota. Python oferuje szeroki wybór bibliotek i narzędzi wspierających uczenie maszynowe oraz sztuczną inteligencję, takich jak Tensorflow oraz Keras. Dzięki Pythonowi możecie zaprojektować własną architekturę konwolucyjnej sieci neuronowej lub zaimplementować różne algorytmy sztucznej inteligencji. Chciałbyś zaprojektować własną architekturę sieci neuronowej? Python się do tego nada! Źródło zdjęcia. 3. Analiza obrazów Dzięki Pythonowi można łatwo przetwarzać obrazy, tworzyć algorytmy do analizy wizualnej oraz integrować te rozwiązania z innymi aplikacjami. Przykładowo, OpenCV umożliwia implementację algorytmów do rozpoznawania twarzy, co znajduje zastosowanie w systemach bezpieczeństwa i monitoringu. Python oferuje biblioteki umożliwiające efektywną analizę obrazu. Źródło zdjęcia. Filozofia i Zen Pythona Przed rozpoczęciem nauki Pythona warto zapoznać się z jego filozofią, która przyświecała twórcom języka i społeczności programistycznej. Python został zaprojektowany z myślą o czytelności i prostocie. Te wartości są ujęte w Zen Pythona, czyli zestawie 19 zasad przewodnich sformułowanych przez Tima Petersa. Można je wyświetlić w konsoli Pythona, wpisując: import this Fragment Zen: Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated… Charakterystyka Pythona i narzędzia do pisania w Pythonie Python jest językiem interpretowanym, co oznacza, że jest wykonywany bezpośrednio przez interpreter, linia po linii, zamiast być kompilowanym do kodu maszynowego przed wykonaniem. Jest również dynamiczny. Nie wymaga deklarowania typu deklarowanej zmiennej. Istnieje kilka różnych podejść do pracy z Pythonem. Zależnie od osobistych preferencji oraz specyfiki projektu powinieneś dobrać narzędzie, które będzie Ci pasowało: Interaktywny interpreter: interaktywne programowanie i testowanie kodu w czasie rzeczywistym. Edytor tekstu: możliwe jest używanie klasycznych edytorów, takich jak Vim, Emacs, czy Nano. Notatnik typu Google Colab: to świetne połączenie skryptu, tekstu i wizualizacji w jednym miejscu. Wykorzystywany często do nauki programowania lub uczenia maszynowego. Zintegrowane Środowisko Programistyczne (IDE): środowiska takie jak Visual Studio Code oferują pełną integrację z Pythonem, wtyczki do debugowania i wsparcie w pisaniu kodu. Niezależnie jaką metodę wybierzesz, znajomość podstawowej składni jest niezbędna. Źródło zdjęcia. W tym artykule będę wykorzystywał Visual Studio Code. Instalacja Pythona została tu pominięta. Przystępując do poniższej treści, powinieneś już mieć zainstalowanego Pythona oraz skonfigurowany edytor tekstu lub ulubione IDE. Otwórzmy Terminal i włączmy interaktywny interpreter. Włączenie Terminala i interaktywnego interpretera. Terminal włącza się poprzez zakładkę lub skrót klawiszowy Ctrl + Shift + `. Po włączeniu należy wpisać komendę python. Podstawowa składnia i słowa kluczowe Składnia jest podstawowym elementem każdego języka programowania, ponieważ określa zasady, które rządzą tworzeniem poprawnego kodu. Przedstawię Ci najważniejsze funkcje i słowa kluczowe. Zrozumienie tych podstawowych elementów pomoże w efektywnym tworzeniu kodu, który jest nie tylko poprawny, ale także łatwy do zrozumienia i utrzymania. 1. Deklarowanie zmiennych i podstawowe operatory matematyczne Podobnie jak w innych językach programowania istnieje możliwość deklarowania zmiennych. Tak jak wspomniałem, Python jest językiem dynamicznym. Nie ma więc potrzeby podawania typu zmiennej. >>> a = 3 >>> b = 4.5 >>> c = 3.333 >>> a + b * c 17.9985 W Python występują podstawowe operatory matematyczne: Dodawanie: + Odejmowanie: - Mnożenie: * Dzielenie: / Reszta z dzielenia: % Potęgowanie: ** Dzielenie całkowite: // >>> 5 % 2 1 >>> 3 ** 4 81 >>> 10 // 3 3 Możemy zadeklarować łańcuch znaków (napis): >>> napis = "Hello Forbot!" >>> napis 'Hello Forbot!' Napisy możemy zawierać w cudzysłowie lub w apostrofie. Nie ma to znaczenia. Do zmiennej możemy przypisać wartość logiczną i wykonywać za pomocą niej operacje. >>> logika_1 = True >>> logika_2 = False >>> logika_1 + logika_2 1 >>> logika_1 * logika_2 0 Warto zauważyć, że True oraz False można reprezentować jako kolejno: 1 i 0. 2. Kontenery danych W Pythonie występują 4 główne kontenery danych: Lista (ang. list): deklaracja nawiasami kwadratowymi. Mutowalny (zmienny) kontener. Krotka (ang. tuple): deklaracja nawiasami okrągłymi. Niemutowalny (niezmienny) kontener. Zbiór (ang. set): deklaracja nawiasami klamrowymi. Niemutowalny, nieindeksowany i posortowany kontener. Jego główną zaletą jest usuwanie powtórzeń elementów. Słownik (ang. dictionary): deklaracja nawiasami klamrowymi. Nieindeksowany kontener, który zawiera pary klucz: wartość. Elementy w słowniku się nie powtarzają. Deklaracja kolejnych kontenerów danych: >>> lista = [1, 2, 'a', ['zagniezdzona', 'lista'], 3] >>> krotka = (1, 2, 'a', []) >>> zbior = {1, 3.14, 'abc'} >>> slownik = {"jablko":"czerwony", "marchewka":"pomaranczowy", "banan":"zolty"} Możemy odwołać się do elementów po indeksach w liście i krotce. W słowniku należy podać klucz, aby odwołać się do poszczególnej wartości. Przykłady odwołań: >>> lista[2] 'a' >>> krotka[1] 2 >>> slownik["jablko"] 'czerwony' 3. Skrypty i Hello World! Czas na skrypty. Stwórzmy plik main.py i wypiszmy w konsoli Hello World! korzystając z funkcji print(). Twój pierwszy program w Pythonie: Hello World! Jeżeli wszystko jest skonfigurowane dobrze, to w terminalu lub w konsoli powinien się wyświetlić napis Hello World! W Pythonie nie ma jawnie zadeklarowanej funkcji main(), jak w C/C++. Wszystkie polecenia piszemy z góry do dołu. Instrukcje wliczające się w pętle, instrukcje warunkowe i funkcje poprzedzamy wcięciem jednego tabulatora. Nie stosuje się średników na końcu instrukcji. 4. Instrukcje warunkowe Konstrukcja instrukcji warunkowych wygląda następująco: if warunek: instrukcje elif warunek_2: instrukcje else: instrukcje Po warunkach występuje dwukropek, który oznacza, że instrukcje poniżej tyczą się tego warunku. Dodatkowo przed instrukcjami występują wcięcia. Stwórzmy skrypt, który będzie sprawdzał, czy może istnieć trójkąt o podanych bokach. Należy także sprawdzić, czy podane wartości są poprawne, tj. Czy nie są ujemne lub zerowe. Instrukcje porównania logicznego obejmują operatory or oraz and. a = 5 b = 4 c = 6 if a <= 0 or b <= 0 or c <= 0: print("Blad! Wartosci sa niepoprawne!") elif a + b > c and a + c > b and b + c > a: print("Trojkat moze istniec") else: print("Trojkat NIE moze istniec") 5. Pętle Python posiada dwa rodzaje pętli: while warunek: dopóki warunek jest spełniony, instrukcje zawarte w pętli się wykonują. for element in zbior: instrukcje związane z pętlą wykonują się dla każdego elementu w zbiorze. Z obu pętli możemy wyjść poprzez zastosowanie komendy break lub przejść do następnej iteracji słowem continue. Zaletą pętli for w Pythonie jest bezpośrednie odwoływanie się do elementów w zbiorze. Dzięki temu nie musimy martwić się o indeksy i długość zbioru. Utwórzmy skrypt, który w pętli while będzie powtarzał potęgowanie, dopóki zmienna będzie mniejsza od stu. x = 2 while x < 100: x = x**2 Zastosujmy pętlę for do iterowania po liście. Jeżeli element w liście wyniesie 0, to zliczmy ją i na końcu podajmy ilość zer w tej liście. lista_liczb = [1, 2, 0, 56, 89, 0, -1, 12, 0] licznik_zer = 0 for liczba in lista_liczb: if liczba == 0: licznik_zer = licznik_zer + 1 print(licznik_zer) Jeżeli jednak potrzebujemy iteratora, to możemy zrobić to na dwa sposoby: Chcąc iterować po konkretnych liczbach, możemy zastosować poniższą składnię: for iterator in range(start, stop, krok) Stosujemy polecenie range(), które zawiera indeks początkowy, indeks końcowy oraz krok, z jakim iterator będzie przeskakiwał po kolejnych liczbach. Pętla wykona się w zakresie od start do stop-1. Potrzebując iteratora przy liście elementów możemy zastosować polecenie enumerate(): for iterator, element in enumerate(lista_elementow) Wtedy do zmiennej iterator zostanie wpisany aktualny indeks, a do zmiennej element aktualna wartość ze zbioru lista_elementow. Skrypt wypisujący w konsoli liczby od 0 do 9: for i in range(0, 10): print(i) 6. Funkcje Funkcje służą do zwiększenia czytelności kodu niejako chowając powtarzający się kod. Definicja funkcji z dwoma parametrami odbywa się zgodnie z poniższą składnią: def nazwa_funkcji(arg_1: typ, arg_2:typ) -> typ_zwracanej_zmiennej Strzałka i typ zwracannej zmiennej jest opcjonalny. Jeżeli nie musimy podawać argumentów do funkcji, to je też możemy pominąć. Przydatnym słowem kluczowym jest pass. Stosuje się go, jeżeli będziemy implementować funkcję, ale jeszcze nie chcemy budować jej ciała. Na zakończenie parę słów o komentarzach. Standardowym komentarzem jednowierszowym jest napis poprzedzony znakiem #. Komentarze wielowierszowe poprzedzamy i kończymy trzema znakami apostrofa (‘ ‘ ‘ komentarz ‘ ‘ ‘) lub cudzysłowami (“ “ “ komentarz “ “ “). W języku Python możemy dodać opis funkcji, umieszczając go na początku jej ciała w postaci tzw. docstringa. Aby to zrobić, należy otoczyć opis potrójnymi apostrofami (''') lub cudzysłowami ("""). def wylicz_pole(bok_1: int, bok_2: int) -> int: ‘’’tu bedzie opis funkcji wylicz_pole‘’’ pass def wylicz_prad(napiecie: float, rezystancja: float) -> float: prad = napiecie / rezystancja # wyliczenie pradu return prad aktualne_napiecie = 5.45 rezystancja = 1000 aktualny_prad = wylicz_prad(aktualne_napiecie, rezystancja) print(aktualny_prad) # wypisanie pradu Oprócz wszystkich wymienionych przeze mnie funkcji i słów kluczowych istnieje jeszcze wiele przydatnych elementów języka Python, takie jak lambda, with, yield. Gorąco zachęcam Cię do szczegółowego zapoznania się z tym językiem, bo znajdzie zastosowanie w wielu projektach. Podsumowanie Python to wszechstronny język programowania, który zyskał popularność dzięki swojej prostocie i czytelnej składni. Python jest używany w wielu dziedzinach, w tym w analizie danych, sztucznej inteligencji, web development i automatyzacji. Dzięki bogatej bibliotece standardowej oraz licznym zewnętrznym modułom Python jest idealnym narzędziem zarówno dla początkujących, jak i zaawansowanych programistów. Warto się z nim zapoznać, ponieważ jego elastyczność i wsparcie społeczności sprawiają, że jest jednym z najważniejszych języków programowania na świecie.- 2 odpowiedzi
-
- 1
-
-
- Programownie
- python
-
(i 2 więcej)
Tagi:
-
Współczesne narzędzia pozwalają na tworzenie skomplikowanych symulacji rzeczywistych systemów. Taki zabieg pozwala na przetestowanie układu w różnych okolicznościach. Dzięki temu inżynierowie i naukowcy mogą przeprowadzać analizy oraz optymalizować działanie systemów bez konieczności narażania rzeczywistych obiektów na ryzyko. Dzięki modelowaniu komputerowemu i identyfikacji możemy dokładnie zrozumieć dynamikę obiektów i układów, i precyzyjnie sterować ich działaniem. W tym artykule przedstawię Ci: Czym jest modelowanie i identyfikacja? Klasyfikację modeli. Różne postacie modeli. Identyfikację w Matlab. Elektroniczny przykład. Modelowanie pozwala na symulację systemu, który chcemy zbudować. Źródło zdjęcia. Czym jest modelowanie i identyfikacja? Konstrukcja, schemat lub opis ukazujący działanie, budowę, cechy, zależności jakiegoś zjawiska lub obiektu - definicja PWN modelu. Powszechnie znanym przykładem modelowania jest modelarstwo. Odwzorowując samolot, analizujemy jego pełnowymiarowy odpowiednik i konstruujemy jego pomniejszoną wersję, łącząc ze sobą odpowiednie elementy zgodnie z rzeczywistą strukturą. W podobny sposób działa modelowanie matematyczne – zamiast fizycznych części używamy równań i zależności, aby oddać kluczowe właściwości obiektu. Dzięki temu, mając rzeczywisty obiekt, możemy go opisać za pomocą równań matematycznych. Takim obiektem może być samochód, jego silnik, czy nawet kondensator w jego sterowniku. Po co modelujemy? W inżynierii stosuje się to przede wszystkim do testowania zachowania obiektu pod wpływem różnych czynników zewnętrznych, takich jak sterowanie za pomocą sygnałów wejściowych o zmiennym charakterze. Dzięki modelowaniu możemy zbadać wpływ zakłóceń na obiekt. Z punktu widzenia sterowania, dzięki modelowi możemy przeprowadzić symulację różnych strategii regulacji. Współczesne narzędzia pozwalają modelować i identyfikować nawet największe systemy i urządzenia. Źródło zdjęcia. Równie ważnym pojęciem co modelowanie jest identyfikacja. Polega ona na znalezieniu modelu istniejącego systemu na podstawie przeprowadzenia eksperymentów. W trakcie identyfikacji szukamy zależności wyjścia do wejścia. Innymi słowy, podanie sygnału na obiekt spowoduje wygenerowanie wyjścia zależnego od sygnału wejściowego. Znalezienie zależności tych sygnałów pozwoli na wygenerowanie modelu. Podobnie jak w modelowaniu, identyfikacja jest użyteczna przy tworzeniu symulacji sterowania obiektem. Dobieranie nastaw PID do obiektu może być czasochłonne, ale po wygenerowaniu modelu symulacje są zazwyczaj szybkie, co pozwala na przetestowanie wielu nastaw w krótkim czasie i wybranie tych najlepszych. Podsumowując: Modelowanie ma miejsce, gdy wyprowadzamy model obiektu za pomocą praw fizyki i równań matematycznych. Identyfikacja opiera się na znalezieniu modelu istniejącego już systemu na podstawie eksperymentów. Klasyfikacja modeli Główną klasyfikacją jest podział modeli na czarne skrzynki (black box) i białe skrzynki (white box). W przypadku czarnych skrzynek nie posiadamy żadnej informacji o zachowaniu układu. Czarną skrzynką może być mikser audio z kilkoma nieoznaczonymi pokrętłami, ponieważ obracając losowo gałki (nie wiedząc, jakie dokładnie parametry zmieniamy) słyszymy zmodyfikowany dźwięk (nie wiedząc, jaki dokładnie efekt uzyskamy). O białych skrzynkach wiemy wszystko, tym samym możemy przewidzieć jego zachowanie w każdej okoliczności. Możemy powiedzieć, że białą skrzynką jest samochód z bardzo dokładną dokumentacją techniczną, która zawiera każdy szczegół. Różnica między czarnymi i białymi skrzynkami. O czarnych skrzynkach nic nie wiemy, natomiast białe skrzynki są w pełni transparentne i dają nam pełny wgląd w działanie systemu. Różne postacie modeli W jaki sposób można przedstawić model? Istnieje na to wiele sposobów. Jedne z najpopularniejszych to: Równania różniczkowe: opisują obiekt za pomocą równania, które zawiera funkcję zależną od czasu i jej pochodne. Równania uwzględniają zmiany obiektu w czasie. Równania różniczkowe mogą posłużyć do pełnego opisu systemów modelowanych oraz do tworzenia białych skrzynek. Znając prawa fizyki jakiegoś systemu możemy wyprowadzić równania, które w pełni opisują ten system. Przykład równania różniczkowego. Równanie różniczkowe możemy wykorzystać do zamodelowania masy w wodzie, która jest zawieszona na sprężynie. Źródło zdjęcia. Transmitancja operatorowa (funkcja przejścia): matematyczne narzędzie, które umożliwia opisanie dynamiki systemu poprzez związek między sygnałem wyjściowym a sygnałem wejściowym, wyrażonym w dziedzinie zespolonej 's'. Transmitancja jest szczególnie użyteczna w identyfikacji czarnych skrzynek, gdzie mając znane sygnały wejściowe i wyjściowe, możemy określić zależność, która reprezentuje cały układ. Przykład obliczenia transmitancji operatorowej układu elektronicznego RC. Źródło zdjęcia. Oczywiście, istnieje wiele innych metod modelowania obiektów, takich jak równania stanów. Każda z metod modelowania ma swoje specyficzne zastosowania i jest przydatna w różnych kontekstach. Identyfikacja w Matlab. Elektroniczny przykład Jeżeli chcesz się dowiedzieć, w jaki sposób modelować w środowisku Simulink, koniecznie przeczytaj artykuł o Simulinku, w którym został przedstawiony przykład modelowania masy w wodzie zawieszonej na sprężynie. W tym artykule skupimy się na identyfikacji czarnej skrzynki w Simulinku. Spróbujemy wyprowadzić jej model i przy okazji pokażę Ci bardzo przydatne narzędzie System Identification. Służy ono do identyfikacji obiektów i wyprowadzania modeli pod różnymi postaciami. Spróbuj w trakcie czytania artykułu zgadnąć jaki obiekt znajduje się pod czarną skrzynką. Podpowiem tylko, że to układ elektroniczny. Załóżmy, że mamy obiekt przedstawiony poniżej. Posiada on jedno wejście i jedno wyjście. Czarna skrzynka w Simulink. Czarna skrzynka, którą stworzyłem w Simulinku, to jedynie symulacja rzeczywistej sytuacji, w której przeprowadzamy eksperymenty na prawdziwym obiekcie. W normalnych warunkach wszystkie sygnały wejściowe pochodzą z różnych urządzeń, takich jak generator funkcyjny, i są podawane na rzeczywisty układ, który generuje sygnały wyjściowe. Te sygnały są odczytywane za pomocą narzędzi, które mogą je rejestrować i przenieść je na dysk komputera. Zapisane dane, czyli przebiegi tych sygnałów, analizowalibyśmy w ten sam sposób, co w późniejszej części artykułu. Zgodnie z regułą identyfikacji powinniśmy wprowadzić pewne wejście i obserwować wyjście. Podanie wejścia i obserwacja wyjścia wraz z wejściem. Na wejście obiektu podajmy sygnał o wartości 1 i obserwujmy sygnał wyjściowy. Zmiana parametrów bloku Step. Od początku symulacji będziemy pobudzali układ sygnałem o wartości jeden. Po czasie 0.1 s ten sygnał wyzeruje się. Rezultat symulacji. Czy potrafisz na tym etapie ustalić, jaki układ elektroniczny kryje się pod czarną skrzynką? Mając informację o wejściu i wyjściu obiektu możemy wykorzystać System Identification Toolbox i znaleźć model czarnej skrzynki. Jednak przed włączeniem tej aplikacji musimy przenieść interesujące nas sygnały do Workspace Matlaba. Dodajmy więc bloki To Workspace i podłączmy je do linii sygnałowych. Dodanie dwóch bloków To Workspace wraz z połączeniami. Przykładowe parametry bloku To Workspace. Format ustawiony jest na Array. Rezultat przeniesienia danych z Simulinka. Narzędzie do identyfikacji włączymy w Matlab za pomocą wpisania komendy systemIdentification w Command Window. Po wpisaniu komendy wyskoczy nam okno, w którym będziemy mogli rozpocząć swoją pracę. Okno główne System Identification. Na początku musimy wczytać zapisane wcześniej dane. W tym celu należy rozwinąć listę Import data w lewym górnym rogu i wybrać opcję Time domain data. Dzięki niej będziemy mogli importować dane w dziedzinie czasu. Importowanie danych w dziedzinie czasu. Okno importowania danych. Możemy uzupełnić odpowiednie pola o nasze dane: Input: sygnały wejściowy na nasz obiekt. W naszym przypadku wektor o nazwie out.wejscie. Output: wyjście/odpowiedź naszego obiektu. Zmienna out.wyjscie. Data Name: nazwa reprezentująca nasze dane. Możesz tutaj wpisać cokolwiek. Start Time: czas początkowy symulacji. Nasza symulacja zaczynała się w czasie 0. Sample time: czas próbkowania. Tę daną znajdziesz w Workspace po zmienną tout. Różnica między drugim a pierwszym czasem to czas próbkowania. Uzupełnienie pól o dane symulacji. Po wciśnięciu przycisku Import w oknie głównym aplikacji ukaże się kafelek reprezentujący nasze dane. Klikając pole wyboru Time plot wyskoczą wykresy z naszymi przebiegami. Efekt importu danych. Rozwinięcie listy Preprocess pozwala na obróbkę danych przed procesem identyfikacji. Dostępne opcje pozwalają na filtrowanie sygnałów, wybranie zakresu do identyfikacji lub zmianę próbkowania sygnałów. Lista przetwarzania wstępnego importowanych sygnałów. Nie potrzebujemy przetwarzać naszych sygnałów. Zabierzmy się za identyfikację. Klikając listę Estimate wyświetlą nam się dostępne opcje możliwych technik modelowania. Znajdziemy tutaj takie postacie modeli jak modele funkcji przejścia (Transfer Function Models), modele przestrzeni stanów lub modele ARX. Dostępne postacie modeli. Wybierzmy funkcję przejścia. Wyskoczy okno konfiguracji identyfikacji modelu. Estymacja funkcji przejścia. Oprócz nazwy wygenerowanego modelu możemy ustawić ilość zer i biegunów. Zasadniczo próbujemy przewidzieć, jaką postać ma nasz obiekt. Nasz przypadek nie wygląda zbyt skomplikowanie, więc wybierzmy 1 biegun i 0 zer. Konfiguracja estymacji modelu w postaci funkcji przejścia. Estymujmy nasz obiekt poprzez wciśnięcie przycisku Estimate. Przebieg identyfikacji. Wyskoczyło okno z przebiegiem identyfikacji i jej rezultat. Wykres przedstawia, w jaki sposób wygenerowany model odpowiada naszym danym. Akurat ten przykład nie jest zbyt edukacyjny, ponieważ wygenerowany model pokrywa się w 100% z naszym sygnałem wyjściowym. Przykład identyfikacji wykonanej przez MathWorks. Znaleziony model nie pokrywa się w 100% z sygnałem wyjściowym obiektu. Na szaro wyjście obiektu, a na niebiesko znaleziony model. Wróćmy do okna głównego aplikacji. Po procesie identyfikacji pojawi się kafelek z naszym modelem. Dodany model w przeglądarce. Aby wyświetlić porównanie wygenerowanego modelu wraz z naszymi sygnałami wyjściowymi, należy wcisnąć ten model oraz model output. Przebieg znalezionego modelu. Klikając dwukrotnie na okno naszego modelu, wyświetlą nam się szczegółowe informacje o tym modelu. Szczegóły na temat modelu. Widnieje tu jego transmitancja, parametry i kolor, pod jakim widnieje na wykresach. Eksport modelu jest bardzo prosty. Wystarczy przeciągnąć okienko modelu na opcję To Workspace. Eksport modelu do Workspace Matlaba. W taki sposób wykorzystaliśmy tę aplikację do identyfikacji czarnej skrzynki. Przedstawiłem tylko niektóre z dostępnych możliwości aplikacji systemIdentification. Oprócz tego możesz również: Importować dane, które są w dziedzinie częstotliwości. Generować wiele modeli dla jednego obiektu. Wyświetlać zera i bieguny wygenerowanego modelu na wykresie. Usuwać sygnały wejściowe i wyjściowe. Oraz wiele więcej. Eksportowany model pod nazwą tf1. Wróćmy do Simulinka. Wykorzystamy blok LTI System. Jednym z jego parametrów jest nazwa systemu, który ma reprezentować. Dzięki temu ten blok będzie implementował znaleziony przez nas model. LTI System. Jako jego parametr wpisujemy wygenerowany model. Podobnie jak z czarną skrzynką, na wejście naszego modelu podamy wejścia i będziemy obserwowali wyjścia. Podamy te sygnały jednocześnie na black box, jak i na nasz model. Wynik symulacji. Podobnie jak w systemIdentification wykresy pokrywają się praktycznie w 100%. Wykorzystajmy inny sygnał, na przykład sinusoidę. Pobudzenie obiektów sinusoidą. Wykresy również się pokrywają. W taki sposób dokonaliśmy identyfikacji czarnej skrzynki. Podkreślę jeszcze raz: czarną skrzynką może być rzeczywisty układ. Poprzez dokonanie pomiarów i eksperymentów w rzeczywistości, możemy zmierzone sygnały przenieść do Matlaba, dokonać identyfikacji i znaleźć model tego układu. A jaki model skrywał się pod tą transmitancją? Ujawniona czarna skrzynka. Nasza czarna skrzynka stała się białą skrzynką. Była to implementacja transmitancji operatorowej układu RC. Transmitancja, która ukrywała się pod czarną skrzynką jest identyczna jak ta po identyfikacji. Dodatkowo współczynniki modelu, który znaleźliśmy były takie same jak w rzeczywistym obiekcie. Co prawda model miał trochę inną postać niż czarna skrzynka, ale dokonując kilku przekształceń otrzymalibyśmy to samo. Podsumowanie Dzięki modelowaniu i identyfikacji jest możliwe zrozumienie zachowania obiektu przed faktycznym wdrożeniem sterowania lub innych procesów inżynierskich. Współczesne narzędzia umożliwiają tworzenie zaawansowanych modeli matematycznych i ich symulację, co znacząco redukuje ryzyko błędów oraz koszty związane z eksperymentami na rzeczywistych obiektach. W dobie rosnącej złożoności systemów technicznych oraz zaawansowanych algorytmów sterowania, narzędzia te stają się nieodzownym elementem pracy inżynierów i naukowców w wielu dziedzinach, od automatyki przemysłowej po medycynę i robotykę. Jeżeli chcesz zobaczyć identyfikację w praktyce, to odsyłam Cię do artykułu o implementacji regulacji PID dla silnika z enkoderem.
-
- 7
-
-
- Początkujący
- Elektronika
- (i 2 więcej)
-
Matlab Co to Simulink? Podstawy, zastosowanie, pierwsze kroki
mcsw_02 opublikował temat w Artykuły użytkowników
W jaki sposób stworzyć symulację lotu drona, systemu ogrzewania pomieszczenia lub silnika prądu stałego? Jest na to jedno, bardzo uniwersalne i dobre narzędzie - Simulink. Jest to narzędzie, które wchodzi w skład środowiska programistycznego Matlab. Jeżeli jeszcze nie wiesz, czym jest ten program to odsyłam do mojego artykułu omawiającego czym jest Matlab. Simulink is a block diagram environment used to design systems with multidomain models, simulate before moving to hardware, and deploy without writing code. - definicja Simulinka według MathWorks. Możemy więc spodziewać się, że jest to środowisko, które służy do modelowania, symulacji i implementacji systemów dynamicznych bez potrzeby ręcznego kodowania. W tym artykule przedstawię Ci: Czym jest Simulink? Zastosowania Simulinka. Podstawy Simulinka. Praktyczne modele i projekty w Simulinku. Simulink to potężne narzędzie pozwalające na modelowanie różnorodnych systemów. Źródło zdjęcia. Czym jest Simulink? Zgodnie z opisem producenta, jest to środowisko służące do symulacji multi-domenowych modeli. Oznacza to, że będziemy w stanie modelować systemy charakteryzujące się posiadaniem komponentów należących do różnych dziedzin inżynierii - elektryki, mechaniki, pneumatyki itp. Te układy buduje się za pomocą schematów blokowych. To wszystko umożliwia symulację skomplikowanego systemu przed przeniesieniem rozwiązania na rzeczywisty sprzęt. Całe środowisko opiera się na modelach, czyli wyidealizowanej reprezentacji jakiegoś zjawiska/urządzenia/systemu. Modelami sterujemy za pomocą przepływu sygnałów przez połączone między sobą bloki. Sygnały możemy modyfikować i analizować. Zastosowania Simulinka Simulinka stosuje się głównie do symulacji procesów i algorytmów przed przeniesieniem ich na sprzęt. W samym środowisku jest możliwość jednocześnie zbudowania całego systemu oraz jego algorytmu sterowania za pomocą, np. maszyny stanów (Stateflow). Stosuje się go w różnorodnych branżach wykorzystujących skomplikowane systemy. Przykładami takich branż mogą być: Automotive - sterowanie autonomicznymi pojazdami. Lotnictwo i kosmonautyka - skomplikowane sterowanie nieliniowe. Automatyka przemysłowa - sterowanie procesami regulacji. Sektor medyczny - przetwarzanie sygnałów, np. EKG. Więcej o zastosowaniach możecie przeczytać na stronie producenta. Dodatkowe biblioteki do Simulinka rozszerzają jego możliwości. Źródło zdjęcia. Podstawy Simulinka. 1. Włączenie Simulinka Można to zrobić na dwa sposoby: wpisując komendę simulink w Command Window Matlaba lub klikając logo Simulinka w zakładce. Opcje uruchomienia Simulinka. Po uruchomieniu środowiska wyświetli się poniższe okno. Możemy w nim utworzyć nowy pusty projekt lub wybrać wcześniej stworzony wzór. Strona startowa. Wybierzmy Blank Model i rozpocznijmy modelowanie! Stworzenie pustego projektu będzie skutkowało pojawieniem się głównego okna z naszym projektem. Okno Simulinka. 2. Podstawy modelowania W Simulinku modeluje się za pomocą bloków. Do bloków można dostać się za pomocą zakładki Library Browser lub klikając dwukrotnie lewym przyciskiem myszy i wpisując pożądany blok. Załóżmy, że mamy za zadanie zamodelować poniższe równanie: y = ax + b, gdzie: a, b - dowolne stałe, x - czas rzeczywisty. Na pierwszy rzut oka widać, że potrzeba kilka bloków: Mnożenia - Product. Dodawania - Sum. Stałych - Constant. Aktualnego czasu - Clock. Dodajmy je poprzez Library Browser. Pierwsze 3 znajdziesz w zakładkach Simulink > Commonly Used Blocks. Blok Clock znajduje się w Simulink > Sources. Po znalezieniu ich wystarczy przeciągnąć je na okno robocze. Dodanie odpowiednich bloków na obszar roboczy. Bloki łączy się za pomocą linii przeciągając lewym przyciskiem myszy z wyjścia bloku do wejścia kolejnego. Połączenia między blokami. Czerwona strzałka oznacza niedokończone połączenie. Upewnij się, że wszystko jest połączone. Wyświetlmy wynik. Zrobimy to korzystając z bloku Scope, który pokaże nam przebieg monitorowanego sygnału w czasie. Tym razem dodajmy go klikając dwukrotnie na okno robocze i wpisując w wyszukiwarkę Scope. Dodanie bloku Scope. Gotowy schemat powinien wyglądać tak jak poniżej: Gotowy model. Istnieje możliwość dodania opisów, zaznaczając odpowiedni blok i zmieniając jego nazwę. Nazwę linii sygnałowej zmienia się poprzez dwukrotne naciśnięcie jej. Program wraz z etykietami. Zmieńmy wartość współczynnika b, tak aby wynosiła 0. Otrzymamy wtedy równanie: y = ax, W naszym przypadku a = 1, więc równanie będzie wynosiło: y = x, czyli otrzymamy wartości y równe aktualnemu czasowi. Dwukrotne kliknięcie bloku wywoła okno zmiany parametrów tego bloku. Niektóre bloki pokazują aktualne wartości parametrów bloku. Blok ‘b’ zmienił wyświetlaną wartość z 1 na 0 po zmianie jego parametru. Włączmy symulację za pomocą przycisku Run. Przy okazji zmieńmy czas symulacji na 20 sekund. Opcje włączenia symulacji. Czas wykonywania symulacji zmienia się w oknie Stop Time. Otwórzmy Scope. Klikając na niego dwukrotnie zobaczmy przebieg sygnału wyjściowego. Wynik symulacji. Zmieńmy wartości a i b, i sprawdźmy, jak zachowa się przebieg. Symulację można włączyć klikając zielony przycisk startu bezpośrednio w Scope. Zmienione współczynniki równania. Współczynnik kierunkowy zmieniłem na ujemny, przez co nie widać dobrze przebiegu symulacji. Spowodowane jest to zachowaniem przez Scope poprzednich ustawień z poprzedniej symulacji. Za pomocą zaznaczonego przycisku można automatycznie wyskalować osie. Wygenerowany przebieg z wyskalowanymi osiami. To równanie było tylko prostym przykładem. Pamiętajmy, że to środowisko oferuje znacznie więcej, o czym będzie napisane później. 3. Równania różniczkowe w Simulinku Przejdźmy do cięższego przykładu - równań różniczkowych. Nie bój się, nie musisz wiedzieć, jak je rozwiązywać. Simulink zrobi to za nas! Przeanalizujemy problem krok po kroku. Załóżmy, że chcemy zamodelować zachowanie masy na sprężynie w wodzie. Wychylamy ją na pewną odległość i obserwujemy, co się dzieje. Logicznym jest, że sprężyna na początku będzie oscylować. Jednocześnie będzie tłumiona przez wodę, aż do jej całkowitego zatrzymania. Wizualizacja problemu. Nazywa się to oscylator harmoniczny tłumiony. Istnieje równanie, które opisuje powyższy problem: Równanie oscylatora harmonicznego tłumionego. Źródło zdjęcia. Współczynniki w równaniu: m - masa obciążenia. b - współczynnik tłumienia. k - stała sprężyny. Równanie zawiera pochodne. Pochodna to zmiana pewnej wielkości w czasie. Pochodna położenia to prędkość, bo jest to zmiana położenia w czasie - jak szybko obiekt się porusza. Analogicznie przyspieszenie to pochodna prędkości - jak szybko zmienia się prędkość w czasie. W przypadku równania oscylatora zapisane są pochodne położenia. Oznaczone są zapisem: gdzie: n - rząd pochodnej. Tak więc, gdy: n = 1 - prędkość. n = 2 - przyspieszenie. Gdy n = 0, to mamy do czynienia ze zwykłą funkcją. W tym przypadku z położeniem. Podsumowując, będziemy badali: x(t) - położenie. dx(t)/dt lub v(t) - prędkość. d2x(t)/dt2 lub a(t) - przyspieszenie. Najprostszym sposobem na modelowanie takiego równania jest przeniesienie wszystkich pochodnych i stałych na prawą stronę oraz pozostawienie po lewej najwyższej pochodnej. Jeżeli tak zrobimy, to powyższe równanie zyska postać: Postać równania z przeniesieniem niższych pochodnych i stałych na prawą stronę. Przeanalizujmy powyższe równanie. Najwyższą pochodną, możemy obliczyć na podstawie niższych pochodnych. Aby je uzyskać, musimy scałkować wyższą pochodną. Wtedy otrzymamy pochodne niższego rzędu. Dodatkowo całe wyrażenie należy podzielić przez ‘m’. Odpowiednie pochodne musimy wzmocnić przez pewne współczynniki. Nawias po prawej stronie ma postać sumy ujemnych wartości. Na cały układ musimy zadziałać wymuszeniem, czyli sygnałem, który wprawi w ruch cały układ. Można je wyobrazić sobie, jako odchylenie sprężyny w jednym kierunku, a następnie puszczenie jej, tym samym wprawienie jej w ruch. Uwaga: w równaniu nie jest uwzględnione wymuszenie. Jeżeli chcielibyśmy je uwzględnić, musielibyśmy dopisać po prawej stronie +u(t). Zatem będziemy potrzebowali bloków: Step - generowanie sygnału o stałej wartości przez pewien czas. Wymuszenie/początkowe odchylenie sprężyny. Sum - odejmowanie tłumienia i stałej sprężyny. Gain - pomnożenie sygnału przez pewną wartość. Wzmocnienie odpowiednich pochodnych. Integrator - całka sygnału. Potrzebujemy dwóch integratorów, żeby z najwyższej pochodnej, równej 2, przejść do pochodnej 0-rzędu - położenia. Scope - analiza przebiegów w czasie. Wszystkie potrzebne bloki znajdziemy w Library Browser. Po dwukrotnym naciśnięciu na blok Sum można dostosować jego wejścia. Zmieńmy go na rectangular i zmodyfikujmy jego znaki poprzez wpisanie w poniższym polu żądanych symboli: plus (sygnał wymuszający) i dwa minusy (ujemne współczynniki). Parametry bloku Sum. Przygotowane bloki z błędami. Tym razem w blokach wpiszemy zmienne, które należy zadeklarować. Dodaje się je w workspace projektu i przypisuje się im odpowiednią wartość. W tym celu najeżdżamy na blok i klikamy symbol error oraz wybieramy dodanie zmiennej. Stworzenie nowej zmiennej. Okno, które wyskoczy po wciśnięciu Fix. Wartość zmiennej wpisujemy w <expression>. Ja wykorzystam wartości: m = 10. k = 3. b = 2. Jeżeli pomylisz się przy wpisywaniu wartości, to musisz przejść do workspace Simulinka. Przejście do Model Explorer i Workspace modelu. Do tego miejsca przechodzi się w następujący sposób: Zakładka Modelling > Model Explorer > Model Workspace. Po stworzeniu odpowiednich zmiennych czerwone podświetlenie powinno zniknąć. Teraz połączmy wszystkie bloki zgodnie ze wzorem. Połączony schemat. Zauważ, że możliwe są rozgałęzienia oznaczone kropką (tak jak w schematach elektronicznych). Wyjaśnienie połączeń: wzór opisuje, ile wynosi przyspieszenie. Więc musimy je obliczyć na podstawie odpowiednich wartości prędkości i położenia, które są wzmocnione o współczynniki przy nich stojących. Dzięki temu utworzy nam się równanie po prawej stronie. Dodatkowo całą sumę musimy pomnożyć przez 1/m, dlatego na wyjściu sumatora jest Gain. Wyjaśnienie graficzne równania. Poszczególne kolory odpowiadają kolejnym częściom równania. Zostało jeszcze zmodyfikowanie bloku Step. Chcemy, aby wymuszenie pojawiło się od startu symulacji i zniknęło po pewnym czasie. Klikamy dwukrotnie na blok i modyfikujemy parametry. Zmodyfikowane parametry bloku Step. Step time - czas po jakim blok zadziała. Chcemy, aby wymuszenie zniknęło po sekundzie, więc wpisujemy 1. Initial value - wartość początkowa. Ustawiamy na 1, bo zadziałamy jednostkową siłą rozciągając sprężynę. Final value - wartość, która pojawi się po Step time. Chcemy zatrzymać wymuszenie, więc wpisujemy 0. Reszty nie zmieniamy. Do bloku Scope przyłączmy sygnały wymuszenia, przyspieszenia i prędkości, aby zobaczyć jak zachowują się te wielkości. Aby połączyć pożądany sygnał do Scope należy przytrzymać prawym przyciskiem na linię tego sygnału i przeciągnąć kursor w inne miejsce. Pojawi się strzałka, którą należy najechać bezpośrednio na Scope. Połączenie kilku sygnałów do Scope. Przed uruchomieniem zmień czas na minimum 40 sekund. Sprawdźmy jak wygląda wyjście! Wyjście modelu. Wykres nie jest zbyt czytelny. Poprawmy to. Rozbijmy poszczególne wykresy na pojedyncze okna - Layout. Włączmy legendę - Legend. Dostosujmy skalę. Włączenie opcji Layoutu. Podział Scope na poszczególne sygnały. Włączenie legendy. Automatyczne skalowanie wszystkich przebiegów. Wygenerowany wykres. Nasz wykres jest kanciasty. To wina solvera, który oblicza stany modelu podczas symulacji. Nie wdając się w szczegóły naprawmy to klikając napis w prawym dolnym rogu informujący nas o aktualnym solverze. Po kliknięciu wybierzmy koło zębate i przejdźmy do ustawień. Włączenie opcji solvera. Zmiana typu i kroku solvera. Krok solvera ustaw, np. na 0.01. Sprawdźmy, jak teraz wygląda wykres. Finalnie wygenerowany wykres. Teraz możemy dokładnie przeanalizować wygenerowany przebiegi przez nasz model. Przez sekundę działa wymuszenie, które zanika. Następnie model (ciężarek na sprężynie) wykonuje ruch oscylacyjny wokół punktu 0. Tłumienie (woda) w końcu go zatrzymuje. Przy okazji widać, jak zachowuje się prędkość i przyspieszenie. Praktyczne modele i projekty w Simulinku Simulink nie służy tylko i wyłącznie do rozwiązywania skomplikowanych równań różniczkowych. Znajduje on zastosowanie w wielu branżach. Poniżej przedstawiam modele i przykłady rzeczywistych obiektów. 1. Winda (Elevator) Dzięki bibliotece Simscape możliwe jest symulowanie części mechanicznych. Za pomocą kilku bloków można zbudować windę, która porusza się z zadaną prędkością. Model można przerobić na sterowanie położeniem/przyspieszeniem. Przykład windy zbudowanej w Simulinku. Wygenerowane przebiegi przez windę. 2. Sterowanie silnikiem (Control DC Motor with PWM Voltage Source and H-Bridge Driver) Simscape oferuje również pakiet Simscape Electrical, za pomocą której można symulować układy elektroniczne. W połączeniu z częściami mechanicznymi możemy zasymulować jednocześnie część elektryczną i mechaniczną systemu - model multi-domenowy. Przykładem może być sterowanie silnikiem prądu stałego mostkiem typu H przy jednoczesnym monitorowaniu obrotów wału silnika. Sterowanie silnika mostkiem typu H. Pokazane przebiegi prądu i RPM. 3. Sterowanie Arduino za pomocą Simulinka (Get Started with Arduino Hardware) Za pomocą Simulinka możesz tworzyć aplikacje komunikujące się z Arduino. Simulink umożliwia tworzenie aplikacji, sterowania i wizualizacji programów tworzonych na Arduino. Jeżeli chcesz zobaczyć rzeczywiste użycie tego programu, to zajrzyj do tego artykułu. Robot mobilny wykorzystujący Arduino Due. Źródło zdjęcia. W internecie można znaleźć modele/implementacje innych typów robotów, które zostały zaprojektowane w Simulinku: linefollower, typu roomba lub manipulatory przemysłowe Podsumowanie Simulink to świetne narzędzie do modelowania, symulowania i tworzenia aplikacji dla rzeczywistych systemów i obiektów. Sprawdzi się zarówno do rozwiązywania skomplikowanych problemów matematycznych, jak i dla sterowania rzeczywistymi obiektami, takimi jak np. roboty mobilne. Jeżeli chcesz przetestować swoje rozwiązanie sterowania, nastawy PID lub układ elektroniczny, to Simulink będzie dobrym wyborem.- 1 odpowiedź
-
- 5
-
-
- automatyka
- Programownie
- (i 2 więcej)
-
Intermediate Resource Integration System (IRIS2) IRIS to projekt, który leżał u mnie od dłuższego czasu - co jakiś czas projektuję urządzenia podłączane do komputera, ale zawsze ciężko dorobić do nich oprogramowanie, bo co urządzenie to zwykle inaczej się one komunikują (inne pakiety danych etc.) Rolą IRIS jest "uprościć" (może lepszym określeniem było ułatwić analizę kodu przez AI) ten proces maksymalnie jak tylko się da, a że moją domeną jest C# to padło też na wybór tego języka programowania. Przykładowe użycie IRIS /// <summary> /// Represents an example of a device that changes or reads the value of an LED /// using RUSTIC protocol messages. /// </summary> public sealed class ExampleArduinoLEDChangingDevice(SerialPortDeviceAddress deviceAddress, SerialInterfaceSettings settings) : SerialDeviceBase(deviceAddress, settings) { /// <summary> /// Get LED value /// </summary> public async Task<bool> GetLEDValue(CancellationToken cancellationToken = default) => await GetLEDValue<GetValueTransaction>(cancellationToken); private async Task<bool> GetLEDValue<TTransactionType>(CancellationToken cancellationToken = default) where TTransactionType : IDataExchangeTransaction<GetValueTransaction, GetValueRequestData, GetValueResponseData> { // Create request data GetValueRequestData requestData = new("LED"); // Exchange data GetValueResponseData result = await TTransactionType .ExchangeAsync<ExampleArduinoLEDChangingDevice, SerialPortInterface>(this, requestData, cancellationToken); // Return result of the operation return result.value.ToString() == "1"; } /// <summary> /// Set LED value /// </summary> public async Task<bool> SetLEDValue(bool value, CancellationToken cancellationToken = default) => await SetLEDValue<SetValueTransaction>(value, cancellationToken); private async Task<bool> SetLEDValue<TTransactionType>(bool value, CancellationToken cancellationToken = default) where TTransactionType : IDataExchangeTransaction<SetValueTransaction, SetValueRequestData, SetValueResponseData> { // Create request data SetValueRequestData requestData = new("LED", value ? "1" : "0"); // Exchange data SetValueResponseData result = await TTransactionType .ExchangeAsync<ExampleArduinoLEDChangingDevice, SerialPortInterface>(this, requestData, cancellationToken); // Return result of the operation return !result.IsError; } } Przykład korzysta z wbudowanego protokołu, który nazwałem RUSTIC. Protokół ten opiera się na prostych przypisaniach wartości przesyłanych jako linijki poprzez UART np. // Przypisanie zmiennej > ZMIENNA=32 < ZMIENNA=OK // Pobranie wartości zmiennej > ZMIENNA=? < ZMIENNA=32 Oprócz protokołu RUSTIC standardowo jest też zaimplementowany protokół LINE, który jest prostym protokołem wymiany wiadomości (np. do zaimplementowania w formie konsoli do debugowania). /// <summary> /// Read message from device /// </summary> public async Task<string> ReadMessage() => await ReadMessage<LineReadTransaction>(); private async Task<string> ReadMessage<TTransaction>() where TTransaction : IReadTransaction<TTransaction, LineTransactionData>, new() { // Read message LineTransactionData response = await TTransaction.ReadAsync<ExampleArduinoEchoDevice, SerialPortInterface>(this); // Return response return response.ToString(); } Oraz przykład użycia samego urządzenia w docelowej aplikacji: public static class ExampleApp { public static async void RunApp(string comPort) { // Create new Arduino echo device ExampleArduinoLEDChangingDevice device = new(new SerialPortDeviceAddress(comPort), new SerialInterfaceSettings(115200)); device.Connect(); // Exchange data example bool ledValue = await device.GetLEDValue(); Console.WriteLine("LED value: " + ledValue); // Wait for 500 ms to see the result await Task.Delay(500); // Set LED value bool setOk = await device.SetLEDValue(true); Console.WriteLine("Set LED value was success: " + setOk); // Read LED value ledValue = await device.GetLEDValue(); Console.WriteLine("LED value after set: " + ledValue); // Wait for 500 ms to see the result await Task.Delay(500); // Set LED value setOk = await device.SetLEDValue(false); Console.WriteLine("Set LED value was success: " + setOk); // Read LED value ledValue = await device.GetLEDValue(); Console.WriteLine("LED value after set: " + ledValue); // Disconnect device device.Disconnect(); } } Ale jak to działa? Podstawowym elementem IRIS jest klasa DeviceBase, która reprezentuje urządzenie (zazwyczaj sprzęt podłączony do komputera, ale nie jest to twarde wymaganie, równie dobrze urządzeniem może być API REST, ale to nadużywanie elastyczności projektu). Urządzenie to punkt dostępu dla zewnętrznych aplikacji, które będą komunikować się ze sprzętem (nie powinny one używać funkcji niskiego poziomu, aczkolwiek są one dostępne do bardziej radykalnych zastosowań). Urządzenie wykonuje Transakcje - wymianę danych pomiędzy komputerem, a sprzętem do niego podłączonym. Rolą transakcji jest wymiana pakietów danych, najprościej można sprowadzić transakcję do komendy, aczkolwiek jest to porównanie dość rozbieżne z możliwościami, gdyż jedna transakcja może również reprezentować serię komend wykonywanych w urządzeniu. Transakcje zawierają opis "jak" interfejs komunikacyjny powinien wykonać transmisję danych (odczyt/zapis) do urządzenia. Przykładowa trasakcja odczytania tekstu z urządzenia: public struct LineReadTransaction : IReadTransaction<LineReadTransaction, LineTransactionData>, ILineTransaction { public async Task<LineTransactionData> _ReadAsync<TDevice, TCommunicationInterface>( TDevice device, CancellationToken cancellationToken = default) where TDevice : DeviceBase<TCommunicationInterface> where TCommunicationInterface : ICommunicationInterface { // Get the communication interface and receive data ICommunicationInterface communicationInterface = device.GetCommunicationInterface(); return await communicationInterface .ReceiveDataAsync<LineReadTransaction, LineTransactionData>(this, cancellationToken); } } Transakcja ta implementuje interfejs IReadTransaction, który informuje iż jest to transakcja odczytu. Pierwszym parametrem generycznym (osoby zaznajomione z C++ mogą używać określenia template') jest typ transakcji (tzw. TSelf), a drugim jest typ zwracanej struktury danych. Transakcja wykorzystuje wbudowaną implementację odbioru danych z urządzenia poprzez jego interfejs komunikacyjny (zazwyczaj port szeregowy). Dodatkowo transakcja implementuje interfejs ILineTransaction, który zawiera kilka istotnych informacji: public interface ILineTransaction : ITransactionReadUntilByte, IWithEncoder<LineDataEncoder, byte[]> { byte ITransactionReadUntilByte.ExpectedByte => 0x0A; } Informuje on, iż pakiet danych kończy się zawsze bajtem 0x0A oraz, że do konwersji danych binarnych do struktur wykorzystywany jest konkretny Enkoder/Dekoder. By nie zagłębiać się za bardzo w szczegóły - niektóre interfejsy typu port szeregowy (w tym ten podłączony przez USB) używają danych binarnych do transmisji. Takie interfejsy nie wykorzystują standardowej implementacji interfejsu komunikacyjnego, tylko implementację rozszerzoną przeznaczoną dla interfejsów operujących danymi surowymi. Ta implementacja posiada wbudowane metody do wykrywania i dostosowywania się do wymagań danej transakcji - potrafią wykryć jaki enkoder jest w danej transakcji zaimplementowany i automatycznie użyć go do konwersji danych. Dla chętnych implementacja jest przedstawiona poniżej: async Task<TResponseDataType> ICommunicationInterface.ReceiveDataAsync<TTransactionType, TResponseDataType>( TTransactionType transaction, CancellationToken cancellationToken) { // Check if transaction supports data reader, if not throw exception if (transaction is not IWithDataReader withDataReader) throw new NotSupportedException("Transaction type is not supported"); // Read data using raw data reader byte[] data = await withDataReader .ReadDataAsync<IRawDataCommunicationInterface, TTransactionType, IRawDataReader, byte[]>(this, transaction, cancellationToken); // Decode data return await DecodeData<TResponseDataType, TTransactionType>(transaction, data); } private Task<TResponseDataType> DecodeData<TResponseDataType, TTransactionType>( TTransactionType transaction, byte[] rawData) where TResponseDataType : struct { // Check if user expects raw data and convert it if needed if (typeof(TResponseDataType) == typeof(byte[])) return Task.FromResult((TResponseDataType) Convert.ChangeType(rawData, typeof(TResponseDataType))); // Check if transaction supports encoder, if not throw exception if (transaction is not IWithEncoder withEncoder) throw new NotSupportedException("Transaction does not support encoder. Cannot decode data."); // Decode data using encoder withEncoder.Decode(rawData, out TResponseDataType responseData); return Task.FromResult(responseData); } Czytaki IRIS posiada też kilka bardziej zaawansowanych możliwości. Jedną widać w poprzedniej implementacji - czytaki. Czytaki służą do automatycznego odczytywania danych (zazwyczaj) binarnych z interfejsu i są niskopoziomową implementacją wcześniej wspomiananego systemu, który określa bajt na którym interfejs komunikacyjny ma zakończyć odczyt danych transakcji LINE. Wbudowane czytaki to odczytujący konkretną ilość bajtów z interfejsu oraz odczytujący do momentu napotkania konkretnego bajtu. Implementacja nowych czytaków jest bardzo prosta: public readonly struct UntilByteRawDataReader : IRawDataReader { public Task<byte[]> PerformRead<TTransactionType>(IRawDataCommunicationInterface communicationInterface, TTransactionType transaction, CancellationToken cancellationToken = default) where TTransactionType : ICommunicationTransaction<TTransactionType> { // Check if transaction is a read until byte transaction if (transaction is ITransactionReadUntilByte untilByte) return communicationInterface.ReadRawDataUntil(untilByte.ExpectedByte, cancellationToken); // If transaction is not supported, throw exception throw new NotSupportedException("Transaction type is not supported."); } } Ten czytak jest jednym z wbudowanych i działa wyłącznie z interfejsami binarnymi (w innym przypadku program wyrzuci wyjątek, że interfejs komunikacyjny nie jest prawidłowego typu). Pozwala on na automatyczny odczyt transakcji zgodnie z predefiniowaną wartością oczekiwanego bajtu. No i teraz wreszcie intefejsy komunikacyjne Interfejsy komunikacyjne to niskopoziomowe obiekty, które służą do komunikacji pomiędzy funkcjami systemowymi (np. port szeregowy), a funkcjami wysokopoziomowymi (np. wykonaj daną transakcję). Są to najbardziej złożone obiekty w IRIS co przekłada się na ich czasochłonną implementację. Poniżej można zobaczyć przykładowy kod interfejsu dla portu szeregowego: public sealed class SerialPortInterface : SerialPort, IRawDataCommunicationInterface { /// <summary> /// Used when reading data stream by single character to prevent unnecessary allocations /// </summary> private readonly byte[] _singleCharReadBuffer = new byte[1]; public SerialPortInterface(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) { PortName = portName; BaudRate = baudRate; DataBits = dataBits; Parity = parity; StopBits = stopBits; Handshake = Handshake.None; DtrEnable = false; RtsEnable = false; NewLine = Environment.NewLine; ReceivedBytesThreshold = 1024; } /// <summary> /// Connect to device - open port and start reading data /// </summary> /// <exception cref="CommunicationException">If port cannot be opened</exception> public void Connect() { try { // Open the port Open(); if (!IsOpen) throw new CommunicationException("Cannot connect to device - port open failed."); } catch (UnauthorizedAccessException) { throw new CommunicationException( "Cannot access device. Access has been denied. Is any software accessing this port already?"); } } public void Disconnect() => Close(); #region IRawDataCommunicationInterface /// <summary> /// Transmit data to device over serial port /// </summary> void IRawDataCommunicationInterface.TransmitRawData(byte[] data) { if (!IsOpen) throw new CommunicationException("Port is not open!"); // Write data to device Write(data, 0, data.Length); } /// <summary> /// Read data from device over serial port /// </summary> /// <param name="length">Amount of data to read</param> /// <param name="cancellationToken">Used to cancel read operation</param> /// <returns></returns> /// <exception cref="CommunicationException">If port is not open</exception> async Task<byte[]> IRawDataCommunicationInterface.ReadRawData(int length, CancellationToken cancellationToken) { if (!IsOpen) throw new CommunicationException("Port is not open!"); // Create buffer for data // TODO: Get rid of this allocation byte[] data = new byte[length]; int bytesRead = 0; // Read data until all data is read while (bytesRead < length) { bytesRead += await BaseStream.ReadAsync(data, bytesRead, length - bytesRead, cancellationToken); } // Return data return data; } /// <summary> /// Reads data until specified byte is found /// </summary> /// <param name="receivedByte">Byte to find</param> /// <param name="cancellationToken">Used to cancel read operation</param> /// <returns>Array of data, if byte is not found, empty array is returned</returns> /// <exception cref="CommunicationException">If port is not open</exception> async Task<byte[]> IRawDataCommunicationInterface.ReadRawDataUntil(byte receivedByte, CancellationToken cancellationToken) { // Check if device is open if (!IsOpen) throw new CommunicationException("Port is not open!"); // Read data until byte is found // TODO: Get rid of this allocation List<byte> data = new List<byte>(); // Read data until byte is found while (true) { int bytesRead = await BaseStream.ReadAsync(_singleCharReadBuffer, 0, 1, cancellationToken); // Check if data is read if (bytesRead == 0) continue; // If data is read, add it to list data.Add(_singleCharReadBuffer[0]); // Check if byte is found if (_singleCharReadBuffer[0] == receivedByte) break; } // Return data return data.ToArray(); } #endregion Obserwatory Obserwatory to obiekty, których rolą jest wykrywanie zmian w podłączonych urządzeniach. Robią to skanując wszystkie dostępne urządzenia co pewien czas (standardowo 500ms) oraz porównując dane do poprzedniego skanu. Gdy dane się różnią aktualizują pamięć podręczną (usuwają/dodają urządzenia) jednocześnie wysyłając zdarzenia o dodaniu/usunięciu urządzenia. Przykładowo chcąc obserwować wszystkie systemowe porty szeregowe tworzymy obserwator: public sealed class SerialPortDeviceWatcher : DeviceWatcherBase<SerialPortDeviceWatcher, SerialPortDeviceAddress> { /// <summary> /// Scan for all available devices /// </summary> protected override Task<(List<SerialPortDeviceAddress>, List<SerialPortDeviceAddress>)> ScanForDevicesAsync(CancellationToken cancellationToken) { // Get all available serial ports string[] ports = SerialPort.GetPortNames(); // Create lists for hardware and software devices List<SerialPortDeviceAddress> hardwareDevices = new(); List<SerialPortDeviceAddress> softwareDevices = new(); // Loop through all ports for (int serialPortIndex = 0; serialPortIndex < ports.Length; serialPortIndex++) { string port = ports[serialPortIndex]; // Create device address SerialPortDeviceAddress deviceAddress = new(port); // Add device to list hardwareDevices.Add(deviceAddress); softwareDevices.Add(deviceAddress); } // Return devices return Task.FromResult((hardwareDevices, softwareDevices)); } } A następnie możemy go użyć w programie: public static class ExampleCOMRecognitionApp { private static SerialPortDeviceWatcher _deviceWatcher = default!; public static async void RunApp() { // Create new COM recognition watcher _deviceWatcher = new SerialPortDeviceWatcher(); // Attach event handler _deviceWatcher.OnDeviceAdded += OnDeviceAdded; _deviceWatcher.OnDeviceRemoved += OnDeviceRemoved; // Start watching for COM devices _deviceWatcher.Start(); } public static async void KillApp() { // Stop watching for COM devices _deviceWatcher.Stop(); } private static void OnDeviceRemoved(SerialPortDeviceAddress hardwareDevice, SerialPortDeviceAddress softwareDevice) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Device disconnected: {softwareDevice.Address}"); Console.ResetColor(); } private static void OnDeviceAdded(SerialPortDeviceAddress hardwareDevice, SerialPortDeviceAddress softwareDevice) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($"Device connected: {softwareDevice.Address}"); Console.ResetColor(); } } Obserwatory są w pełni asynchroniczne (działają w tle). Powyższy przykład wykrywa zmiany w urządzeniach portu szeregowego oraz wyświetla stosowny monit na konsoli. Podsumowanie To by było chyba na tyle... Projekt można znaleźć na GitHubie oraz przejrzeć Przykłady, znajomość języka Szekspira się przydaje. Plany na przyszłość? Obsługa BLE Obsługa REST poprzez WiFi dla ESP32 (tutaj się zastanawiam) Obsługa MQTT? Zrobienie obserwatora USB dla Linuxa (obecny działa wyłącznie na Windowsie) ... pewnie coś jeszcze
-
Jest taki zestaw oferowany między innymi na Aliexpress: Oprócz tego można dokupić dedykowany do zestawu wyświetlacz, co ma wielki sens: Z wielu powodów ma to sens, choćby że jest to znakomicie dopasowane, a LCD jest dołączone do 16 bitowej magistrali FSMC dzięki czemu wyświetlacz nie jest tragicznie wolny. Schemat zestawu: Podstawowe właściwości zestawu: 1. Procesor STM32F407VET6 - max do 168MHZ, 512KB internal FLASH i 192KB internal static RAM, obudowa LQFP100 2. LCD 3.2 cala, rozdzielczość 320x200, FSMC 16bit sterownik ILI9341 Resztę dodatkowych użytków widać na schemacie i zdjęciu, dlatego pominę ich wyliczanie. Istnieją także inne wersje np. niegdyś sprzedawane przez sklep OMDAZZ, także wersje black z procesorem STM32F407ZE lub ZGT6 (LQFP144). To co jest tutaj głównym celem, to sprawne skonfigurowanie i oprogramowanie wyświetlacza. Nie jest to może super łatwe, ale mając do dyspozycji CUBE, czyli graficzny interfejs do ustalenia ustawień, nie jest to także bardzo trudne. Konfiguracja procesora w CUBE wygląda tak: Procesor jest ustawiony na 168MHZ i taktowanie z zewnętrznego kwarcu. Ustawienia FSMC są widoczne w CUBE, a dla uzupełnienia podam kod wynikowy inicjujący magistralę FSMC: /* FSMC initialization function */ static void MX_FSMC_Init(void) { FSMC_NORSRAM_TimingTypeDef Timing = {0}; FSMC_NORSRAM_TimingTypeDef ExtTiming = {0}; /** Perform the SRAM1 memory initialization sequence */ hsram1.Instance = FSMC_NORSRAM_DEVICE; hsram1.Extended = FSMC_NORSRAM_EXTENDED_DEVICE; /* hsram1.Init */ hsram1.Init.NSBank = FSMC_NORSRAM_BANK1; hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE; hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM; hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16; hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE; hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW; hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE; hsram1.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS; hsram1.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE; hsram1.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE; hsram1.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE; hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE; hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE; hsram1.Init.PageSize = FSMC_PAGE_SIZE_NONE; /* Timing */ Timing.AddressSetupTime = 15; Timing.AddressHoldTime = 15; Timing.DataSetupTime = 60; Timing.BusTurnAroundDuration = 0; Timing.CLKDivision = 16; Timing.DataLatency = 17; Timing.AccessMode = FSMC_ACCESS_MODE_A; /* ExtTiming */ ExtTiming.AddressSetupTime = 9; ExtTiming.AddressHoldTime = 15; ExtTiming.DataSetupTime = 8; ExtTiming.BusTurnAroundDuration = 0; ExtTiming.CLKDivision = 16; ExtTiming.DataLatency = 17; ExtTiming.AccessMode = FSMC_ACCESS_MODE_A; if (HAL_SRAM_Init(&hsram1, &Timing, &ExtTiming) != HAL_OK) { Error_Handler( ); } } Kolejnym poziomem jest "dogadanie się" z ILI9341 poprzez sterownik. Pominę tu jego program, jest on dostępny w załączonych źródłach. Końcowy program w bin ma poniżej 5000 bajtów, i robi następująco: 1. Inicjalizuje systemclock na 168MHZ 2. Inicjalizuje GPIO i FSMC 3. Inicjalizuje LCD 4. Wypełnia ekran kolorem niebieskim, poniżej zdjęcie: W załączeniu program z STM32CubeIDE: STM32F407VET6-BLACK-ILI9341-INIT.zip Wersja na github z załączonymi plikami dokumentacji: STM32F407VET6-BLACK-ILI9341-INIT Bardziej rozbudowaną wersję można znaleźć na moim githubie: STM32F407VET6-BLACK-ILI9341-BENCHMARK Działanie benchmarku można obejrzeć na youtube:
-
Firma Arduino głównie jest znana ze swoich płytek deweloperskich o tej samej nazwie. W sprzedaży jest wiele rodzajów Arduino, ale czy wiedziałeś, że Arduino ma w swojej ofercie sterowniki PLC? Arduino Opta jest to sterownik micro PLC wyprodukowany we współpracy z firmą Finder, która specjalizuje się w projektowaniu i produkcji komponentów elektromechanicznych, takich jak przekaźniki. Chociaż projekt miał swoją premierę już dość dawno, to do tej pory nie był pokazywany szerzej na Forbocie. Mam nadzieję, że ten artykuł opisujący moje pierwsze uruchomienie tego sterownika będzie pomocny dla osób, które chcą rozpocząć przygodę z Arduino Opta. W tym artykule przedstawię Ci: Czym właściwie jest Arduino Opta? Twoje pierwsze kroki z tym sterownikiem. Jakie funkcje i możliwości oferuje? Projekt: implementacja sterowania temperaturą w terrarium. Arduino Opta PLC. Źródło zdjęcia. Czym właściwie jest Arduino Opta? Sterownik charakteryzuje się swoją małą skalą. Mikro PLC oznacza, że jest to urządzenie wyprodukowane w standardzie zwykłego sterownika, ale w mniejszej skali - np. mniej wejść i/lub wyjść, mniej funkcjonalności. Takie rozwiązania sprawdzą się w mniej skomplikowanych aplikacji. A jakie parametry cechują sterownik? Generalna specyfikacja PLC. Źródło zdjęcia. Sterownik jest certyfikowany, co oznacza, że można go stosować w przemyśle - ograniczeniem są parametry techniczne, takie jak pamięć, klasa ochrony IP, itp. Sterownik na pewno nie ma problemu z szybkością przez swój dwurdzeniowy procesor STM32. Parametry wejść analogowych. Źródło zdjęcia. Parametry wejść cyfrowych i wyjść przekaźnikowych. Źródło zdjęcia. Maksymalny prąd wyjściowy na pojedyncze wyjście sterownika wynosi 10 A. W sterowniku zastosowano wyjścia przekaźnikowe, które są o wiele wolniejsze od tranzystorowych. Przez to czas przełączania stanu wyjść jest rzędu milisekund, ale w zamian możliwe jest przełączanie stosunkowo wysokich prądów, przy jednoczesnej izolacji sygnałów. Po więcej informacji nt. danych technicznych odsyłam do dokumentacji sterownika. Pierwsze kroki z Arduino Opta: micro PLC Producent oferuje bezpłatny kurs, który wprowadzi Cię w podstawy sterowników logicznych, a także pokaże jak możesz stworzyć swoje pierwsze programy. Są to świetne materiały dla początkujących. Dowiecie się czym są sterowniki PLC, jakie są języki programowania lub jak odczytywać wartości analogowe z czujnika temperatury. Dodatkowo kurs wprowadzi Cię w techniki łączenia ze sobą kilku sterowników za pomocą standardu Modbus TCP/IP. Dla zainteresowanych polecam mój bliźniaczy artykuł, w którym omówiłem dokładniej czym są sterowniki PLC. Pomoże Ci przy pierwszych uruchomieniach programów na Arduino Opta. A teraz dość gadania i przejdźmy do praktyki! W poniższym artykule testuję Arduino PLC Starter Kit, który możecie zakupić na Botlandzie. Na zestaw składają się: sterownik Arduino Opta WiFi. moduł DIN Simul8 (przełączniki). moduł DIN Celcius (płytka grzewcza wraz z czujnikiem temperatury). Co oferuje Arduino Opta? Sterownik z dedykowanym środowiskiem programistycznym Arduino PLC IDE to naprawdę potężne narzędzie. Nie sposób w jednym artykule zmieścić wszystkich dostępnych możliwości, dlatego poniżej znajdziesz skrót tych najważniejszych, a potem przejdziemy do realnego wykorzystania Arduino Opta. Do testów oscyloskopu i trybów debugowania wykorzystałem środowisko Arduino PLC IDE. WiFi i Bluetooth zostały przetestowane w Arduino IDE. Wszystkie adresy ukryłem - lepiej dmuchać na zimne . a) Proste programowanie i diody Sterownik zaprogramujemy za pomocą USB-C w bardzo szybki i przyjemny sposób. Do dyspozycji na sterowniku mamy kilka diod, których zachowanie możemy zaprogramować w taki sposób, jaki chcemy. b) Cyfrowy oscyloskop W Arduino PLC IDE możemy śledzić konkretne wartości włączając oscyloskop i dodając do niego interesującą nas zmienną. Wygenerowany wykres możemy analizować i pobrać. Dodanie do oscyloskopu zmiennej sens_temp_cels, która symuluje temperaturę. Widok oscyloskopu. c) WiFi Wykorzystuję Arduino Opta WiFi, więc głupio byłoby nie przetestować jego tytułowej funkcjonalności. Na początku połączyłem się z moim domowym WiFi za pomocą przykładu Scan Network Advanced. Wykrycie dostępnych sieci WiFi i wypisanie ich na Serial Monitor. Udane połączenie z moją siecią WiFi. Do połączenia wykorzystałem ten przykład. Czas na rozmowę! Wykorzystuję przykład WiFiAdvancedChatServer, dzięki któremu mogę stworzyć chat server i wysyłać wiadomości do sterownika. Za pomocą laptopa połączę się bezprzewodowo z serwerem i wyślę wiadomość. Sterownik będzie połączony z moim komputerem stacjonarnym za pomocą przewodu, na którym wyświetlę odebraną wiadomość. Przykład musiałem lekko zmodyfikować, aby wyświetlał znaki, a nie pełne wiadomości. Wtedy lepiej działało . Połączenie do WiFi i utworzenie chat server. Strona Arduino Opta. Połączenie do serwera za pomocą komendy telnet <IP> i wpisanie wiadomości. Strona laptopa. Odebrana wiadomość i rozłączenie klienta. Strona Arduino OPTA. d) Ethernet i Modbus Niestety nie byłem w stanie przetestować tych funkcjonalności, dlatego odsyłam do materiałów od Finder . e) Bluetooth Low Energy Oprócz WiFi jest także możliwość połączenia się ze sterownikiem za pomocą Bluetooth! Skan pobliskich urządzeń z włączonym Bluetooth. Opta wykrył mój telefon. Wykorzystałem przykład Arduino BLE Scan. f) Live debug mode Środowisko Arduino PLC IDE oferuje podglądanie stanu zmiennych na żywo. Było to bardzo przydatne, gdy tworzyłem algorytm do sterowania terrarium, który przedstawię w dalszej części tego artykułu. Podgląd zmiennych na żywo. Aktywowane zmienne są podświetlone. Wyświetlany jest także odliczony czas timera obok jego wyjścia ET. g) Debugowanie Wykonywany kod można debugować, zaznaczając odpowiednie punkty stopu. Wynik debugowania. W prawym dolnym rogu możemy zauważyć status sterownika HALTED, co oznacza, że przez debugowanie został zatrzymany. Twój pierwszy projekt wykorzystując Opta! W imię zasady Learning-by-doing i w celu przedstawienia możliwości sterownika wymyślmy problem, na podstawie którego krok po kroku przeprowadzę Cię przez podstawy programowania tej jednostki. Zaprojektujmy program sterujący ogrzewaniem terrarium. Nie jestem ekspertem zoologii. Użycie algorytmu na żywych jednostkach na własną odpowiedzialność! System ma działać zgodnie z następującymi zasadami: Standardowe ogrzewanie: Terrarium jest ogrzewane co minutę, aby utrzymać temperaturę 27°C, gdy drzwi są zamknięte. Zamknięcie zrealizujemy za pomocą symulacji krańcówki - wykorzystamy przełącznik. Zakładamy, że jeżeli drzwi są otwarte, to zmienna drzwi = 1. Jeżeli są zamknięte, to drzwi = 0. Reakcja na otwarcie drzwiczek: W stanie otworzonego terrarium niemożliwe jest załączenie grzałki. Jeśli drzwiczki zostaną otwarte i zamknięte, system natychmiast podnosi temperaturę do 30°C. Tryb manualny: Użytkownik może włączyć ogrzewanie ręcznie za pomocą przełącznika. Grzałka działa w tym trybie, dopóki przełącznik nie zostanie zwolniony. Informacja dla programisty: Po podłączeniu sterownika do komputera i włączeniu terminala powinny co 5 sekund pojawiać się informacje o: Temperaturze. Stanie drzwi (otwarte/zamknięte). Informacje mogą pojawić się także po wciśnięciu przycisku na PLC (USER). Zaprojektowany algorytm powinien uwzględniać bezpieczeństwo i zapewniać płynne przełączanie między trybami pracy. Włączenie grzałki powinno być zasygnalizowane włączeniem LED 1 na PLC. Połączenie układu Zanim zabierzemy się do programowania musimy wykonać odpowiednie połączenia między sterownikiem a modułami. Starter Kit oferuje przewody, za pomocą których możemy wszystko połączyć. Poniżej znajduje się schemat, w jaki sposób należy połączyć układ: Schemat połączeniowy dla naszego ćwiczenia. Powyższy układ połączono następująco: +24 V połączono razem między modułami. Osobne połączenia wykonano dla GND. Wyjście przełączników w DIN SIMUL8: nr 1 → I1. nr 8 → I2. Do wyjścia przekaźnikowego nr 1 podłączono na wejście +24 V. Wyjście z niego podłączono do INPUT HEAT 1. Gdy wyjście będzie aktywne, to rozpocznie się grzanie płytki. OUTPUT VOLTAGE w Din Celcius połączono do I7. Tym wejściem będziemy odczytywali temperaturę. Kolory przewodów: Czerwony - +24 V. Czarny - GND. Niebieski - sygnały logiczne/informacyjne. Znaczenie wejść i wyjść, i zmienne odpowiadające za nie: I1 - grzanie manualne (grzanie_manual). I2 - otworzenie drzwiczek (drzwi). I7 - temperatura terrarium (temperatura_terrarium). Przycisk USER na PLC - wysłanie informacji o stanie układu (info). Wyjście nr 1 - załączenie grzania terrarium (grzalka). LED STATUS 1 - informacja o załączeniu grzania (led_grzanie). Jeżeli uruchamiasz sterownik po raz pierwszy, to skorzystaj z lekcji Getting Started na stronie Arduino. Lekcja nauczy Cię jak skonfigurować sterownik i upewnić się, że wszystko działa. Oprogramowanie 1. Deklaracja zmiennych Zacznijmy od zadeklarowania wejść i wyjść. Robi się to w tabeli, co gwarantuje przejrzystość i czytelność. Konfiguracja wejść programowalnych. I7 ustawiamy jako wartość analogową o rozdzielczości 12 bitów. Konfiguracja wyjść programowalnych. Konfiguracja LED. Konfiguracja przycisku USER umieszczonego na PLC. Arduino OPTA umożliwia dodanie kilku programów, które będą równolegle wykonywane. Przyda nam się to, bo nasz projekt będzie się składał z: Pętli głównej odpowiedzialnej za: Pracę manualną. Pracę automatyczną. Przełączanie między pracą automatyczną a manualną. Wykrycie otworzenia terrarium. Załączanie grzałki. Skryptu, który będzie przeliczał wartość wyjściową czujnika temperatury na temperaturę wyrażoną w stopniach Celsjusza. Skryptu wyświetlającego informację o stanie układu. 2. Tryb manualny Sprawa jest prosta - załączając I1 włączamy grzałkę. Dodajmy nowy program: Dodawanie nowego programu. Po wybraniu New program wyskoczy okno: Wybieramy język LD, czyli najpopularniejszy język programowania PLC. Program nazwiemy main. Istnieją 4 rodzaje programów: Opisy typów programów. Źródło zdjęcia. Wybierzemy Fast, bo będzie to nasz główny program, w którym będą odbywały się najważniejsze rzeczy. Wyskoczy nam okno programu: Poświęćmy chwilę na wyjaśnieniu jak działa język LD. Język drabinkowy korzysta ze styków i cewek. Styki symbolizują wejścia, a cewki wyjścia. Rodzaje styków i cewek: -| |- - styk normalnie otwarty. Aktywuje się, gdy przypisana zmienna wynosi 1. -| / |- - styk normalnie zamknięty. Aktywuje się, gdy przypisana zmienna wynosi 0. -| S |- - styk set. Po aktywacji zmienna pozostaje aktywna do momentu resetu. -| R |- - resetuje zasetowany styk. -| P |- - styk wykrywający zbocze narastające zmiennej. -| N |- - styk wykrywający zbocze opadające zmiennej. -( )- - cewka normalnie otwarta. Aktywacja poprzez 1 na wejściu. -( / )- cewka normalnie zamknięta. Aktywacja poprzez 0 na wejściu. Po dwukrotnym naciśnięciu na styk pojawi się okno, w którym możemy skonfigurować go, np. przypisać do niego zmienną: Konfiguracja styku. Nie zapominajmy o diodzie, która ma nas informować o grzaniu. Cewkę dodamy poprzez wciśnięcie ikony coil: Ikona Coil. Bądź poprzez wciśnięcie prawego przycisku myszki i wybranie odpowiedniej opcji: Opcja dodania Coil. A oto nasz tryb manualny: Dobrym nawykiem jest stosowanie markerów. Są to zmienne w pamięci, w których przechowuje się wynik operacji logicznej. Wynik załączenia grzania przypiszmy do markera, a następnie za pomocą markera ustawmy odpowiednie cewki. Utwórzmy zmienną lokalną: Dodanie zmiennej lokalnej. Zmienna lokalna. I przenieśmy przypisanie wyjść do następnej linijki za pomocą markera. Dodanie kolejnej linijki kodu. Tryb manualny W taki sposób zbudowaliśmy nasz pierwszy funkcjonalny program! Aby go przetestować, należy przesłać go do sterownika. Opcja wysłania programu do sterownika. Po przesłaniu programu możemy włączyć podgląd (watch) i zobaczyć jak się zachowują nasze zmienne: Watch. Należy uniemożliwić grzanie, gdy drzwiczki są otwarte: Styk NC blokuje przepływ sygnału do cewek. Widzimy, że przy otwartych drzwiach grzałka nie działa. 3. Pobranie informacji o temperaturze Aby pobrać informację o temperaturze wewnątrz terrarium, posłużymy się poradnikiem. W skrócie: Poniżej przedstawiam program w języku ST do przeliczania wartości z czujnika na temperaturę: Dodajemy nowy program i nowe zmienne globalne. 4. Zamknięcie drzwiczek Teraz zajmijmy się grzaniem do 30 stopni, gdy drzwiczki zostaną zamknięte. Dodajmy następujące instrukcje w main: Jeżeli zamkną się drzwi (zbocze opadające na zmiennej drzwi), to ustawi się flaga drzwi_N_flaga (potrzebna do dalszej części kodu). Jeżeli osiągniemy 30 stopni, to resetujemy flagę. Dodatkowo tworzymy nowy tryb grzania (tryb_drzwi_N). Napiszmy skrypt w języku ST, który będzie obsługiwał zmienną tryb_drzwi_N: Jeżeli flaga zamknięcia drzwi jest aktywna, to włączamy tryb grzania. Jeżeli osiągnięto temperaturę 30 stopni, to włączamy odpowiednią flagę, a w main wyłączamy drzwi_N_flaga. 5. Standardowe ogrzewanie Stwórzmy tryb standardowego grzania. W tym celu stwórzmy zmienną odliczanie, dzięki której będziemy sygnalizować, czy mamy odliczać minutę do grzania. Dodatkowo utworzymy program w trybie Init, który wykona się tylko raz przy włączeniu sterownika. Wystartujemy w nim odliczanie. Zawartość programu Init. Zmienna jest typu bool. W zastosowaniach przemysłowych praca maszyny musi się odbyć po jawnym sygnale operatora, więc nasze rozwiązanie nie jest zgodne ze sztuką. Jednak na cele edukacyjne i hobbystyczne to nam ułatwia sprawę. Do mierzenia czasu służą timery. Aby go dodać klikamy opcję New Block: Dodanie bloku. W Object browser wyszukujemy timer TON. TON działa w następujący sposób: Opis timera TON. Źródło zdjęcia: Arduino PLC IDE. Obsługa trybu standardowego. Powyższy kod działaja w następujący sposób: Jeżeli odliczanie jest załączone i nie osiągnięto temperatury 27 stopni, to odliczamy 60 sekund. Po odliczeniu czasu wyłączamy odliczanie (reset) i załączamy tryb standardowy. Jeżeli osiągniemy 27 stopni, to załączamy znowu odliczanie i ściągamy flagę trybu standardowego. Dodajemy program, który obsłuży flagi i wykryje przekroczenie 27 stopni. Zauważ, że jest on bardzo podobny do trybu drzwi. Dodajemy włączenie grzałki pod wpływem trybu standardowego. Dodatkowo widoczne jest zabezpieczenie, w którym przy otworzonych drzwiach nie ma możliwości grzania - styk NC drzwi. Jeżeli dotrwałeś do tego momentu, to chciałbym Ci serdecznie pogratulować. Właśnie stworzyliśmy system ogrzewania do terrarium! Działanie programu. Przedstawiłem tryb manualny i reakcję na zamknięcie drzwi. Czerwona dioda na DIN CELSIUS sygnalizuje grzanie. 6. Informacja dla programisty Stwórzmy ostatnią część projektu, jakim jest wyświetlanie co pewien czas, bądź na żądanie, pewnych parametrów związanych z algorytmem. Wykorzystamy bardzo ciekawą funkcjonalność narzędzia Arduino PLC IDE - połączenie Sketcha z Arduino IDE i algorytmu sterowania z Arduino PLC IDE. Shared variables to zmienne, które będą wymieniane między algorytmem sterowania, a Sketchem. W Shared Variables w Outputs wpisujemy zmienne, które chcielibyśmy śledzić: Tworzymy nowy skrypt o nazwie do_zmiennych_OUT, w którym będziemy przypisywali wartości do zmiennych w Sketchu: Następnie tworzymy skrypt, który co wciśnięcie przycisku lub co 5 sekund wyświetli informacje o statusie algorytmu: Program do przesyłu informacji. Funkcja, która umożliwia wysłanie informacji do odbiornika. Przetestujmy wyświetlanie informacji w Serial monitor w Arduino IDE: Nasz program jest skończony! Podsumowanie To była bardzo długa i intensywna bitwa… Ale udało się! Poznaliśmy razem dużo możliwości sterownika. WiFi, Bluetooth, równoległość wykonywania operacji, sterowanie temperaturą, wyświetlanie informacji to tylko niektóre z możliwości tego PLC. Trzeba przyznać, że to potężna jednostka, która ma ogrom potencjalnych zastosowań. To naprawdę wszechstronne urządzenie, które może ułatwić wiele zadań i sprawdzić się w różnych projektach. Jest łatwe w obsłudze i daje dużo możliwości, co czyni je świetnym wyborem do nowoczesnych rozwiązań. ________ Informacja: zestaw z Arduino Opta na potrzeby niniejszego artykułu dostarczyła firma Botland - oficjalny dystrybutor Arduino.
- 3 odpowiedzi
-
- 6
-
-
- Elektronika
- Programownie
-
(i 1 więcej)
Tagi:
-
Matlab Co to Matlab? Podstawy, zastosowanie, pierwsze kroki
mcsw_02 opublikował temat w Artykuły użytkowników
Wstęp Dotychczasowe moje artykuły dotyczyły przeważnie prostych tematów. Sortowanie danych, systemy liczbowe, czy sterowniki PLC. Teraz zaprezentuję Wam bardziej zaawansowane narzędzie. Napotkacie go na studiach, ale także jest szansa, że wykorzystacie go w swoich projektach. W tym artykule przedstawię Ci: Czym jest Matlab? Gdzie stosuje się Matlaba? Czy warto się go uczyć? Jak zastosować podstawowe techniki do pisania twoich pierwszych programów! Na swojej drodze projektowej na pewno spotkasz się z tym programem, dlatego warto wiedzieć, czym on jest. Źródło zdjęcia. Co to MATLAB? Logo Matlaba. Źródło zdjęcia. Matlab to interaktywne środowisko wykorzystywane przez inżynierów i naukowców na całym świecie. Służy on do zaawansowanych obliczeń i symulacji. Nazwa Matlab wywodzi się od słów Matrix Laboratory i pierwotnie został stworzony do obliczeń na macierzach. Macierze to bardzo ważny temat, bo dzięki nim możesz np. rozwiązać skomplikowany układ elektroniczny lub wykorzystać je do reprezentacji danych, przykładowo odczyty czujnika w czasie. Zastosowania Matlaba Matlaba możesz wykorzystać tam, gdzie masz styczność z: skomplikowanymi operacjami na macierzach i obliczeniami matematycznymi, przetwarzaniem sygnałów - obróbką danych i ich analizą, modelowaniem - przeprowadzaniem symulacji, np. w dziedzinie robotyki, teorią sterowania - implementacją algorytmów sterowania, regulacją, sztuczną inteligencją - machine learningiem i sztucznymi sieciami neuronowymi. Dzięki temu środowisku można wykonywać obliczenia arytmetyczne i na macierzach, pisać skrypty i rozmaite algorytmy lub wykreślać wykresy funkcji 2D i 3D. Należy jednak wspomnieć, że to nie jest arkusz kalkulacyjny jak Excel! Jest to narzędzie, które umożliwia znacznie więcej, szczególnie dla inżyniera. Praktycznym wykorzystaniem programu jest sterowanie urządzeniami. Matlab oferuje biblioteki, za pomocą których można przykładowo regulować temperaturę przedmiotu odpowiednio wysterowując grzałkę i pobierając dane o temperaturze. Takie dane możemy następnie przetworzyć i wykorzystać algorytmy przetwarzania sygnałów. Matlaba można wykorzystać przy symulacji robotyki. Możliwe jest stworzenie modelu manipulatora przemysłowego, na który działają różne obciążenia. Modelowanie i symulacje to ważny etap w projektowaniu skomplikowanych rozwiązań. Źródło zdjęcia. Podsumowując: Matlab to potężne narzędzie, które warto znać, bo ma wiele zastosowań. Jest bardzo wygodne, gdy potrzebne jest zaimplementowanie bardzo skomplikowanego algorytmu. Czy warto się uczyć Matlaba? Jak najbardziej! Warto spróbować swoich sił z tym środowiskiem. Dzięki niemu można rozwiązać wiele skomplikowanych problemów we względnie krótkim czasie przy niewielkim wysiłku. Matlab jest użyteczny w wielu dziedzinach, dlatego nawet podstawowa wiedza o nim będzie bardzo przydatna. Środowisko Matlab to nie tylko program do teoretycznych obliczeń, ale także do praktycznych zastosowań. Źródło zdjęcia. Niestety jest pewien haczyk… Matlab nie jest całkowicie darmowy. Istnieją różne wersje, z których można korzystać. Jeżeli jesteś studentem kierunku technicznego, to twoja uczelnia powinna oferować Ci darmowy dostęp do wersji akademickiej. W innym wypadku istnieje 30-dniowa wersja Trial. Możesz też korzystać z Matlaba Online w wersji Basic, który oferuje darmowe korzystanie z programu przez 20 godzin miesięcznie. Podstawy Matlaba Poniżej przedstawiam podstawowe instrukcje, które pozwolą Ci pisać pierwsze programy. Korzystam z Matlaba w wersji R2024a. Po uruchomieniu zobaczymy taki widok: MATLAB R2024a. Jest to okno główne Matlaba. Na razie zajmiemy się tylko jednym jego elementem. 1. Command window Jest to największe, białe okno, w którym widnieją znaki “>>”. Okno umożliwia wpisywanie pojedynczych komend i wykonywanie ich na bieżąco. Na tym etapie możemy zacząć wykonywać proste czynności, na przykład: przypisanie: a = 5 dodawanie, odejmowanie, mnożenie, dzielenie: +, -, *, / operatory porównania: >, <, >=, <=, ~=, komentarze: % Wynik pojawi się po wpisaniu komendy. Wstawienie średnika na końcu spowoduje niepokazanie wyniku. Przykład wykorzystania command window. Jeżeli w command window utworzymy zmienną, to zostanie ona zapamiętana w środowisku i będziemy mogli ją wykorzystać później. Zmienne są zapisywane w workspace. Aby go wyświetlić należy wpisać w command window polecenie workspace. 2. Podstawowe operacje na macierzach a) Definicja Aby zdefiniować macierz należy określić jej strukturę. Gdy definiujemy macierz zapisujemy jej elementy w nawiasie kwadratowym wpisując po kolei jej elementy. Kolejne wiersze oddzielamy średnikiem. Między elementami może być przecinek, lecz nie musi. Ważna uwaga: indeks pierwszego elementu wynosi 1! Zaznaczam to, bo w innych językach może wynosić 0. Aby utworzyć wektor należy stworzyć macierz o jednym wierszu, czyli nie rozdzielać liczb średnikiem. Przykład definicji macierzy: Definicja macierzy w command window. b) Odwołanie się do elementów Podobnie jak w innych językach programowania, aby odwołać się do konkretnego elementu należy podać jego indeksy. W przypadku Matlaba indeksy podaje się w nawiasach okrągłych: Wpisanie A(3, 2) zwróci element w trzecim wierszu, drugiej kolumnie, czyli 32. Odwołanie się do pojedynczego elementu. Możemy odwołać się do całego wiersza. Polecenie A(2, : ) zwraca wszystkie elementy z drugiego wiersza. Jeżeli chcemy odwołać się do całej drugiej kolumny, to napiszemy A(:, 2). Odwołanie się do całego wiersza lub kolumny. W przypadku, gdy potrzebujemy kilku wybranych wierszy/kolumn, to możemy przekazać wektor z potrzebnymi indeksami. Wektor, podobnie jak macierz, zapisuje się w nawiasach kwadratowych. Wybranie elementów z 1. i 3. wiersza i z 1. i 3. kolumny. Chcąc wybrać następujące po sobie wiersze/kolumny należy wpisać w odpowiednie miejsce następującą formułę ze swoimi danymi: indeks_startu:krok:indeks_stopu. Utworzyłem nową macierz. Wybrałem z niej elementy od 2. do 4. wiersza. Liczby są z kolumn od 1 do 5, ale z krokiem co 2. Ostatecznie zostanie wybrany element, z co drugiej kolumny. Krok można pominąć. Wtedy wyniesie 1. Stosując polecenie end jako w miejscu indeksu stopu Matlab wybierze wszystkie elementy od indeksu startu do ostatniego możliwego elementu. c) Macierze specjalne Matlab oferuje 3 podstawowe funkcje, dzięki którym można stworzyć specjalną macierz o charakterystycznych elementach: zeros() - macierz wypełniona zerami. ones() - macierz wypełniona jedynkami. rand() - macierz o losowych elementach. We wszystkich przypadkach pierwszy argument do funkcji to ilość wierszy, a drugi to liczba kolumn. Wykorzystanie funkcji zeros(), ones() i rand(). Może zdarzyć się sytuacja, w której będziesz potrzebował/a macierz o jednakowych elementach, ale różnych od 1. W tym celu: pomnóż macierz ones() przez tę liczbę… …lub dodaj do niej o 1 mniejszą liczbę. Dwie techniki definicji macierzy o jednakowych elementach. Macierz rand() zwraca losowe elementy od 0 do 1. Jeżeli chcesz przesunąć zakres, to zastosuj następującą technikę: losowa_macierz = rand(liczba_wierszy, liczba_kolumn) * rozpiętość_przedziału + indeks_rozpoczęcia. Przykładowo: index_rozpoczęcia = 5 - dolna granica przedziału, rozpiętość_przedziału = 7 - ile elementów będzie w dobranym zakresie, Ostatecznie największa możliwa liczba wyniesie 5+7=12, a więc przedział będzie wynosił liczby z zakresu <5, 12>. Macierz o losowych elementach z zakresu <5, 12>. d) Operacje na macierzach Oczywiście macierze możemy dodawać, mnożyć i modyfikować poprzez stałe. Zapamiętaj, że w Matlabie występują dwa rodzaje mnożenia macierzy. Zwykłe mnożenie zapisujemy jako gwiazdka ( * ). Element-wise multiplication zapisuje się jako kropka i gwiazdka ( .* ). Definicje nowych macierzy. Przykładowe operacje na macierzach. 3. Przydatne funkcje Przed rozpoczęciem tego punktu wygodniej będzie przenieść się do skryptu. W tym celu należy utworzyć nowy skrypt w lewym górnym rogu: Tworzenie nowego skryptu. Ukaże się okno, w którym można pisać skrypt. Znajduje się nad command window. a) Wykres funkcji 2D. Funkcja plot() Przed wyświetleniem funkcji, należy najpierw wygenerować dane osi x i y. Najprostszym sposobem jest wygenerowanie wektorów, które będą reprezentowały te dane. Można posłużyć się funkcją linspace(). Generuję wartości osi x. Posłużę się funkcją linspace(), która tworzy wektor o podanej rozpiętości i ilości elementów. Argumenty funkcji to odpowiednio: pierwszy element, ostatni element, ilość elementów w wektorze. Jako dane dla osi y wybiorę funkcję sinus. Wykorzystam funkcję sin(). Utworzę okno posługując się funkcją figure(n), gdzie n to numer okna. To nasze pierwsze okno, więc n wyniesie 1. Czas na wyświetlenie wykresu - korzystam z funkcji plot(x, y). Pierwszym argumentem jest wektor x a drugim y. Prosty skrypt wykorzystujący funkcję plot(). Po kliknięciu przycisku run powinien wyświetlić się poniższy wykres: Funkcja sinus. Można zauważyć, że wykres jest kanciasty. To przez małą liczbę elementów w wektorze. Zmieńmy liczbę elementów ze 100 do 1000. Wykres sinusa przy większej ilości danych. Wykres wygląda lepiej i dokładniej odwzorowuje funkcję. Oprócz funkcji sinus możesz zwizualizować inne funkcje trygonometryczne lub swoje własne dane. b) Funkcja subplot() Służy do wyświetlania kilku wykresów w jednym oknie. Moglibyśmy wyświetlać je w kilku oknach tworząc nowe funkcją figure(), ale metoda, którą teraz przedstawię, często przydaje się, gdy porównujemy ze sobą kilka danych przedstawionych na wykresach. Wykorzystuję wcześniej zrobiony sinus i dodatkowo tworzę cosinusa. Tworzę okno dla wykresów funkcji funkcją figure(). Wykorzystuję funkcję subplot(w, k, p). Argumenty funkcji kolejno: w – liczba wierszy w oknie, k – liczba kolumn w oknie, p – pozycja funkcji, którą chcemy wyświetlić. Gdy wyświetlamy pierwszy wykres, to piszemy 1, przy drugim 2 itp… Zakładając, że mamy dwie funkcje do wykreślenia, to będziemy potrzebowali dwóch wierszy (na dwie funkcje) i jedną kolumnę. Wykreślam kolejne wykresy funkcją plot(x, y). Skrypt wykorzystujący funkcję subplot(). Wynik: Wynik skryptu. c) Help i dokumentacja Matlaba Za nami już kilka przydatnych funkcji. Nie trzeba ich się uczyć na pamięć, bo Matlab posiada bogatą dokumentację. Wystarczy w command window wpisać help, a następnie nazwę funkcji, którą chcemy użyć. Wykorzystanie komendy help. W helpie jest opisana funkcja, jej działanie, argumenty, które przyjmuje, co zwraca, przykłady i wiele innych przydatnych informacji. Oprócz tego zachęcam Cię do przejrzenia ogólnej dokumentacji. Znajdziesz ją w prawym górnym rogu, klikając znak zapytania. Prawy górny róg Matlaba. Tutaj znajdziesz kilka cennych elementów, takich jak dokumentacja środowiska. d) Instrukcja warunkowa if Bardzo przydatnym elementem Matlaba jest możliwość wykorzystania instrukcji warunkowej. Jej składnia prezentuje się następująco: if warunek Działanie elseif warunek Operacja else Operacja end Utwórzmy prosty skrypt, który zaprezentuje działanie ifa. Sprawdźmy, czy podając 3 długości można z nich utworzyć trójkąt: Definiujemy 3 liczby, które będą reprezentowały długości 3 boków trójkąta: a, b, c. Trójkąt jest możliwy do stworzenia, jeżeli suma dowolnych dwóch boków jest większa od trzeciego boku. Innymi słowy, poniższe warunki muszą zostać spełnione: a + b > c, a + c > b, b + c > a. Jeżeli warunek będzie spełniony, to wyświetlimy napis ‘Można utworzyć trójkąt’. W przeciwnym wypadku wyświetlimy ‘NIE można utworzyć trójkąta’. Wykorzystanie instrukcji warunkowej if. Do wyświetlenia napisu można też użyć funkcji disp(). Taki program powinien wyświetlać wynik w command window. e) Funkcje Przenieśmy ten program do osobnej funkcji, którą będziemy mogli wywoływać wielokrotnie bez powtarzania nadmiernej ilości kodu. W tym celu wykonajmy następujące kroki: W tym samym folderze, w którym jest twój główny skrypt, utwórzmy nowy skrypt. Pamiętaj, że nazwa funkcji musi mieć taką samą nazwę, co nazwa skryptu. Utwórzmy funkcję zgodnie z poniższą składnią: function zmienna_wyjściowa = nazwa_pliku(zmienne_wejściowe) W naszym przypadku: Zmienną wyjściową nazwijmy odp (odpowiedź). Nazwę pliku nazwijmy czy_trójkąt. Zmienne wejściowe to będą liczby a, b, c. Przepiszmy całą funkcję z głównego skryptu zamieniając funkcje wyświetlającą napis na przypisanie odpowiedzi do zmiennej odp. Funkcja czy_trojkat. Wywołanie funkcji. f) Pętla for Ostatnim przydatnym elementem, który chcę Ci pokazać są pętle. Służą one powtarzania pewnej czynności tyle razy ile zadeklarowaliśmy. Jej składnia wygląda następująco: for iterator = pierwszy_element:krok:ostatni_element Operacje end Napiszmy prosty przykład, w którym kilka razy wykonamy kilka operacji na zmiennej. Wykorzystano pętlę for do powtórzenia operacji. Podsumowanie MATLAB to wszechstronne i potężne narzędzie, które oferuje szerokie możliwości w zakresie rozwiązywania skomplikowanych problemów inżynieryjnych, matematycznych i naukowych. Chociaż MATLAB nie jest darmowy, jego zalety w projektowaniu, modelowaniu i analizie danych czynią go wartym nauki i inwestycji, zwłaszcza dla osób związanych z dziedzinami technicznymi. Nawet podstawowa znajomość tego środowiska może otworzyć nowe możliwości i ułatwić pracę przy wielu projektach. Jeżeli chcesz zobaczyć jak Matlab jest wykorzystywany do praktycznych celów polecam artykuł o programowaniu Arduino z użyciem tego narzędzia. Spróbuj napisać kilka skryptów/algorytmów samodzielnie. Poznawaj więcej funkcji i możliwości i spróbuj wykorzystać potencjał środowiska.- 3 odpowiedzi
-
- 7
-
-
- Elektronika
- Programownie
- (i 1 więcej)
-
Dzień dobry, od wczoraj testuje wyświetlacz TFT. Wszystko idzie dobrze, ale nie wiem jak mam wyświetlić zmienną int na takim wyświetlaczu. Bardzo proszę o odpowiedź. Z góry dziękuję!
- 17 odpowiedzi
-
- elektronika
- int
-
(i 3 więcej)
Tagi:
-
Wstęp Czy wiesz, że FORBOTJESTCOOL(36) = 2676043599332257617141(10)? Ja też nie wiedziałem. Dowiedziałem się, gdy włączyłem kalkulator systemów liczbowych i odkryłem system trzydziesto szóstkowy. Do zapisu liczb wykorzystuje on cyfry od 0 do 9 i litery od A do Z. Rzeczywiście, istnieją systemy liczbowe, w których jest tak dużo dostępnych znaków, że można z nich zapisywać słowa, a nawet całe zdania. W tym przykładzie pokazałem Ci, że istnieją większe systemy liczbowe, niż te powszechnie znane, np. dwójkowy, czwórkowy, ósemkowy, czy dziesiętny. Przedstawię Ci system szesnastkowy, za pomocą którego można reprezentować kolory lub adresy urządzeń podłączonych do twojego Arduino System szesnastkowy stosuje się do adresowania urządzeń, które komunikują się za pomocą standardu I2C. Źródło zdjęcia. Jeżeli nie znasz podstaw systemów liczbowych lub nie wiesz jak zamienić liczbę dziesiętną na binarną i na odwrót, to zapraszam Cię do mojego poprzedniego artykułu artykułu o systemie binarnym. To kluczowy temat, a wiedza z niego będzie przydatna w dalszych częściach tego artykułu! Konwersja liczb szesnastkowych i dziesiętnych System szesnastkowy, nazywany również heksadecymalnym (w skrócie hex), jak sama nazwa wskazuje, zawiera w sobie 16 znaków, którym przypisane są odpowiednie wartości systemu dziesiętnego. W systemie szesnastkowym korzystamy z cyfr 0..9 i liter A...F: A(16) = 10(10) B(16) = 11(10) C(16) = 12(10) D(16) = 13(10) E(16) = 14(10) F(16) = 15(10) a) Zamiana przy użyciu operacji modulo (dec → hex) Jest to standardowa, algorytmiczna operacja, którą można wykonać z każdym innym systemem liczbowym. W naszym przypadku liczbę dzieli się całkowicie przez 16(10) i zapisuje się resztę z dzielenia. Powtarza się to do momentu, aż w wyniku dzielenia znajdzie się 0. Wynik odczytywany jest od końca z reszt z dzielenia. Spróbujmy zamienić liczbę 234(10) na liczbę hex: Wynik dzielenia całkowitego kolejnych liczb zapisujemy w lewej kolumnie a resztę z dzielenia po prawej. Wynik, czyli liczbę szesnastkową, odczytuje się z reszt z dzielenia - od dołu do góry. Poniżej jeszcze dwa przykłady. b) Konwersja za pomocą wag (hex → dec) W tej metodzie korzystamy z definicji systemu liczbowego - każda cyfra na konkretnej pozycji definiuje wagę tej pozycji. Przeliczmy liczbę 1CA9(16): Podstawą liczby heksadecymalnej jest 16(10). Cyfra na ostatniej pozycji ma wagę 160(10), przedostatnia 161(10), kolejna 162(10) itp. Mnożymy wagi przez cyfry na ich pozycjach. Suma wszystkich iloczynów to wynik. c) Konwersja za pomocą systemu binarnego (hex → bin → dec) Jest to sztuczka, która może Ci pomóc zamienić w szybki sposób względnie małą liczbę hex na liczbę dziesiętną. Rozsuń liczbę hex na pojedyncze cyfry. Każdą cyfrę zamień na liczbę binarną. Złóż powstałe liczby binarne. Zamień liczbę binarną na decymalną. Metodę rozsuwania stosuje się głównie do zamiany hex → bin. Weźmy na tapetę liczbę D8(16): Rozdzielamy D8(16) na poszczególne cyfry - D(16) i 8(16). D(16) w hex to 13(10) w dec. 8(16) w hex to 8(10) w dec. Wiedząc to jesteśmy w stanie zapisać te liczby w systemie binarnym. Składamy obliczone części. Złożoną część przeliczamy na system dziesiętny. d) Konwersja za pomocą systemu binarnego (dec→ bin → hex) Tego typu zamiana liczb odbywa się analogicznie do poprzedniego przykładu, ale w odwrotnej kolejności: Zamień liczbę dec na bin. Rozsuń liczbę bin co 4 bity (4 cyfry). Zamień otrzymane liczby bin na hex. Złóż otrzymane liczby hex. Jak widzisz konwersja między systemem hex a dziesiętnym nie jest trudna. Użyliśmy tylko i wyłącznie wiedzy z poprzedniego artykułu. Polecam przećwiczyć te umiejętności wymyślając jakąś małą liczbę heksadecymalną (np. składającą się z dwóch cyfr) i zamienić ją na liczbę binarną/dziesiętną. Możesz też wymyślić liczbę dziesiętną i dokonać konwersji na heksadecymalną. Zastosowania liczb hex Do czego mogą się przydać liczby szesnastkowe? Ich najważniejszą właściwością jest zwięzły zapis dużych liczb: FFFF(16) = 65535(10) = 1111111111111111(2) Jak widać powyżej, liczbę 16 bitową można zapisać za pomocą 4 cyfr (liter) w systemie heksadecymalnym. a) Reprezentacja kolorów Jednym ze sztandarowych przykładów zastosowania systemu szesnastkowego jest zapis koloru. Kod składa się ze znaku # i trzech dwucyfrowych liczb szesnastkowych, które odpowiednio oznaczają poziomy kolorów: czerwonego, zielonego i niebieskiego (RGB). Im wyższa liczba, tym intensywniejszy jest poszczególny składnik koloru. Na przykład: ● #FF0000 - czerwony, rgb(255, 0, 0), ● #00FF00 - zielony, rgb(0, 255, 0), ● #0000FF - niebieski, rgb(0, 0, 255), ● #000000 - czarny, brak jakiegokolwiek składnika, rgb(0, 0, 0), ● #FFFFFF - biały, połączenie wszystkich składników, rgb(255, 255, 255), ● #A020F0 - fioletowy, rgb(160, 32, 240). b) Adresy pamięci W jaki sposób zapisać adres pod którym ma być przechowywana zmienna? Dzisiejsze komputery charakteryzują się ogromną pamięcią. Jest wiele możliwych adresów w pamięci pod które można zapisać jakąś informację. Wiąże się to z dużymi wartościami tych adresów. Liczby, które definiują dany adres są po prostu długie. W takim wypadku możemy skorzystać z liczby szesnastkowej, która skróci nam ten zapis. Tę technikę stosuje się często. Przykładem jest np. odczyt adresu zmiennej w języku C : Deklarujemy 3 zmienne po sobie. Odczytujemy po kolei ich adresy. Każdy odczytany adres będzie zapisany w systemie szesnastkowym… …a każdy adres będzie się różnił od poprzedniego o rozmiar zadeklarowanej zmiennej. Deklaracja zmiennej char (1 bajt): char a = 'X'; char b = 'Y'; char c = 'Z'; printf("Rozmiar pojedynczego znaku: %d\n", sizeof(char)); printf("Adres zmiennej a: %p\n", &a); printf("Adres zmiennej b: %p\n", &b); printf("Adres zmiennej c: %p\n", &c); Wyjście: Rozmiar pojedynczego znaku: 1 Adres zmiennej a: 0061FF1F Adres zmiennej b: 0061FF1E Adres zmiennej c : 0061FF1D Deklaracja zmiennej short (2 bajty) : short x = 1; short y = 2; short z = 3; printf("Rozmiar pojedynczego shorta: %d\n", sizeof(short)); printf("Adres zmiennej x: %p\n", &x); printf("Adres zmiennej y: %p\n", &y); printf("Adres zmiennej z: %p\n", &z); Wyjście: Rozmiar pojedynczego shorta: 2 Adres zmiennej x: 0061FF1A Adres zmiennej y: 0061FF18 Adres zmiennej z: 0061FF16 c) Adresy urządzeń w transmisji I2C Jednym z najpopularniejszych zastosowań systemu szesnastkowego jest zapis adresów urządzeń w komunikacji I2C (TWI). Skorzystajmy z karty katalogowej czujnika temperatury Adafruit 4089 z cyfrowym termometrem ADT7410, który może komunikować się właśnie przez ten protokół. Wycinek karty katalogowej Adafruit 4089. Źródło zdjęcia. Karta katalogowa urządzenia komunikującego się przez I2C powinna dostarczać klientowi informację o adresie danego urządzenia. Niektóre urządzenia dają możliwość konfiguracji adresu za pomocą pinów tego urządzenia. W przykładzie powyżej, jeżeli korzystamy z kilku tych samych czujników lub adres tego czujnika powtarza się z adresem innego, to za pomocą pinów A0 i A1 możemy zmienić jego adres. d) Adres MAC Jest to unikatowy i niepowtarzalny adres karty sieciowej nadany przez producenta. Stanowi on 48 bitową liczbę z czego pierwsze 24 bity oznaczają producenta karty sieciowej (ID producenta). Pozostałe 24 to ID urządzenia. Ze względu na rozmiary liczb, które są używane w adresach MAC, pisze się je w systemie szesnastkowym, co znacznie ułatwia odczyt takiego adresu. Przykładowe sposoby zapisu adresu MAC: 00:0c:29:cc:55:5e - MAC w Linux. Separatorem między parami znaków jest dwukropek. 00-0c-29-cc-55-5e - MAC w Windows. Separatorem między parami znaków jest myślnik. 000c.29cc.555e - MAC w urządzeniu sieciowym Cisco. Kropki między hextetami Adres MAC w Linux. Źródło zdjęcia. e) Komendy w postaci liczb hex Wysyłanie komend do mikrokontrolera może odbywać się właśnie w tym systemie. Dlaczego? Powód jest ten sam co wcześniej - możemy zawrzeć wiele komend w zwartym zapisie. Np. 0x00 - uśpij urządzenie, 0x01 - wybudź urządzenie, 0x02 - sparuj urządzenie, 0x03 - skonfiguruj urządzenie, 0x1F - włącz LED, itp. Jest to moim zdaniem dobry pomysł do organizacji i implementacji komunikacji z uC. Podsumowanie System szesnastkowy to bardzo przydatny i elastyczny system, który pozwala na zapisanie dużych liczb w krótkim zapisie. Jest on wykorzystywany praktycznie wszędzie, gdzie korzysta się z wielobitowych liczb. Nasuwa się jednak pytanie: Dlaczego nie korzystamy z większych systemów liczbowych? Jest kilka powodów: Złożoność zapisu - w systemie hex stosuje się 16 cyfr. Wyższe systemy liczbowe wprowadzają kolejne znaki oznaczające kolejne cyfry. W pewnym momencie może być po prostu za dużo tych znaków do interpretacji, co może komplikować program. Zgodność z potęgą liczby dwa - 16(10) = 24(10). System będący potęgą dwójki ułatwia obliczenia matematyczne i jest zgodny z logiką komputerową i cyfrową.
- 2 odpowiedzi
-
- 6
-
-
- Początkujący
- Elektronika
- (i 2 więcej)