SantyagoSantyago
Avatar

Witaj!
Blog archiwalny. Już niebawem nowy serwis!

YouTube RSS Facebook GitHub

Arduino poradnik

Wstęp

Teoria

Biblioteki

Komponenty

Czujniki i sensory

Rozwiązania i algorytmy

Narzędzia

Mikrokontrolery i Arduino IDE

Arduino i klony

Poradniki wideo

Reklama na Blogu

Najnowsze poradniki

Ostatnie komentarze

Ostatnie fotografie

polskie-gorypolskie-gorypolskie-gorypolskie-gorypolskie-gorypolskie-gorypolskie-gorypolskie-gorypolskie-gorywieliczka-szyb-danilowicza

myAHRS+ z układem MPU9150

myAHRS+ jest jednym z najwydajniejszych systemów AHRS (Attitude Heading Reference System) z jakim dotychczas przyszło mi pracować. Jego ogromną i niezaprzeczalną zaletą jest wysoka stabilność wyników względem znacznych przyśpieszeń oraz występowania zaburzeń pola magnetycznego.

Komunikacja i konfiguracja modułu myAHRS+ może odbywać się za pomocą interfejsu USB/UART, co czyni go przyjaznym we współpracy z płytkami takimi jak Raspberry Pi czy ODROID. Projektanci i pasjonaci Arduino bez problemu uzyskają dostęp do danych poprzez magistralę I2C.

Dodatkową zaletą jest dostępność GUI myAHRS+ Monitior, który pozwala użytkownikowi na konfigurację wszystkich ustawień pracy modułu oraz podgląd stanu i danych z IMU w czasie rzeczywistym, a także zapis do pliku tekstowego.  Za pomocą myAHRS+ Monitior możemy również dokonać stosownej kalibracji magnetometru i czujników.

Najważniejsze parametry modułu myAHRS+ to:

  • Trójosiowy, 16-bitowy żyroskop o zakresie pomiaru ±2000 dps
  • Trójosiowy, 16-bitowy akcelerometr o zakresie pomiaru ±16 g 
  • Trójosiowy, 13-bitowy magnetometr o zakresie pomiaru ±1200 μT
  • Rozbudowany filtr Kalmana
  • Częstotliwość wyników na poziomie 100 Hz
  • Możliwość odczytu przeliczonych wyników: kąty Eulera lub Quaternion
  • Możliwość odczytu sensorów: przyśpieszenie, prędkość kątowa, pole magnetyczne
  • Komunikacja USB (wirtualny port COM), UART (do 460800 bps), I2C (do 1kHz)

Sercem jest 32-bitowy mikrokontroler STM32F103CBU6 taktowany zegarem 72MHz, wykonany w architekturze ARM Cortex-M3. Do pomiarów wartości wykorzystany została jednostka MPU9150.

Pinologia modułu przedstawia się następująco:

Pin Oznaczenie Typ pinu Opis
J3-1 INT O Przerwanie gotowości danych DATA READY
J3-2 SLEEP I Wybór trybu pracy (stan niski - tryb uśpienia. stan wysoki - normalna praca)
Normalnej pracy odpowiada również pozostawienie pinu nie podłączonego
J3-3 I2C_SCL I Zegar I2C
J3-4 I2C_SDA I/O Dane I2C
J3-5 USB_DM I/O USB D-
J3-6 USB_DP I/O USB D+
J3-7 NC   Nie używany
J3-8 NC   Nie używany
J3-9 NC   Nie używany
J3-10 NC   Nie używany
J4-1 VDD PWR Zasilanie +5V
J4-2 nRST I Stan niski - Reset, stan wysoki - normalna praca
J4-3 NC   Nie używany
J4-4 UART_TX O UART TX
J4-5 UART_RX I UART RX
J4-6 NC   Nie używany
J4-7 NC   Nie używany
J4-8 NC   Nie używany
J4-9 NC   Nie używany
J4-10 GND PWR Masa

