Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: IMU.cpp
- Revision:
- 0:3fb3c13f3cf5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IMU.cpp Wed Apr 15 12:53:31 2020 +0000
@@ -0,0 +1,348 @@
+/*
+ * IMU.cpp
+ * Copyright (c) 2020, ZHAW
+ * All rights reserved.
+ */
+#include <mbed.h>
+#include "IMU.h"
+#include "LowpassFilter.h"
+#include "stdio.h"
+#include <mbed.h>
+#include <EthernetInterface.h>
+#include "IMU.h"
+#include "HTTPServer.h"
+#include "HTTPScriptIMU.h"
+
+using namespace std;
+
+const float IMU::PERIOD = 0.002f; // the period of the timer interrupt, given in [s]
+const float IMU::M_PI = 3.14159265358979323846f; // the mathematical constant PI
+const float IMU::LOWPASS_FILTER_FREQUENCY = 2.0f*M_PI; // given in [rad/s]
+
+// init lowpasses
+
+
+/**
+ * Creates an IMU object.
+ * @param spi a reference to an spi controller to use.
+ * @param csAG the chip select output for the accelerometer and the gyro sensor.
+ * @param csM the chip select output for the magnetometer.
+ */
+IMU::IMU(SPI& spi, DigitalOut& csAG, DigitalOut& csM) : spi(spi), csAG(csAG), csM(csM), thread(osPriorityHigh, STACK_SIZE) {
+
+ // initialize SPI interface
+
+ spi.format(8, 3);
+ spi.frequency(1000000);
+
+ // reset chip select lines to logical high
+
+ csAG = 1;
+ csM = 1;
+
+ // initialize accelerometer and gyro
+
+ writeRegister(csAG, CTRL_REG1_G, 0xC3); // ODR 952 Hz, full scale 245 deg/s
+ writeRegister(csAG, CTRL_REG2_G, 0x00); // disable interrupt generation
+ writeRegister(csAG, CTRL_REG3_G, 0x00); // disable low power mode, disable high pass filter, high pass cutoff frequency 57 Hz
+ writeRegister(csAG, CTRL_REG4, 0x38); // enable gyro in all 3 axis
+ writeRegister(csAG, CTRL_REG5_XL, 0x38); // no decimation, enable accelerometer in all 3 axis
+ writeRegister(csAG, CTRL_REG6_XL, 0xC0); // ODR 952 Hz, full scale 2g
+ writeRegister(csAG, CTRL_REG7_XL, 0x00); // high res mode disabled, filter bypassed
+ writeRegister(csAG, CTRL_REG8, 0x00); // 4-wire SPI interface, LSB at lower address
+ writeRegister(csAG, CTRL_REG9, 0x04); // disable gyro sleep mode, disable I2C interface, disable FIFO
+ writeRegister(csAG, CTRL_REG10, 0x00); // self test disabled
+
+ // initialize magnetometer
+
+ writeRegister(csM, CTRL_REG1_M, 0x10); // temperature not compensated, low power mode for x & y axis, data rate 10 Hz
+ writeRegister(csM, CTRL_REG2_M, 0x00); // full scale 4 gauss
+ writeRegister(csM, CTRL_REG3_M, 0x80); // disable I2C interface, low power mode, SPI write only, continuous conversion mode
+ writeRegister(csM, CTRL_REG4_M, 0x00); // low power mode for z axis, LSB at lower address
+ writeRegister(csM, CTRL_REG5_M, 0x00); // fast read disabled
+
+ // start thread and timer interrupt
+
+ thread.start(callback(this, &IMU::run));
+ ticker.attach(callback(this, &IMU::sendThreadFlag), PERIOD);
+
+ FilterX.setPeriod(PERIOD);
+ FilterX.setFrequency(LOWPASS_FILTER_FREQUENCY);
+ FilterY.setPeriod(PERIOD);
+ FilterY.setFrequency(LOWPASS_FILTER_FREQUENCY);
+
+ mxMin = 0.05;
+ mxMax = 0.1;
+ myMin = 0.05;
+ myMax = 0.1;
+
+ myX_korr = 0;
+ myY_korr = 0;
+}
+
+/**
+ * Deletes the IMU object.
+ */
+IMU::~IMU() {
+
+ ticker.detach();
+}
+
+/**
+ * This private method allows to write a register value.
+ * @param cs the chip select output to use, either csAG or csM.
+ * @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 csAG or csM.
+ * @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 acceleration in x-direction.
+ * @return the acceleration in x-direction, given in [m/s2].
+ */
+float IMU::readAccelerationX() {
+
+ mutex.lock();
+
+ char low = readRegister(csAG, OUT_X_L_XL);
+ char high = readRegister(csAG, OUT_X_H_XL);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ 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() {
+
+ mutex.lock();
+
+ char low = readRegister(csAG, OUT_Y_L_XL);
+ char high = readRegister(csAG, OUT_Y_H_XL);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ 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() {
+
+ mutex.lock();
+
+ char low = readRegister(csAG, OUT_Z_L_XL);
+ char high = readRegister(csAG, OUT_Z_H_XL);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ return (float)value/32768.0f*2.0f*9.81f;
+}
+
+/**
+ * Reads the gyroscope about the x-axis.
+ * @return the rotational speed about the x-axis given in [rad/s].
+ */
+float IMU::readGyroX() {
+
+ mutex.lock();
+
+ char low = readRegister(csAG, OUT_X_L_G);
+ char high = readRegister(csAG, OUT_X_H_G);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ return (float)value/32768.0f*245.0f*M_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() {
+
+ mutex.lock();
+
+ char low = readRegister(csAG, OUT_Y_L_G);
+ char high = readRegister(csAG, OUT_Y_H_G);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ return (float)value/32768.0f*245.0f*M_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() {
+
+ mutex.lock();
+
+ char low = readRegister(csAG, OUT_Z_L_G);
+ char high = readRegister(csAG, OUT_Z_H_G);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ return (float)value/32768.0f*245.0f*M_PI/180.0f;
+}
+
+/**
+ * Reads the magnetic field in x-direction.
+ * @return the magnetic field in x-direction, given in [Gauss].
+ */
+float IMU::readMagnetometerX() {
+
+ mutex.lock();
+
+ char low = readRegister(csM, OUT_X_L_M);
+ char high = readRegister(csM, OUT_X_H_M);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ return (float)value/32768.0f*4.0f;
+
+
+}
+
+/**
+ * Reads the magnetic field in y-direction.
+ * @return the magnetic field in y-direction, given in [Gauss].
+ */
+float IMU::readMagnetometerY() {
+
+ mutex.lock();
+
+ char low = readRegister(csM, OUT_Y_L_M);
+ char high = readRegister(csM, OUT_Y_H_M);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ return (float)value/32768.0f*4.0f;
+}
+
+/**
+ * Reads the magnetic field in z-direction.
+ * @return the magnetic field in z-direction, given in [Gauss].
+ */
+float IMU::readMagnetometerZ() {
+
+ /*mutex.lock();
+
+ char low = readRegister(csM, OUT_Z_L_M);
+ char high = readRegister(csM, OUT_Z_H_M);
+
+ short value = (short)(((unsigned short)high << 8) | (unsigned short)low);
+
+ mutex.unlock();
+
+ return (float)value/32768.0f*4.0f;*/
+ return readHeading();
+}
+
+float IMU::readHeading() {
+
+ float orient = atan2(myX_korr,myY_korr);
+
+ if (orient < -M_PI){
+ orient = orient + M_PI;
+ return orient;
+ }
+ else if (orient > M_PI){
+ orient = orient - M_PI;
+ return orient;
+ }
+ else {
+ return orient;
+ }
+}
+
+/**
+ * This method is called by the ticker timer interrupt service routine.
+ * It sends a flag to the thread to make it run again.
+ */
+void IMU::sendThreadFlag() {
+
+ thread.flags_set(threadFlag);
+}
+
+/**
+ * This <code>run()</code> method contains an infinite loop with the run logic.
+ */
+void IMU::run() {
+
+ while (true) {
+
+ // wait for the periodic thread flag
+
+ ThisThread::flags_wait_any(threadFlag);
+ float myX = FilterX.filter(readMagnetometerX());
+ float myY = FilterY.filter(readMagnetometerY());
+ // filter and process sensor data...
+ if (myX < mxMin) {
+ mxMin = myX;
+ }
+ if (myX > mxMax) {
+ mxMax = myX;
+ }
+ if (myY < myMin) {
+ myMin = myY;
+ }
+ if (myY > myMax) {
+ myMax = myY;
+ }
+
+ myX_korr = (2*(myX-mxMin)/(mxMax-mxMin)) - 1;
+ myY_korr = (2*(myY-myMin)/(myMax-myMin)) - 1;
+
+
+ }
+}
+