Es loht sich compile und lieferet au Wert. Das wärs aber au scho gsi.

IMU.cpp

Committer:
wannesim
Date:
2018-04-09
Revision:
0:1a79273bc3e6

File content as of revision 0:1a79273bc3e6:

/*
 * IMU.cpp
 * Copyright (c) 2018, ZHAW
 * All rights reserved.
 */

#include <cmath>
#include "IMU.h"

using namespace std;

const float IMU::PI = 3.14159265f;                  // the constant PI


/**
 * Creates an IMU object.
 * @param spi a reference to an spi controller to use.
 * @param csG the chip select output for the gyro sensor.
 * @param csXM the chip select output for the accelerometer and the magnetometer.
 */
IMU::IMU(SPI& spi, DigitalOut& csG, DigitalOut& csXM) : spi(spi), csG(csG), csXM(csXM) {
    
    // initialize SPI interface
    
    lowMagX = 1000.0f;
    maxMagX = -1000.0f;
    lowMagY = 1000.0f;
    maxMagY = -1000.0f;
    
    spi.format(8, 3);
    spi.frequency(1000000);
    
    // reset chip select lines to logical high
    
    csG = 1;
    csXM = 1;
    
    // initialize gyro
    
    writeRegister(csG, CTRL_REG1_G, 0x0F);  // enable gyro in all 3 axis
    
    // initialize accelerometer
    
    writeRegister(csXM, CTRL_REG0_XM, 0x00);
    writeRegister(csXM, CTRL_REG1_XM, 0x5F);
    writeRegister(csXM, CTRL_REG2_XM, 0x00);
    writeRegister(csXM, CTRL_REG3_XM, 0x04);
    
    // initialize magnetometer
    
    writeRegister(csXM, CTRL_REG5_XM, 0x94);
    writeRegister(csXM, CTRL_REG6_XM, 0x00);
    writeRegister(csXM, CTRL_REG7_XM, 0x00);
    writeRegister(csXM, CTRL_REG4_XM, 0x04);
    writeRegister(csXM, INT_CTRL_REG_M, 0x09);
}

/**
 * Deletes the IMU object.
 */
IMU::~IMU() {}

/**
 * This private method allows to write a register value.
 * @param cs the chip select output to use, either csG or csXM.
 * @param address the 7 bit address of the register.
 * @param value the value to write into the register.
 */
void IMU::writeRegister(DigitalOut& cs, char address, char value) {
    
    cs = 0;
    
    spi.write(0x7F & address);
    spi.write(value & 0xFF);
    
    cs = 1;
}

/**
 * This private method allows to read a register value.
 * @param cs the chip select output to use, either csG or csXM.
 * @param address the 7 bit address of the register.
 * @return the value read from the register.
 */
char IMU::readRegister(DigitalOut& cs, char address) {
    
    cs = 0;
    
    spi.write(0x80 | address);
    int value = spi.write(0xFF);
    
    cs = 1;
    
    return (char)(value & 0xFF);
}

/**
 * Reads the gyroscope about the x-axis.
 * @return the rotational speed about the x-axis given in [rad/s].
 */
float IMU::readGyroX() {
    
    char low = readRegister(csG, OUT_X_L_G);
    char high = readRegister(csG, OUT_X_H_G);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*245.0f*PI/180.0f;
}

/**
 * Reads the gyroscope about the y-axis.
 * @return the rotational speed about the y-axis given in [rad/s].
 */
float IMU::readGyroY() {

    char low = readRegister(csG, OUT_Y_L_G);
    char high = readRegister(csG, OUT_Y_H_G);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*245.0f*PI/180.0f;
}

/**
 * Reads the gyroscope about the z-axis.
 * @return the rotational speed about the z-axis given in [rad/s].
 */
float IMU::readGyroZ() {
    
    char low = readRegister(csG, OUT_Z_L_G);
    char high = readRegister(csG, OUT_Z_H_G);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*245.0f*PI/180.0f;
}

/**
 * Reads the acceleration in x-direction.
 * @return the acceleration in x-direction, given in [m/s2].
 */
float IMU::readAccelerationX() {
    
    char low = readRegister(csXM, OUT_X_L_A);
    char high = readRegister(csXM, OUT_X_H_A);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*2.0f*9.81f;
}

/**
 * Reads the acceleration in y-direction.
 * @return the acceleration in y-direction, given in [m/s2].
 */
float IMU::readAccelerationY() {
    
    char low = readRegister(csXM, OUT_Y_L_A);
    char high = readRegister(csXM, OUT_Y_H_A);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*2.0f*9.81f;
}

/**
 * Reads the acceleration in z-direction.
 * @return the acceleration in z-direction, given in [m/s2].
 */
float IMU::readAccelerationZ() {
    
    char low = readRegister(csXM, OUT_Z_L_A);
    char high = readRegister(csXM, OUT_Z_H_A);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*2.0f*9.81f;
}

/**
 * Reads the magnetic field in x-direction.
 * @return the magnetic field in x-direction, given in [Gauss].
 */
float IMU::readMagnetometerX() {
    
    char low = readRegister(csXM, OUT_X_L_M);
    char high = readRegister(csXM, OUT_X_H_M);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*2.0f;
}

/**
 * Reads the magnetic field in x-direction.
 * @return the magnetic field in x-direction, given in [Gauss].
 */
float IMU::readMagnetometerY() {
    
    char low = readRegister(csXM, OUT_Y_L_M);
    char high = readRegister(csXM, OUT_Y_H_M);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*2.0f;
}

/**
 * Reads the magnetic field in x-direction.
 * @return the magnetic field in x-direction, given in [Gauss].
 */
float IMU::readMagnetometerZ() {
    
    char low = readRegister(csXM, OUT_Z_L_M);
    char high = readRegister(csXM, OUT_Z_H_M);
    
    short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
    
    return (float)value/32768.0f*2.0f;
}

/**
 * Reads the compass heading about the z-axis.
 * @return the compass heading in the range -PI to +PI, given in [rad].
 */
float IMU::readHeading() {
    float magX = readMagnetometerX();
    float magY = readMagnetometerY();
    
    // X-Achse
    if (magX < lowMagX) lowMagX = magX;    
    if (magX > maxMagX) maxMagX = magX;
    
    float magX2 = (magX-lowMagX)/(maxMagX-lowMagX)-0.5f;
    
    //printf ("minX in Gauss = %f\n\r",lowMagX);
    //printf ("maxX in Gauss = %f\n\r",maxMagX);
    //printf ("magX2 in Gauss = %f\n\r",magX2);
    
    // Y-Achse
    if (magY < lowMagY) lowMagY = magY;    
    if (magY > maxMagY) maxMagY = magY;
    
    float magY2 = (magY-lowMagY)/(maxMagY-lowMagY)-0.5f;
    
   
   // printf ("minY in Gauss = %f\n\r",lowMagY);
   // printf ("maxY in Gauss = %f\n\r",maxMagY);
   // printf ("magY2 in Gauss = %f\n\r",magY2);
    
    return atan2(magY2,magX2);
}