myAHRS+ Monitor

myAHRS+ Monitor to specjalny program, za pomocą którego możemy monitorować pracę modułu oraz przeprowadzić jego konfigurację. Warto się nad nim pochylić, ponieważ pozwala na dokonanie bardzo ważnej kalibracji magnetometru w celu uwzględnienia deklinacji magnetycznej o której już pisałem w artykule na temat magnetometru HMC5883L.

Kiedy podłączymy moduł do gniazda USB musimy wybrać odpowiedni, wirtualny port komunikacyjny STMicroelectronics Virtual COM Port (ikona lornetki). W przypadku systemu Windows 7 nie są wymagane żadne dodatkowe sterowniki.

Po tym zabiegu będziemy mogli już odczytywać dane bezpośrednio z myAHRS+. Oprócz wykresów i przetworzonych już wartości, mamy również podgląd na wydawane polecenia UART oraz odbierane dane. Na poniższym przykładzie są to dane w formacie binarnym.

Jeśli nie odpowiada nam binarny format, prędkość transmisji, częstotliwość pomiarów lub format zwracanych danych, możemy odpowiednio skonfigurować moduł oraz skalibrować czujniki według własnych potrzeb:

Konfigurator pozwala na nadanie identyfikatora naszemu modułowi, aby był odróżniany w przypadku, gdybyśmy chcieli mieć ich większą ilość. Parametr Divider oznacza dzielnik bazowej częstotliwości 100Hz dla pomiarów - przykładowo dla wartości "2" otrzymamy 50Hz itd.

Ciekawą opcją jest również określenie trybu transmisji jako ciągłej (Continuous) lub na żądanie (Trigger). Mamy również możliwość zdefiniowania, jakie dane chcemy odbierać - czy tylko wartości mierzone czujników, czy już przeliczone kąty. Oczywiście możemy zdecydować się na różne kombinacje.

Należy jednak pamiętać, że zapisanie ustawień nie powoduje przechowanie wszystkich parametrów w pamięci, gdzie ponowne zasilenie modułu będzie wymagało ponownego ich ustawienia. Dlatego projektując urządzenie pamiętajmy, aby wydać stosowne polecenia w trakcie inicjalizacji modułu. Wyjątkiem od tej reguły są parametry kalibracyjne poszczególnych czujników, prędkości magistrali UART oraz ID modułu.

Kalibracja magentometru (deklinacja magnetyczna)

Szalenie ważnym krokiem jest poprawna kalibracja magnetometru uwzględniającego deklinację magnetyczną. Kiedy zobrazujemy sobie wyniki pomiaru pola magnetycznego obracając moduł we wszystkich kierunkach, zauważymy, że powstała sfera nie pokrywa się ze sferą odniesienia.

Do kalibracji magnetometru posłuży nam odpowiednia opcja oznaczona śrubokrętem, kluczem i igły magnetycznej. Wszystko co musimy zrobić, to wykonać jak największą ilość losowych obrotów modułu w możliwie największej ilości płaszczyzn - tak aby zostało pobrane 6000 próbek. Najlepiej jeśli otrzymamy dobrze widoczną sferę:

Kiedy program pobierze 6000 próbek, możemy wyliczyć dane kalibracyjne magnetometru i zapisać je w pamięci EEPROM:

Po takim zabiegu, nowo powstała sfera powinna pokrywać się ze sferą odniesienia:

Komunikacja UART

Za pomocą magistrali UART możemy ustawiać parametry pracy oraz odczytywać przetworzone przez niego dane. Standardowo będziemy posługiwali się nagłówkiem startu ramki komunikacyjnej, zakończenia ramki oraz wyliczoną sumą kontrolną po znaku *

Każde wydawane polecenie poprzedzamy znakiem @, a kończymy znakami powrotu r/n

@polecenie,ewentualny_parametr*suma_kontrolna

