TriSense Pro20 min čtení· středně pokročilé

TriSense Pro: magnetometr a kurz k severu

Jak z magnetometru AK09918C přečíst magnetické pole, zkalibrovat ho v MotionCalu a spočítat kurz vůči zeměpisnému severu.

Obsah návodu7 kapitol
  1. 1Co budete potřebovat
  2. 2Instalace knihovny
  3. 3Zapojení přes I²C
  4. 4Čtení dat a výpočet kurzu
  5. 5Kalibrace v MotionCalu
  6. 6Použití kalibračních hodnot
  7. 7Řešení problémů

1Co budete potřebovat

TriSense Pro nese tři samostatné čipy. V tomto návodu se zaměříme na digitální 3osý magnetometr AK09918C od AKM, který měří sílu a směr magnetického pole — a umožňuje tak spočítat kurz. Použijeme knihovnu Voltino-TriSense-Library, jejíž třída AK09918C data vrací rovnou v mikrotestlách (µT).

  • Modul Voltino TriSense Pro
  • Arduino Uno nebo kompatibilní deska
  • 4 propojovací vodiče (samec–samice)
  • Počítač s Arduino IDE

2Instalace knihovny

  1. 1Otevřete github.com/VoltinoLabs/Voltino-TriSense-Library a klikněte na Code → Download ZIP.
  2. 2V Arduino IDE zvolte Sketch → Include Library → Add .ZIP Library a vyberte stažený soubor.
  3. 3Restartujte Arduino IDE.

3Zapojení přes I²C

AK09918C komunikuje po I²C na standardní adrese 0x0C.

VIN5Vlogika Arduina Uno
GNDGNDspolečná zem
SDAA4I²C data
SCLA5I²C hodiny
Zapojení TriSense Pro k Raspberry Pi Pico přes I2C — konektor modulu
TriSense Pro zapojený k Raspberry Pi Pico přes I²C.

4Čtení dat a výpočet kurzu

Tento kód inicializuje magnetometr, nastaví vzorkovací frekvenci na 100 Hz a průběžně tiskne zkalibrované složky pole i vypočítaný kurz. Kalibrační konstanty v horní části zatím nechte být — získáte je v dalším kroku.

AK09918C_heading.inoposuňte doprava →
/*
  AK09918C Magnetometer Example
  -----------------------------
  Čtení a kalibrace dat z 3osého magnetometru AK09918C.
  Aplikuje hard-iron offset i soft-iron korekční matici
  a počítá kurz opravený o lokální magnetickou deklinaci.

  Autor: Tomas Michal / VoltinoLabs
  Licence: MIT
*/

#include <Wire.h>
#include <TriSense.h>
#include <math.h>

AK09918C mag;

// --- Hard-iron offset (statická korekce) --- [µT] X, Y, Z
float magOffset[3] = {-44.96, 9.21, -36.31};

// --- Soft-iron korekční matice (3x3) ---
float magSoftIron[3][3] = {
  { 0.961, 0.004, -0.018},
  { 0.004, 0.998,  0.128},
  {-0.018, 0.128,  1.059}
};

// --- Očekávaná velikost pole (kontrola kalibrace) ---
float magFieldNorm = 49.72;      // [µT]

// --- Lokální magnetická deklinace (kladná = východní) ---
float declinationAngle = 5.02;   // ČR 2025 = +5,02° E

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println("Starting AK09918C example...");

  if (!mag.beginI2C()) {
    Serial.println("Error: AK09918C not found!");
    while (1);
  }

  // Rychlost cteni 100 Hz. Dalsi moznosti: AK_ODR_10HZ, AK_ODR_20HZ, AK_ODR_50HZ.
  // Prefix AK_ je dulezity: pres TriSense.h se holy nazev ODR_100HZ
  // preklada na konstantu IMU a sketch by se nezkompiloval.
  mag.setODR(AK_ODR_100HZ);

  Serial.println("AK09918C initialized.");
}

void loop() {
  if (mag.readData()) {
    // --- Odečtení hard-iron offsetu ---
    float x = mag.x - magOffset[0];
    float y = mag.y - magOffset[1];
    float z = mag.z - magOffset[2];

    // --- Aplikace soft-iron matice ---
    float mx = magSoftIron[0][0]*x + magSoftIron[0][1]*y + magSoftIron[0][2]*z;
    float my = magSoftIron[1][0]*x + magSoftIron[1][1]*y + magSoftIron[1][2]*z;
    float mz = magSoftIron[2][0]*x + magSoftIron[2][1]*y + magSoftIron[2][2]*z;

    // --- Velikost magnetického pole ---
    float magStrength = sqrt(mx*mx + my*my + mz*mz);

    // --- Kurz vůči magnetickému severu ---
    float heading = atan2(my, mx) * 180.0 / PI;
    if (heading < 0) heading += 360.0;

    // --- Oprava na zeměpisný sever ---
    heading += declinationAngle;
    if (heading >= 360.0) heading -= 360.0;

    Serial.print("MX: ");   Serial.print(mx, 2);
    Serial.print("  MY: "); Serial.print(my, 2);
    Serial.print("  MZ: "); Serial.print(mz, 2);
    Serial.print("  | Mag: "); Serial.print(magStrength, 2);
    Serial.print(" uT  | Heading (true north): ");
    Serial.print(heading, 1);
    Serial.println(" deg");

    // --- Kontrola kvality kalibrace ---
    float deviation = fabs(magStrength - magFieldNorm);
    if (deviation > 5) {
      Serial.print("! Warning: magnetic field deviation: ");
      Serial.print(deviation, 2);
      Serial.println(" uT");
    }
  }

  delay(10);   // 100 Hz
}
Serial Monitor · 115200 baud
AK09918C initialized.
MX: 21.44  MY: -8.03  MZ: 43.11  | Mag: 49.51 uT  | Heading (true north): 159.6 deg
MX: 21.51  MY: -8.11  MZ: 43.08  | Mag: 49.55 uT  | Heading (true north): 159.9 deg

