LIS3MDL I2C Mbed class with compass heading function

LIS3MDL.cpp

Committer:
gpmbed
Date:
2021-04-13
Revision:
0:4aa6b3804281
Child:
1:fe199024ddfe

File content as of revision 0:4aa6b3804281:

#include "LIS3MDL.h"


LIS3MDL::LIS3MDL(PinName sda, PinName scl) : i2c(sda, scl) 
{
     _address = LIS3MDL_ADDRESS;//LIS3MDL_DEFAULT_ADDRESS;
}

/* ****
            addr           data        len
i2c.write(LSM6DS0_ADDRESS, data_write, 2);
*/

int LIS3MDL::i2c_write(uint8_t DeviceAddr, uint8_t RegisterAddr,uint8_t value, uint16_t NumByteToWrite)
{
        int ret;
        int TEMP_BUF_SIZE = 5;
        uint8_t tmp[TEMP_BUF_SIZE];

        if(NumByteToWrite >= TEMP_BUF_SIZE) return -2;

        /* First, send device address. Then, send data and STOP condition */
        tmp[0] = RegisterAddr;
        tmp[1] = value;
        //memcpy(tmp+1, pBuffer, NumByteToWrite);

        ret = i2c.write(DeviceAddr, (const char*)tmp, NumByteToWrite+1, false);

        if(ret) return -1;
        return 0;
}

int LIS3MDL::i2c_read(uint8_t DeviceAddr, uint8_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToRead) {
        int ret;

        /* Send device address, with no STOP condition */
        ret = i2c.write(DeviceAddr, (const char*)&RegisterAddr, 1, true);
        if(!ret) {
            /* Read data, with STOP condition  */
            ret = i2c.read(DeviceAddr, (char*)pBuffer, NumByteToRead, false);
        }

        if(ret) return -1;
        return 0;
    }

bool LIS3MDL::init(void) {
 
    
    // Choose device mode (bits 1:0 = 00 = continuous data read, 01 = single conversion, 10 & 11 = default power down)
    //writeByte(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG3, 0x00); // Enable continuous data read mode (bits 1:0 = 00)
    i2c_write(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG3,0x00,1);
    // Enable temperature sensor (bit 7 = 1)
    // Set magnetometer operative mode for x and y axes (bits 6:5)
    // Set magnetometer ODR (bits 4:2)
    //writeByte(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG1, 0x80 | Mopmode << 5 | Modr << 2);
    //i2c_write(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG1, 0x80 | Mopmode << 5 | Modr << 2,1);
    
    //writeByte(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG2, Mscale << 5); // Set magnetometer full scale range
    //i2c_write(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG2, Mscale << 5,1);
    
    //writeByte(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG4, Mopmode << 2); // Set magnetometer operative mode for z axis
    //i2c_write(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG4, Mopmode << 2,1); // Set magnetometer operative mode for z axis
    
    //writeByte(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG5, 0x40); // output registers not updated until both data bytes have been read
    i2c_write(LIS3MDL_ADDRESS, LIS3MDL_CTRL_REG5, 0x40,1); // output registers not updated until both data bytes have been read


    //Put into the correct operating mode 
    //disableLowPower();
    //enableAxisXYZ();
    //setDataRate(2);
    
    return 1;
}

bool LIS3MDL::writeRegister(const uint8_t register_addr, const uint8_t value) {
    //send write call to sensor address
    //send register address to sensor
    //send value to register
    /*
    bool write_status = 0;
    Wire.beginTransmission(_address); //open communication with 
    Wire.write(register_addr);  
    Wire.write(value); 
    Wire.endTransmission(); 
    */
    i2c_write(_address,register_addr,value,1);

    return 1; //returns whether the write succeeded or failed
}

uint8_t LIS3MDL::readRegister(const uint8_t register_addr)
{
    uint8_t reg_val = 0;
    i2c_read(_address, register_addr, &reg_val, 1);
    
    return reg_val;
}

uint16_t LIS3MDL::readRegisters(const uint8_t msb_register, const uint8_t lsb_register) {
    uint8_t msb = readRegister(msb_register);
    uint8_t lsb = readRegister(lsb_register);
    return (((int16_t)msb) << 8) | lsb;
}

bool LIS3MDL::writeMaskedRegister(const uint8_t register_addr, const uint8_t mask, const bool value) {
    uint8_t data = readRegister(register_addr);
    uint8_t combo;
    if(value) {
        combo = (mask | data);
    } else {
        combo = ((~mask) & data);
    }
    return writeRegister(register_addr, combo);
}

bool LIS3MDL::writeMaskedRegister(const int register_addr, const int mask, const int value) {
    uint8_t data = readRegister(register_addr);
    uint8_t masked_value = (data | (mask & value)); //Not sure if right...
    return writeRegister(register_addr, masked_value);
}

uint8_t LIS3MDL::readMaskedRegister(const uint8_t register_addr, const uint8_t mask) {
    uint8_t data = readRegister(register_addr);
    return (data & mask);
}


/** Read the X axis registers
 * @see LIS3MDL_OUT_X_H
 * @see LIS3MDL_OUT_X_L
 */
int16_t LIS3MDL::getAxisX(void) {
    return readRegisters(LIS3MDL_OUT_X_H, LIS3MDL_OUT_X_L);
}

float LIS3MDL::getAxisX_mag()
{
    float res = 0;
    float factor = 6842;
    res = (int16_t)getAxisX();
    res = res / factor;
    
    return res;
}


/** Read the Y axis registers
 * @see LIS3MDL_OUT_Y_H
 * @see LIS3MDL_OUT_Y_L
 */
int16_t LIS3MDL::getAxisY(void) {
    return readRegisters(LIS3MDL_OUT_Y_H, LIS3MDL_OUT_Y_L);
}

float LIS3MDL::getAxisY_mag()
{
    float res = 0;
    float factor = 6842;
    res = (int16_t)getAxisY();
    res = res / factor;
    
    return res;
}

/** Read the Z axis registers
 * @see LIS3MDL_OUT_Z_H
 * @see LIS3MDL_OUT_Z_L
 */
int16_t LIS3MDL::getAxisZ(void) {
    return readRegisters(LIS3MDL_OUT_Z_H, LIS3MDL_OUT_Z_L);
}

int16_t LIS3MDL::getTemperature(void) {
    return readRegisters(LIS3MDL_TEMP_OUT_H,LIS3MDL_TEMP_OUT_L);
}


float LIS3MDL::getHeading()
{
    float xH = getAxisX_mag();
    float yH = getAxisY_mag();
    //float xH = (float)mag_axes[0]; //milliGauss
    //float yH = (float)mag_axes[1]; //milliGauss
    xH *=1000; //milliGauss
    yH *=1000; //milliGauss
    
    xH = xH - 190; //taratura manuale
    yH = yH + 550;
    
    float heading = atan(yH/xH)*LIS3MDL_Rad2Degree;
    
    
    if(xH<0){heading=180-heading;}
    else if(xH>0  && yH<0){heading=-heading;}
    else if(xH>0  && yH>0){heading=360-heading; }
    else if(xH==0 && yH<0){heading=90; }
    else if(xH==0 && yH>0){heading=270; }
    
    heading = (360-heading)+180;
    
    if(heading<0){ heading +=360; }
    else if(heading>360){ heading -=360; }

    
    return heading;
}

void getMag(int16_t* ax, int16_t* ay, int16_t* az) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool whoAmI(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getTempEnabled(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setTempEnabled(bool enable) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

uint8_t getOperativeMode(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setOperativeMode(uint8_t mode) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

uint8_t getDataRate(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setDataRate(uint8_t rate) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getSelfTestEnabled(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setSelfTestEnabled(bool enable) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

uint8_t getFullScale(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setFullScale(uint8_t sccale) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool reboot(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool softReset(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getLowPowerMode(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setLowPowerMode(bool mode) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getSPIMode(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setSPIMode(bool mode) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

uint8_t getOperatingMode(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setOperatingMode(uint8_t mode) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

uint8_t getOMZ(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setOMZ(uint8_t mode) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getEndian(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setEndian(bool selection) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool disableDataUpdate(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool enableDataUpdate(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getDataUpdateStatus(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getXYZOverrun(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getZOverrun(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getYOverrun(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getXOverrun(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getXYZDataAvailable(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getZDataAvailable(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getYDataAvailabl(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool getXDataAvailable(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool enableXInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool disableXInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool isXIntEnabled(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool enableYInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool disableYInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool isYIntEnabled(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool enableZInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool disableZInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool isZIntEnabled(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setIntHigh(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setIntLow(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool checkIntConfig(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool setInteruptLatch(bool latch) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool checkInteruptLatch(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool enableIntInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool disableIntInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool checkIntInterupt(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}


bool posXThreshold(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool posYThreshold(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool posZThreshold(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool negXThreshold(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool negYThreshold(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool negZThreshold(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool measurementOverflow(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

bool checkInteruptEvent(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}


bool setInteruptThreshold(uint16_t threshold) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}

uint16_t getInteruptThreshold(void) {
    //return (readMaskedRegister(LIS3MDL_CTRL_REG2, LIS3MDL_HPIS2_MASK) != 0);
}





/** Read the all axis registers
 * @see getAxisZ()
 * @see getAxisY()
 * @see getAxisZ()
 */
void LIS3MDL::getMotion(int16_t* ax, int16_t* ay, int16_t* az) {
    *ax = getAxisX();
    *ay = getAxisY();
    *az = getAxisZ();
}

//bool LIS3MDL::tempHasOverrun(void) {
//    uint8_t overrun = readMaskedRegister(LIS3MDL_STATUS_REG_AUX, LIS3MDL_TOR_MASK);
//    return (overrun != 0);
//}

//bool LIS3MDL::tempDataAvailable(void) {
//    uint8_t data = readMaskedRegister(LIS3MDL_STATUS_REG_AUX, LIS3MDL_TDA_MASK);
//    return (data != 0);
//}

//uint16_t LIS3MDL::getTemperature(void) {
//    if(tempDataAvailable()){
//        return readRegisters(LIS3MDL_OUT_TEMP_H, LIS3MDL_OUT_TEMP_L);
//    } else {
//        //if new data isn't available
//        return 0;
//    }
//}

bool LIS3MDL::whoAmI(void) {
    return (LIS3MDL_I_AM_MASK == readRegister(LIS3MDL_WHO_AM_I));
}

bool LIS3MDL::getTempEnabled(void) {
    //return (readMaskedRegister(LIS3MDL_TEMP_CFG_REG, LIS3MDL_TEMP_EN_MASK) != 0);
}

bool LIS3MDL::setTempEnabled(bool enable) {
    //return writeRegister(LIS3MDL_TEMP_CFG_REG, enable ? LIS3MDL_TEMP_EN_MASK : 0);
}

uint8_t LIS3MDL::getDataRate(void) {
    //return readMaskedRegister(LIS3MDL_CTRL_REG1, LIS3MDL_ODR_MASK);
}

bool LIS3MDL::setDataRate(uint8_t rate) {
    if(rate > 9) {
        return 0;
    }
    uint8_t data_rate = rate << 4;
   // return writeMaskedRegister(LIS3MDL_CTRL_REG1, LIS3MDL_ODR_MASK, data_rate);
}