> ## Documentation Index
> Fetch the complete documentation index at: https://learn.pcbcupid.com/llms.txt
> Use this file to discover all available pages before exploring further.

> QMC6309 3-Axis Electronic Compass with I²C interface, high stability, and built-in self-test. Perfect for drones, robotics, and navigation.

# QMC6309 Magnetometer

export const ShopHeader = ({title, url}) => <div style={{
  display: 'flex',
  justifyContent: 'flex-end',
  alignItems: 'center',
  width: '100%',
  marginBottom: '1rem',
  gap: '20px'
}}>
    <a href={url} target="_blank" rel="noopener noreferrer" style={{
  display: 'inline-flex',
  alignItems: 'center',
  backgroundColor: '#00b894',
  color: '#fff',
  padding: '8px 18px',
  borderRadius: '8px',
  textDecoration: 'none',
  fontSize: '0.95rem',
  fontWeight: 600,
  whiteSpace: 'nowrap',
  flexShrink: 0
}}>
      Shop now
    </a>
  </div>;

export const ImgGallery = ({images, modelUrl}) => {
  var [active, setActive] = useState(0);
  var [show3D, setShow3D] = useState(false);
  useEffect(function () {
    if (show3D || images.length <= 1) return;
    var t = setTimeout(function () {
      setActive(function (p) {
        return (p + 1) % images.length;
      });
    }, 3500);
    return function () {
      clearTimeout(t);
    };
  });
  var img = images[active];
  return <div style={{
    position: 'relative',
    background: 'linear-gradient(to bottom, #fff 0%, #fff 80%, #f8f8f8 100%)',
    borderRadius: '32px',
    border: '1px solid rgba(0,0,0,0.08)',
    overflow: 'hidden',
    marginTop: '0.75rem',
    marginBottom: '1.5rem'
  }}>
      <div style={{
    position: 'relative',
    height: '450px',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    background: '#fff',
    padding: '1rem'
  }}>
        {show3D && modelUrl ? <div ref={function (el) {
    if (!el || el._mv) return;
    el._mv = true;
    var s = document.createElement('script');
    s.src = "https://ajax.googleapis.com/ajax/libs/model-viewer/4.2.0/model-viewer.min.js";
    s.type = "module";
    s.onload = function () {
      var mv = document.createElement('model-viewer');
      mv.setAttribute('src', modelUrl);
      mv.setAttribute('camera-controls', '');
      mv.setAttribute('auto-rotate', '');
      mv.style.width = "100%";
      mv.style.height = "100%";
      mv.style.backgroundColor = "#f8f8f8";
      el.innerHTML = "";
      el.appendChild(mv);
    };
    document.head.appendChild(s);
  }} style={{
    width: "100%",
    height: "100%"
  }} /> : <img src={img && img.url} alt={img && img.label} loading="lazy" style={{
    maxWidth: '100%',
    maxHeight: '100%',
    objectFit: 'contain',
    borderRadius: '8px'
  }} />}
      </div>
      <div style={{
    display: 'flex',
    justifyContent: 'center',
    gap: '12px',
    padding: '1rem',
    background: '#eee',
    borderTop: '1px solid rgba(0,0,0,0.08)'
  }}>
        {images.map(function (img, idx) {
    return <button key={img.id || idx} onClick={function () {
      setActive(idx);
      setShow3D(false);
    }} style={{
      padding: '0.6rem 1.5rem',
      borderRadius: '12px',
      border: !show3D && idx === active ? '1px solid #00b894' : '1px solid rgba(0,184,148,0.4)',
      background: !show3D && idx === active ? '#00b894' : '#fff',
      color: !show3D && idx === active ? '#fff' : '#000',
      cursor: 'pointer',
      fontSize: '0.75rem',
      fontWeight: 700,
      textTransform: 'uppercase',
      fontFamily: 'inherit'
    }}>
              {img.label}
            </button>;
  })}
        {modelUrl ? <button onClick={function () {
    setShow3D(true);
  }} style={{
    padding: '0.6rem 1.5rem',
    borderRadius: '12px',
    border: show3D ? '1px solid #00b894' : '1px solid rgba(0,184,148,0.4)',
    background: show3D ? '#00b894' : '#fff',
    color: show3D ? '#fff' : '#000',
    cursor: 'pointer',
    fontSize: '0.75rem',
    fontWeight: 700,
    textTransform: 'uppercase',
    fontFamily: 'inherit'
  }}>
            3D VIEW
          </button> : null}
      </div>
    </div>;
};

<ShopHeader title="QMC6309 Magnetometer" url="https://shop.pcbcupid.com/product/gs005/" />

<ImgGallery modelUrl="https://raw.githubusercontent.com/pcbcupid/pcbcupid-hardware-libraries/main/pcbcupid_3dmodels/glb/MAGNETOMETER.glb" images={[{url: "https://files.pcbcupid.com/Documentation/Boards/g-sense/qmc6309/magnetometer.avif", label: "ILLUSTRATION VIEW", id: "illustration"}, {url: "https://files.pcbcupid.com/Documentation/Boards/g-sense/qmc6309/pcbcupid-qmc6309-sideview-1-1000x1000.avif", label: "BOARD VIEW", id: "board"}]} />

