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
}
}

0 comments: