2018-05-09 00:59:09 +02:00
|
|
|
#include <math.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2018-05-05 15:56:39 +02:00
|
|
|
#include "i2c.h"
|
2018-05-09 00:59:09 +02:00
|
|
|
#include "imu.h"
|
2018-05-05 15:56:39 +02:00
|
|
|
|
|
|
|
int gyroFd;
|
2018-05-09 00:59:09 +02:00
|
|
|
int acelFd;
|
|
|
|
pthread_t tIMU;
|
2018-05-05 15:56:39 +02:00
|
|
|
|
|
|
|
void configureIMU()
|
|
|
|
{
|
|
|
|
gyroFd = openI2C(GYRO_ADDR);
|
2018-05-09 00:59:09 +02:00
|
|
|
acelFd = openI2C(ACEL_ADDR);
|
|
|
|
|
|
|
|
writeI2C(gyroFd, GYRO_CTRL_REG1, 0x0F); // PD = 1 (normal mode); Zen = Yen = Xen = 1 (all axes enabled)
|
|
|
|
writeI2C(gyroFd, GYRO_CTRL_REG4, 0xB0); // Block data update, 2000 dps full scale
|
2018-05-05 15:56:39 +02:00
|
|
|
|
2018-05-09 00:59:09 +02:00
|
|
|
writeI2C(acelFd, ACEL_CTRL1, 0x6F); // 50 Hz Acceleration data-rate; block data update; Zen = Yen = Xen = 1 (all axes enabled)
|
|
|
|
writeI2C(acelFd, ACEL_CTRL2, 0x20); // +/- 16G full scale
|
|
|
|
|
|
|
|
pthread_create(&tIMU, NULL, TaskIMU, NULL);
|
2018-05-05 15:56:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool connectedIMU()
|
|
|
|
{
|
2018-05-09 00:59:09 +02:00
|
|
|
return (uint8_t)readI2C(gyroFd, GYRO_WHO_AM_I) == GYRO_IDENTITY && (uint8_t)readI2C(acelFd, ACEL_WHO_AM_I) == ACEL_IDENTITY;
|
2018-05-05 15:56:39 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 00:59:09 +02:00
|
|
|
struct axesRaw readGyroRaw()
|
2018-05-05 15:56:39 +02:00
|
|
|
{
|
2018-05-09 00:59:09 +02:00
|
|
|
struct axesRaw res;
|
2018-05-05 15:56:39 +02:00
|
|
|
res.x = (readI2C(gyroFd, GYRO_OUT_X_H) << 8 | readI2C(gyroFd, GYRO_OUT_X_L));
|
|
|
|
res.y = (readI2C(gyroFd, GYRO_OUT_Y_H) << 8 | readI2C(gyroFd, GYRO_OUT_Y_L));
|
|
|
|
res.z = (readI2C(gyroFd, GYRO_OUT_Z_H) << 8 | readI2C(gyroFd, GYRO_OUT_Z_L));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2018-05-09 00:59:09 +02:00
|
|
|
struct axes readGyro()
|
|
|
|
{
|
|
|
|
struct axesRaw raw = readGyroRaw();
|
|
|
|
struct axes computed;
|
|
|
|
computed.x = (float)raw.x * GYRO_GAIN;
|
|
|
|
computed.y = (float)raw.y * GYRO_GAIN;
|
|
|
|
computed.z = (float)raw.z * GYRO_GAIN;
|
|
|
|
return computed;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct axesRaw readAcelRaw()
|
|
|
|
{
|
|
|
|
struct axesRaw res;
|
|
|
|
res.x = (readI2C(acelFd, ACEL_OUT_X_H_A) << 8 | readI2C(acelFd, ACEL_OUT_X_L_A));
|
|
|
|
res.y = (readI2C(acelFd, ACEL_OUT_Y_H_A) << 8 | readI2C(acelFd, ACEL_OUT_Y_L_A));
|
|
|
|
res.z = (readI2C(acelFd, ACEL_OUT_Z_H_A) << 8 | readI2C(acelFd, ACEL_OUT_Z_L_A));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct axes readAcel()
|
|
|
|
{
|
|
|
|
struct axesRaw raw = readAcelRaw();
|
|
|
|
struct axes computed;
|
|
|
|
computed.x = atan2(raw.y, raw.z) + M_PI;
|
|
|
|
computed.y = atan2(raw.z, raw.x) + M_PI;
|
|
|
|
computed.z = atan2(raw.x, raw.y) + M_PI;
|
|
|
|
return computed;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct timespec imuStart;
|
|
|
|
struct timespec imuNow;
|
|
|
|
struct timespec imuEcoule;
|
|
|
|
|
|
|
|
void* TaskIMU(void* pData)
|
2018-05-05 15:56:39 +02:00
|
|
|
{
|
2018-05-09 00:59:09 +02:00
|
|
|
(void)pData;
|
|
|
|
|
|
|
|
struct axes gyroNew;
|
|
|
|
struct axes gyro;
|
|
|
|
struct axes acel;
|
|
|
|
struct axes complemFilter;
|
|
|
|
|
|
|
|
clock_gettime(CLOCK_REALTIME, &imuStart);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
clock_gettime(CLOCK_REALTIME, &imuNow);
|
|
|
|
if ((imuNow.tv_nsec - imuStart.tv_nsec) < 0) {
|
|
|
|
imuEcoule.tv_sec = imuNow.tv_sec - imuStart.tv_sec - 1;
|
|
|
|
imuEcoule.tv_nsec = imuNow.tv_nsec - imuStart.tv_nsec + 1000000000UL;
|
|
|
|
} else {
|
|
|
|
imuEcoule.tv_sec = imuNow.tv_sec - imuStart.tv_sec;
|
|
|
|
imuEcoule.tv_nsec = imuNow.tv_nsec - imuStart.tv_nsec;
|
|
|
|
}
|
|
|
|
imuStart.tv_sec = imuNow.tv_sec;
|
|
|
|
imuStart.tv_nsec = imuNow.tv_nsec;
|
|
|
|
float dt = imuEcoule.tv_sec + imuStart.tv_nsec * 1E-9;
|
|
|
|
|
|
|
|
gyroNew = readGyro();
|
|
|
|
gyro.x += gyroNew.x * dt;
|
|
|
|
gyro.y += gyroNew.y * dt;
|
|
|
|
gyro.z += gyroNew.z * dt;
|
2018-05-05 15:56:39 +02:00
|
|
|
|
2018-05-09 00:59:09 +02:00
|
|
|
acel = readAcel();
|
|
|
|
|
|
|
|
/* complemFilter.x = c * (complemFilter.x + gyroNew.x * dt) + (1 - AA) * acel.x; */
|
|
|
|
|
|
|
|
usleep(IMU_INTERVAL * 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void deconfigureIMU()
|
|
|
|
{
|
|
|
|
pthread_cancel(tIMU);
|
2018-05-05 15:56:39 +02:00
|
|
|
}
|