Showing posts with label magnetometer. Show all posts
Showing posts with label magnetometer. Show all posts

Wednesday, April 19, 2023

Teensy 4.1 with QMC6310 Magnetometer to USB MIDI

Overview

The QMC6310 magnetometer sensor outputs 16 bit for each axis X, Y and Z. The code uses the Wire library to communicate via the I2C protocol. This example prints the raw axis values to the serial monitor and also sends as a USB MIDI control change message (scaled to 0 - 127). The datasheet for this sensor can be found here


Hardware






The following connections should be made between the Teensy 4.1 and the QMC6310:
  • Teensy 4.1 3V to QMC6310 VCC - orange in the above photo
  • Teensy 4.1 ground to QMC6310 GND - blue in the above photo
  • Teensy 4.1 pin 19 / A5 / SCL / PWM to QMC6310 SCL - green in the above photo
  • Teensy 4.1 pin 18 / A4 / SDA / PWM to QMC6310 SDA - yellow in the above photo


Software

const int address = 0x1c; // 0x1c if part number is QMC6310U or 0x3c if part number is QMC6310N
int16_t axis[3]; // array for axis data X, Y, Z - force 2's compliment for a signed 16 bit integer

#include <Wire.h>

void setup() {

// Begin serial port
Serial.begin(57600);
Serial.println("Begin...");

// Begin Wire library
Wire.begin();

// set up magnetometer
// writeMag(0x29, 0x06); // define sign for XYZ
writeMag(0x0b, 0x00 | 0x01 << 2); // define set / reset on
// field range: 2gauss = 0x11 << 2, 8gauss = 0x10 << 2, 12gauss = 0x01 << 2, 30guass = 0x00 << 2
writeMag(0x0a, 0xcd); // set normal range and ODR to 200 Hz
}

void loop() {
if (readMag()) { // if there is new data present, print the values of the three axis as a sixteen bit value
Serial.print("X: ");
Serial.print(axis[0]);
usbMIDI.sendControlChange(1, map(axis[0], -32768, 32767, 0, 127), 1);
Serial.print(" Y: ");
Serial.print(axis[1]);
usbMIDI.sendControlChange(2, map(axis[1], -32768, 32767, 0, 127), 1);
Serial.print(" Z: ");
Serial.println(axis[2]);
usbMIDI.sendControlChange(3, map(axis[2], -32768, 32767, 0, 127), 1);
}
}

// this function writes data to the magnetometer
void writeMag(byte reg, byte val) {
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write(val);
Wire.endTransmission();
}

// this function reads X,Y,Z data from the magnetometer
int readMag() {
// set reg 9 to read from
Wire.beginTransmission(address);
Wire.write(0x09);
Wire.endTransmission();

// read from reg 9 for 1 byte - this is the status byte
byte status; // status byte which stores the
Wire.requestFrom(address, 1);
while (Wire.available()) {
status = Wire.read() & 1;
}

if (status == true) {
// set reg 1 to read from
Wire.beginTransmission(address);
Wire.write(0x01);
Wire.endTransmission();
// read from reg 9 for 6 bytes - these are the data bytes X LSB, X HSB, Y LSB, Y HSB, Z LSB, Z HSB
Wire.requestFrom(address, 0x06);
byte index = 0;

// read data into axis array
while (Wire.available()) {
axis[index] = Wire.read() | Wire.read() << 8;
index++;
}
return true; // true if new data is present
}

else {
return false; // false if no new data is present
}
}