Skocz do zawartości

Wydzielone z: Raspberry Pi vs Arduino - którą platformę wybrać?


Pomocna odpowiedź

Napisano

Dzięki Treker. Nie widziałem tego wcześniej. Czyli wychodzi na no, że językiem Arduino jest C ew. C++(a i to najwyżej 98r). Cudów brak 😉. Więc może to i dobrze, że wziąłem się za C++ 😃 .

Nie rozumiem jeszcze jednego, rzecz o której się wszędzie pisze i czyta, a która dla mnie jest niewyjaśniona. Czym są biblioteki, np. w Arduino. Rozumiem, że konkretne biblioteki są przypisane konkretnemu językowi programowania, wydaje się, że to są jakieś zbiory instrukcji czy coś w tym sensie. Chyba to je się wpisuje na początku każdego programu. Ale prosiłbym kogoś o wytłumaczenie co to, z czym to i dlaczego, oraz skąd to się bierze... 🙂

Pozdrawiam.

Biblioteka to fragment kodu, który może być użyty ponownie w innym programie. Przykładowo - wyobraź sobie, że nie możesz używać funkcji sqrt() i musisz ją napisać sam - używając podstawowych operacji, czyli mnożenia, dzielenia itd. Okazuje się, że można to zrobić. Załóżmy więc że czytasz odpowiednią literaturę, męczysz się niemiłosiernie i na koniec masz piękną funkcję my_sqrt. Jesteś z niej dumny, ale co więcej chcesz ją wykorzystać w kolejnych programach - albo nawet udostępnić innym, żeby mogli się nią nacieszyć. To jest właśnie biblioteka - niewielka, bo z tylko jedną funkcją, ale na początek wystarczy. Podobnie jest z bibliotekami Arduino - programiści siedzą i męczą, a jak wymęczą to publikują, żeby inni mogli też się z ich bibliotekami pomęczyć. Niestety jakość takiego kodu bywa różna, stąd fora dyskusyjne pełne są pytań i problemów, ale wiele osób zamiast pisać wszystko od podstaw, może pobrać gotowca z netu i chwilę później utworzyć nowy wątek - jak zrobić cośtam... I to właśnie są biblioteki Arduino. C++ ich nie zawiera, bo i kto wpadłby na pomysł jak napisać najbardziej niewydajny kod na świecie do sterowania pinami.

Wyczuwam odrobinę sarkazmu co do Arduino, co do C++ to myślałem, że też ma biblioteki...

To co wstawia M. Zelent po #include...np?? To nie biblioteki?

Po prostu zdarzyło mi się kilka razy przglądać kody źródłowe różnych bibliotek Arduino - i nie zawsze był to miły widok.

Dyrektywa #include oznacza wstawienie całego pliku podanego jako parametr w jej miejsce. Narzędzie, które taką pracę wykonuje nazywane jest proprocesorem. Mając więc #include na początku pliku powiedzmy main.cpp, preprocesor tworzy tymczasowy plik, gdzie linijka #include nie występuje, a w jej miejscu jest treść time.h.

W ten sposób można włączać różne pliki, np. inne pliki z kodem programu (.c, .cpp).

Prawidłowo używając #include, włączamy nim tzw. pliki nagłówkowe - są to pliki nie zawierające kodu, tylko deklaracje elementów. Sam kompilator nie wiem, np. co znaczy my_sqrt. Dopiero zapis:

uint32_t my_sqrt(uint32_t x);

sprawi, że kompilator "zrozumie" co znaczy my_sqrt - jest to funkcja o parametrze całkowitoliczbowym, która zwraca również wartość całkowitą. Domyślnie sqrt działa na liczbach zmiennopozycyjnych, ale my_sqrt to tylko nazwa, może mieć inną liczbę, typ parametrów, ale może oznaczać np. nazwę zmiennej.

Co ważniejsze na razie mamy tylko deklarację funkcji. Gdybyśmy spróbowali jej użyć, pojawi się bład braku definicji. Deklaracja to poinformowanie kompilatora co dana nazwa oznacza (jest to np. funkcja o określonych parametrach). Definicja do kod programu, który będzie wykonany po wywołaniu tej funkcji.

