STEVAL-MKI063V1. Przykład oprogramowania akcelerometru i magnetometru LSM303DLH

STEVAL-MKI063V1. Przykład oprogramowania akcelerometru i magnetometru LSM303DLH
Pobierz PDF Download icon
Technologia MEMS na dobre zagościła już w takich zastosowaniach jak akcelerometry, magnetometry, żyroskopy, czujniki ciśnienia czy mikrofony, a w ofercie ST Microelectronics można znaleźć szeroką gamę tego typu układów. Oprócz samych układów, STM udostępnia także moduły demonstrujące możliwości poszczególnych grup produktów. Jednym z takich modułów jest STEVAL-MKI1063V1 oparty na układzie LSM303DLH zawierającym akcelerometr i magnetometr. W artykule opisano moduł oraz przedstawiono sposób komunikacji z nim z poziomu komputera PC na przykładzie aplikacji napisanej w języku C++/CLI (.NET).

Moduł demonstracyjny

Rysunek 1. Moduł STEVAL-MKI1063V1 z zaznaczonymi układami współrzędnych

Pokazany na rysunku 1 moduł STEVAL-MKI1063V1 jest oparty na układzie LSM303DLH. Jest to układ typu system-in-package zawierający 3-osiowy akcelerometr i 3-osiowy magnetometr. Oprócz wspomnianego układu, moduł zawiera także mikrokontroler ST7, którego zadaniem jest zapewnienie komunikacji przez złącze USB pomiędzy komputerem PC a układem. Na płytce modułu umieszczono także 3 przyciski, SW1 służy do zerowania układu natomiast SW2 i SW3 nie mają przypisanych funkcji i można je wykorzystać dowolnie.

Poznawanie możliwości modułu najlepiej jest zacząć od pobrania spod adresu http://www.st.com/internet/com/SOFTWARE_ RESOURCES/SW_COMPONENT/SW_FUNCTION/ mems_demonstration_kit_sw_%20package.zip archiwum z pakietem o nazwie MEMS demonstration kit SW package. Zawiera on program Unico, który służy do wizualizacji danych z różnych modułów demonstracyjnych MEMS od STM. Oprócz Unico, pakiet ten zawiera między innymi sterownik wirtualnego portu szeregowego dla mikrokontrolerów ST7 i STM32 oraz pliki źródłowe programów i wykorzystywanych przez nie bibliotek obsługi układów umieszczonych na poszczególnych modułach demonstracyjnych. Należy pamiętać, że podczas instalacji programu Unico sterowniki portu szeregowego nie są automatycznie instalowane i należy tę czynność wykonać samodzielnie. Odpowiedni plik .inf znajduje się w podkatalogu UnicodriversST7_VCOM_Driver.

Tabela 1. Zakresy i czułości magnetometru

Po podłączeniu modułu i wykryciu go przez system Windows można uruchomić program Unico. Na ekranie startowym należy wybrać rodzaj modułu, który podłączyliśmy. Następnie, po uruchomieniu się zasadniczej części Unico, trzeba wybrać odpowiedni port COM, a następnie kliknąć ikonę nawiązania połączenia. Po połączeniu można, po wybraniu ikony Start, rozpocząć obserwację napływających danych. Kolejne ikony pozwalają przywołać ekrany, na których można zmienić konfigurację układu, obejrzeć i modyfikować zawartość rejestrów, a także obserwować i wizualizować odbierane dane na kilka sposobów. Jeden ze sposobów wizualizacji pokazano na rysunku 2.

Układ LSM303DLH

Rysunek 2. Jeden ze sposobów wizualizacji danych odbieranych przez program Unico

Jak już wspomniano, głównym elementem modułu demonstracyjnego jest układ LSM303DLH, zawierający w sobie 3-osiowy akcelerometr (o dostępnych zakresach ±2, ±4 lub ±8 g) i 3-osiowy magnetometr (o zakresach ±1,3, ±1,9, ±2,5, ±4,0, ±4,7, ±5,6 i ±8,1 Gaussa). Ponadto układ ma m.in. możliwość wykrywania swobodnego spadku oraz zgłaszania przerwań, których źródła można konfigurować. Komunikacja pomiędzy mikrokontrolerem a układem odbywa się z wykorzystaniem interfejsu I²C. Układ wykonuje pomiary z rozdzielczością 12 bitów, a wyniki udostępnianie są w postaci słów 16-bitowych, z tym, że dane z akcelerometru wyrównane są do lewej, a z magnetometru do prawej strony słowa. Ponadto, czułość magnetometru w osi Z jest o około 10% niższa niż w osiach X i Y, co należy uwzględniać przy przetwarzaniu danych z pomiarów. Odpowiednie wartości wzmocnień podane są w tabeli 1.