Jeśli polecenie zostanie wykonane otrzymamy odpowiedź z nagłówkiem znaku ~

~odpowiedz,ewentualny_parametr*suma_kontrolna

Dane z czujników poprzedzane są natomiast znakiem $

$typ_ramki,dane*suma_kontrolna

Obliczenie sumy kontrolnej odbywa się poprzez obliczenie bitowej różnicy symetrycznej każdego znaku w poleceniu:

Przykładowo tak będzie wyglądało wysłanie polecenia Pythonie:

  1. def send_command(serial_port, cmd_msg):
  2.   cmd_msg = '@' + cmd_msg.strip()
  3.   crc = 0
  4.   for c in cmd_msg:
  5.   crc = crc^ord(c)
  6.   serial_port.write(cmd_msg + '*%02X'%crc + chr(13) + chr(10))

Pełny przykład znajdziecie tutaj: https://github.com/withrobot/myAHRS_plus/blob/master/common_python/basic_example/python_example.py

Listę komend UART wraz z opcjonalnymi parametrami oraz formatem wyników opublikowano na GitHub: https://github.com/withrobot/myAHRS_plus/tree/master/tutorial

Komunikacja I2C

Pomimo tego, że logika modułu wynosi 3.3V to toleruje on również logikę 5V, dzięki czemu możemy podłączyć go bezpośrednio do Arduino UNO. Jedyne co musimy zrobić, to podciągnąć linie sygnałowe do zasilania rezystorami z przedziału 1kΩ - 10kΩ (typowo 4.7kΩ).

Komunikacja po I2c nie umożliwia konfiguracji modułu - pozwala jedynie na odczytanie wartości rejestrów czujników i obliczonych danych. Adres modułu na magistrali I2c to 0x20.

Lista rejestrów przedstawia się następująco:

