mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-30 19:47:50 +08:00
Added driver for QMC5883L Magnetometer (#2953)
Co-authored-by: Open UAS <noreply@openuas.org>
This commit is contained in:
@@ -200,8 +200,8 @@
|
||||
* PB3 - Digital input (JTAG_TDO/SWD)
|
||||
* PB4 - Open Drain output 50MHz (LED2)
|
||||
* PB5 - Digital input (IMU_MAG_DRDY)
|
||||
* PB6 - Alternate Push Pull output 50MHz (SERVO7-Timer4Ch1)/USART1_TX
|
||||
* PB7 - Alternate Push Pull output 50MHz (SERVO8-Timer4Ch2)/USART1_RX
|
||||
* PB6 - Alternate Open Drain output 2MHz (SERVO7-Timer4Ch1)/USART1_TX
|
||||
* PB7 - Alternate Open Drain output 2MHz (SERVO8-Timer4Ch2)/USART1_RX
|
||||
* PB8 - Digital input. (CAN_RX)
|
||||
* PB9 - Open Drain output 50MHz. (CAN_TX)
|
||||
* PB10 - Alternate Open Drain output 2MHz.(I2C2_SCL)
|
||||
@@ -233,8 +233,8 @@
|
||||
PIN_OTYPE_PUSHPULL(3) | \
|
||||
PIN_OTYPE_OPENDRAIN(4) | \
|
||||
PIN_OTYPE_PUSHPULL(5) | \
|
||||
PIN_OTYPE_PUSHPULL(6) | \
|
||||
PIN_OTYPE_PUSHPULL(7) | \
|
||||
PIN_OTYPE_OPENDRAIN(6) | \
|
||||
PIN_OTYPE_OPENDRAIN(7) | \
|
||||
PIN_OTYPE_PUSHPULL(8) | \
|
||||
PIN_OTYPE_OPENDRAIN(9) | \
|
||||
PIN_OTYPE_OPENDRAIN(10) | \
|
||||
@@ -297,8 +297,8 @@
|
||||
PIN_AFIO_AF(3, 0) | \
|
||||
PIN_AFIO_AF(4, 0) | \
|
||||
PIN_AFIO_AF(5, 0) | \
|
||||
PIN_AFIO_AF(6, 7) | \
|
||||
PIN_AFIO_AF(7, 7))
|
||||
PIN_AFIO_AF(6, 4) | \
|
||||
PIN_AFIO_AF(7, 4))
|
||||
#define VAL_GPIOB_AFRH (PIN_AFIO_AF(8, 9) | \
|
||||
PIN_AFIO_AF(9, 9) | \
|
||||
PIN_AFIO_AF(10, 4) | \
|
||||
|
||||
@@ -217,6 +217,10 @@
|
||||
#define MAG_DATALINK_SENDER_ID 6
|
||||
#endif
|
||||
|
||||
#ifndef MAG_QMC5883L_SENDER_ID
|
||||
#define MAG_QMC5883L_SENDER_ID 7
|
||||
#endif
|
||||
|
||||
#ifndef IMU_MAG_PITOT_ID
|
||||
#define IMU_MAG_PITOT_ID 50
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Paparazzi Team
|
||||
*
|
||||
* This file is part of paparazzi.
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file modules/sensors/mag_qmc5883l.c
|
||||
*
|
||||
* Module for QST QMC5883L magnetometer, the DB version
|
||||
*/
|
||||
|
||||
#include "modules/sensors/mag_qmc5883l.h"
|
||||
#include "mcu_periph/uart.h"
|
||||
#include "pprzlink/messages.h"
|
||||
#include "modules/datalink/downlink.h"
|
||||
#include "generated/airframe.h"
|
||||
#include "modules/core/abi.h"
|
||||
|
||||
#ifndef QMC5883L_CHAN_X
|
||||
#define QMC5883L_CHAN_X 0
|
||||
#endif
|
||||
#ifndef QMC5883L_CHAN_Y
|
||||
#define QMC5883L_CHAN_Y 1
|
||||
#endif
|
||||
#ifndef QMC5883L_CHAN_Z
|
||||
#define QMC5883L_CHAN_Z 2
|
||||
#endif
|
||||
#ifndef QMC5883L_CHAN_X_SIGN
|
||||
#define QMC5883L_CHAN_X_SIGN +
|
||||
#endif
|
||||
#ifndef QMC5883L_CHAN_Y_SIGN
|
||||
#define QMC5883L_CHAN_Y_SIGN +
|
||||
#endif
|
||||
#ifndef QMC5883L_CHAN_Z_SIGN
|
||||
#define QMC5883L_CHAN_Z_SIGN +
|
||||
#endif
|
||||
|
||||
#ifndef QMC5883L_DATA_RATE
|
||||
#define QMC5883L_DATA_RATE QMC5883L_ODR_DEFAULT
|
||||
#endif
|
||||
|
||||
#ifndef QMC5883L_ADDR
|
||||
#define QMC5883L_ADDR QMC5883L_ADDR0
|
||||
#endif
|
||||
|
||||
#if MODULE_QMC5883L_UPDATE_AHRS
|
||||
|
||||
#if defined QMC5883L_MAG_TO_IMU_PHI && defined QMC5883L_MAG_TO_IMU_THETA && defined QMC5883L_MAG_TO_IMU_PSI
|
||||
#define USE_MAG_TO_IMU 1
|
||||
static struct Int32RMat mag_to_imu; ///< rotation from mag to imu frame
|
||||
#else
|
||||
#define USE_MAG_TO_IMU 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct Qmc5883l mag_qmc5883l;
|
||||
|
||||
void mag_qmc5883l_module_init(void)
|
||||
{
|
||||
qmc5883l_init(&mag_qmc5883l, &(MAG_QMC5883L_I2C_DEV), QMC5883L_ADDR, QMC5883L_DATA_RATE);
|
||||
|
||||
#if MODULE_QMC5883L_UPDATE_AHRS && USE_MAG_TO_IMU
|
||||
struct Int32Eulers mag_to_imu_eulers = {
|
||||
ANGLE_BFP_OF_REAL(QMC5883L_MAG_TO_IMU_PHI),
|
||||
ANGLE_BFP_OF_REAL(QMC5883L_MAG_TO_IMU_THETA),
|
||||
ANGLE_BFP_OF_REAL(QMC5883L_MAG_TO_IMU_PSI)
|
||||
};
|
||||
int32_rmat_of_eulers(&mag_to_imu, &mag_to_imu_eulers);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mag_qmc5883l_module_periodic(void)
|
||||
{
|
||||
qmc5883l_periodic(&mag_qmc5883l);
|
||||
}
|
||||
|
||||
void mag_qmc5883l_module_event(void)
|
||||
{
|
||||
qmc5883l_event(&mag_qmc5883l);
|
||||
|
||||
if (mag_qmc5883l.data_available) {
|
||||
#if MODULE_QMC5883L_UPDATE_AHRS
|
||||
// current timestamp
|
||||
uint32_t now_ts = get_sys_time_usec();
|
||||
|
||||
// set channel order
|
||||
struct Int32Vect3 mag = {
|
||||
QMC5883L_CHAN_X_SIGN(int32_t)(mag_qmc5883l.data.value[QMC5883L_CHAN_X]),
|
||||
QMC5883L_CHAN_Y_SIGN(int32_t)(mag_qmc5883l.data.value[QMC5883L_CHAN_Y]),
|
||||
QMC5883L_CHAN_Z_SIGN(int32_t)(mag_qmc5883l.data.value[QMC5883L_CHAN_Z])
|
||||
};
|
||||
// only rotate if needed
|
||||
#if USE_MAG_TO_IMU
|
||||
struct Int32Vect3 imu_mag;
|
||||
// rotate data from mag frame to imu frame
|
||||
int32_rmat_vmult(&imu_mag, &mag_to_imu, &mag);
|
||||
// unscaled vector
|
||||
VECT3_COPY(mag, imu_mag);
|
||||
#endif
|
||||
|
||||
AbiSendMsgIMU_MAG_RAW(MAG_QMC5883L_SENDER_ID, now_ts, &mag);
|
||||
#endif
|
||||
#if MODULE_QMC5883L_SYNC_SEND
|
||||
mag_qmc5883l_report();
|
||||
#endif
|
||||
#if MODULE_QMC5883L_UPDATE_AHRS || MODULE_QMC5883L_SYNC_SEND
|
||||
mag_qmc5883l.data_available = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void mag_qmc5883l_report(void)
|
||||
{
|
||||
uint8_t id = MAG_QMC5883L_SENDER_ID;
|
||||
struct Int32Vect3 mag = {
|
||||
QMC5883L_CHAN_X_SIGN(int32_t)(mag_qmc5883l.data.value[QMC5883L_CHAN_X]),
|
||||
QMC5883L_CHAN_Y_SIGN(int32_t)(mag_qmc5883l.data.value[QMC5883L_CHAN_Y]),
|
||||
QMC5883L_CHAN_Z_SIGN(int32_t)(mag_qmc5883l.data.value[QMC5883L_CHAN_Z])
|
||||
};
|
||||
DOWNLINK_SEND_IMU_MAG_RAW(DefaultChannel, DefaultDevice, &id, &mag.x, &mag.y, &mag.z);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Paparazzi Team
|
||||
*
|
||||
* This file is part of paparazzi.
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file modules/sensors/mag_qmc5883l.h
|
||||
*
|
||||
* Module wrapper for QNI QMC5883L magnetometer.
|
||||
*/
|
||||
|
||||
#ifndef MAG_QMC5883L_H
|
||||
#define MAG_QMC5883L_H
|
||||
|
||||
#include "peripherals/qmc5883l.h"
|
||||
|
||||
extern struct Qmc5883l mag_qmc5883l;
|
||||
|
||||
extern void mag_qmc5883l_module_init(void);
|
||||
extern void mag_qmc5883l_module_periodic(void);
|
||||
extern void mag_qmc5883l_module_event(void);
|
||||
extern void mag_qmc5883l_report(void);
|
||||
|
||||
#endif /* MAG_QMC5883L_H */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Paparazzi Team
|
||||
*
|
||||
* This file is part of paparazzi.
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file peripherals/qmc5883l.c
|
||||
*
|
||||
* QST QMC5883L 3-axis magnetometer driver interface (I2C).
|
||||
*/
|
||||
|
||||
#include "peripherals/qmc5883l.h"
|
||||
|
||||
/* Registers Axis X,Y,Z */
|
||||
#define QMC5883L_REG_DATXL 0x00
|
||||
#define QMC5883L_REG_DATXM 0x01
|
||||
#define QMC5883L_REG_DATYL 0x02
|
||||
#define QMC5883L_REG_DATYM 0x03
|
||||
#define QMC5883L_REG_DATZL 0x04
|
||||
#define QMC5883L_REG_DATZM 0x05
|
||||
|
||||
/* Register I2C bus transaction Status */
|
||||
#define QMC5883L_REG_STATUS 0x06
|
||||
|
||||
/* Registers Temperature, relative thus not so useful ATM, therefore not implemented in reading */
|
||||
#define QMC5883L_REG_TEMPM 0x07
|
||||
#define QMC5883L_REG_TEMPL 0x08
|
||||
|
||||
/* Registers Config */
|
||||
#define QMC5883L_REG_CONTROL_1 0x09 /* settings for MODE */
|
||||
#define QMC5883L_REG_CONTROL_2 0x0A /* settings for INT_ENB */
|
||||
#define QMC5883L_REG_RESET_PERIOD 0x0B
|
||||
|
||||
#define QMC5883L_REG_IDC 0x0C /* OEM reserved */
|
||||
#define QMC5883L_REG_IDD 0x0D /* OEM reserved */
|
||||
|
||||
/* Options for CONTROL_1 */
|
||||
#define QMC5883L_MODE_STBY 0x00
|
||||
#define QMC5883L_MODE_CONT 0x01
|
||||
|
||||
/* Options for scale RaNGe(RNG) Gauss */
|
||||
#define QMC5883L_RNG_2G 0x00
|
||||
#define QMC5883L_RNG_8G 0x10
|
||||
|
||||
/* options for Over-Sample Ratio (OSR) */
|
||||
#define QMC5883L_OSR_512 0x00 /* Use 512 if powerusage of chip is not an issue */
|
||||
#define QMC5883L_OSR_256 0x40
|
||||
#define QMC5883L_OSR_128 0x80
|
||||
#define QMC5883L_OSR_64 0xC0
|
||||
|
||||
void qmc5883l_init(struct Qmc5883l *mag, struct i2c_periph *i2c_p, uint8_t addr, uint8_t data_rate)
|
||||
{
|
||||
/* set i2c_peripheral */
|
||||
mag->i2c_p = i2c_p;
|
||||
/* set i2c address */
|
||||
mag->i2c_trans.slave_addr = addr;
|
||||
mag->i2c_trans.status = I2CTransDone;
|
||||
/* store data rate */
|
||||
mag->data_rate = data_rate;
|
||||
mag->initialized = false;
|
||||
mag->status = QMC5883L_CONF_UNINIT;
|
||||
mag->data_available = false;
|
||||
}
|
||||
|
||||
void qmc5883l_configure(struct Qmc5883l *mag)
|
||||
{
|
||||
// Only configure when not busy
|
||||
if (mag->i2c_trans.status != I2CTransSuccess && mag->i2c_trans.status != I2CTransFailed
|
||||
&& mag->i2c_trans.status != I2CTransDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only when successful continue with next
|
||||
if (mag->i2c_trans.status == I2CTransSuccess) {
|
||||
mag->status++; //Here the Enum Counter goes to the next one
|
||||
}
|
||||
|
||||
mag->i2c_trans.status = I2CTransDone;
|
||||
switch (mag->status) {
|
||||
|
||||
case QMC5883L_CONF_UNINIT:
|
||||
/* prepare config request */
|
||||
mag->i2c_trans.buf[0] = QMC5883L_REG_RESET_PERIOD;
|
||||
mag->i2c_trans.buf[0] = 0x01;
|
||||
/* send config request, ask for i2c frame for set/reset period */
|
||||
i2c_transmit(mag->i2c_p, &(mag->i2c_trans), mag->i2c_trans.slave_addr, 2);
|
||||
break;
|
||||
|
||||
case QMC5883L_CONF_CCR_DONE:
|
||||
mag->i2c_trans.buf[0] = QMC5883L_REG_CONTROL_1;
|
||||
mag->i2c_trans.buf[1] = (QMC5883L_MODE_CONT|QMC5883L_ODR_200|QMC5883L_RNG_8G|QMC5883L_OSR_512);//todo datarate from settings mag->data_rate;
|
||||
i2c_transmit(mag->i2c_p, &(mag->i2c_trans), mag->i2c_trans.slave_addr, 2);
|
||||
break;
|
||||
|
||||
case QMC5883L_CONF_TMRC_DONE:
|
||||
mag->i2c_trans.buf[0] = QMC5883L_REG_CONTROL_1;
|
||||
mag->i2c_trans.buf[1] = (QMC5883L_MODE_CONT|QMC5883L_ODR_200|QMC5883L_RNG_8G|QMC5883L_OSR_512);//todo datarate from settings //mag->data_rate;
|
||||
i2c_transmit(mag->i2c_p, &(mag->i2c_trans), mag->i2c_trans.slave_addr, 2);
|
||||
break;
|
||||
|
||||
case QMC5883L_CONF_CCM_DONE:
|
||||
mag->status = QMC5883L_STATUS_IDLE;
|
||||
mag->initialized = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void qmc5883l_read(struct Qmc5883l *mag)
|
||||
{
|
||||
if (mag->status != QMC5883L_STATUS_IDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* get 3 x 2 bytes data = 6 Bytes and one status byte = 7 */
|
||||
mag->i2c_trans.buf[0] = QMC5883L_REG_DATXL;
|
||||
mag->i2c_trans.buf[1] = QMC5883L_REG_DATXM;
|
||||
mag->i2c_trans.buf[2] = QMC5883L_REG_DATYL;
|
||||
mag->i2c_trans.buf[3] = QMC5883L_REG_DATYM;
|
||||
mag->i2c_trans.buf[4] = QMC5883L_REG_DATZL;
|
||||
mag->i2c_trans.buf[5] = QMC5883L_REG_DATZM;
|
||||
|
||||
/* Chip transaction status, not used ATM in case of driver mishap once can considder using it */
|
||||
mag->i2c_trans.buf[6] = QMC5883L_REG_STATUS;
|
||||
// Add some code if you experience reading issue
|
||||
// DRDY = ((mag->i2c_trans.buf[6]) >> 0) & 1;
|
||||
// OVL = ((mag->i2c_trans.buf[6]) >> 1) & 1;
|
||||
// DOR = ((uint8_t)(mag->i2c_trans.buf[6]) >> 2) & 1;
|
||||
|
||||
i2c_transceive(mag->i2c_p, &(mag->i2c_trans), mag->i2c_trans.slave_addr, 1, 7);
|
||||
mag->status = QMC5883L_STATUS_MEAS;
|
||||
}
|
||||
/* Convert and align raw values */
|
||||
#define Int16FromBuf(_buf,_idx) ((int16_t)(_buf[_idx] | (_buf[_idx+1] << 8)))
|
||||
|
||||
|
||||
void qmc5883l_event(struct Qmc5883l *mag)
|
||||
{
|
||||
if (!mag->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mag->status) {
|
||||
|
||||
case QMC5883L_STATUS_MEAS:
|
||||
if (mag->i2c_trans.status == I2CTransSuccess) {
|
||||
mag->data.vect.x = Int16FromBuf(mag->i2c_trans.buf, 0);
|
||||
mag->data.vect.y = Int16FromBuf(mag->i2c_trans.buf, 2);
|
||||
mag->data.vect.z = Int16FromBuf(mag->i2c_trans.buf, 4);
|
||||
|
||||
/* only set available if measurements valid: -4096 if ADC under/overflow in sensor
|
||||
The sensor sends out 12 bit wrapped in 16 bit, that sometimes gets corrupded */
|
||||
if (mag->data.vect.x >= 4096 || mag->data.vect.y >= 4096 || mag->data.vect.z >= 4096) {
|
||||
//mag->data.adc_overflow_cnt++;
|
||||
mag->data_available = false;
|
||||
}
|
||||
else {
|
||||
mag->data_available = true;
|
||||
}
|
||||
/* End of measure reading, go back to idle */
|
||||
mag->status = QMC5883L_STATUS_IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (mag->i2c_trans.status == I2CTransSuccess || mag->i2c_trans.status == I2CTransFailed) {
|
||||
/* Per default set to idle */
|
||||
mag->i2c_trans.status = I2CTransDone;
|
||||
mag->status = QMC5883L_STATUS_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Paparazzi Team
|
||||
*
|
||||
* This file is part of paparazzi.
|
||||
*
|
||||
* paparazzi is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* paparazzi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with paparazzi; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file peripherals/qmc5883l.h
|
||||
*
|
||||
* QST QMC5883L 3-axis magnetometer driver interface (I2C).
|
||||
*/
|
||||
|
||||
#ifndef QMC5883L_H
|
||||
#define QMC5883L_H
|
||||
|
||||
#include "std.h"
|
||||
#include "mcu_periph/i2c.h"
|
||||
#include "math/pprz_algebra_int.h"
|
||||
|
||||
/**
|
||||
* The default I2C 7bit address is 0D: 0001101. no option to change the address by e.g. bridging pins of the chip
|
||||
* From the official datasheet "If other I2C address options are required, one must contact the chip factory"
|
||||
* Just in cse one comes across an custom chip one can extend the ADDR option here
|
||||
*/
|
||||
#define QMC5883L_ADDR0 (0b00001101 << 1) //from 0x0D to 0x1A since 7bits and 1 for R/W setting
|
||||
|
||||
/* Continuous mode Output Data Rate (ODR) options in Hz */
|
||||
#define QMC5883L_ODR_10 0x00
|
||||
#define QMC5883L_ODR_50 0x04
|
||||
#define QMC5883L_ODR_100 0x08
|
||||
#define QMC5883L_ODR_200 0x0C
|
||||
|
||||
/* Default data rate */
|
||||
#define QMC5883L_ODR_DEFAULT QMC5883L_ODR_200 //We are never interested in powersavings 200 is best
|
||||
|
||||
/* Status states */
|
||||
enum Qmc5883lStatus {
|
||||
QMC5883L_CONF_UNINIT, // Perform Initialization
|
||||
QMC5883L_CONF_CCR_DONE, // Is done set CCR = Configure Continuous Rate done
|
||||
QMC5883L_CONF_TMRC_DONE, // Is done set Datarate
|
||||
QMC5883L_CONF_CCM_DONE, // Is done set Mode continuous or single CCM = Configure Continuous Measurement
|
||||
QMC5883L_STATUS_IDLE, // Ready for data requests
|
||||
QMC5883L_STATUS_MEAS // Get data
|
||||
};
|
||||
|
||||
struct Qmc5883l {
|
||||
struct i2c_periph *i2c_p; ///< peripheral used for communcation
|
||||
struct i2c_transaction i2c_trans; ///< i2c transaction
|
||||
uint8_t data_rate; ///< sensor data rate
|
||||
bool initialized; ///< config done flag
|
||||
enum Qmc5883lStatus status; ///< init status
|
||||
volatile bool data_available; ///< data ready flag
|
||||
union {
|
||||
struct Int32Vect3 vect; ///< data vector in mag coordinate system
|
||||
int32_t value[3]; ///< data values accessible by channel index
|
||||
} data;
|
||||
};
|
||||
|
||||
extern void qmc5883l_init(struct Qmc5883l *mag, struct i2c_periph *i2c_p, uint8_t addr, uint8_t data_rate);
|
||||
extern void qmc5883l_configure(struct Qmc5883l *mag);
|
||||
extern void qmc5883l_event(struct Qmc5883l *mag);
|
||||
extern void qmc5883l_read(struct Qmc5883l *mag);
|
||||
|
||||
/// convenience function: read or start configuration if not already initialized
|
||||
static inline void qmc5883l_periodic(struct Qmc5883l *mag)
|
||||
{
|
||||
if (mag->initialized) {
|
||||
qmc5883l_read(mag);
|
||||
} else {
|
||||
qmc5883l_configure(mag);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* QMC5883L_H */
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user