Warto w tym miejscu zauważyć, że układ LSM- 303DLH został już wycofany z oferty ST Microelectronics, a jego miejsce zajęły układy LSM303DLM i LSM- 303DLHC. Ten pierwszy różni się od wersji DLH przede wszystkim niższym poborem mocy oraz nieco innymi czułościami magnetometru, jest jednak zgodny pod względem zakresów pomiarów oraz znaczenia rejestrów (z wyjątkiem zamiany adresów rejestrów wynikowych dla osi Y i Z magnetometru). Natomiast w układzie DLHC m.in. akcelerometr ma dodatkowo zakres ±16g, inaczej zorientowane są osie czujników, dostępnych jest więcej opcji konfiguracji, a co za tym idzie, niektóre rejestry mają inną zawartość i znaczenie niż w pozostałych dwóch układach.

Komunikacja z modułem

Tabela 2. Najważniejsze komendy sterujące modułem

Jak wspomniano, moduł można podłączyć do komputera poprzez interfejs USB i obserwować wyniki jego działania w programie Unico. Jest to jednak mało przydatne z punktu widzenia możliwości wykorzystania modułu do własnych aplikacji. Na szczęście z modułem można skomunikować się samodzielnie poprzez wirtualny port COM, a polecenia wydawane są w postaci dość prostego zestawu komend (tabela 2). Wysyłane są one w postaci tekstowej i muszą być zakończone znakiem 0x10 (r) co sprawia, że można sterować modułem nawet z poziomu zwykłego terminala. Na przykład komenda *mw000Cr oznacza zapis wartości 0x0C do rejestru magnetometru o adresie 0x00. Parametry połączenia to: szybkość 115200 bps, 8 bitów danych, baz kontroli parzystości, 1 bit stopu, bez kontroli przepływu.

Po nawiązaniu połączenia szeregowego, układ LSM- 303DLH można aktywować komendą *zoff. Dopiero później można wykonać inne komendy. Wyjątkiem są jedynie komendy *dev i *ver, na które moduł reaguje również wtedy, gdy układ LSM303DLH jest nieaktywny.

Rysunek 3. Ekran programu demonstracyjnego

Po wysłaniu komendy *start moduł zaczyna automatycznie wysyłać dane z układu LSM303DLH. Są one zwracane w postaci pakietów zawierających 19 znaków i zakończonych sekwencją rn. Kolejne bajty zawierają:

  • Literę "s".
  • Literę "t".
  • Starszy bajt wyniku pomiaru przyśpieszenia w osi X.
  • Młodszy bajt wyniku pomiaru przyśpieszenia w osi X.
  • Starszy bajt wyniku pomiaru przyśpieszenia w osi Y.
  • Młodszy bajt wyniku pomiaru przyśpieszenia w osi Y.
  • Starszy bajt wyniku pomiaru przyśpieszenia w osi Z.
  • Młodszy bajt wyniku pomiaru przyśpieszenia w osi Z.
  • Starszy bajt wyniku pomiaru natężenia pola magnetycznego w osi X.
  • Młodszy bajt wyniku pomiaru natężenia pola magnetycznego w osi X.
  • Starszy bajt wyniku pomiaru natężenia pola magnetycznego w osi Y.
  • Młodszy bajt wyniku pomiaru natężenia pola magnetycznego w osi Y.
  • Starszy bajt wyniku pomiaru natężenia pola magnetycznego w osi Z.
  • Młodszy bajt wyniku pomiaru natężenia pola magnetycznego w osi Z.
  • Zgłoszenie przerwania 1 (0x00 – brak przerwania, 0x40 – zgłoszenie aktywne).
  • Zgłoszenie przerwania 2 (0 x00 – brak przerwania, 0x40 – zgłoszenie aktywne).
  • Stan przycisków SW (0x00 – oba zwolnione, 0x01 – wciśnięty SW2, 0x02 – wciśnięty SW3, 0x03 – wciśnięte SW2 i SW3).