Nazwa rejestru Atrybut Adres Domyślna wartość Opis
WHO_AM_I R 0x01 0xB1 Rejestr identyfikacyjny
REV_ID_MAJOR R 0x02 - -
REV_ID_MINOR R 0x03 - -
STATUS R 0x04 0x80 -
I_ACC_X_LOW R 0x10 DATA Akcelerometr (surowe wartości)
I_ACC_X_HIGH R 0x11 DATA Akcelerometr (surowe wartości)
I_ACC_Y_LOW R 0x12 DATA Akcelerometr (surowe wartości)
I_ACC_Y_HIGH R 0x13 DATA Akcelerometr (surowe wartości)
I_ACC_Z_LOW R 0x14 DATA Akcelerometr (surowe wartości)
I_ACC_Z_HIGH R 0x15 DATA Akcelerometr (surowe wartości)
I_GYRO_X_LOW R 0x16 DATA Żyroskop (surowe wartości)
I_GYRO_X_HIGH R 0x17 DATA Żyroskop (surowe wartości)
I_GYRO_Y_LOW R 0x18 DATA Żyroskop (surowe wartości)
I_GYRO_Y_HIGH R 0x19 DATA Żyroskop (surowe wartości)
I_GYRO_Z_LOW R 0x1A DATA Żyroskop (surowe wartości)
I_GYRO_Z_HIGH R 0x1B DATA Żyroskop (surowe wartości)
I_MAGNET_X_LOW R 0x1C DATA Magnetometr (surowe wartości)
I_MAGNET_X_HIGH R 0x1D DATA Magnetometr (surowe wartości)
I_MAGNET_Y_LOW R 0x1E DATA Magnetometr (surowe wartości)
I_MAGNET_Y_HIGH R 0x1F DATA Magnetometr (surowe wartości)
I_MAGNET_Z_LOW R 0x20 DATA Magnetometr (surowe wartości)
I_MAGNET_Z_HIGH R 0x21 DATA Magnetometr (surowe wartości)
C_ACC_X_LOW R 0x22 DATA Akcelerometr (skalibrowane wartości)
C_ACC_X_HIGH R 0x23 DATA Akcelerometr (skalibrowane wartości)
C_ACC_Y_LOW R 0x24 DATA Akcelerometr (skalibrowane wartości)
C_ACC_Y_HIGH R 0x25 DATA Akcelerometr (skalibrowane wartości)
C_ACC_Z_LOW R 0x26 DATA Akcelerometr (skalibrowane wartości)
C_ACC_Z_HIGH R 0x27 DATA Akcelerometr (skalibrowane wartości)
C_GYRO_X_LOW R 0x28 DATA Żyroskop (skalibrowane wartości)
C_GYRO_X_HIGH R 0x29 DATA Żyroskop (skalibrowane wartości)
C_GYRO_Y_LOW R 0x2A DATA Żyroskop (skalibrowane wartości)
C_GYRO_Y_HIGH R 0x2B DATA Żyroskop (skalibrowane wartości)
C_GYRO_Z_LOW R 0x2C DATA Żyroskop (skalibrowane wartości)
C_GYRO_Z_HIGH R 0x2D DATA Żyroskop (skalibrowane wartości)
C_MAGNET_X_LOW R 0x2E DATA Magnetometr (skalibrowane wartości)
C_MAGNET_X_HIGH R 0x2F DATA Magnetometr (skalibrowane wartości)
C_MAGNET_Y_LOW R 0x30 DATA Magnetometr (skalibrowane wartości)
C_MAGNET_Y_HIGH R 0x31 DATA Magnetometr (skalibrowane wartości)
C_MAGNET_Z_LOW R 0x32 DATA Magnetometr (skalibrowane wartości)
C_MAGNET_Z_HIGH R 0x33 DATA Magnetometr (skalibrowane wartości)
TEMPERATURE_LOW R 0x34 DATA Temperatura
TEMPERATURE_HIGH R 0x35 DATA Temperatura
ROLL_LOW R 0x36 DATA Kąt Eulera
ROLL_HIGH R 0x37 DATA Kąt Eulera
PITCH_LOW R 0x38 DATA Kąt Eulera
PITCH_HIGH R 0x39 DATA Kąt Eulera
YAW_LOW R 0x3A DATA Kąt Eulera
YAW_HIGH R 0x3B DATA Kąt Eulera
QUATERNION_X_LOW R 0x3C DATA Quaternion
QUATERNION_X_HIGH R 0x3D DATA Quaternion
QUATERNION_Y_LOW R 0x3E DATA Quaternion
QUATERNION_Y_HIGH R 0x3F DATA Quaternion
QUATERNION_Z_LOW R 0x40 DATA Quaternion
QUATERNION_Z_HIGH R 0x41 DATA Quaternion
QUATERNION_W_LOW R 0x42 DATA Quaternion
QUATERNION_W_HIGH R 0x43 DATA Quaternion

Jak nie trudno zauważyć, wszystkie dane czujników są zapisane w formacie 16 bitowym, dlatego w przypadku Arduino, chcąc uzyskać prawidłową wartość, musimy odczytać dwa bajty spod wskazanego adresu.

W przypadku danych surowych I_ACC_X_LOW ~ I_MAGNET_Z_HIGH, wystarczy odczytać tylko młodszy i starszy bajt, gdzie uzskana wartość jest wartością rzeczywistą.

Inaczej sprawa wygląda dla danych skalibrowanych dla czujników, gdzie odczytaną wartość należy przemnożyć przez dany współczynnik skali:

Akcelerometr (g) = OdczytanaWartosc × 16 / 32767

Żyroskop (dps) = OdczytanaWartosc × 2000 / 32767

Magnetometr (uT) = OdczytanaWartosc × 0.3

Temperatura (°C) = OdczytanaWartosc × 200 / 32767

Kąt Eulera (°) = OdczytanaWartosc × 180 / 32767

Quaternion = OdczytanaWartosc / 32767

Przykład dla Arduino