5Kalibrace v MotionCalu

Bez kalibrace kurz nebude sedět — okolní kov a magnetická pole data zkreslují. Rozlišujeme dva druhy zkreslení: hard-iron (posun celé koule měření) a soft-iron (její deformace do elipsoidu). Oba spočítá volný nástroj MotionCal od PJRC.

  1. 1Stáhněte MotionCal (soubor MotionCal.zip, autor Paul Stoffregen).
  2. 2Nahrajte na Arduino následující sketch, který data do MotionCalu streamuje.
  3. 3Zavřete Serial Monitor, spusťte MotionCal, vyberte COM port a klikněte na Start.
  4. 4Otáčejte deskou plynule ve všech osách, jako byste malovali kouli.
  5. 5Až hodnota Gaps klesne pod 2 %, opište si offsety i matici z dolní části okna.
AK09918C_motionCal.inoposuňte doprava →
/*
  AK09918C Magnetometer — MotionCal Example
  ------------------------------------------
  Posílá data magnetometru do nástroje MotionCal,
  který z nich spočítá hard-iron offsety a soft-iron matici.

  Postup:
  1. Nahrajte tento sketch na Arduino.
  2. Zavřete Serial Monitor v Arduino IDE.
  3. Spusťte MotionCal, vyberte COM port a dejte Start.
  4. Otáčejte deskou plynule ve všech osách, dokud se
     nevykreslí koule a "Gaps" neklesnou pod 2 %.
  5. Zapište si vypsané offsety a matici.

  Poznámka: posíláme jen data magnetometru; hodnoty
  akcelerometru a gyroskopu jsou nulové kvůli kompatibilitě
  s formátem, který MotionCal očekává.
*/

#include <Wire.h>
#include <TriSense.h>

AK09918C mag;

void setup() {
  Serial.begin(115200);
  delay(1000);

  if (!mag.beginI2C()) {
    Serial.println("AK09918C not found!");
    while (1);
  }

  // Prefix AK_ je nutny — viz poznamka v predchozim sketchi.
  mag.setODR(AK_ODR_100HZ);
  Serial.println("AK09918C initialized!");
}

void loop() {
  if (mag.readData()) {
    // MotionCal očekává 9 hodnot: ax, ay, az, gx, gy, gz, mx, my, mz
    Serial.print("Raw:0,0,0,0,0,0,");
    Serial.print(int(mag.x * 10)); Serial.print(",");
    Serial.print(int(mag.y * 10)); Serial.print(",");
    Serial.println(int(mag.z * 10));

    Serial.print("Uni:0.0,0.0,0.0,0.0,0.0,0.0,");
    Serial.print(mag.x / 1000.0, 4); Serial.print(",");
    Serial.print(mag.y / 1000.0, 4); Serial.print(",");
    Serial.println(mag.z / 1000.0, 4);
  }

  delay(10);   // 100 Hz
}

6Použití kalibračních hodnot

Hodnoty z MotionCalu vložte zpět do prvního sketche: tři čísla hard-iron do pole magOffset[3], matici 3×3 do magSoftIron a naměřenou velikost pole do magFieldNorm.

Do proměnné declinationAngle zadejte magnetickou deklinaci svého místa — v České republice je to zhruba +5° východně. Bez ní bude kurz ukazovat na magnetický, ne na zeměpisný sever.

7Řešení problémů

  • „AK09918C not found!“: zkontrolujte VIN a GND, ověřte, že napětí na VIN odpovídá logice vaší desky, a zkontrolujte I²C adresu 0x0C.
  • Nestabilní data: kalibrace je nutná. Opakujte ji, dokud Gaps neklesnou pod 2 %, a hlídejte, aby poblíž nebylo silné magnetické pole.
  • Kurz „ujíždí“ při náklonu: to je normální — samotný magnetometr náklon nekompenzuje. Řeší to fúze s gyroskopem a akcelerometrem.
  • SPI nefunguje: čip AK09918C ani knihovna SPI nepodporují, magnetometr běží výhradně po I²C.

Máte kurz — co dál?

Samotný magnetometr kolísá při náklonu. Spojte ho s gyroskopem a akcelerometrem a získáte stabilní orientaci ve všech osách.