Bajty 0 i 1 zawsze zawierają sekwencję "st" co pozwala sprawdzić, czy pakiet został odebrany prawidłowo.

Tabela 3. Najważniejsze rejestry układu LSM303DLH

Patrząc na listę częstotliwości próbkowania dostępnych dla akcelerometru (0,5, 1, 2, 5 i 10 Hz w trybie low- -power oraz 50, 100, 400 i 1000 Hz w trybie normalnym) i magnetometru (0,75, 1,5, 3, 7,5, 15, 30 i 75 Hz) można zauważyć, że nie są one ze sobą zgodne. Powstaje więc pytanie, z jaką częstotliwością moduł będzie wysyłać dane do komputera PC. W przypadku modułu, do którego dostęp miał autor, była to częstotliwość wybrana w ustawieniach akcelerometru. Analiza kodu źródłowego firmware dostarczanego wraz z Unico wykazała jednak, że w niektórych jego wersjach wybierana jest wyższa z częstotliwości wybranych dla obu układów, co wydaje się być bardziej uzasadnionym rozwiązaniem. Niezależnie od wyboru, wysyłane pakiety zawierają zawsze komplet wartości, z tym, że dane z czujnika "wolniejszego" są kilkukrotnie powtarzane w kolejnych pakietach. Domyślna konfiguracja układu jest następująca: częstotliwość próbkowania akcelerometru 50 Hz, zakres akcelerometru ±2 g, częstotliwość próbkowania magnetometru 15 Hz, zakres magnetometru ±1,5 Gaussa. Wybór częstotliwości próbkowania wiąże się z automatycznym wyborem nastaw wewnętrznego filtru dolnoprzepustowego (antyaliasingowego). Oprócz tego, dla akcelerometru można także włączyć filtrowanie danych filtrem górnoprzepustowym, co m.in. pozwala usunąć z sygnału składową stałą. Jeżeli chcemy zmienić konfigurację układu, należy zatrzymać wysyłanie danych komendą *stop, a następnie poprzez komendy *waadd i *mwaadd ustawić odpowiednie wartości w rejestrach układu. W tabeli 3 zawarto zestawienie najważniejszych z nich.

Program demonstracyjny

Aby zaprezentować sposób komunikacji z modułem STEVAL-MKI1063V1, napisano aplikację w języku C++/ CLI w środowisku Microsoft Visual C++ 2008 Express. Jej ekran pokazany jest na rysunku 3. Pozwala ona na skonfigurowanie parametrów pomiaru, a następnie obserwowanie danych nadchodzących z modułu. Dodatkowo, w programie zaimplementowano cyfrowy kompas z funkcją automatycznej kalibracji.

Listingi 1, 2 i 3

Na listingu 1 pokazano deklarację kilku zmiennych należących do klasy Form1 opisującej formularz okna programu. Zmienne te wykorzystywane są w dalszej części programu. Pierwsze trzy z nich to tablice daneS, daneP i danePKor, które zawierają, kolejno: dane "surowe", czyli odebrane z modułu STEVAL i odkodowane; dane przeliczone na jednostki fizyczne; dane przeliczone na jednostki fizyczne i skorygowane. Zmienna azymut zawiera kąt azymutu wyznaczony w celu narysowania wskaźnika kompasu. Na końcu listingu znajduje się uchwyt do zmiennej obiektowej serialPort, która jest odpowiedzialna za komunikację przez port szeregowy. Klasa SerialPort jest klasą standardową zawartą w bibliotekach środowiska .NET od wersji 2.0. Inicjalizacja większości z tych zmiennych odbywa się w konstruktorze klasy Form1 (listing 2). Z kolei na listingu 3 przedstawiono deklarację klasy LSMKonfigClass, której zadaniem jest przechowywanie aktualnego zestawu nastaw konfiguracyjnych układu LSM303DLH.