W poniższym przykładzie, przedstawiam sposób dobrania się do rejestrów, zawierających kąty Euelara: Pitch, Roll oraz Yaw.

  1. #include <Wire.h>
  2.  
  3. #define MYAHRS_ADDRESS 0x20
  4.  
  5. uint8_t readRegister8(uint8_t reg)
  6. {
  7.   uint8_t value;
  8.  
  9.   Wire.beginTransmission(MYAHRS_ADDRESS);
  10.  
  11.   #if ARDUINO >= 100
  12.     Wire.write(reg);
  13.   #else
  14.     Wire.send(reg);
  15.   #endif
  16.  
  17.   Wire.endTransmission(false);
  18.  
  19.   Wire.beginTransmission(MYAHRS_ADDRESS);
  20.   Wire.requestFrom(MYAHRS_ADDRESS, 1);
  21.  
  22.   while(!Wire.available()) {};
  23.  
  24.   #if ARDUINO >= 100
  25.     value = Wire.read();
  26.   #else                     
  27.     value = Wire.receive();
  28.   #endif;
  29.  
  30.   Wire.endTransmission();
  31.  
  32.   return value;
  33. }             
  34.  
  35. int16_t readRegister16(uint8_t reg)
  36. {
  37.   int16_t value;
  38.  
  39.   Wire.beginTransmission(MYAHRS_ADDRESS);
  40.  
  41.   #if ARDUINO >= 100
  42.     Wire.write(reg);
  43.   #else
  44.     Wire.send(reg);
  45.   #endif
  46.  
  47.   Wire.endTransmission(false);
  48.     
  49.   Wire.beginTransmission(MYAHRS_ADDRESS);
  50.   Wire.requestFrom(MYAHRS_ADDRESS, 2);
  51.  
  52.   #if ARDUINO >= 100
  53.     uint8_t vla = Wire.read();
  54.     uint8_t vha = Wire.read();
  55.   #else
  56.     uint8_t vla = Wire.receive();
  57.     uint8_t vha = Wire.receive();
  58.   #endif;
  59.  
  60.   Wire.endTransmission();
  61.  
  62.   value = vha << 8 | vla;
  63.  
  64.   return value;
  65. }
  66.  
  67. float getRoll()
  68. {
  69.   int value = readRegister16(0x36);
  70.   return (float)value * 180 / 32767;
  71. }
  72.  
  73. float getPitch()
  74. {
  75.   int value = readRegister16(0x38);
  76.   return (float)value * 180 / 32767;
  77. }
  78.  
  79. float getYaw()
  80. {
  81.   int value = readRegister16(0x3A);
  82.   return (float)value * 180 / 32767;
  83. }
  84.  
  85. void setup()
  86. {
  87.   Serial.begin(115200);
  88.   Wire.begin();
  89.  
  90.   Serial.print("WHO_I_AM = ");
  91.   Serial.println(readRegister8(0x01), HEX);  
  92. }
  93.  
  94. void loop()
  95. {
  96.   Serial.print(" ROLL = ");
  97.   Serial.print(getRoll());
  98.   Serial.print(" PITCH = ");
  99.   Serial.print(getPitch());
  100.   Serial.print(" YAW = ");
  101.   Serial.println(getYaw());
  102. }

Porówanie

Poniżej możecie zobaczyć porównanie modułu myAHRS+ z MPU9150 Motion Fit

Podsumowanie

myAHRS+ jest bardzo dobrym, szybkim i szalenie dokładnym modułem - jest niestety też modułem z wyższej półki cenowej. W zależności od sklepu możemy dostać go w cenie od 400zł do 500zł. W sklepach zagranicznych dostępny jest w cenie 75$, co przekłada się na kwotę około 250zł (bez kosztów przesyłki, opłaty celnej, podatku VAT).