The **QMC6309**, produced by QST Corporation, is a compact and energy-efficient digital magnetometer designed to detect magnetic fields across three axes (X, Y, Z). It integrates both magnetic sensing elements and signal-conditioning circuitry into a single silicon chip.

The QMC6309 stands out as a diminutive, energy-efficient, and accurate 3-axis magnetometer solution, ideal for compact and embedded electronics like VR trackers and flight controllers. With its seamless integration of sensing and signal conditioning, it provides high-precision magnetic field data with minimal PCB footprint.

## Pin Configuration

* **VCC** : Power supply
* **GND** : Ground connection
* **SDA** : SDA of GLYPH board
* **SCL** : SCL of GLYPH board

## Key Features

* 3-axis magnetic field sensing (X, Y, Z)
* I²C digital interface for easy MCU integration
* 16-bit ADC resolution for high-precision measurements
* Wide supply voltage range: 2.5 V – 3.6 V
* Low operating current: \~2 mA (ideal for battery-powered devices)
* Designed for consumer electronics like VR trackers, wearables, and flight controllers

## Applications

* VR / AR Trackers – orientation tracking and drift correction
* Robotics & Drones – navigation, stabilization, and position control
* Consumer Electronics – smartwatches, handheld devices, portable gadgets
* Flight Controllers – magnetic heading reference in UAVs and quadcopters
* Research & Education – low-cost magnetometer for embedded learning projects

## QMC6309 Simple Example

### Step 1: Hardware Required

1. Glyph Boards
2. QMC6309

### Step 2: Circuit Diagram