Dwa główne elementy kodu programu to klasa watekOdczytuClass oraz metoda z klasy Form1 o nazwie buttonStart_ Click(). Metoda ta jest wywoływana po naciśnięciu przez użytkownika przycisku Start. Realizowane w niej polecenia mają za zadanie przygotować transmisję z i do modułu STEVAL-MKI063V1, wykonać konfigurację układu LSM303DLH, a następnie rozpocząć zasadniczą część transmisji, czyli uruchomić wątek programu odpowiedzialny za odbiór danych pomiarowych.

Kod metody jest pokazany na listingu 4. Na jej początku znajdują się deklaracje tablic zawierających komendy które trzeba wysłać do modułu STEVAL w zależności od wybranej przez użytkownika konfiguracji układu LSM- 303DLH. Pierwszą istotną operacją jest sprawdzenie czy port szeregowy nie jest już otwarty. Jeśli jest – zostaje zamknięty. Ma to na celu zakończenie poprzedniego połączenia, jeśli z jakiejś przyczyny nie został on zamknięty w prawidłowy sposób, np. nastąpiło wyłączenie modułu w czasie pomiaru. W kolejnym kroku następuje właściwe otwarcie portu z parametrami ustawionymi w konstruktorze klasy Form1 oraz przez użytkownika w oknie wyboru portu COM. Następnie, program wysyła do modułu STEVAL komendy *zoff oraz *stop. Pierwsza z nich aktywuje układ LSM303DLH, zaś druga zatrzymuje wysyłanie danych. Jest to konieczne, ponieważ układ, po połączeniu, nie musi być w stanie zatrzymania (np. wcześniej wykonane było połączenie przez terminal, które nie zostało zakończone komendą *stop). Komendy wysyłane są za pomocą metody PortWrite( ), której kod pokazano na listingu 5.

Listing 4

W kolejnych krokach, wysyłane są komendy zapisujące do rejestrów układu odpowiednie nastawy zakresów i częstotliwości próbkowania akcelerometru i magnetometru. Wybór komend zależy od ustawień dokonanych przez użytkownika z list rozwijalnych w oknie programu. Po zakończeniu konfiguracji pomiaru, jest tworzony nowy wątek o nazwie watekOdczytu. Jego zadaniem jest cykliczne odczytywanie bufora odbiorczego portu szeregowego, dekodowanie zawartych w nim pakietów danych oraz konwersja odczytanych danych. Wykorzystanie mechanizmu wielowątkowości jest konieczne, aby operacje odczytu nie zablokowały użytkownikowi możliwości interakcji z programem. Gdyby odczyt danych realizowany był w pętli wewnątrz metody buttonStart_Click( ), wówczas aż do zakończenia pętli interfejs użytkownika byłby nieaktywny. Nie można by więc nawet użyć przycisku Stop. Uruchomienie wątku pozwoli powrócić programowi do obsługi kolejki komunikatów systemu, a co za tym idzie, program będzie reagował na polecenia użytkownika, zaś odczyt danych i aktualizacja interfejsu nowymi wyświetlanymi wartościami pomiarów będą wykonywane w tle.

Po przygotowaniu wątku odczytu następuje wysłanie do modułu komendy *start. Od tego momentu moduł rozpoczyna wysyłanie pakietów danych. Następnie uruchamiany jest utworzony przed chwilą wątek. W przypadku wystąpienia błędów przy otwarciu portu lub podczas wysyłania komend system zgłasza wyjątki. Są one obsługiwane na końcu metody buttonStart_Click( ). Obsługa ta sprowadza się do wyświetlenia komunikatu o błędzie i zakończeniu transmisji. Występująca w tym fragmencie metoda StopTransimsji( ) wysyła komendę *stop i zamyka port. Wywoływana jest ona w programie w sytuacji gdy użytkownik kliknie przycisk Stop, zamknie program lub, co opisano powyżej, gdy wystąpi wyjątek związany z błędem dostępu do portu szeregowego.

Jak już wspomniano, zasadniczą część programu związaną z odczytem kolejnych pakietów wysyłanych przez moduł STEVAL do komputera PC realizuje osobny wątek. Kod klasy watekOdczytuClass opisującej ten wątek pokazany jest na listingu 6. Konstruktor klasy, jako parametry wywołania pobiera ustawienia konfiguracji pomiaru, które wykorzystywane są później do konwersji danych, oraz uchwyt do okna formularza programu, który wykorzystywany jest w celu aktualizacji wartości wyświetlanych na tymże formularzu.

