Skocz do zawartości

Elvis

Użytkownicy
  • Zawartość

    2543
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    187

Wszystko napisane przez Elvis

  1. Nie wiem o co chodzi z tym "certyfikatem dopuszczenia do obrotu". Deklarację CE w większości przypadków wystawia producent i to producent dopuszcza swój wyrób do obrotu: https://www.ce-polska.pl/deklaracja-zgodnosci-ue Natomiast na podstawie jakich przesłanek wystawia deklarację - to sprawa i odpowiedzialność producenta. Ale każdy kto jest odważny może taki papierek podpisać i oznaczyć wyrób jako zgodny z CE. Natomiast jeśli będzie to poświadczenie nieprawdy to już sprawa tego kto nieprawdę napisał. Są dziedziny, np. sprzęt medyczny, gdzie konieczny jest zewnętrzny audyt oraz udział jednostki notyfikowanej. Przykład takiej deklaracji: http://ascor.pl/certyfikaty_2020/pl/Dyrektywa 93_42_EEC.pdf W przypadku kalkulatora nie ma raczej takiego wymogu. Przykład jak wygląda deklaracja zgodności dla Raspberry Pi: https://www.raspberrypi.org/documentation/hardware/raspberrypi/compliance/rpi_DOC_4b_EU_RED.pdf edit: Jeszcze dla ułatwienia deklaracja dla starszego RaspberryPi https://www.raspberrypi.org/documentation/hardware/raspberrypi/compliance/rpi_DOC_bplus_CE.pdf Jest tutaj o tyle łatwiej, że nie ma WiFi czy BT - ale jak widać do badania EMC nie wystarczy stare radio.
  2. Jak chodzi o CE mam głównie doświadczenie z dyrektywą medyczną, czyli 93/42/EWG i moje podejście może się wydawać niektórym zbyt rygorystyczne, ale pozwólcie że włączę się do dyskusji. Zacznijmy od samego początku, czyli dyrektyw oraz norm. Dyrektywy są prawem europejskim i nie tylko obowiązują jak każde inne prawo, ale są również nadrzędne nad prawem państw członkowskich. Same dyrektywy jako akty prawne są dostępne publicznie i są darmowe. Natomiast ich zapisy są bardzo ogólnikowe i to sprawia, że dla osób technicznych mogą wydawać się dziwne, albo nielogiczne - takie "lanie wody". Natomiast prawnicy rozumieją te zapisy aż za dobrze. W dyrektywach znajdziemy właśnie cytowane wcześniej fragmenty, czyli co ma zapewnić producent, albo dokładniej - podmiot wprowadzający na rynek. Te zapisy są mocno życzeniowe, urządzenia mają być bezpieczne, poprawnie skonstruowane, udokumentowane itd. Natomiast dyrektywy zawierają niewiele informacji, albo wcale o tym jak takie piękne idee wcielić w życie. Po prostu producent, albo podmiot który wprowadza na rynek UE wyroby innego producenta (np. spoza unii), ma wykazać, że wykonał niezbędne kroki, aby wymogi dyrektywy spełnić. I tutaj pojawia się problem. Bo jak zapewnić np. bezpieczeństwo urządzenia? Można latami prowadzić badania, wykonać ogromną pracę naukową aby udowodnić, że nasz produkt nie stwarza żadnych zagrożeń - i jest tutaj o wiele trudniej niż nam się wydaje. Bo np. co będzie jeśli dziecko weźmie nasz amatorski kalkulator, który ma przyciski drukowane na drukarce 3D, połknie przycisk i się zadławi? Kto będzie odpowiadał za takie zdarzenie? Czy umieściliśmy w instrukcji informację że kalkulator nie może być używany przez dzieci do lat 3? Jeszcze do niedawna taki rozważania pewnie uznalibyśmy za idiotyczne. Niestety moda na procesy o odszkodowanie zapoczątkowana w USA dotarła już do starej europy, więc moglibyśmy być bardzo zaskoczeni o jakie kwoty przyjdzie nam się sądzić... Wracając do CE. Ktoś wpadł na genialny w prostocie pomysł, jak zarabiać na darmowym teoretycznie prawie. Mamy dyrektywę, każdym może ją pobrać z sieci i za darmo czytać. Ale jak wiemy, ciężko jest z nią cokolwiek praktycznego zrobić. I tutaj pojawiają się tzw. normy zharmonizowane, na które potocznie mówimy po prostu normy. W prawie unii jest przyjęte, że jeśli wyrób spełnia wymagania norm zharmonizowanych, to spełnia też wymagania dyrektywy. Jest w tym tylko jeden kruczek - normy są już płatne, a np. wykonywanie badań na zgodność z normami jest płatne nawet bardziej. Mamy więc taką sytuację. Dyrektywy unijne są prawem i działają jak każde inne prawo - można je łamać i narażać się na konsekwencje. Ale aby go przestrzegać właściwie musimy spełniać wymogi norm zharmonizowanych, inaczej zawsze ryzykujemy, że ktoś oskarży nas o niedopełnienie obowiązków wynikających z dyrektywy i zażąda odpowiedniego odszkodowania. No i tutaj dochodzimy do sedna sprawy. Spełniając normy, posiadając odpowiednie wyniki badań - niezależnie czy wykonanych samemu, czy w zewnętrznej firmie, możemy nadać oznaczenie CE oraz podpisać się pod deklaracją zgodności, ale co najważniejsze spać spokojnie. Natomiast jeśli nie wykonamy tych kroków, to albo bezpośrednio łamiemy prawo, albo narażamy się na pozew o odszkodowanie, za to że nie spełniliśmy odpowiednich wymagań. To wszystko brzmi może nieco abstrakcyjnie, bo przecież "nikomu nic się nie stanie", ale jak wspominałem już o sądach i prawnikach - nawet pozornie prosty kalkulator może narazić nas na ogromne problemy. Jeśli nie wierzycie to poczytajcie np. o pozwach składanych przez rodziców za to że dziecko w supermarkecie otworzyło butelkę żrącego płynu i wypiło. Mamy teraz takie czasy, że nie jest to wina rodziców, ani dziecka, ale producenta że nie zrobił lepszego zamknięcia no i sklepu... W każdym razie oznaczenie CE to poważniejsza sprawa niż się wydaje.
  3. Nie sprawdzałem jak jest w najnowszych wersjach, ale dawniej takiej opcji nie było - i nie był to błąd, ale raczej założenie projektowe (it's not bug, it's a feature). Problemem w przypadku tak skomplikowanych układów jak STM32MP1 jest konieczność współdzielenia peryferiów między równolegle działające rdzenie i systemy. GPIO są dobrym przykładem - projektant musi zadecydować, które piny przydzielić dla Linux-a, a którymi ma sterować rdzeń M4. Ponieważ w wersji "produkcyjnej" najpierw startuje Linux i to on jest głównym systemem, za konfigurację GPIO odpowiada ten system. Dlatego CubeMX nie generuje kodu inicjalizującego GPIO dla M4 - po prostu ma to zrobić A7. CubeMX generuje za to plik konfiguracyjny, czyli device-tree, który należy dodać do jądra linuxa - dzięki czemu piny zostaną skonfigurowane poprawnie jeszcze zanim kod na M4 zacznie działać. Niestety takie podejście nie sprawdza się w przypadku trybu inżynierskiego i w nim trzeba konfigurację GPIO napisać samemu. Ale to chyba nie jest zbyt skomplikowane zadanie
  4. Skoro nie masz jeszcze kopii zapasowej systemu, najwyższy czas ją przygotować: https://forbot.pl/blog/kopia-zapasowa-raspberry-pi-jak-skopiowac-karte-microsd-id29561 Na szczęście w przypadku RaspberryPi bardzo łatwo jest zachować dane - wystarczy wyjąć kartę microSD, a wszystko od nowa zainstalować na innej. Na koniec można po prostu przekopiować pliki konfiguracyjne, dane, bazy, itd. Oczywiście najlepiej byłoby naprawić obecny system, ale i tak lepiej tego nie robić na aktualnej i jedynej kopii. Więc jeśli chcesz poeksperymentować, to najpierw zrób backup, następnie odwiń go na inną kartę i zacznij naprawiać system. Jak coś pójdzie źle to zawsze można próbować jeszcze raz.
  5. STM32MP157 nie posiada pamięci flash, to nie jest mikrokontroler jak typowe STM32. Program dla rdzenia Cortex-M musi być załadowany do pamięci RAM i z niej wykonywany. Podczas debugowania można załadować program używając JTAG-a, natomiast w "produkcyjnej" wersji kod jest wczytywany z karty SD lub innej pamięci przez skrypt systemu Linux, albo bootloader.
  6. Proponuję nie zakładać nic ponad to, że ktoś szuka darmowej informacji kto i za ile taki projekt chciałby wykonać. Jak dla mnie tekst: "Budżet 10000zł. Jeśli nierealny proszę składać także wyższe oferty." oznacza, że to nie jest poważna oferta. Przecież nikt podając budżet nie zakłada, że szuka kogoś za więcej... cytując jak sądzę autora tej oferty "Gdzie sens? Gdzie logika?".
  7. Nigdzie i nikogo nie hejtowalem, chyba pod hejt znacznie bardziej pasuje zarzucanie komuś braku umiejętności. Jedyne co napisałem to ostrzeżenie, bo moim zdaniem w przypadku takich "anonimowych" ogłoszeń trzeba być ostrożnym. Szkoda czasu np. na pisanie oferty skoro ktoś przykładowo chce udowodnić że projekt powinien kosztować daną kwotę, zrobić badanie rynku, albo po prostu zyskać trochę rozgłosu w sieci.
  8. @atMegaTona nie słyszałeś nigdy o ogłoszeniach dawanych zupełnie nie po to żeby wykonać projekt? O tym właśnie pisałem odnośnie ostrożności - bo wcale nie jestem pewien, czy to ogłoszenie faktycznie ma na celu znalezienie wykonawcy, czy np. sprawdzenie za ile takie projekty są wykonywane, albo po prostu zrobienie komuś reklamy. Oczywiście mogę się mylić, ale jakoś zakres wymagań idealnie pokrywa się z tym co w EP i EdW opisuje jeden z zablokowanych użytkowników tego i innych forów... Więc jak dla mnie to nie ma żadnego budżetu, żadnego projektu, jest ogłoszenie, na które wielu naiwnych może się nabrać.
  9. A ja bym proponował mocno zastanowić się nad wiarygodnością "zlecenia" w tym temacie. Po pierwsze, ktoś sobie zadał sporo trudu, żeby napisać prawie dwie strony "wymagań". Wygląda to profesjonalnie, wreszcie jakieś poważnie wyglądające ogłoszenie - ale autor się nie podpisał. Bo chyba Fast Rabbit to nie imię i nazwisko, ani nazwa firmy. Więc jeśli ktoś spędza sporo czasu pisząc "ofertę", ale się nie podpisuje to istotne ostrzeżenie. Bo jeśli nie chce podawać swoich danych, to czego się obawia? Druga sprawa to same "założenia" projektu. Nawet po szybkim przeglądzie widać, że nic się tutaj nie zgadza. O samym działaniu rządzenia praktycznie brak informacji - 230VAC, termostat i 3 przekaźniki 8A to właściwie cały opis części wykonawczej... Natomiast o niepotrzebnych wodotryskach jest całe mnóstwo. Po co komu aż 3 wyświetlacze: oled, tft oraz matryca LED? Dlaczego aż tyle i dlaczego akurat 128x160 pikseli? to już 480x272, albo 128x128 będzie złe? Standard MISRA, który ma mieć jakieś związki z zawieszaniem... itd. itp. Prawdę mówiąc po przeczytaniu założeń mam nieodparte wrażenie, że pisał je ktoś związany z EdW i EP, kto ma opisane moduły pod ręką i z jakiegoś powodu chce z nich ulepić projekt... Mogę się oczywiście mylić, ale radziłbym ewentualnym zleceniobiorcom daleko idącą ostrożność - a moderatorom uwagę.
  10. @Harnas dziękuję za uwagi. Odczyt z plików, jak i samo przygotowanie danych jest oczywiście zrobione absolutnie nieprofesjonalnie. To co opisałem powstawało jako "dłubanina" metodą prób i błędów, a moim celem było uruchomienie przykładu z X-CUBE-AI, planowałem później wszystko zrobić od początku, ładniej, lepiej, i poprawniej oraz z ciekawszym czujnikiem (chciałem użyć czujnik gestów https://botland.com.pl/pl/czujniki-gestow/3065-apds-9960-czujnik-rgb-i-wykrywacz-gestow-33v-i2c-sparkfun-sen-12787.html). Plan był dobry, ale zabrakło czasu, więc opisałem po prostu to co udało mi się zrobić, za niedoskonałości bardzo przepraszam.
  11. W poprzednich częściach udało się zebrać dane treningowe oraz przygotować sieć neuronową. Zostało ostatnie i najprzyjemniejsze, czyli napisanie końcowego programu. Jako punkt wyjścia używam program w wersji użytej do zbierania danych. Jest w nim już praktycznie wszystko co potrzebne, czyli konfiguracja modułów peryferyjnych oraz odczyt danych z akcelerometru. Spis treści serii artykułów: Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.1 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.2 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.3 Przechodzimy do widoku CubeMX i odnajdujemy wyjątkowo kiepsko widoczny przycisk "Additional Software": Po jego naciśnięciu zobaczymy okno pozwalające na dodawanie modułów do naszego projektu. Nas interesuje moduł "STMicroelectronics.X-CUBE-AI". Jeśli wcześniej tego nie zrobiliśmy, musimy najpierw ten moduł pobrać i zainstalować. Niezbędne opcje zobaczymy w prawej części okna: Po instalacji modułu X-CUBE-AI wystarczy zaznaczyć checkbox i użyć podstawową funkcjonalność, czyli Core. Gdybyśmy planowali wykorzystanie sieci neuronowej w poważniejszym programie, takie ustawienie byłoby chyba najlepszą opcją. Jednak na potrzeby nauki możemy wykorzystać gotowiec i dodać jeszcze opcję "Application Template". Jakość kodu, który zostanie dodany jako "template" jest delikatnie mówiąc niezbyt imponująca. Dlatego napisałem, że lepiej chyba nie używać go w poważniejszych zastosowaniach - ale do nauki to bardzo wygodne rozwiązanie. Teraz możemy wrócić do głównego widoku CubeMX i odszukać moduł "STMicroelectronics.X-CUBE-AI" w kategorii "Additional Software": W środkowej części okna widzimy konfigurację modułu naciskamy przycisk-zakładkę z symbolem "+" i dodajemy naszą sieć. Domyślna nazwa to "network", ale warto ją zmienić na coś bardziej opisowego, ja wybrałem "forbot_ai". Następnie wybieramy typ modelu "Keras" oraz sam model, czyli nasz plik data2.h5 utworzony w poprzedniej części. Gdy wszystko jest już gotowe możemy nacisnąć przycisk "Analyze" i poczekać aż X-CUBE-AI sprawdzi, czy nasza sieć pasuje do wybranego mikrokontrolera. Wynik powinien wyglądać następująco: Jak widzimy cała skomplikowana sieć wykorzystuje 8.39KB pamięci flash oraz 72 bajty RAM. To bardzo mało jak dla STM32L475, ale nawet znacznie słabiej wyposażone mikrokontrolery mogą skorzystać z możliwości jakie dają sieci neuronowe. Natomiast w przypadku większych sieci możemy wykorzystać opcję kompresji. Po zapisaniu projektu i wygenerowaniu kodu zobaczymy dwie ważne zmiany w pliku main.c. Przed pętlą główną pojawi się wywołanie MX_X_CUBE_AI_Init(), a w samej pętli znajdziemy MX_X_CUBE_AI_Process(). Inicjalizacja nie będzie nas interesować i możemy zostawić wygenerowany kod bez zmian. Warto natomiast zapoznać się z treścią funkcji MX_X_CUBE_AI_Process(). Kod, który w niej znajdziemy może przyprawić o palpitacje serca, ale na szczęście to tylko przykład, chociaż chyba niezbyt udany. Możemy więc spróbować zrozumieć o co w tym kodzie chodzi - i szybko odkryjemy, że jedyne co istotne to wywołanie funkcji aiRun(), która przyjmuje dwa parametry: pierwszy to tablica z danymi wejściowymi dla sieci, a w drugiej pojawią się wyniki. Warto jeszcze odszukać jakie są wymiary tych tablic: AI_FORBOT_AI_IN_1_SIZE ma wartość 128, i jest to wielkość zdefiniowana podczas trenowania sieci, właśnie tyle danych musimy podać na wejście. Wielkość danych wynikowych znajdziemy w stałej AI_FORBOT_AI_OUT_1_SIZE, która ma wartość 2. Przykładowy kod wykonuje mnóstwo dziwnych operacji na typach danych, ale w rzeczywistości dane wejściowe i wyjściowe to zwykłe float-y. Możemy więc skasować wszystko co automat nam wygenerował i napisać pierwszy kod: void MX_X_CUBE_AI_Process(void) { /* USER CODE BEGIN 1 */ float nn_input[AI_FORBOT_AI_IN_1_SIZE]; float nn_output[AI_FORBOT_AI_OUT_1_SIZE]; aiRun(nn_input, nn_output); /* USER CODE END 1 */ } Taki program oczywiście nic nie robi, ani nie działa poprawnie, ale umieściłem go aby pokazać jak łatwe jest używanie sieci neuronowej. Musimy wypełnić tablicę nn_input danymi do przetworzenia, następnie wywołujemy aiRun() i w nn_output mamy wyniki. Poniżej wstawiam już pełny kod: static uint32_t next_ms = 1000; static float nn_input[AI_FORBOT_AI_IN_1_SIZE]; float nn_output[AI_FORBOT_AI_OUT_1_SIZE]; while (HAL_GetTick() < next_ms) {} next_ms += READ_DELAY_MS; lsm6_value_t acc; acc = lsm6_read_acc(); for (int i = 0; i < AI_FORBOT_AI_IN_1_SIZE - 1; i++) nn_input[i] = nn_input[i + 1]; nn_input[AI_FORBOT_AI_IN_1_SIZE - 1] = sqrt(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z); aiRun(nn_input, nn_output); if (nn_output[0] >= 0.5f) HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); else HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET); Tablica nn_input jest definiowana jako statyczna, aby zachować historię pomiarów. Pomiary są wykonywane co 20ms, stąd czekanie w pętli while. Następnie odczytywana jest wartość przyspieszeń z akcelerometru. Wyniki przechowywane w tablicy nn_input są przesuwane o jedną pozycję, a najnowszy pomiar dodawany jest na końcu. Następnie wywoływana jest funkcja aiRun() i przetwarzane są wyniki. nn_ouput zawiera dwie wartości - pierwsza pozycja to prawdopodobieństwo, że nie wykryto gestu, druga to że wykryto - ich suma wynosi 1, więc wystarczyłaby jedna wartość, ale tak była trenowana sieć. Na podstawie obliczonego prawdopodobieństwa gaszona lub zapalana jest dioda LED. Poniżej efekt działania program (z drobną poprawką o której za moment): Uczenie sieci wymaga dużej ilości danych treningowych, w sumie im więcej tym lepiej. Niestety przykładowa sieć była trenowana na bardzo małej próbce. Efekty były i tak bardzo dobre, ale po wykryciu gestu pojawiały się pewne "zakłócenia". Po pierwsze czas zapalenia diody był bardzo różny, po drugie czasem dioda zapalała się kilka razy. Oczywiście najlepiej byłoby spędzić więcej czasu ucząc sieć, ale ja zastosowałem pewne obejście. W programie, po wykryciu machania płytką dioda jest zapalana na 1s - sieć mogłaby to robić sama, ale o wiele łatwiej było zmienić program. Podsumowanie Projekt opisany w tych artykułach miał być jedynie pierwszym krokiem, taką próbą użycia X-CUBE-AI. Planowałem poprawić opisywane przykłady, dodać bardziej rozbudowany projekt z innym czujnikiem oraz wykorzystać bardziej zaawansowaną topologię sieci. Ale jak to z planami często bywa, zostały niezrealizowane. Mam jedna nadzieję, że opisane możliwości zachęcą czytelników do eksperymentowania ze sztuczną inteligencją w systemach wbudowanych oraz dzielenia się swoimi doświadczeniami. Spis treści serii artykułów: Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.1 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.2 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.3
  12. W poprzedniej części udało mi się zebrać dane treningowe, czas te dane wykorzystać oraz przygotować własną sieć neuronową. X-CUBE-AI pozwala na wykorzystanie sieci zapisanych za pomocą różnych bibliotek, zdecydowałem się wykorzystać Keras, która jest nie tylko bardzo łatwa w użyciu, ale jeszcze całkiem dobrze opisana. Wydawnictwo Helion ma o ofercie świetną książkę pt. "Deep Learning. Praca z językiem Python i biblioteką Keras", którą bardzo polecam i z której korzystałem intensywnie przygotowując ten artykuł. Spis treści serii artykułów: Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.1 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.2 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.3 Podstawą biblioteki Keras, jak i chyba większości innych związanych z AI jest język Python, więc poznanie chociaż jego podstaw jest niestety niezbędne. Kolejny brakujący element to zainstalowanie interpretera języka Python3 oraz potrzebnych bibliotek. Znacznym ułatwieniem jest wykorzystani gotowej "dystrybucji" o nazwie Anaconda. Ze strony projektu wystarczy pobrać program instalacyjny i zainstalować. Za jednym zamachem uzyskamy dostęp do języka Python3 oraz mnóstwa narzędzi pomocnych przy przetwarzaniu danych. Domyślna instalacja nie zawiera potrzebnych nam bibliotek, warto więc uruchomić program Anaconda Navigator oraz doinstalować pakiety: keras, tensorflow oraz matplotlib. Skrypty używane do trenowania sieci możemy pisać w dowolnym edytorze tekstu, a następnie uruchamiać jak każdy inny program w języku Python3, ale jest to dość niewygodne. Znacznie wygodniejszym i polecanym w wielu książkach rozwiązaniem jest wykorzystanie edytora Jupyter, albo jego nowszego kuzyna JupyterLab. W pakiecie Anaconda znajdziemy obie aplikacje. Wystarczy uruchomić wspomniany Anaconda Navigator, a w nim JupyterLab: Sam JupyterLab działa wewnątrz przeglądarki internetowej, co jest o tyle wygodne, że pozwala łatwo pracować na zdalnym komputerze - nie zawsze mamy bezpośredni dostęp do odpowiednio wydajnej maszyny, a pracując w narzędziach Jupyter możemy wykorzystać moc zdalnej jednostki. Co więcej możemy tak samo pracować na płytce typu Jetson Nano, jak i na potężnej stacji roboczej w chmurze. Zanim przejdziemy dalej warto nieco bliżej zapoznać się z zebranymi danymi. Napiszmy w pythonie prosty skrypt, który wczyta oraz przedstawi graficznie pobrane dane: Już na pierwszy rzut oka widać, że dane nie są tak łatwe do analizy jak nieco wyidealizowany przykład z wykrywaniem uderzeń serca. Na szczęście użycie sieci neuronowej zwalnia nas z obowiązku pisania programu, który będzie musiał te dane ręcznie przetwarzać. Jak pamiętamy, dane z akcelerometru to 3 liczby, które reprezentują wartości przyspieszenia względem osi XYZ. W przypadku rozpoznawania gestów możemy nieco uprościć sobie zadanie i obliczyć wypadkowe przyspieszenie. Jedna liczba to nie tylko mniej danych, ale i o wiele łatwiejsza prezentacja diagramów. Oczywiście tworząc bardziej zaawansowane projekty możemy wykorzystywać wszystkie dane. W każdym razie na wykresie widzimy jak wyglądają nasze dane źródłowe oraz momenty gdy podczas uczenia naciskany był przycisk. Poniżej jeszcze kilka przykładów kiedy następowało wykrycie samego gestu: Jak pamiętamy pomiary wykonujemy co 20 ms, ale jeden wynik nie wystarczy do stwierdzenia, czy nastąpiło wykrycie poszukiwanego gestu. Musimy więc pamiętać "historię" pomiarów. Jak pisałem w poprzedniej części, wybrałem pomiary co 20ms oraz wielkość okna pomiarowego 128 wyników. Więc nasza sieć na wejściu będzie dostawała ostatnie 128 pomiarów i ma stwierdzić - czy nastąpiło wówczas poszukiwane machanie płytką, czy nie. Teraz możemy utworzyć nowy projekt projekt w JupyterLab i zacząć trenować naszą bazę. W JupyterLab nasz skrypt można podzielić na fragmenty, edytować i uruchamiać niezależnie. Dzięki temu jeśli np. dostroimy parametry sieci, nie musimy uruchamiać całego skryptu - wystarczy ponownie wykonać zmienioną część. To ogromne ułatwienie oraz oszczędność czasu. Na początku mamy więc import używanych bibliotek: import math import numpy as np from keras import models from keras import layers from keras.utils import to_categorical Następnie podobnie jak poprzednio wczytanie naszych danych treningowych oraz wykonania niezbędnych obliczeń: f = open('data1.csv','r') values = [] results = [] for line in f: fields = line.strip().split(',') if len(fields) == 4: x = float(fields[0]) y = float(fields[1]) z = float(fields[2]) values.append([math.sqrt(x**2 + y**2 + z**2)]) results.append(float(fields[3])) f.close() print('number of values: {}'.format(len(values))) Teraz musimy zmienić trochę postać danych. Plik wejściowy to 6467 wierszy z wynikami. Do uczenia sieci chcemy jednak wykorzystać okna po 128 wyników, które dają na wyjściu odpowiedź czy wykryto uczony wzorzec, czy nie. Co więcej dane powinniśmy podzielić na część treningową oraz testową - właściwie powinna być jeszcze trzecia część przeznaczona do walidacji, jednak jako prosty pierwszy przykład mam tylko dwie części: trening i test. train_values = [] train_labels = [] test_values = [] test_labels = [] split = len(values) * 0.8 for i in range(len(values) - 128): if i < split: train_values.append(values[i:i+128]) train_labels.append(results[i+128]) else: test_values.append(values[i:i+128]) test_labels.append(results[i+128]) train_values = np.array(train_values).reshape(-1, 128).astype('float32') train_labels = np.array(train_labels).astype('float32') test_values = np.array(test_values).reshape(-1, 128).astype('float32') test_labels = np.array(test_labels).astype('float32') Przyznać się muszę do jeszcze jednego niedociągnięcia - dane powinny być również znormalizowane. Najpierw planowałem wykorzystać wszystkie składowe XYZ, a wówczas normalizacja nie była konieczna. Jednak przeliczenie przyspieszenia na wartość wypadkową wprowadziło stałą odpowiadającą przyspieszeniu ziemskiemu - a w skryptach już tego niestety nie uwzględniłem. Teraz najważniejsza część czy uczenie samej sieci. Struktura jest banalnie prosta i pochodzi bezpośrednio z przykładów opisywanych w książce "Deep Learning. Praca z językiem Python i biblioteką Keras" train_labels = to_categorical(train_labels) test_labels = to_categorical(test_labels) network = models.Sequential() network.add(layers.Dense(16, activation='relu', input_shape=(128,))) network.add(layers.Dense(2, activation='softmax')) network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) network.fit(train_values, train_labels, epochs=5, batch_size=8) network.summary() Po uruchomieniu kodu zobaczymy podsumowanie naszej sieci: Jak widzimy dokładność uczenia to 0.9086, moglibyśmy uzyskać dużo lepsze rezultaty tworząc bardziej wyszukaną sieć, ale przykład jest ogromnym uproszczeniem. Warto zwrócić uwagę na liczbę parametrów: 2064 dla pierwszej i 34 dla drugiej warstwy. Musimy pamiętać, że te parametry trzeba będzie zapisać w pamięci mikrokontrolera - jednak niewiele ponad 2000 parametrów to bardzo mało i pewnie dałoby się uruchomić nawet na STM32F0. Zanim zakończymy tworzenie sieci, jeszcze dwie ważne sprawy. Pierwsza to testowanie. Wynik, który widzieliśmy wcześniej dotyczy danych, na których sieć była uczona - jednak ważniejsze jest jak zachowa się z danymi, których "nie widziała". Podczas przygotowywania danych 20% zostało zapisane w zmiennych test_values, test_results i teraz mogą posłużyć do sprawdzenia jak sieć radzi sobie z nowymi informacjami: Uzyskujemy dokładność na poziomie 89.35%, czyli podobnie jak dla danych użytych do trenowania sieci. Ostatnia rzecz to zapisanie samej sieci do pliku, czyli wywołanie: network.save('data2.h5') Teraz mamy plik data2.h5, który jest gotowy do użycia z X-CUBE-AI, co opiszę w kolejnej części. data2.zip Spis treści serii artykułów: Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.1 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.2 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.3
  13. Algorytmy związane z szeroko pojętą sztuczną inteligencją (AI, Artificial Intelligence) są ostatnio bardzo popularnym tematem. Na ogół AI kojarzy się z ogromnym zapotrzebowaniem na moc obliczeniową, wykorzystaniem GPU (Graphics Processing Unit) oraz obliczeniami w chmurze. Okazuje się jednak, że sztuczna inteligencja znajduje również zastosowanie w świecie mikrokontrolerów. Powstał nawet termin na określenie takich zastosowań - Edge AI. O tym jak popularny jest temat AI świadczy chociażby pojawienie się sprzętowych akceleratorów przeznaczone dla urządzeń wbudowanych, tzw. TPU (Tensor Processing Unit), przykładowo Google Coral, albo Intel Neural Compute Stick. Dostępne są również mikrokontrolery z wbudowanym TPU, np. Kendryte K210 . Spis treści serii artykułów: Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.1 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.2 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.3 Firma STMicroelectronics, czyli producent popularnych również na naszym forum układów STM32 postanowiła dostarczyć produkt związany z AI. Na razie nie oferuje sprzętowej akceleracji, ale możemy za darmo pobrać pakiet oprogramowania o nazwie X-CUBE-AI, który pozwala na łatwe wykorzystanie możliwości jakie daje sztuczna inteligencja. W niniejszym artykule postaram się opisać bardzo prosty przykład wykorzystania biblioteki X-CUBE-AI na płytce ewaluacyjnej z układem STM32L475. Planowałem napisać dłuższy artykuł na zakończony niedawno konkurs, ale w trakcie przygotowywania projektu odkryłem jak dużo muszę się jeszcze sam nauczyć, zanim będę w stanie dzielić się wiedzą. Jednak to co udało mi się poznać i zrobić postaram się opisać w tym temacie. Proszę jednak o wyrozumiałość, tematem sztucznej inteligencji zajmuję się wyłącznie hobbistycznie i cały czas się uczę, więc z góry przepraszam za niedoskonałości opisywanego rozwiązania. Wybór platformy sprzętowej Sztuczna inteligencja nie bez powodu kojarzy się z ogromnym zapotrzebowaniem na pamięć i moc obliczeniową, rozpoznawanie mowy lub obrazu jest chyba dobrym przykładem, gdzie moc chmury wydaje się niezbędna. Okazuje się jednak, że AI można również zastosować w znacznie mniej wymagających obszarach. Jakiś czas temu na forum pojawił się opis projektu czujnika HRV: Wykrywanie bicia serca na podstawie sygnału jest jednym z przykładów, gdzie algorytmy sztucznej inteligencji mogą znaleźć zastosowanie. Ja co prawda nie jestem entuzjastą projektowania urządzeń medycznych metodami mocno hobbistycznymi, ale wspomniany artykuł zachęcił mnie do wypróbowania X-CUBE-AI do wykrywania wzroca w pewnym sygnale. Jako platformę testową wybrałem płytkę B-L475E-IOT01A, wyposażoną w mikrokontroler STM32L475 oraz całkiem sporo interesujących modułów peryferyjnych, a co najważniejsze w akcelerometr LSM6DSL. Płytka posiada ogromny potencjał, ja wykorzystam tylko mały jej fragment: port UART do komunikacji z PC, przede wszystkim do wysyłania danych akcelerometr posłuży jako źródło sygnału przycisk wykorzystam do uczenia sieci dioda LED będzie sygnalizowała wykrycie gestu Zbieranie danych treningowych Danymi źródłowymi będą pomiary z akcelerometru. Podczas uczenia, po wykonaniu gestu, który chcę nauczyć sieć będę naciskał przycisk na płytce. Dane treningowe mają więc postać 4 liczb: odczytu z akcelerometru dla osi XYZ oraz stanu przycisku. Ponieważ obraz jest wart tysiąca słów poniżej filmik z uczenia sieci: Moim celem było nauczenie sieci wykrywania dwukrotnego machnięcia płytką. W sumie nie wyszło mi to trenowanie do końca, bo wcale nie łatwo jest taki gest wielokrotnie wykonywać i się nie pomylić. Więc ostatecznie sieć ma wykrywać dwu- lub więcej- krotne pobujanie płytką. Jednokrotne, albo dwukrotne wykonane z odstępem gesty mają być ignorowane. Oczywiście można sieć nauczyć właściwie dowolnego gestu, pod warunkiem oczywiście, że sami jesteśmy w stanie ten gest wielokrotnie wykonać (i nie stracimy cierpliwości). Dane z akcelerometru odczytuję co 20ms. Z moich obliczeń wyszło, że 128 wyników, czyli 2.56s w zupełności wystarcza na wykonanie interesującego mnie gestu. Wyniki pomiarów wysyłane są przez port szeregowy Uczenie polegało na włączeniu zapisu danych do pliku oraz cierpliwym machaniu płytką oraz naciskaniu przycisku po wykonaniu uczonego gestu. W wyniku powstał plik data1.csv data1.zip Program do zbierania danych został napisany w środowisku STM32CubeIDE, dzięki temu jego kod będzie można później wykorzystać od testowania wytrenowanej sieci. Sam program jest właściwie banalny, do jego napisania wystarczy w zupełności materiał kursu STM32F4. Skoro mamy już dane treningowe, czas przystąpić do najważniejszego, czyli uczenia sieci. W następnej części postaram się opisać jak możemy wykorzystać zebrane dane. Spis treści serii artykułów: Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.1 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.2 Sztuczna inteligencja na STM32, czyli przykład użycia X-CUBE-AI cz.3
  14. Bez podstaw pythona raczej nie da się używać keras, ani nic sensownego w AI zrobić. Nie musisz być od razu pythonowym guru, ale postawy są niezbędne. Inaczej zostanie tylko uruchamianie gotowców i zabawa przygotowanymi przez kogoś sieciami.
  15. Wydaje mi się, że jeśli ktoś chce poznać lepiej uczenie maszynowe, to do tego przyda się dobra książka i bardzo mocny komputer, najlepiej z solidną kartą graficzną. Natomiast użycie AI w systemach embedded to trochę inny temat. I tak trzeba sieć wytrenować na PC, później zostaje już tylko konwersja na mikrokontroler i w tym faktycznie może pomóc AI-CUBE. Miałem o tym napisać artykuł, ale trochę zabrakło czasu.
  16. Pytanie tylko czy @SOYER jest bardziej zainteresowany nauką budowy frezarek, czy raczej ich wykorzystania. Bo zbudowanie frezarki, czy drukarki to dopiero początek. Ale oczywiście jak ktoś ma mnóstwo wolnego czasu i dużo pieniędzy, to niech buduje od podstaw, w końcu kto bogatemu zabroni
  17. To ja podam argument żeby NIE budować czegoś takiego samemu. Pierwszą drukarkę 3d składałem sam - działała bardzo marnie, narobiłem się przy niej mnóstwo, ale właściwie zanim zdobyłem doświadczenie należałoby zacząć od początku. Drugą kupiłem gotową, składaną przez kogoś - było dużo lepiej, ale nadal daleko do ideału, a im dłużej jej używałem tym gorzej działała. Trzecią kupiłem gotową, tanią chińską - kosztowała praktycznie tyle co pierwsza, a jakbym doliczył części dokupione później do mojego składaka, to zdecydowanie mniej. Natomiast jakość wydruków gotowej drukarki była o wiele lepsza od obu pierwszych razem wziętych. Nie wiem jak to się ma do CNC, czy laserów, ale seryjnie produkowane urządzenie po prostu działa lepiej niż składane samemu - albo raczej działa lepiej niż kilka pierwszych składaków, przy których składający dopiero się uczy... Natomiast jeśli policzyłbym czas spędzony na takim składaniu, to taniej wyjdzie nie tylko gotowa chińska, ale i porządna, firmowa drukarka. Z laserami dochodzi jeszcze kwestia bezpieczeństwa - jak to ładnie kiedyś na laborkach było: na laser można popatrzeć dwa razy w życiu, raz lewym okiem, a raz prawym.
  18. Dyskusja nad wyższością jednego środowiska / procesora / biblioteki nad innym nie ma sensu. Żadne z tych rozwiązań nie jest absolutnie lepsze, ani absolutnie gorsze - gdyby tak było już dawno zostałoby tylko to lepsze. Natomiast nie mieszajmy edytora / środowiska z biblioteką. Arduino IDE jest... proste i chyba to wszystko co można napisać. Ale to dla wielu osób, szczególnie początkujących może być zaletą. Powiem więcej - nawet dla dawno temu początkujących może to być zaleta. Jak potrzebuję szybko przetestować np. nowy moduł, do którego mam bibliotekę pod Arduino to używam Arduino IDE. Bo tak jest po prostu najszybciej. Później mogę używać innych środowisk, bibliotek, czy mikrokontrolerów, ale żeby szybko przetestować np. nowy mały wyśwetilacz, albo czujnik użycie Arduino jest po prostu oszczędnością czasu. Na koniec jeszcze odnośnie wydajności bibliotek - wcale nie zawsze biblioteki HAL są szybsze od Arduino. Przyznam, że pisząc artykuł o wyświetlaczach przeżyłem ogromne rozczarowanie biblioteką HAL. Jeśli będziemy wysyłać dane w małych paczkach, np. po bajcie, biblioteki Arduino są wydajniejsze niż HAL... Okazuje się, że implementacja od ST jest tak przekombinowana, że zajmuje to mnóstwo czasu. Natomiast Arduino zapisuje od razu do rejestrów. Ot taka ciekawostka.
  19. Używanie bibliotek Arduino na STM32, jak i dowolnym innym mikrokontrolerze ma jak najbardziej sens. Wbrew nazwie użytej przez ST, ich HAL nie zapewniaja właściwie żadnej abstrakcji sprzętu, a teoretycznie powinien bo w końcu HAL to skrót od Hardware Abstraction Layer. Przykra prawda jest niestety taka, że używając STM32 HAL trzeba nadal dobrze znać sprzęt, nie możemy zmienić mikrokontrolera na inny bez modyfikacji wyższych warstw programu, a nawet biblioteki HAL dla różnych rodzin STM32 nie są ze sobą w pełni zgodne. Natomiast Arduino - niezależnie od oceny jakości kodu, zapewnia prawdziwą abstrakcję sprzętu, czyli prawdziwy HAL. Dzięki tym bibliotekom można ten sam program np. blink uruchomić zarówno na stm32, atmedze, czy esp8266. Jak napisałem wcześniej, nie jest to szczyt osiągnięć sztuki programistycznej, ale zawsze jakiś standard. Więc jak chodzi o sens to po pierwsze jest łatwiej, po drugie mamy niezależność od sprzętu. Warto też pamiętać, że kod biblioteki STM32 HAL jest również bardzo daleki od optymalnego, natomiast to co generuje CubeMX nie dość że jest paskudne, to jeszcze nie zawsze działa.
  20. O stm32mp1 są na Forbocie co najmniej dwa artykuły: https://forbot.pl/blog/nowe-stm32-ze-wsparciem-dla-linuksa-cos-dla-fanow-rpi-id33971 https://forbot.pl/blog/stm32mp1-co-warto-wiedziec-jak-zaczac-id37003 Ogólnie ten mikroprocesor jest bardziej interesujący, ale raczej ma niewiele wspólnego z instalacją Linux-a na mikrokontrolerach, co było opisane w tym temacie. Co do komunikacji między rdzeniami, to używana jest biblioteka OpenAMP (https://github.com/OpenAMP/open-amp/wiki/OpenAMP-Overview), ale najprościej jest użyć wirtualnego uart-a. W przykładach od ST znajdziemy gotowe rozwiązanie, które działa tak jakby oba rdzenie były połączone łączem szeregowym (po stronie linuxa używamy zwykłego urządzenia /dev/tty*, po stronie mikrokontrolera mamy gotowe funkcje do wysyłania i odbierania danych). Natomiast przypisanie GPIO i większości modułów peryferyjnych można samemu zmodyfikować, więc jeśli chcemy to rdzeń cortex-m może kontrolować więcej GPIO niż cortex-a. Wszystko zależy od zastosowania. Niektóre moduły oraz ich piny (np. pamięć DDR) są dostępne tylko dla cortex-a, ale na pewno nie jest to większość.
  21. Mikrokontrolery nie mają MMU. Dostępny jest mikroprocesor stm32mp1 z mmu, ale artykuł dotyczył mikrokontrolerów.
  22. @marek1707 nie jestem adminem, ani moderatorem, nie mam więc możliwości zamknięcia tego tematu. Inna sprawa, że przeniesienie go do działu „na luzie” byłoby wskazane, ale już samo zamykanie - właściwie dlaczego? Nikt nic złego nikomu w tym temacie nie zrobił, mamy dość ciekawe hasło, chociaż jego rozwinięcie raczej nie ma żadnego sensu. Moim zdaniem najlepsze co wszyscy razem możemy zrobić, to przestać się w tym temacie odzywać i już nie karmić trola.
  23. Żeby się cieszyć, najpierw trzeba uwierzyć że opisywane rozwiązanie istnieje i jest cokolwiek warte. Na razie słyszymy tylko przechwałki i nic konkretnego. Więc jak dla mnie więcej treści miał offtop o teatrze. I jak na razie bajki dla dzieci są dla mnie bardziej wiarygodne niż ten tajemniczy wynalazek - ale bardzo chętnie zmienię zdanie, tylko daj nam szansę i napisz cokolwiek, bo pisać że wiem ale nie powiem to każdy umie... I chyba lepiej brzmi: za siedmioma górami, za siedmioma lasami..
×
×
  • Utwórz nowe...