![QMC6309](https://files.pcbcupid.com/Documentation/Boards/g-sense/qmc6309/pcbcupid_qmc1.avif)

### Step 3: Code Setup

1. Open Arduino IDE.
2. Make sure to install the library
3. Copy and paste the following code into the Arduino IDE:

### Step 4: Upload the Code

```cpp theme={null}
//You can download the PCBCUPID_QMC6309 library from here : https://github.com/pcbcupid/PCBCUPID-QMC6309
#include <Wire.h>
#include "PCBCUPID_QMC6309.h"
#include "ExponentialFilter.h"

PCBCUPID_QMC6309 mag(Wire);

// Calibrated offsets
const float x_offset = 3485.0;
const float y_offset = 1290.0;
const float declination = 0.22;

// Filter object: 0.2 weight (20%)
ExponentialFilter headingFilter(0.2, 0.0);

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

  if (!mag.begin()) {
    Serial.println("Magnetometer init failed");
    while (1);
  }

  Serial.println("Heading with Exponential Filter");
}

void loop() {
  int16_t x, y, z;
  if (mag.readRaw(x, y, z)) {
    float x_cal = x - x_offset;
    float y_cal = y - y_offset;

    float heading = atan2(-x_cal, y_cal) + declination;
    if (heading < 0) heading += 2 * PI;
    if (heading > 2 * PI) heading -= 2 * PI;

    float headingDeg = heading * 180.0 / PI;

    // Apply exponential filter
    headingFilter.update(headingDeg);
    float smoothedHeading = headingFilter.get();

    Serial.print("Heading: ");
    Serial.print(smoothedHeading, 1);
    Serial.print("° (");
    Serial.print(mag.headingToDirection(smoothedHeading));
    Serial.println(")");
  }

  delay(200);
}
```

1. **Connect the Board**

* Connect your GLYPH board to your computer

2. **Select the Board and Port**

Do the following settings in your Arduino IDE,

* `Tools > Board > esp32 > Pcbcupid GLYPH C3`

<Warning>
  For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
</Warning>

* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***

<Warning>
  If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
</Warning>

3. **Upload the Code**

   * Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.

### Step 5: Observe the Output

The output shows the smoothed compass heading in degrees (0–360°) along with its cardinal direction (e.g., N, NE, E, SE, etc.).
Might not have accurate reading as this was not the intended purpose, This module is very useful to find strong magnetic field in 3 dimensional space.

![QMC6309 result](https://files.pcbcupid.com/Documentation/Boards/g-sense/qmc6309/pcbcupid_qmc_without_oled.avif)

## QMC6309 with oled

### Step 1: Hardware Required

1. Glyph Boards
2. QMC6309
3. OLED Display

### Step 2: Circuit Diagram

![QMC6309 With OLED](https://files.pcbcupid.com/Documentation/Boards/g-sense/qmc6309/qmc%20oled%20circuit%20diagram%20step%202/PCBCUPID-QMC-OLED.jpg)

### Step 3: Code Setup

1. Open Arduino IDE.
2. Make sure to install the "Audio Tool" library
3. Copy and paste the following code into the Arduino IDE:

### Step 4: Upload the Code

```cpp theme={null}
#include <Wire.h>
#include "PCBCUPID_QMC6309.h"
#include <U8g2lib.h>

// === OLED & Magnetometer ===
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
PCBCUPID_QMC6309 mag(Wire);

// === Graph Box Settings ===
const int graphX = 70;
const int graphY = 8;
const int graphWidth = 54;
const int graphHeight = 48;
const int baselineY = graphY + graphHeight / 2;
const int barHeightMax = graphHeight / 2;
const int barWidth = 5;
const int barSpacing = 18;
const int barStartX = graphX + 9;
const int barRange = 500;

// === Baseline Calibration ===
long avgX = 0, avgY = 0, avgZ = 0;
int samples = 0;

void setup() {
  Serial.begin(115200);
  Wire.begin();

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

  u8g2.begin();
}

void loop() {
  int16_t x, y, z;

  if (mag.readRaw(x, y, z)) {
    samples++;
    avgX = ((avgX * (samples - 1)) + x) / samples;
    avgY = ((avgY * (samples - 1)) + y) / samples;
    avgZ = ((avgZ * (samples - 1)) + z) / samples;

    u8g2.clearBuffer();

    // === Serial Debug ===
    Serial.print("X: "); Serial.print(x);
    Serial.print("  Y: "); Serial.print(y);
    Serial.print("  Z: "); Serial.println(z);

    // === Left Side Text ===
    u8g2.setFont(u8g2_font_5x8_tr);
    u8g2.setCursor(4, 10);  u8g2.print("X: "); u8g2.print(x);
    u8g2.setCursor(4, 20);  u8g2.print("Y: "); u8g2.print(y);
    u8g2.setCursor(4, 30);  u8g2.print("Z: "); u8g2.print(z);

    // === G-SENSE Label Box (Left) ===
    u8g2.setDrawColor(1);
    u8g2.drawBox(2, 38, 52, 12);   // G-SENSE Box
    u8g2.setDrawColor(0);
    u8g2.setCursor(8, 47); u8g2.print("G-SENSE");
    u8g2.setDrawColor(1);

    // === QMC6309 Label aligned to right end of box ===
    u8g2.setFont(u8g2_font_4x6_tr);
    u8g2.setCursor(54 - u8g2.getStrWidth("QMC6309"), 59);
    u8g2.print("QMC6309");

    // === Graph Box ===
    u8g2.drawFrame(graphX, graphY, graphWidth, graphHeight);
    u8g2.drawHLine(graphX, baselineY, graphWidth);  // Midline only

    // === Draw Bars (without vertical axis lines) ===
    drawBar(barStartX + barSpacing * 0, x - avgX, "X");
    drawBar(barStartX + barSpacing * 1, y - avgY, "Y");
    drawBar(barStartX + barSpacing * 2, z - avgZ, "Z");

    u8g2.sendBuffer();
  }

  delay(150);
}

void drawBar(int xCenter, int16_t delta, const char* label) {
  int percent = map(delta, -barRange, barRange, -100, 100);
  percent = constrain(percent, -100, 100);

  int barHeight = map(abs(percent), 0, 100, 0, barHeightMax);
  int yStart = (percent >= 0) ? (baselineY - barHeight) : baselineY;

  // Clip to graph box
  if (yStart < graphY) {
    barHeight -= (graphY - yStart);
    yStart = graphY;
  }
  if (yStart + barHeight > graphY + graphHeight) {
    barHeight = (graphY + graphHeight) - yStart;
  }

  // Draw the bar
  u8g2.drawBox(xCenter - barWidth / 2, yStart, barWidth, barHeight);

  // % text outside box
  u8g2.setFont(u8g2_font_4x6_tr);
  int percentY = (percent >= 0) ? (graphY - 2) : (graphY + graphHeight + 8);
  u8g2.setCursor(xCenter - 6, percentY);
  u8g2.print(percent); u8g2.print("%");

  // Axis label below bar
  u8g2.setCursor(xCenter - 2, graphY + graphHeight + 16);
  u8g2.print(label);
}

```

1. **Connect the Board**

* Connect your GLYPH board to your computer

2. **Select the Board and Port**

Do the following settings in your Arduino IDE,

* `Tools > Board > esp32 > Pcbcupid GLYPH C3`

<Warning>
  For the `Pcbcupid Glyph C3 ` to appear under `Tools > Board > esp32`, the esp32 board version installed in the Arduino IDE should be greater or equal to 3.1.0.
</Warning>

* `Tools > Port` and select the port connected to your GLYPH.
* `Tools > USB CDC on Boot >` ***Enabled***

<Warning>
  If `USB CDC on BOOT` not enabled, you won't be seeing any serial data on Arduino IDE.
</Warning>

3. **Upload the Code**

   * Click the upload button (➡️ icon) or use the shortcut `CRTL + U` in Arduino IDE to upload the code to the board.

### Step 5: Observe the Output

outputs real-time X, Y, Z magnetometer readings as both serial text and dynamic bar graphs on an OLED, showing deviation from running average with percentage values.

![QMC6309 With OLED](https://files.pcbcupid.com/Documentation/Boards/g-sense/qmc6309/pcbcupid_qmc_result.avif)

![QMC6309](https://files.pcbcupid.com/Documentation/Boards/g-sense/qmc6309/pcbcupid_qmc_oled_result.avif)