Listing 5 i 6

Najważniejszą częścią klasy jest metoda PortRead( ). Rozpoczyna się ona od sprawdzenia, czy w buforze odbiorczym portu jest co najmniej 19 bajtów danych. Wartość ta wynika z długości pojedynczego pakietu danych. Jeśli w buforze jest wystarczająca liczba znaków, rozpoczyna się ich odczyt pakiet po pakiecie. Następnie wykonywane jest dekodowanie (wyniki zapisane w tablicy daneS) i przeliczenie odczytanych danych na fizyczne wartości przyśpieszenia i natężenia pola magnetycznego (wyniki zapisane w tablicy daneP). Kolejną wykonywaną operacją jest wprowadzenie korekt kalibrujących odczyty. W przypadku akcelerometru korekty te zostały wyznaczone off-line, tzn. zaobserwowano wskazania akcelerometru w poszczególnych osiach i na stałe zapisano odpowiednie wartości korygujące w kodzie programu. W przypadku magnetometru zastosowano procedurę automatycznej kalibracji.

Należy tu zwrócić uwagę, że "surowe" odczyty z magnetometru często są obarczone dużymi błędami. W przypadku idealnym wszystkie odczytane wartości powinny opisywać punkty znajdujące się na powierzchni kuli. Tymczasem wzmocnienia w poszczególnych osiach nie są takie same (nawet po uwzględnieniu wzmocnień podanych w danych katalogowych układu), co sprawia, że zamiast kuli punkty reprezentujące odczyty tworzą elipsoidę. Ponadto, środek tej elipsoidy nie wypada w środku układu współrzędnych – jest ona dość znacznie przesunięta. Błędy te można na szczęście skorygować w dość prosty sposób. Wystarczy rejestrować maksymalne i minimalne wartości natężeń pola w poszczególnych osiach, a następnie, na ich podstawie wyznaczyć odpowiednie przesunięcia oraz wzmocnienia dla każdej z osi. Korekta odczytów wykonywana jest według wzoru:
Wkor=(Wmierz–A–Wmin)(Amax/A)
gdzie
Wkor – wartość skorygowana
Wmierz – wartość zmierzona
A – amplituda sygnału A=(Wmax–Wmin)/2
Wmax – wartość maksymalna sygnału
Wmin – wartość minimalna sygnału
Amax – najwyższa amplituda dla wszystkich trzech osi magnetometru

Listing 7

W module, którym dysponował autor przesunięcia wynosiły nawet 40% odczytywanego zakresu (np. w jednej z osi wartości maksymalne były rzędu +0,05 Gaussa, minimalne –0,45 Gaussa, a prawidłowo powinno to być ±0,25 Gaussa). Z kolei różnice wzmocnień pomiędzy osiami nie przekraczały 5%. Zawarty na listingu 6 fragment dotyczący korekcji odczytów z magnetometru realizuje opisaną wyżej metodę. Przy takim rozwiązaniu, żeby skalibrować układ wystarczy po każdym uruchomieniu pomiarów kilkukrotnie obrócić go we wszystkich osiach. Uzyskuje się w ten sposób efekt automatycznej, samoczynnej kalibracji odczytów. Dodać należy również, że przy kalibracji brane są pod uwagę odczyty ze wszystkich trzech osi magnetometru mimo, że do dalszych obliczeń związanych z wyznaczaniem azymutu dla kompasu wykorzystywane są tylko osie X i Y. Jak wspomniano, opisana metoda jest dość prosta, jednak do wielu zastosowań daje zadowalające rezultaty. Jeśli konieczna byłaby dokładniejsza kalibracja należałoby zastosować bardziej złożone metody aproksymacji pa-rametrów elipsoidy. Również korekta odczytów z akcelerometru polegająca tylko na kompensacji składowej stałej jest metodą uproszczoną. Aby uzyskać dalszą poprawę wyników należałoby np. również korygować wzmocnienia w poszczególnych osiach.