Pliki nagłówkowe zawierają deklaracje funkcji, zmiennych, klas itd. a definicje są przechowywane w plikach źródłowych np. .c, .cpp.

Kompilacja przebiega w kilku etapach. Pliki źródłowe tłumaczone są do kodu obiektowego .o, .obj, który następnie jest łączony w ostateczny program, np. .exe, .hex.

Istnieje kilka możliwości stworzenia biblioteki. Najprościej jest mieć kilka plików .c (z definicjami) oraz .h (z deklaracjami) i kompilując główny program dołączyć je - mamy wtedy jeden program, który powstaje z kilku plików źródłowych.

Takie działanie czasem jest niewygodne, kompilacja dodatkowych plików zajmuje czas, a innym razem chcemy komuś przesłać naszą bibliotekę, ale nie chcemy żeby czytał nasz kod źródłowy.

Można wtedy skompilować pliki źródłowe biblioteki (.c/.cpp) do plików obiektowych .o /.obj, a następnie zamiast pliku wykonywalnego, utworzć bibliotekę - jest to plik o rozszerzeniu .lib lub podobnym.

Taki plik nie może działać sam w sobie, ale może być użyty przez kompilator jako zamiennik plików źródłowych i obiektowych.

Program główny włącza tylko pliki nagłówkowe z deklaracją elementów, a definicje są już skompilowane w pliku .lib. Jest to tzw. biblioteka statyczna - program będzie działał nawet bez plików .lib, są one potrzebne tylko podczas kompilacji (a dokładniej linkowania).

Najbardziej znany typ bibliotek to biblioteki dynamiczne. W systemie Windows mają rozszerzenie .dll, Linux używa plików .so. W tym przypadku program główny nie zawiera definicji funkcji, zamiast tego odwołuje się do zewnętrznego pliku. Ponieważ bibilioteka nie jest włączona do pliku .exe, musi być obecna podczas uruchamiania programu. Może być też zamieniana na inną wersję bez potrzeby kompilacji.

Teraz można wyjaśnić jak biblioteki są związane z językiem programowania. Jeśli jako bibliotekę używasz kodu źródłowego, to język programowania jest określony. Pliki .lib są mocno związane z kompilatorem, ale często mogą być łączone z programami w innym języku - np. środowisko .Net Microsoftu pozwala na łączenie programów w różnych językach, Python używa bibliotek pisanych w C.

Natomiast bibilioteki dynamiczne są niezależne od języka - ale najtrudniejsze w użyciu.

  • Lubię! 1

ahaaaa 😅

udało Ci się, niewiele z tego zrozumiałem 😉

Ok, przeczytałem drugi raz i zaczyna docierać... pytanie, skąd program bierze te pliki źródłowe?

wpisujemy deklarację, skąd (fizycznie)bierze definicję? (chyba nic nie pokręciłem)

Ok, przeczytałem trzeci i czwarty raz 😉 pierwsza połowa jasna, druga gorzej...

Drugie pytanie: co to pliki obiektowe?

Starałem się podać bardziej ogólną definicję, później próbowałem podać szczegóły, więcej pomysłów nie mam.

Najprościej - biblioteka to po prostu fragment programu. Programy mogą się składać z wielu plików i jak jeden lub więcej takich plików można użyć w kilku projektach, to jest właśnie biblioteka. Technicznie jest trochę trudniej, więc nie warto chyba powtarzać.

Biblioteki są pisane w określonych językach, ale nie muszą być do nich przypisane. Wszystkie szczegóły zależą od wyboru kompilatora i środowiska. Sketch sam pobiera pliki źródłowe bibliotek i dołącza je do projektu - wystarczy więc dodać znacznik #include, ale pod spodem dzieje się to co opisywałem wcześniej.

Dzięki Elvis, jak zwykle jesteś niezwykle pomocny, a co najważniejsze zmuszasz do myślenia co zawsze pomaga w nauce.

Pytałem skąd pobiera biblioteki, ale tak fizycznie... skąd je bierze? Ściąga na bieżąco z netu, ma je w swoich folderach? Pytanie banalne, ale nie wiem 😕 . Skąd bierze się wiedza kiedy i jakie biblioteki użyć? W trakcie nauki do tego dojdę? wraz z jakimś osprzętem jest info o bibliotekach obsługi? Pewnie z czasem się dowiem ale pozwól, że Cię wykorzystam póki mogę 😅

