Sterownik IMU jest granicą między fizycznym sensorem a estymatorem. Jego zadanie nie kończy się na odczytaniu sześciu rejestrów. Musi jednoznacznie skonfigurować układ, zachować czas próbkowania, obsłużyć FIFO i błędy magistrali, przeliczyć jednostki, oznaczyć clipping, zastosować właściwy alignment oraz wykryć reset lub zmianę konfiguracji. Błędny sterownik może publikować płynne, wiarygodnie wyglądające dane o złej skali albo z fałszywym timestampem.
Poniższy tekst opisuje architekturę bezpiecznego sterownika dla nieuzbrojonej platformy laboratoryjnej. Nazwy i wartości rejestrów są zależne od konkretnego IMU; przed implementacją trzeba użyć datasheetu właściwej rewizji.
Spis treści#
- Kontrakt sterownika
- Warstwy implementacji
- Analiza datasheetu
- Zasilanie i sekwencja resetu
- WHO_AM_I nie wystarcza
- SPI: tryb i transakcja
- Integralność sygnałów
- Maszyna stanów inicjalizacji
- Konfiguracja zakresów i ODR
- Data-ready i capture timestamp
- DMA
- FIFO
- Rekonstrukcja czasu próbek
- Dekodowanie danych
- Skala i jednostki SI
- Alignment i kalibracja
- Filtry i decymacja
- Clipping, status i jakość
- Recovery po błędzie
- Watchdog konfiguracji
- Interfejs do estymatora
- Kod przykładowy
- Testy jednostkowe
- Testy HIL i sprzętowe
- Logowanie i metryki
- Najczęstsze awarie
- Powiązane tematy
- Przypisy
Kontrakt sterownika#
Odbiorca powinien dostać rekord o jawnej semantyce:
typedef struct {
uint64_t sample_time_us;
uint64_t publish_time_us;
float gyro_rad_s[3];
float accel_m_s2[3];
float temperature_deg_c;
uint32_t sequence;
uint32_t status;
uint8_t sensor_id;
uint8_t config_generation;
} ImuSample;
sample_time oznacza fizyczny czas próbki, a publish_time pozwala zmierzyć latency. sequence wykrywa luki. config_generation zmienia się po resecie lub rekonfiguracji, aby estymator nie łączył danych o różnych skalach. Status powinien zawierać clipping, overflow FIFO, synchronizację czasu, self-test i degradację.
Nie należy publikować surowego int16[6] poza warstwę urządzenia. Jednostki, kolejność osi i znak byłyby wtedy niejawne. Jednocześnie warto opcjonalnie logować surowe kody do diagnostyki.
Sterownik nie powinien wykonywać pełnej fuzji orientation. Może stosować fabryczną kompensację, kalibrację sensora i filtr antyaliasingowy, ale estymacja należy do osobnej warstwy. Ułatwia to testowanie i wymianę sensora.
Warstwy implementacji#
Przejrzysty podział:
HAL SPI/GPIO/timer
↓
transport rejestrowy
↓
device driver konkretnego IMU
↓
pipeline kalibracji i ramek
↓
publisher / kolejka próbek
↓
estymator, logger, diagnostyka
HAL zna kontroler SPI, DMA i timer, ale nie wie, co oznacza rejestr ODR. Transport zapewnia read_reg, write_reg, burst i deadline. Driver zna banki rejestrów, reset, FIFO i format ramek. Pipeline przelicza jednostki i alignment.
Warstwy nie powinny połykać błędów. Timeout DMA musi dotrzeć do maszyny zdrowia. read_reg() zwracające zero przy awarii jest niebezpieczne, bo zero może być poprawną wartością.
Analiza datasheetu#
Przed kodem przygotowuje się tabelę:
| Obszar | Pytania |
|---|---|
| zasilanie | napięcia, kolejność, czas startu, decoupling |
| identyfikacja | WHO_AM_I, revision, serial, reset value |
| SPI | mode, maksymalny zegar, bit read/write, auto-increment |
| banki | wybór banku, stan po resecie, rejestry współdzielone |
| gyro/accel | zakresy, ODR, tryby low-noise/low-power |
| filtry | tor przed ADC, DLPF, decymacja, latency |
| FIFO | rekordy, header, endian, watermark, overflow |
| przerwania | polarity, pulse/latched, clear semantics |
| timestamp | częstotliwość, wrap, reset, relacja z FIFO |
| diagnostyka | self-test, saturation, data invalid |
Nie wolno zakładać, że układy jednej rodziny mają identyczne bity. Sterownik powinien być związany z konkretnym part ID. Jeśli obsługuje rodzinę, wariant wybiera jawna tabela capability.
Errata producenta jest częścią specyfikacji. Workaround musi mieć komentarz z numerem erraty i warunkiem zastosowania.
Zasilanie i sekwencja resetu#
Po narastaniu zasilania sensor potrzebuje czasu przed pierwszą komunikacją. Linie IO nie powinny podawać napięcia do niezasilonego układu przez diody zabezpieczające. Jeżeli VDD i VDDIO są osobne, kolejność musi odpowiadać datasheetowi.
Reset może być sprzętowy, programowy lub oba. Po komendzie software reset część rejestrów wraca do default, FIFO traci zawartość, a interfejs przez pewien czas nie odpowiada. Kod powinien czekać do deadline i odpytywać gotowość, nie wykonywać blokującego delay bez kontroli.
Sekwencja przykładowa:
POWER_WAIT → BUS_PROBE → SOFT_RESET → RESET_WAIT → ID_VERIFY
→ CLOCK_CONFIG → SENSOR_CONFIG → FIFO_CONFIG → IRQ_CONFIG
→ CONFIG_VERIFY → DISCARD_TRANSIENT → RUN
Każdy krok ma timeout i licznik prób. Nieudana inicjalizacja przechodzi do FAULT_BACKOFF, aby nie zajmować całego CPU ciągłymi resetami.
WHO_AM_I nie wystarcza#
Poprawny identyfikator dowodzi tylko, że jedna transakcja zwróciła oczekiwany bajt. Nie potwierdza stabilnej magistrali, rewizji, ODR ani zakresu. Po identyfikacji trzeba sprawdzić:
- wartości resetowe kilku rejestrów;
- zapis i odczyt kontrolowanego bitu;
- rewizję, jeśli dostępna;
- status resetu i zegara;
- zmianę data-ready przy włączonym ODR;
- fizyczną plausibility danych.
Przy zwartej MISO odczyt może zwracać stale 0x00 albo 0xFF. Jeśli WHO_AM_I jednego wariantu przypadkiem odpowiada temu wzorcowi, test wielu rejestrów jest konieczny.
Identyfikator nie powinien być sprawdzany tylko przy starcie. Okresowy watchdog konfiguracji może wykryć reset brownout.
SPI: tryb i transakcja#
Tryb SPI określa CPOL i CPHA. Zły tryb może czasem działać przy małej częstotliwości, a zawodzić po zmianie temperatury lub zegara. Parametry per-device muszą być ustawione przed aktywacją chip select.
Typowa transakcja odczytu burst:
CS low
adres | READ_BIT
dummy/read bytes...
CS high
Niektóre układy wymagają dummy byte albo limitu czasu między transakcjami. Auto-increment może zależeć od bitu adresu. Bank rejestrów jest wspólnym stanem urządzenia, więc równoległe wywołania muszą być serializowane.
Chip select powinien być sterowany sprzętowo lub z gwarantowanymi czasami. Przerwanie transakcji przez inny klient SPI jest niedopuszczalne. Arbiter magistrali musi respektować deadline szybkiego IMU.
Zegar konfiguracyjny bywa niższy niż maksymalny zegar odczytu danych. Przełączenie szybkości wymaga kontroli ustawień kontrolera.
Integralność sygnałów#
Szybkie zbocza SPI na długich ścieżkach powodują odbicia, przesłuch i ringing. Rezystory szeregowe blisko nadajnika mogą spowolnić zbocze. Ważna jest ciągła płaszczyzna masy, krótkie powroty prądu i brak rozcięć pod liniami.
Analizator logiczny może obciążyć magistralę i zmienić zachowanie. Oscyloskop pokazuje poziomy analogowe, nie tylko zdekodowane bity. Testuje się minimalne/maksymalne napięcie, temperaturę i aktywność innych urządzeń.
CRC nie jest standardem w prostych SPI IMU. Integralność zapewnia się przez layout, ograniczenie szybkości, sanity checks, sequence/FIFO i odczyt konfiguracji. Pojedynczy bit w raw gyro może wyglądać jak rzeczywisty impuls, więc detektor powinien uwzględniać fizyczne limity bez bezwarunkowego wygładzania.
Maszyna stanów inicjalizacji#
Nieblokująca maszyna stanów pozwala uruchamiać inne zadania i obsługiwać retry. Przykład:
switch (imu->state) {
case IMU_RESET:
if (write_reg(REG_RESET, RESET_BIT)) {
imu->deadline = now + RESET_TIMEOUT_US;
imu->state = IMU_WAIT_RESET;
}
break;
case IMU_WAIT_RESET:
if (reset_done()) imu->state = IMU_CONFIGURE;
else if (now > imu->deadline) imu_fault(TIMEOUT);
break;
case IMU_CONFIGURE:
if (apply_config(&imu->requested)) imu->state = IMU_VERIFY;
break;
case IMU_VERIFY:
if (verify_config()) imu_enter_run();
else imu_fault(CONFIG_MISMATCH);
break;
}
Funkcja apply_config nie może uznawać samego sukcesu transferu za sukces konfiguracji. Krytyczne rejestry są odczytywane i porównywane z maską bitów writable. Pola statusowe i reserved pomija się.
Po wejściu RUN odrzuca się określoną liczbę pierwszych próbek, jeśli datasheet wskazuje settling filtra.
Konfiguracja zakresów i ODR#
Zakres gyro i accel określa scale factor oraz clipping. Wartość enum mapuje się do bitów i współczynników w jednej tabeli:
typedef struct {
uint8_t reg_bits;
float lsb_to_si;
float clip_si;
} RangeConfig;
Współczynnik nie powinien być rozproszony po kodzie. Po każdej zmianie zakresu zwiększa się config_generation, czyści FIFO i oznacza przejście.
ODR musi być zgodny z trybem zasilania i filtrem. Nie wszystkie kombinacje są legalne. Konfigurator waliduje żądanie przed zapisem. Rzeczywisty ODR należy zmierzyć liczbą przerwań/timestampów.
Gyro i accel mogą mieć różne ODR. Jeśli rekord FIFO zawiera je osobno, driver nie może zakładać pary 1:1. Estymator powinien otrzymać zsynchronizowane lub osobne rekordy z czasem.
Data-ready i capture timestamp#
Sygnał data-ready informuje o powstaniu próbki. Najlepiej podłączyć go do wejścia timer capture albo przerwania o niskim jitterze. ISR zapisuje czas i uruchamia transfer, ale nie wykonuje filtracji ani logowania.
void imu_drdy_isr(void) {
const uint64_t t = timer_capture_us();
if (!imu_dma_busy()) {
imu_pending_time = t;
imu_start_dma();
} else {
imu_stats.drdy_while_busy++;
}
}
Przerwanie może być pulse lub latched. Sposób kasowania zależy od układu — odczyt statusu, danych albo zapis bitu. Zła konfiguracja powoduje burzę przerwań lub utratę kolejnych zboczy.
Priorytet IRQ musi być zgodny z API RTOS i DMA. Funkcja ISR nie może wywoływać blokującego mutexu.
DMA#
DMA przenosi burst bez angażowania CPU, ale tworzy asynchroniczny lifecycle bufora. Bufor nie może być na stosie funkcji, która wróci przed zakończeniem. Cache na MCU klasy Cortex-M7 wymaga clean/invalidate albo pamięci non-cacheable.
Po callbacku:
- sprawdź status transferu;
- zwolnij CS, jeśli nie zrobił tego sprzęt;
- przypisz timestamp z DRDY;
- przekaż bufor do dekodera bez blokowania ISR;
- uruchom kolejny transfer lub obsłuż zaległe FIFO.
Double buffering pozwala dekodować jedną ramkę podczas transferu następnej. Własność bufora musi być jednoznaczna; sequence state zapobiega nadpisaniu.
Timeout DMA jest możliwy po błędzie magistrali. Watchdog powinien anulować transfer, zresetować peryferium SPI i przejść przez recovery urządzenia.
FIFO#
FIFO pozwala zachować próbki podczas krótkiego opóźnienia CPU i zmniejsza overhead transakcji. Zwiększa jednak złożoność. Rekord może zawierać header, gyro, accel, temperaturę, timestamp i pola rozszerzone o różnej długości.
Algorytm:
- odczytaj atomowo licznik bajtów/rekordów;
- sprawdź limit względem pojemności i bufora;
- odczytaj burst do DMA;
- parsuj header po headerze;
- sprawdź, czy długość rekordu mieści się w danych;
- obsłuż rekordy specjalne i timestamp;
- wykryj overflow oraz nieznany header;
- po desynchronizacji opróżnij FIFO i zwiększ generation.
Nie wolno zaokrąglać liczby bajtów do „spodziewanego rozmiaru” i interpretować reszty jako próbki. Jeden utracony bajt może przesunąć wszystkie pola.
Watermark dobiera się jako kompromis latency/obciążenie. W szybkim rate loop duży watermark dodaje niedopuszczalne opóźnienie. Można użyć DRDY dla najnowszej próbki i FIFO jako ochrony, jeśli układ to wspiera.
Rekonstrukcja czasu próbek#
Jeżeli FIFO zawiera N równomiernych próbek kończących się w czasie t_last:
t_i = t_last - (N - 1 - i) · T_sample
T_sample powinno pochodzić z rzeczywistego zegara sensora lub jego timestampu. Nominalne 1/ODR nie uwzględnia tolerancji oscylatora. Długoterminowo mapuje się licznik sensora na timer MCU modelem offset + scale.
Wrap timestampu obsługuje arytmetyka modularna i licznik epok. Reset sensora odróżnia się od wrap przez status oraz nieciągłość konfiguracji.
Timestamp rejestru może odpowiadać początkowi, środkowi lub końcowi integracji. Dla precyzyjnej synchronizacji potrzebna jest definicja producenta. Opóźnienie filtra wewnętrznego jest osobne od czasu próbki i powinno być znane estymatorowi.
Dekodowanie danych#
Nie wolno rzutować bufora SPI na struct bez kontroli packing, alignmentu i endianowości. Bezpieczny dekoder składa pola jawnie:
static int16_t be_i16(const uint8_t *p) {
return (int16_t)(((uint16_t)p[0] << 8) | p[1]);
}
Dla 20-bitowych wartości trzeba wykonać sign extension. Przesunięcie signed typu może mieć problemy językowe; najpierw operuje się na unsigned, potem jawnie rozszerza znak.
Każdy rekord przechodzi sanity checks. Temperatura poza fizycznym zakresem, wszystkie osie 0x7fff albo identyczna ramka przez setki sekwencji mogą wskazywać błąd.
Status data-ready należy odczytać w sposób, który nie kasuje FIFO przed czasem. Kolejność rejestrów w burst bierze się wyłącznie z datasheetu.
Skala i jednostki SI#
Konwersja:
gyro_rad_s = raw · lsb_to_dps · π/180
accel_m_s2 = raw · lsb_to_g · 9.80665
Można połączyć stałe w lsb_to_si. Wartość zależy od zakresu, trybu i formatu. Factory scale correction może być już zastosowana wewnątrz sensora; nie należy stosować jej podwójnie.
Jednostki SI są kontraktem wewnętrznym. Protokół zewnętrzny może wymagać innych, ale adapter konwertuje na granicy. Nazwy pól zawierają _rad_s, _m_s2, _deg_c.
Przy float mnożenie jest zwykle wystarczające. Fixed-point wymaga analizy zakresu i saturacji. W obu przypadkach surowa wartość graniczna ustawia flagę clipping przed filtracją.
Alignment i kalibracja#
Kolejność pipeline:
raw → scale SI → intrinsic calibration → sensor-to-board rotation
→ board-to-body rotation → publikacja
Kalibracja intrinsic obejmuje bias, scale i nieortogonalność. Alignment jest czystym obrotem. Macierz kalibracji nie musi być ortonormalna; macierz rotacji musi.
Bias temperaturowy może być funkcją temperatury. Estymator dodatkowo śledzi residual bias. Sterownik powinien publikować temperaturę i identyfikator zestawu kalibracji.
Osie sprawdza się fizycznym ruchem. Przy położeniu zgodnym z body i nieruchomym pojeździe akcelerometr powinien mieć oczekiwany znak osi pionowej zgodnie z FRD/NED. Reguła nie może być wyprowadzana tylko z obrazka płytki.
Filtry i decymacja#
Pierwszy filtr antyaliasingowy powinien działać przed próbkowaniem/decymacją wewnątrz IMU. Driver konfiguruje DLPF świadomie. Filtr MCU nie usunie aliasu już obecnego w danych.
Decymacja z 8 kHz do 1 kHz wymaga filtra o tłumieniu powyżej nowego Nyquista. Wybieranie co ósmej próbki bez filtra jest błędem. Jeżeli sensor zapewnia odpowiedni tor, trzeba znać jego latency i effective bandwidth.
Sterownik może publikować delta angle/delta velocity z bloku preintegracji. Musi wtedy podać przedział czasu i liczbę próbek. Estymator nie powinien ponownie całkować rate jak wartości chwilowej.
Notch śledzący RPM zwykle należy do warstwy kondycjonowania/control, nie rejestrowego drivera. Utrzymanie surowego toru diagnostycznego jest ważne.
Clipping, status i jakość#
Clipping wykrywa się przed przeliczeniem lub filtrem. Warto uwzględnić margines kilku LSB, bo dokładna wartość max może nie wystąpić po filtrze. Licznik per-axis jest logowany.
Status próbki może zawierać:
VALID_GYRO
VALID_ACCEL
TIME_SYNCED
GYRO_CLIPPED_X/Y/Z
ACCEL_CLIPPED_X/Y/Z
FIFO_OVERFLOW
BUS_RECOVERED
TEMP_VALID
SELF_TEST_FAILED
CONFIG_CHANGED
Brak bitu VALID nie oznacza zera. Odbiorca nie może użyć starej próbki jako nowej. Kolejka powinna zachować sequence i zgłaszać drop.
Jakość nie jest jednym procentem. Powód degradacji pozwala estymatorowi dobrać reakcję.
Recovery po błędzie#
Błędy dzielą się na transport, urządzenie i dane. Recovery ma poziomy:
- ponów pojedynczą transakcję, jeśli bezpieczne;
- zresetuj kontroler SPI/DMA;
- odczytaj ID i konfigurację;
- opróżnij FIFO;
- wykonaj soft reset oraz pełną konfigurację;
- użyj hardware reset/power cycle, jeśli dostępny;
- oznacz sensor failed i przełącz redundancję.
Każdy reset zmienia generation i tworzy przerwę danych. Nie wolno publikować ramki z okresu konfiguracji. Retry ma limit i exponential backoff.
Jeśli odczyt konfiguracji pokazuje reset brownout, trzeba zbadać zasilanie. Ciągłe programowe recovery nie zastępuje naprawy hardware.
Watchdog konfiguracji#
Okresowo odczytuje się krytyczne rejestry z maską oczekiwanych bitów: power mode, zakres, ODR, filtr, FIFO i interrupt. Odczyt rozkłada się w czasie, aby nie zakłócać próbek.
Mismatch może wynikać z resetu, błędu bitowego albo nieautoryzowanego zapisu. Sterownik nie powinien cicho poprawić pojedynczego rejestru, jeśli zależności konfiguracji wymagają pełnej sekwencji. Przechodzi do kontrolowanego reconfigure.
Rejestry clear-on-read i statusowe nie nadają się do porównania. Reserved bits maskuje się zgodnie z datasheetem.
Interfejs do estymatora#
Estymator potrzebuje:
- wartości w body i SI;
- czasu środka próbki/integracji;
Δtdla delta angle/velocity;- statusu clipping/drop/reset;
- identyfikatora sensora;
- temperatury;
- latency lub historii do fuzji;
- znanej kowariancji/modelu szumu.
Publisher powinien być lock-free lub mieć bounded blocking. Jeżeli odbiorca nie nadąża, polityka drop musi być jawna. Dla regulatora ważniejsza jest najnowsza próbka, dla loggera kompletność; mogą używać różnych kolejek.
Nie należy zmieniać zakresu w locie bez protokołu z estymatorem. Skok scale i filtra zmienia model szumu. Jeśli dynamic range switching jest wymagany, obie strony muszą obsłużyć generation i okres settling.
Kod przykładowy#
Minimalny dekoder ramki rejestrowej:
bool imu_decode(const uint8_t *rx, size_t n,
const ImuConfig *cfg, uint64_t sample_us,
ImuSample *out) {
if (n < IMU_BURST_BYTES || !cfg || !out) return false;
int16_t raw_ax = be_i16(&rx[ACCEL_X_OFFSET]);
int16_t raw_ay = be_i16(&rx[ACCEL_Y_OFFSET]);
int16_t raw_az = be_i16(&rx[ACCEL_Z_OFFSET]);
int16_t raw_gx = be_i16(&rx[GYRO_X_OFFSET]);
int16_t raw_gy = be_i16(&rx[GYRO_Y_OFFSET]);
int16_t raw_gz = be_i16(&rx[GYRO_Z_OFFSET]);
Vec3 a_sensor = vec3(raw_ax, raw_ay, raw_az) * cfg->accel_lsb_to_si;
Vec3 g_sensor = vec3(raw_gx, raw_gy, raw_gz) * cfg->gyro_lsb_to_si;
out->status = detect_clipping(raw_ax, raw_ay, raw_az,
raw_gx, raw_gy, raw_gz, cfg);
Vec3 a_body = cfg->sensor_to_body * calibrate_accel(a_sensor, cfg);
Vec3 g_body = cfg->sensor_to_body * calibrate_gyro(g_sensor, cfg);
if (!finite3(a_body) || !finite3(g_body)) return false;
store3(out->accel_m_s2, a_body);
store3(out->gyro_rad_s, g_body);
out->sample_time_us = sample_us;
out->config_generation = cfg->generation;
return true;
}
Stałe offsetów są przykładowe i muszą pochodzić z datasheetu. Kod produkcyjny dodaje status rejestru, temperaturę, sequence i obsługę konkretnego formatu.
Testy jednostkowe#
Bez sprzętu testuje się:
- dekodowanie dodatnich i ujemnych wartości granicznych;
- endian i sign extension;
- każdy zakres oraz
lsb_to_si; - macierz alignmentu dla osi bazowych;
- clipping i status;
- parser FIFO z rekordami poprawnymi, skróconymi i nieznanym headerem;
- wrap timestampu;
- rekonstrukcję czasu N próbek;
- maszynę stanów: timeout, retry, mismatch;
- zmianę generation;
NaNoraz overflow arytmetyki;- utratę sekwencji i przepełnienie kolejki.
Golden vectors można wygenerować z oficjalnego kodu producenta lub zapisu z analizatora. Muszą przechowywać również konfigurację, bo te same bajty mają inną skalę w innym zakresie.
Mock transportu rejestruje kolejność zapisów i symuluje clear-on-read. Pozwala potwierdzić sekwencję inicjalizacji bez płytki.
Testy HIL i sprzętowe#
Plan:
- oscyloskopem sprawdzić zasilanie, reset, CS i zegar;
- odczytać ID przy małej szybkości;
- zweryfikować rejestry resetowe;
- uruchomić data-ready i zmierzyć ODR timerem;
- sprawdzić burst przy maksymalnym bezpiecznym zegarze;
- wymusić obciążenie CPU i sprawdzić FIFO;
- poruszyć każdą osią oraz sześć pozycji grawitacji;
- cykl temperatury i restartów;
- fault injection: odłączenie, zwarcie/błąd magistrali na stanowisku ochronnym, reset sensora;
- test drgań z bezpiecznie zamocowanym napędem;
- replay próbek do estymatora.
Nie wykonuje się inwazyjnego fault injection na latającym pojeździe. Najpierw stanowisko laboratoryjne, potem HIL i lot nieuzbrojonej platformy z ograniczeniami.
Logowanie i metryki#
Sterownik publikuje liczniki:
bus_error_count;dma_timeout_count;fifo_overflow_count;fifo_bad_header_count;sample_drop_count;duplicate_count;config_mismatch_count;reset_count;- clipping per axis;
- min/max/mean transfer latency;
- ODR measured;
- queue high-water mark.
Liczniki są monotoniczne i resetowane tylko świadomie. Sama ostatnia flaga ukrywa sporadyczny problem. Logger powinien zapisać event z czasem przy zmianie stanu.
Histogram latency ujawnia jitter, którego średnia nie pokazuje. Porównanie sample_time z publish_time mierzy cały sterownik.
Najczęstsze awarie#
Poprawne liczby, zła skala#
Zakres w rejestrze różni się od współczynnika w kodzie albo sensor zresetował się do default. Watchdog konfiguracji i generation wykrywają problem.
Zduplikowane próbki#
Polling jest szybszy od ODR albo status data-ready jest źle kasowany. Sequence/timestamp ujawnia duplikaty.
Pominięte próbki#
Odczyt jest wolniejszy, IRQ blokowane lub FIFO przepełnione. Wykres może nadal wyglądać płynnie po interpolacji.
Losowe impulsy#
Integralność SPI, parser przesunięty o bajt, cache DMA lub prawdziwe drganie. Surowe bajty i oscyloskop rozdzielają przyczyny.
Wszystko działa do włączenia loggera#
Priorytety, blokująca karta SD lub przeciążenie magistrali. FIFO i bounded queues powinny izolować krótkie opóźnienia.
Temperatura jest absurdalna, gyro poprawne#
Zły offset pola, endian albo wzór kompensacji. Nie zakładać wspólnego układu rejestrów z innym wariantem.
Reset bez wykrycia#
WHO_AM_I nadal poprawne, ale zakres/ODR wrócił do default. Potrzebny watchdog krytycznych rejestrów.
Próbki z jednego czasu#
Cały burst FIFO dostał timestamp callbacku DMA. Estymator widzi sztuczny dt=0, a następnie lukę.
Osie działają osobno, ale attitude rozbiega się w ruchu złożonym#
Alignment lub konwencja body jest błędna. Testy pojedynczych osi nie wystarczają; potrzebny obrót złożony i odniesienie.
Powiązane tematy#
- IMU w dronie
- Żyroskop MEMS
- Akcelerometr MEMS
- SPI w UAV
- Harmonogram czasu rzeczywistego FC
- Testy jednostkowe firmware UAV
Przypisy#
- TDK InvenSense, ICM‑42688‑P — datasheet, zakresy, ODR, FIFO, timestamp i interfejs SPI.
- Bosch Sensortec, BMI088 — dokumentacja rozdzielonego toru gyro/accel i parametrów mechanicznych.
- TDK InvenSense, public software repositories — oficjalne sterowniki i przykłady integracji różnych sensorów.
- PX4, PX4 Autopilot source — architektura sterowników IMU, uORB, logowanie i testy.
- ROS, REP 145 — jednostki, osie i kontrakt danych IMU.
Utworzono: 15 sierpnia 2026. Ostatnia aktualizacja: 15 sierpnia 2026. Źródła zweryfikowano: 15 sierpnia 2026.
Źródła z centralnego rejestru
- TDK InvenSense: ICM-42688-P [datasheet]
- Bosch Sensortec: BMI088 [datasheet]
- TDK InvenSense public software organization [repozytoria producenta]
- PX4 Autopilot source repository [repozytorium open source]
- ROS REP 145: Conventions for IMU Sensor Drivers [standard projektu open source]