RoverQMC5883L and RoverHMC5883L classes added.
Signed-off-by: Mustafa Ozcelikors <mozcelikors@gmail.com>
diff --git a/rover/include/roverapi/rover_hmc5883l.hpp b/rover/include/roverapi/rover_hmc5883l.hpp
new file mode 100644
index 0000000..55fb394
--- /dev/null
+++ b/rover/include/roverapi/rover_hmc5883l.hpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2017 FH Dortmund and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Description:
+ * RoverHMC5883L API - Interfaces for Rover HMC5883L bearing sensor application development
+ * Header file
+ *
+ * Contributors:
+ * M.Ozcelikors <mozcelikors@gmail.com>, created RoverHMC5883L class 04.12.2017
+ * David Schmelter, Fraunhofer IEM - compass sensor initial implementation
+ *
+ */
+
+#ifndef ROVERAPI_ROVER_HMC5883L_HPP_
+#define ROVERAPI_ROVER_HMC5883L_HPP_
+
+#include <roverapi/rover_sensor.hpp>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+namespace rover
+{
+ /**
+ * @brief RoverHMC5883L is a class that is inherited from RoverSensor abstract class. RoverHMC5883L class contains member functions and variables to set up and read from HMC5883L bearing sensor that is embedded on the rover.
+ */
+ class RoverHMC5883L : public RoverSensor
+ {
+ private:
+ /* Definitions related to compass sensor */
+ /**
+ * @brief Address for compass sensor
+ */
+ int HMC588L_ADDRESS;
+
+ /**
+ * @brief Calibration duration for compass sensor
+ */
+ int CALIBRATION_DURATION;
+
+ /**
+ * @brief Declination angle / correction factor for compass sensor
+ */
+ float DECLINATION_ANGLE;
+
+ /**
+ * @brief Calibration variable for HMC5883L
+ */
+ mutable unsigned int calibration_start;
+
+ /**
+ * @brief Flag to hold if HMC5883L is set up
+ */
+ int ROVERHMC5883L_SETUP_;
+
+ public:
+ /**
+ * @brief Constructor for the RoverHMC5883L class
+ */
+ explicit RoverHMC5883L ();
+
+ /**
+ * @brief Destructor for the RoverHMC5883L class
+ */
+ ~RoverHMC5883L();
+
+ /**
+ * @brief Function to setup HMC5883L sensor
+ * @return void
+ */
+ void initialize (void);
+
+ /**
+ * @brief Reads the bearing value from Bearing sensor Sunfounder HMC5883L (float).
+ * @return bearing_val in degrees (float).
+ */
+ float read (void);
+
+ /**
+ * @brief Starts calibration for the bearing sensor
+ * @return void
+ */
+ void calibrate (void) const;
+
+ /**
+ * @brief Sets the HMC588L Address
+ * @param address Address to set
+ * @return void
+ */
+ void setHMC588LAddress (const int address);
+
+ /**
+ * @brief Sets the HMC588L Calibration Duration
+ * @param period Period to set
+ * @return void
+ */
+ void setHMC588LCalibrationPeriod(const int period);
+
+ /**
+ * @brief Sets the HMC588L Declination angle
+ * @param angle Declination angle to set
+ * @return void
+ */
+ void setHMC588LDeclinationAngle (const float angle);
+
+ /**
+ * @brief Returns the private attribute HMC588L_ADDRESS
+ * @return address Address to return
+ */
+ int getHMC588LAddress (void);
+
+ /**
+ * @brief Returns the HMC588L Calibration Duration
+ * @return period Period to return
+ */
+ int getHMC588LCalibrationPeriod (void);
+
+ /**
+ * @brief Returns the HMC588L Declination angle
+ * @return angle Declination angle to return
+ */
+ float getHMC588LDeclinationAngle (void);
+
+ private:
+
+ /**
+ * @brief Inline macro to find minimum of two values regardles of their types (template).
+ * @param a Parameter 1
+ * @param b Parameter 2
+ * @return minimum value
+ */
+ template<typename T>
+ inline T MINIMUM_ (const T& a, const T& b);
+
+ /**
+ * @brief Inline macro to find maximum of two values regardles of their types (template).
+ * @param a Parameter 1
+ * @param b Parameter 2
+ * @return maximum value
+ */
+ template<typename T>
+ inline T MAXIMUM_ (const T& a, const T& b);
+
+ };
+}
+
+
+
+#endif /* ROVERAPI_ROVER_HMC5883L_HPP_ */
diff --git a/rover/include/roverapi/rover_qmc5883l.hpp b/rover/include/roverapi/rover_qmc5883l.hpp
new file mode 100644
index 0000000..81b1c00
--- /dev/null
+++ b/rover/include/roverapi/rover_qmc5883l.hpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2017 FH Dortmund and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Description:
+ * RoverQMC5883L API - Interfaces for Rover QMC5883L bearing sensor application development
+ * Header file
+ *
+ * Contributors:
+ * M.Ozcelikors <mozcelikors@gmail.com>, created RoverQMC5883L class 04.12.2017
+ *
+ */
+
+#ifndef ROVERAPI_ROVER_QMC5883L_HPP_
+#define ROVERAPI_ROVER_QMC5883L_HPP_
+
+#include <roverapi/rover_sensor.hpp>
+
+namespace rover
+{
+ /**
+ * @brief RoverQMC5883L is a class that is inherited from RoverSensor abstract class. RoverQMC5883L class contains member functions and variables to set up and read from QMC5883L bearing sensor that is embedded on the rover.
+ */
+ class RoverQMC5883L : public RoverSensor
+ {
+ private:
+ /* Definitions related to compass sensor */
+ /**
+ * @brief Address for compass sensor
+ */
+ int QMC5883L_ADDRESS;
+
+ /**
+ * @brief Calibration duration for compass sensor
+ */
+ int CALIBRATION_DURATION;
+
+ /**
+ * @brief Declination angle / correction factor for compass sensor
+ */
+ float DECLINATION_ANGLE;
+
+ /**
+ * @brief Calibration variable for QMC5883L
+ */
+ mutable unsigned int calibration_start;
+
+ /**
+ * @brief Flag to hold if RoverQMC5883L is set up
+ */
+ int ROVERQMC5883L_SETUP_;
+
+ public:
+ /**
+ * @brief Constructor for the RoverQMC5883L class
+ */
+ explicit RoverQMC5883L ();
+
+ /**
+ * @brief Destructor for the RoverQMC5883L class
+ */
+ ~RoverQMC5883L();
+
+ /**
+ * @brief Function to setup QMC5883L sensor
+ * @return void
+ */
+ void initialize (void);
+
+ /**
+ * @brief Reads the bearing value from Bearing sensor QMC5883L (float).
+ * @return bearing_val in degrees (float).
+ */
+ float read (void);
+
+ /**
+ * @brief Starts calibration for the bearing sensor
+ * @return void
+ */
+ void calibrate (void) const;
+
+ /**
+ * @brief Sets the QMC588L Address
+ * @param address Address to set
+ * @return void
+ */
+ void setQMC5883LAddress (const int address);
+
+ /**
+ * @brief Sets the QMC588L Calibration Duration
+ * @param period Period to set
+ * @return void
+ */
+ void setQMC5883LCalibrationPeriod(const int period);
+
+ /**
+ * @brief Sets the QMC588L Declination angle
+ * @param angle Declination angle to set
+ * @return void
+ */
+ void setQMC5883LDeclinationAngle (const float angle);
+
+ /**
+ * @brief Returns the private attribute QMC588L_ADDRESS
+ * @return address Address to return
+ */
+ int getQMC5883LAddress (void);
+
+ /**
+ * @brief Returns the QMC588L Calibration Duration
+ * @return period Period to return
+ */
+ int getQMC5883LCalibrationPeriod (void);
+
+ /**
+ * @brief Returns the QMC588L Declination angle
+ * @return angle Declination angle to return
+ */
+ float getQMC5883LDeclinationAngle (void);
+
+ private:
+
+ /**
+ * @brief Inline macro to find minimum of two values regardles of their types (template).
+ * @param a Parameter 1
+ * @param b Parameter 2
+ * @return minimum value
+ */
+ template<typename T>
+ inline T MINIMUM_ (const T& a, const T& b);
+
+ /**
+ * @brief Inline macro to find maximum of two values regardles of their types (template).
+ * @param a Parameter 1
+ * @param b Parameter 2
+ * @return maximum value
+ */
+ template<typename T>
+ inline T MAXIMUM_ (const T& a, const T& b);
+
+ };
+}
+
+
+
+#endif /* ROVERAPI_ROVER_QMC5883L_HPP_ */
diff --git a/rover/src/roverapi/rover_hmc5883l.cpp b/rover/src/roverapi/rover_hmc5883l.cpp
new file mode 100644
index 0000000..e36a428
--- /dev/null
+++ b/rover/src/roverapi/rover_hmc5883l.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2017 FH Dortmund and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Description:
+ * RoverHMC5883L API - Interfaces for Rover HMC5883L bearing sensor application development
+ *
+ * Contributors:
+ * M.Ozcelikors <mozcelikors@gmail.com>, created RoverHMC5883L class 04.12.2017
+ * David Schmelter, Fraunhofer IEM - compass sensor initial implementation
+ *
+ */
+
+#include <roverapi/rover_hmc5883l.hpp>
+#include <wiringPi.h>
+#include <wiringPiI2C.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int i2c_hmc588l_fd = -1;
+
+static int16_t xMinRaw = 0;
+static int16_t xMaxRaw = 0;
+static int16_t yMaxRaw = 0;
+static int16_t yMinRaw = 0;
+
+rover::RoverHMC5883L::RoverHMC5883L()
+:HMC588L_ADDRESS(0x1E), //default: 0x1E
+ CALIBRATION_DURATION(10000), //compass calibration has a duration of 5 seconds
+ DECLINATION_ANGLE(0.0413), //correction factor for location Paderborn
+ calibration_start(0),
+ ROVERHMC5883L_SETUP_(0)
+{
+
+}
+
+rover::RoverHMC5883L::~RoverHMC5883L(){}
+
+void rover::RoverHMC5883L::initialize (void)
+{
+#ifdef DEBUG
+ printf ("HMC588L Address is: %x\n", this->HMC588L_ADDRESS);
+ printf ("HMC588L Calibration period is %d\n", this->CALIBRATION_DURATION);
+ printf ("HMC588L Declination angle is %f\n", this->DECLINATION_ANGLE);
+#endif
+
+ if ((i2c_hmc588l_fd = wiringPiI2CSetup(this->HMC588L_ADDRESS)) < 0) {
+ printf("Failed to initialize HMC588L compass sensor");
+ }
+
+ if (i2c_hmc588l_fd >= 0) {
+ int8_t gain = 5;
+
+ wiringPiI2CWriteReg8(i2c_hmc588l_fd, 0x00, 0x70); // 8-average, 15 Hz default, positive self test measurement
+ wiringPiI2CWriteReg8(i2c_hmc588l_fd, 0x01, gain << 5); // Gain
+ wiringPiI2CWriteReg8(i2c_hmc588l_fd, 0x02, 0x00); // Continuous-measurement mode
+ }
+
+ this->ROVERHMC5883L_SETUP_ = 1;
+
+ this->calibration_start = millis();
+}
+
+float rover::RoverHMC5883L::read (void)
+{
+ if (this->ROVERHMC5883L_SETUP_ != 1)
+ {
+ fprintf(stderr,"You havent initialized RoverHMC5883L. Use RoverHMC5883L()::initialize() !\n");
+ }
+ else
+ {
+ int8_t buffer[6];
+
+ //potential optimization: wiringPiI2CReadReg16
+ buffer[0] = wiringPiI2CReadReg8(i2c_hmc588l_fd, 0x03); //MSB x
+ buffer[1] = wiringPiI2CReadReg8(i2c_hmc588l_fd, 0x04); //LSB x
+ buffer[2] = wiringPiI2CReadReg8(i2c_hmc588l_fd, 0x05); //MSB z
+ buffer[3] = wiringPiI2CReadReg8(i2c_hmc588l_fd, 0x06); //LSB z
+ buffer[4] = wiringPiI2CReadReg8(i2c_hmc588l_fd, 0x07); //MSB y
+ buffer[5] = wiringPiI2CReadReg8(i2c_hmc588l_fd, 0x08); //LSB y
+
+ int16_t xRaw = (((int16_t) buffer[0] << 8) & 0xff00) | buffer[1];
+ //int16_t zRaw = (((int16_t) buffer[2] << 8) & 0xff00) | buffer[3];
+ int16_t yRaw = (((int16_t) buffer[4] << 8) & 0xff00) | buffer[5];
+
+ //if calibration is active calculate minimum and maximum x/y values for calibration
+ if (millis() <= this->calibration_start + this->CALIBRATION_DURATION)
+ {
+ xMinRaw = MINIMUM_(xRaw, xMinRaw);
+
+ xMaxRaw = MAXIMUM_(xRaw, xMaxRaw);
+
+ yMinRaw = MINIMUM_(yRaw, yMinRaw);
+
+ yMaxRaw = MAXIMUM_(yRaw, yMaxRaw);
+ }
+
+ //calibration: move and scale x coordinates based on minimum and maximum values to get a unit circle
+ float xf = xRaw - (float) (xMinRaw + xMaxRaw) / 2.0f;
+ xf = xf / (xMinRaw + xMaxRaw) * 2.0f;
+
+ //calibration: move and scale y coordinates based on minimum and maximum values to get a unit circle
+ float yf = yRaw - (float) (yMinRaw + yMaxRaw) / 2.0f;
+ yf = yf / (yMinRaw + yMaxRaw) * 2.0f;
+
+ float bearing = atan2(yf, xf);
+ #ifdef DEBUG
+ printf("%f, bearing\n", bearing);
+ #endif
+
+ //location specific magnetic field correction
+ bearing += this->DECLINATION_ANGLE;
+
+ if (bearing < 0) {
+ bearing += 2 * M_PI;
+ }
+
+ if (bearing > 2 * M_PI) {
+ bearing -= 2 * M_PI;
+ }
+
+ float headingDegrees = bearing * (180.0 / M_PI);
+ #ifdef DEBUG
+ printf("%lf, headingDegrees\n", headingDegrees);
+ #endif
+ return headingDegrees;
+ }
+}
+
+void rover::RoverHMC5883L::setHMC588LAddress (const int address)
+{
+ this->HMC588L_ADDRESS = address;
+}
+
+void rover::RoverHMC5883L::setHMC588LDeclinationAngle (const float angle)
+{
+ this->DECLINATION_ANGLE = angle;
+}
+
+void rover::RoverHMC5883L::setHMC588LCalibrationPeriod(const int period)
+{
+ this->CALIBRATION_DURATION = period;
+}
+
+int rover::RoverHMC5883L::getHMC588LAddress (void)
+{
+ return this->HMC588L_ADDRESS;
+}
+
+float rover::RoverHMC5883L::getHMC588LDeclinationAngle (void)
+{
+ return this->DECLINATION_ANGLE;
+}
+
+int rover::RoverHMC5883L::getHMC588LCalibrationPeriod (void)
+{
+ return this->CALIBRATION_DURATION;
+}
+
+template<typename T>
+inline T rover::RoverHMC5883L::MINIMUM_(const T& a, const T& b)
+{
+ return (a < b ? a : b);
+}
+
+template<typename T>
+inline T rover::RoverHMC5883L::MAXIMUM_(const T& a, const T& b)
+{
+ return (a > b ? a : b);
+}
+
diff --git a/rover/src/roverapi/rover_qmc5883l.cpp b/rover/src/roverapi/rover_qmc5883l.cpp
new file mode 100644
index 0000000..a043ba7
--- /dev/null
+++ b/rover/src/roverapi/rover_qmc5883l.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2017 FH Dortmund and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Description:
+ * RoverQMC5883L API - Interfaces for Rover QMC5883L bearing sensor application development
+ * Header file
+ *
+ * Contributors:
+ * M.Ozcelikors <mozcelikors@gmail.com>, created RoverQMC5883L class 04.12.2017
+ *
+ */
+
+
+#include <roverapi/rover_qmc5883l.hpp>
+#include <wiringPi.h>
+#include <wiringPiI2C.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int i2c_qmc588l_fd = -1;
+
+static int16_t xMinRaw_ = 0;
+static int16_t xMaxRaw_ = 0;
+static int16_t yMaxRaw_ = 0;
+static int16_t yMinRaw_ = 0;
+
+rover::RoverQMC5883L::RoverQMC5883L()
+:QMC5883L_ADDRESS(0x0D), //default: 0x0D
+ CALIBRATION_DURATION(10000), //compass calibration has a duration of 5 seconds
+ DECLINATION_ANGLE(0.0413), //correction factor for location Paderborn
+ calibration_start(0),
+ ROVERQMC5883L_SETUP_(0)
+{
+
+}
+
+rover::RoverQMC5883L::~RoverQMC5883L(){}
+
+void rover::RoverQMC5883L::initialize (void)
+{
+ if ((i2c_qmc588l_fd = wiringPiI2CSetup(this->QMC5883L_ADDRESS)) < 0)
+ {
+ printf("Failed to initialize QMC588L compass sensor");
+ }
+
+ if (i2c_qmc588l_fd >= 0)
+ {
+ wiringPiI2CWriteReg8 (i2c_qmc588l_fd, 0x0B, 0x01); //init SET/PERIOD register
+
+ /*
+ Define
+ OSR = 512
+ Full Scale Range = 8G(Gauss)
+ ODR = 200HZ
+ set continuous measurement mode
+ */
+ wiringPiI2CWriteReg8 (i2c_qmc588l_fd, 0x09, 0x1D);
+ }
+
+ this->ROVERQMC5883L_SETUP_ = 1;
+
+ this->calibration_start = millis();
+
+ //
+ // To do a software reset
+ // wiringPiI2CWriteReg8 (i2c_hmc588l_fd, 0x0A, 0x80);
+ //
+}
+
+float rover::RoverQMC5883L::read (void)
+{
+ if (this->ROVERQMC5883L_SETUP_ != 1)
+ {
+ fprintf(stderr,"You havent set up RoverQMC5883L. Use RoverQMC5883L()::initialize() !\n");
+ }
+ else
+ {
+ int8_t buffer[6];
+
+ //wiringPiI2CWrite (i2c_hmc588l_fd, 0x00); //Start with register 3
+ //delay(25);
+
+ buffer[0] = wiringPiI2CReadReg8(i2c_qmc588l_fd, 0x00); //LSB x
+ buffer[1] = wiringPiI2CReadReg8(i2c_qmc588l_fd, 0x01); //MSB x
+ buffer[2] = wiringPiI2CReadReg8(i2c_qmc588l_fd, 0x02); //LSB y
+ buffer[3] = wiringPiI2CReadReg8(i2c_qmc588l_fd, 0x03); //MSB y
+ buffer[4] = wiringPiI2CReadReg8(i2c_qmc588l_fd, 0x04); //LSB z
+ buffer[5] = wiringPiI2CReadReg8(i2c_qmc588l_fd, 0x05); //MSB z
+
+ int16_t xRaw = (((int16_t) buffer[1] << 8) & 0xff00) | buffer[0];
+ int16_t yRaw = (((int16_t) buffer[3] << 8) & 0xff00) | buffer[2];
+ #ifdef DEBUG
+ printf ("%d %d\n",xRaw,yRaw);
+ #endif
+
+ //if calibration is active calculate minimum and maximum x/y values for calibration
+ if (millis() <= this->calibration_start + this->CALIBRATION_DURATION)
+ {
+ xMinRaw_ = MINIMUM_(xRaw, xMinRaw_);
+
+ xMaxRaw_ = MAXIMUM_(xRaw, xMaxRaw_);
+
+ yMinRaw_ = MINIMUM_(yRaw, yMinRaw_);
+
+ yMaxRaw_ = MAXIMUM_(yRaw, yMaxRaw_);
+ }
+
+ //calibration: move and scale x coordinates based on minimum and maximum values to get a unit circle
+ float xf = xRaw - (float) (xMinRaw_ + xMaxRaw_) / 2.0f;
+ xf = xf / (xMinRaw_ + xMaxRaw_) * 2.0f;
+
+ //calibration: move and scale y coordinates based on minimum and maximum values to get a unit circle
+ float yf = yRaw - (float) (yMinRaw_ + yMaxRaw_) / 2.0f;
+ yf = yf / (yMinRaw_ + yMaxRaw_) * 2.0f;
+
+ float bearing = atan2(yf, xf);
+ #ifdef DEBUG
+ printf("%f, bearing\n", bearing);
+ #endif
+
+ //location specific magnetic field correction
+ bearing += this->DECLINATION_ANGLE;
+
+ if (bearing < 0) {
+ bearing += 2 * M_PI;
+ }
+
+ if (bearing > 2 * M_PI) {
+ bearing -= 2 * M_PI;
+ }
+
+ float headingDegrees = bearing * (180.0 / M_PI);
+ #ifdef DEBUG
+ printf("%lf, headingDegrees\n", headingDegrees);
+ #endif
+ return headingDegrees;
+ }
+}
+
+void rover::RoverQMC5883L::setQMC5883LAddress (const int address)
+{
+ this->QMC5883L_ADDRESS = address;
+}
+
+void rover::RoverQMC5883L::setQMC5883LDeclinationAngle (const float angle)
+{
+ this->DECLINATION_ANGLE = angle;
+}
+
+void rover::RoverQMC5883L::setQMC5883LCalibrationPeriod(const int period)
+{
+ this->CALIBRATION_DURATION = period;
+}
+
+int rover::RoverQMC5883L::getQMC5883LAddress (void)
+{
+ return this->QMC5883L_ADDRESS;
+}
+
+float rover::RoverQMC5883L::getQMC5883LDeclinationAngle (void)
+{
+ return this->DECLINATION_ANGLE;
+}
+
+int rover::RoverQMC5883L::getQMC5883LCalibrationPeriod (void)
+{
+ return this->CALIBRATION_DURATION;
+}
+
+template<typename T>
+inline T rover::RoverQMC5883L::MINIMUM_(const T& a, const T& b)
+{
+ return (a < b ? a : b);
+}
+
+template<typename T>
+inline T rover::RoverQMC5883L::MAXIMUM_(const T& a, const T& b)
+{
+ return (a > b ? a : b);
+}