Jak wiadomo, akcelerometr służy do pomiaru przyśpieszeń, co pozwala pośrednio wyznaczyć także prędkość i zmianę położenia obiektu. Ponadto, może on służyć m.in. do określenia orientacji obiektu względem powierzchni Ziemi. Z kolei magnetometr pozwala określić orientację obiektu względem ziemskich biegunów magnetycznych. Z tego powodu jednym z podstawowych zastosowań, do których przewidziany jest opisywany układ MEMS jest nawigacja i wyznaczanie orientacji przestrzennej urządzenia, w którym został wykorzystany. W tego typu aplikacjach ważne jest zdefiniowanie wykorzystywanych globalnych i lokalnych układów współrzędnych. W przypadku układów lokalnych, w nawigacji lądowej najczęściej stosuje się układ East-North- -Up (ENU), w którym oś X wskazuje kierunek wschodni, Y – północny, a Z – w górę. Natomiast w nawigacji morskiej i lotniczej – układ North-East-Down (NED) gdzie oś X wskazuje kierunek północny, Y – wschodni, a Z – w dół, czyli do wnętrza Ziemi (rysunek 4). W programie demonstracyjnym użytkownik ma możliwość wyboru, według którego układu mają być interpretowane dane. Przyjęto przy tym, że moduł leży płasko na poziomym stole i do określania kierunku wykorzystywane są tylko osie X i Y magnetometru. Gdy przyjmiemy układ ENU i moduł leży wierzchem (stroną z układem i mikrokontrolerem) do góry, wówczas krawędź zaznaczona na fotografii 1 niebieską strzałką pokazuje kierunek wskazywany na ekranie przez igłę kompasu. Gdy z kolei przyjmiemy układ NED i moduł leży stroną spodnią do góry, wówczas kierunek wskazywany przez igłę pokazuje krawędź zaznaczona na fotografii 1 strzałką czerwoną

Rysunek 4. Orientacja przestrzenna osi w układach NED i ENU

Ostatnim zadaniem wykonywanym w metodzie PortRead( ) jest wywołanie, poprzez delegata, metody aktualizującej interfejs użytkownika, tj. wyświetlającej odczytane wartości i rysującej wskaźnik kompasu oraz pola symbolizujące stan przycisków SW2 i SW3. Aktualizacja wykonywana jest przez metodę UpdateUI( ). W systemie Windows dostęp do kontrolek interfejsu ma tylko wątek, w którym zostały one utworzone, i dlatego wątek odczytu nie może tego robić bezpośrednio. Stąd potrzeba delegacji metody UpdateUI( ). Kod tej metody pokazany jest na listingu 7. Listingi 7 i 2 zawierają także pozostałe elementy związane z delegowaniem metody.

Na koniec warto zwrócić uwagę, że odczyty danych z bufora w metodzie PortRead( ) rozpoczynają się co około 0,1 s i realizowane są pakietami, czyli po 19 bajtów. Jeśli częstotliwość próbkowania akcelerometru ustawiona była na więcej niż 10 Hz, wówczas w buforze znajduje się od 1 do ponad 50 pakietów danych. Metoda odczytuje i konwertuje wszystkie pakiety, ale aktualizuje interfejs użytkownika tylko danymi z ostatniego pakietu odczytanego w danej grupie pakietów. Oznacza to, że mamy dostęp do wszystkich pobranych wyników pomiarów, natomiast prezentowane są tylko niektóre z nich, ponieważ użytkownik i tak nie byłby w stanie odczytać tych wartości przy bardzo częstej ich aktualizacji.

Przedstawiony w artykule program demonstracyjny dedykowany jest dla modułu STEVAL-MKI063V1, wiele innych modułów STEVAL z układami MEMS mają takie same zasady komunikacji i obsługują te same polecenia (choć niektóre z nich mają ich więcej). W związku z tym, program można stosunkowo łatwo zmodyfikować i uzupełnić dopasowując go do innych modułów tej rodziny. Ponadto, przedstawiony program ma zawarte tylko podstawowe zabezpieczenia związane z błędami obsługi portu i odczytu danych. Zaprogramowanie pełnych zabezpieczeń wiązałoby się jednak z rozbudową kodu i mogłoby zaciemnić kluczowe fragmenty związane z obsługą modułu.

Marek Galewski
marg@mech.pg.gda.pl

Artykuł ukazał się w
Styczeń 2013
DO POBRANIA
Pobierz PDF Download icon

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik marzec 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio marzec - kwiecień 2024

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka, Podzespoły, Aplikacje marzec 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna marzec 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich kwiecień 2024

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów