Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_Compass/AP_Compass_QMC5883P.cpp
Views: 1798
/*1* This file is free software: you can redistribute it and/or modify it2* under the terms of the GNU General Public License as published by the3* Free Software Foundation, either version 3 of the License, or4* (at your option) any later version.5*6* This file is distributed in the hope that it will be useful, but7* WITHOUT ANY WARRANTY; without even the implied warranty of8* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.9* See the GNU General Public License for more details.10*11* You should have received a copy of the GNU General Public License along12* with this program. If not, see <http://www.gnu.org/licenses/>.13*14* Driver by Lokesh Ramina, Jan 202215*/16#include "AP_Compass_QMC5883P.h"1718#include <stdio.h>1920#include <AP_HAL/AP_HAL.h>21#include <AP_Math/AP_Math.h>2223#if AP_COMPASS_QMC5883P_ENABLED2425//Register Address26#define QMC5883P_REG_ID 0x0027#define QMC5883P_REG_DATA_OUTPUT_X 0x0128#define QMC5883P_REG_DATA_OUTPUT_Z_MSB 0x0629#define QMC5883P_REG_STATUS 0x0930#define QMC5883P_REG_CONF1 0x0A31#define QMC5883P_REG_CONF2 0x0B3233#define QMC5883P_ID_VAL 0x803435//Register values36// Sensor operation modes37#define QMC5883P_MODE_SUSPEND 0x0038#define QMC5883P_MODE_NORMAL 0x0139#define QMC5883P_MODE_SINGLE 0x0240#define QMC5883P_MODE_CONTINUOUS 0x034142// ODR data output rates for 5883L43#define QMC5883P_ODR_10HZ (0x00 << 2)44#define QMC5883P_ODR_50HZ (0x01 << 2)45#define QMC5883P_ODR_100HZ (0x02 << 2)46#define QMC5883P_ODR_200HZ (0x03 << 2)4748// Over sampling Ratio OSR149#define QMC5883P_OSR1_8 (0x00 << 4)50#define QMC5883P_OSR1_4 (0x01 << 4)51#define QMC5883P_OSR1_2 (0x02 << 4)52#define QMC5883P_OSR1_1 (0x03 << 4)5354// Down sampling Rate OSR255#define QMC5883P_OSR2_8 0x085657//RNG58#define QMC5883P_RNG_30G (0x00 << 2)59#define QMC5883P_RNG_12G (0x01 << 2)60#define QMC5883P_RNG_8G (0x10 << 2)61#define QMC5883P_RNG_2G (0x11 << 2)6263#define QMC5883P_SET_XYZ_SIGN 0x296465//Reset66#define QMC5883P_RST 0x806768//Status Val69#define QMC5883P_STATUS_DATA_READY 0x017071#ifndef DEBUG72#define DEBUG 073#endif7475extern const AP_HAL::HAL &hal;7677AP_Compass_Backend *AP_Compass_QMC5883P::probe(AP_HAL::OwnPtr<AP_HAL::I2CDevice> dev,78bool force_external,79enum Rotation rotation)80{81if (!dev) {82return nullptr;83}84AP_Compass_QMC5883P *sensor = NEW_NOTHROW AP_Compass_QMC5883P(std::move(dev),force_external,rotation);85if (!sensor || !sensor->init()) {86delete sensor;87return nullptr;88}89return sensor;90}9192AP_Compass_QMC5883P::AP_Compass_QMC5883P(AP_HAL::OwnPtr<AP_HAL::Device> dev,93bool force_external,94enum Rotation rotation)95: _dev(std::move(dev))96, _rotation(rotation)97, _force_external(force_external)98{99}100101bool AP_Compass_QMC5883P::init()102{103_dev->get_semaphore()->take_blocking();104105_dev->set_retries(10);106#if DEBUG107_dump_registers();108#endif109if (!_check_whoami()) {110goto fail;111}112//As mentioned in the Datasheet 7.2 to do continues mode 0x29 will set sign for X,Y,Z113if (!_dev->write_register(QMC5883P_REG_DATA_OUTPUT_Z_MSB, QMC5883P_SET_XYZ_SIGN)||114!_dev->write_register(QMC5883P_REG_CONF1,115QMC5883P_MODE_CONTINUOUS|116QMC5883P_ODR_100HZ|117QMC5883P_OSR1_8|118QMC5883P_OSR2_8)||119!_dev->write_register(QMC5883P_REG_CONF2,QMC5883P_OSR2_8)) {120goto fail;121}122123// lower retries for run124_dev->set_retries(3);125126_dev->get_semaphore()->give();127128//register compass instance129_dev->set_device_type(DEVTYPE_QMC5883P);130if (!register_compass(_dev->get_bus_id(), _instance)) {131return false;132}133set_dev_id(_instance, _dev->get_bus_id());134135printf("%s found on bus %u id %u address 0x%02x\n", name,136_dev->bus_num(), unsigned(_dev->get_bus_id()), _dev->get_bus_address());137138set_rotation(_instance, _rotation);139140if (_force_external) {141set_external(_instance, true);142}143144//Enable 100HZ145_dev->register_periodic_callback(10000,146FUNCTOR_BIND_MEMBER(&AP_Compass_QMC5883P::timer, void));147148return true;149150fail:151_dev->get_semaphore()->give();152return false;153}154bool AP_Compass_QMC5883P::_check_whoami()155{156uint8_t whoami;157if (!_dev->read_registers(QMC5883P_REG_ID, &whoami,1)||158whoami != QMC5883P_ID_VAL) {159return false;160}161return true;162}163164void AP_Compass_QMC5883P::timer()165{166struct PACKED {167int16_t rx;168int16_t ry;169int16_t rz;170} buffer;171172const float range_scale = 1000.0f / 3000.0f;173174uint8_t status;175if (!_dev->read_registers(QMC5883P_REG_STATUS,&status,1)) {176return;177}178//new data is ready179if (!(status & QMC5883P_STATUS_DATA_READY)) {180return;181}182183if (!_dev->read_registers(QMC5883P_REG_DATA_OUTPUT_X, (uint8_t *) &buffer, sizeof(buffer))) {184return ;185}186187auto x = buffer.rx;188auto y = buffer.ry;189auto z = buffer.rz;190191#if DEBUG192printf("mag.x:%d\n",x);193printf("mag.y:%d\n",y);194printf("mag.z:%d\n",z);195#endif196197Vector3f field = Vector3f{x * range_scale, y * range_scale, z * range_scale };198199accumulate_sample(field, _instance, 20);200}201202void AP_Compass_QMC5883P::read()203{204drain_accumulated_samples(_instance);205}206207void AP_Compass_QMC5883P::_dump_registers()208{209printf("QMC5883P registers dump\n");210for (uint8_t reg = QMC5883P_REG_DATA_OUTPUT_X; reg <= 0x30; reg++) {211uint8_t v;212_dev->read_registers(reg,&v,1);213printf("%02x:%02x ", (unsigned)reg, (unsigned)v);214if ((reg - ( QMC5883P_REG_DATA_OUTPUT_X-1)) % 16 == 0) {215printf("\n");216}217}218}219220#endif //AP_COMPASS_QMC5883P_ENABLED221222223