Ciężko jednoznacznie odpowiedzieć - można samemu napisać, można kupić, część bibliotek jest dołączona do kompilatora (tzw. biblioteka standardowa). Wiele bibliotek jest dostępnych za darmo, ale jak pisałem o Arduino, z tym trzeba czasem uważać. Raczej postępuje się odwrotnie - zamiast szukać bibliotek, a później dla nich zastosowania, najpierw definiuje się projekt. Następnie można pomyśleć jak go zrealizować - i tutaj jest wiele opcji, można wszystko samemu pisać, można kupić gotowe biblioteki. A czasem nawet wykorzystać coś open-source. Ale nie ma jednego miejsca gdzie są wszystkie biblioteki świata.

Możesz poszukać np. na github-ie gotowych bibliotek, ale moim zdaniem to nie jest dobra metoda do nauki. Lepiej chyba samemu coś poznać, niż liczyć na zrobione przez kogoś rozwiązania.

Generalnie Arduino ma być dla mnie jakąś prostą formą początków nauki programowania. Zawsze mnie ta wiedza pociągała i fascynowała. Coś kompletnie kiedyś (i nadal) dla mnie niepojętego kiedy się patrzy na linijki zapisanego kodu. Z racji wieku, obowiązków, rodziny nie jestem w stanie pójść na jakieś późne studia, jedno co mogę to poświęcić max wolnego czasu na naukę we własnym zakresie. Po to by umieć, potrafić i móc powiedzieć sobie dałem radę. Pewnie coś też zbudować.

Na podstawie mojej nikłej wiedzy zaplanowałem to sobie jako Arduino na Forbocie i C++ u M. Zelenta równolegle, później Bluebook i uC Atnela( którego to kursu raczej nie polecasz, a Treker jest innego zdania). FPGA to dla mnie czarna magia, być może na razie. Są jeszcze Java, Python i kilka innych...Najchętniej bym poszedł na jakieś kursy z nauczycielem ale mieszkam na prowincji więc zostaje mi internet.

Ale teraz już szkoda gadania, czas ruszyć do kodowania i ćwiczeń.

Dzięki i pozdrawiam.

Nie chciałem Cię zniechęcać do nauki, czy próbowania sił w programowaniu. Na naukę nigdy nie jest za późno, sam coś o tym wiem 🙂 W każdym razie jeśli chcesz poznać programowanie jako takie, polecam dobrą książkę i kompilator na PC. Zobaczysz wtedy podstawy - jak działa program, debugger, jak wyglądają kolejne etapy kompilacji. Mając taką podstawową wiedzę będzie Ci o wiele łatwiej poradzić sobie z mikrokontrolerami, gdzie wiele rzeczy jest dużo trudniejszych. Chociażby debugowanie - na Arduino nie masz debuggera, po prostu uruchamiasz program, a on coś robi. Na PC (i wielu innych platformach) można program uruchamiać linijka-po-linijce i oglądać zawartość zmiennych - to bardzo ułatwia znajdowanie błędów oraz naukę. Natomiast co do języka programowania to moim zdaniem na początek powinieneś wybrać jeden i od niego zacząć. Jeśli będziesz próbował nauczyć się wszystkich na raz, to raczej nic z tego nie wyjdzie. Ale jak opanujesz jeden, będzie o wiele łatwiej poznać kolejny - to jak z językami naturalnymi, podobno.

Nawiązując do tematu wątku, rozumiem, że RPi radzi sobie bez problemu z wieloma rzeczami naraz do zrobienia(problem niezależnie od siebie migających diod z innego wątku). Po prostu potrafi wykonywać wiele programów równocześnie, tak?

Jednak najlepsze do tego są chyba układy programowalne, dobrze myślę?