Biorąc jednak pod uwagę klasę modułu, braku konieczności samodzielnego programowania jednostki DMP w układach MPUxxx, ogromnej wygody w użytkowaniu i możliwość łatwego podpięcia pod płytki typu Raspberry Pi / Odroid, myAHRS+ jest warty każdej wydanej złotówki.

Na szczególną uwagę zasługuje również pełne wsparcie modułu dla ROS (The Robot Operating System), szalenie popularnego wśród robotyków.

Więcej informacji: https://github.com/withrobot/myAHRS_plus

W Polsce moduł dostępny jest w ofercie sklepów Elty.pl oraz Kamami.pl

Reklama

Komentarze Komentarze
Avatar 1
Kamil Maciejewski Linux Ubuntu / Mozilla Firefox 38.0
04 June 2015 - 15:37 Brak informacji

Ciekawe, czy mając tak dokładny pomiar przyspieszenia (i obrotu z żyroskopu) dało by się w miarę dokładnie wyliczać położenie, bo przecież jeśli prędkość jest pochodną drogi a przyspieszenie pochodną prędkości, to całkując da się to (teoretycznie) policzyć w drugą stronę. Próbowałem kiedyś to zrobić dla telefonu z Androidem (jeśli nie będziemy nim obracać, to wystarczy sam akcelerometr), ale układ za bardzo szumiał i nawet nieruchomy telefon generował narastający w czasie błąd obliczeń wynikający z niedokładnego pomiaru. Próbowałem kulawo implementować jakiś filtr górnoprzepustowy czy właśnie(chyba) filtr kalmana, ale wyniki nie były satysfakcjonujące choć na wykresie przysp. po filtrowaniu wyglądało sensownie. Całkowałem metodą trapezów co przy dobrej rozdzielczości powinno dać sensowne wyniki.

Wiadomo, że w dłuższym czasie taki błąd będzie narastał, ale na krótkich odcinkach można by wyliczać zmianę położenia.

Avatar 2
Korneliusz Linux x86_64 / Mozilla Firefox 34.0
04 June 2015 - 23:07 Bytom

Strzelam, że można :)

Avatar 1
Kamil Maciejewski Windows 7 / Mozilla Firefox 31.0
08 June 2015 - 12:53 Łódź

To chyba muszę chociaż na nowym smartfonie spróbować odpalić, w sumie akcelerometr o kilka generacji lepszy, może jakoś będzie działać.

Avatar 1
MrDoctor Linux x86_64 / Mozilla Firefox 38.0
05 June 2015 - 21:12 Warszawa

Istnieją systemy tzw nawigacji inercyjnej, np na okrętach. W piechocie też się pojawia moda na takie rozwiązania i one właśnie ze względu na wagę wykorzystują czujniki MEMS. To pozwala żołnierzom odnaleźć się w przypadku braku sygnału GPS np. w budynkach, ale jeżeli tylko GPS jest dostępny jest używany do skorygowania błędu nawigacji inercyjnej.

Avatar 1
Saj Windows 7 / Safari 537.36
04 July 2015 - 12:23 Brak informacji

Szukam przykładów połączenia i komunikacji myAHRS+ z Raspberry Pi (Model 2) przez I2C.
Dziękuję z góry.

Avatar 2
Korneliusz Linux x86_64 / Mozilla Firefox 34.0
06 July 2015 - 21:44 Bytom
Avatar 1
Andrzej Windows 7 / Safari 537.36
09 July 2015 - 11:59 Olsztyn

Hej, Co to jest, te takie coś czym zaczepiasz piny na ahrsie w trakcie komunikacji z arduino? można to gdzieś kupic?

Avatar 1
Andrzej Windows 7 / Safari 537.36
25 July 2015 - 03:20 Olsztyn

Hej, jest ktoś komu zalega taki czujnik? chetnie odkupie
shadowpl@gmail.com

Avatar 2
Korneliusz Linux x86_64 / Mozilla Firefox 34.0
25 July 2015 - 10:33 Bytom