Nie, nie można tak łatwo generalizować. W zasadzie, pomijając trywialne zabawki i wprawki dla początkujących, nie ma chyba programów na mikrokontrolery nie robiących wielu rzeczy na raz. Oczywiście, należy oddzielić gigantyczne scalaki mające kilka procesorów w środku, które z definicji mogą wykonywać kilka różnych programów jednocześnie od sposobów, których chwytają się programiści by udawać równoległość w mniejszych maszynkach. Przecież Twoje Arduino, któremu napisałeś program do mrugania diodką 1Hz i wypisywania co sekundę tekstu "Hello world!" także robi w zakamuflowany sposób parę rzeczy na raz. Nie widzisz tego w swoim programie, ale ktoś przecież obsługuje port szeregowy (UART): wykonanie funkcji println() nie kończy się wraz z rozpoczęciem wykonywania następnej linijki Twojego programu. Gdzieś tam wewnątrz łańcuch znaków został tylko zapamiętany w RAMie i właśnie rozpoczęło się jego powolne wysyłanie (sterowane kawałkiem programu obsługującego UART), jednoczesne z kontynuacją dalszych części Twojego programu. Liczenie czasu to także osobny proces. Niezależnie kiedy wywołasz funkcję millis() lub zażądasz opóźnienia delay(500) - bazuje na tym samym mechanizmie, używasz wyrażonego w milisekundach czasu jaki upłynął od włączenia procesora. Przecież te funkcje nie wymyślają go sobie ad hoc tylko odczytują wartość ukrytej, 32-bitowej zmiennej "popychanej" 1000 razy na sekundę przez specjalny kawałek programu. Znaleźliśmy już trzy rzeczy wykonywane "równolegle" w prościutkim programiku. Piszę w cudzysłowie bo przecież procesor jest jeden i się nie rozerwie. Musi porzucić coś jednego by wykonać kawałek czegoś drugiego. Na szczęście wbudowane w niego mechanizmy zapamiętywania i odtwarzania kontekstu umożliwiają robienie takiego myku dziesiątki tysięcy razy na sekundę a Tobie wydaje się, że wszystko dzieje się na raz. I skoro jacyś programiści wykorzystali te mechanizmy by kkazać Arduinowemu maluchowi robić jakieś operacje "pod pokrywką" to dokładnie to samo możesz zrobić Ty w swoim własnym kodzie. Może na razie to wydaje się trudne, ale zapewniam Cię, że sposobów na zmuszanie procesora do podziału czasu jest wiele a co gorsza (chyba już się o tym przekonałeś) w zasadzie nie da się się napisać żadnego niebanalnego programu bez quasi-równoległej pracy wielu(dziesiątek) współbieżnych procesów.

Mając na pokładzie prawdziwy system operacyjny typu Linux jest oczywiście łatwiej, bo przecież po to m.in. on powstał - by zarządzać zasobami maszyny (pamięć, peryferia, czas procesora) w przypadku wykonywania mnóstwa (setek?) zadań na raz. Nie musisz wtedy niczego wymyślać, wystarczy przeczytać dokumentację i zacząć pisać. Nawet używając konsoli i pisząc "zwykły" kod w C mrugający diodką A możesz kazać go wystartować a potem napisać i odpalić drugi program mrugający diodką B. Nie będą nic o sobie wiedzieć i każdy będzie mrugał wesoło swoją diodką. To właśnie Linux zadbał o pamięć dla każdego programu i wpisał je na długą listę zadań, którym należy poświęcić trochę czasu całkiem szybkiego CPU. W mniejszych procesorkach podział zasobów (także czasu procesora) robisz samodzielnie (czego na Malinie bez Linuxa sobie nie wyobrażam) albo korzystasz z istniejących narzędzi. Nawet Arduino dorobiło się kilku pomysłów na prostą wielowątkowość, choć to jednak trochę zabawa - można się temu przyjrzeć by zobaczyć, że w ogóle się da. Warto natomiast poświęcić czas na ogarnięcie systemów typu FreeRTOS. W większych projektach sprawdzają się fajnie a co najważniejsze trochę porządkują sprawy, standaryzując pewne rozwiązania. Nie trzeba przecież za każdym razem odkrywać koła.

  • Lubię! 1

Marek1707 dla Ciebie piwko, a przede mną jeszcze dużo nauki:-)). Faktycznie ilość operacji na sekundę procesora powinna pozwalać na "wielowątkowość" w Arduino, kwestia umiejętności i kodu.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...