|
|
|
@ -22,12 +22,14 @@ static constexpr float MPU_MAG_TO_FLUX = (4912.f) / (32760.f);
@@ -22,12 +22,14 @@ static constexpr float MPU_MAG_TO_FLUX = (4912.f) / (32760.f);
|
|
|
|
|
|
|
|
|
|
static const Vec3f ACCEL_OFFSET = {0., 0., 0.}; |
|
|
|
|
static const Mat3f ACCEL_MAT = {-1., 0., 0., 0., -1., 0., 0., 0., -1.}; |
|
|
|
|
//static const Vec3f MAG_OFFSET = {-7.79683, 3.6735, 32.3868};
|
|
|
|
|
//static const Vec3f MAG_OFFSET = {-118.902, 18.8173, -39.209};
|
|
|
|
|
static const Vec3f MAG_OFFSET = {-135.994629, 19.117216, -33.0}; |
|
|
|
|
//static const Mat3f MAG_MAT = {0., -0.0281408, 0., -0.0284409, 0., 0., 0., 0., 0.0261544};
|
|
|
|
|
static const Mat3f MAG_MAT = {0., -0.0335989, 0., -0.0330167, 0., 0., 0., 0., 0.0335989}; |
|
|
|
|
static const Vec3f GYRO_OFFSET = {-4.33655, -2.76826, -0.908427}; |
|
|
|
|
// static const Vec3f MAG_OFFSET = {-7.79683, 3.6735, 32.3868};
|
|
|
|
|
// static const Vec3f MAG_OFFSET = {-118.902, 18.8173, -39.209};
|
|
|
|
|
static const Vec3f MAG_OFFSET = {-135.994629, 19.117216, -33.0}; |
|
|
|
|
// static const Mat3f MAG_MAT = {0., -0.0281408, 0., -0.0284409, 0., 0.,
|
|
|
|
|
// 0., 0., 0.0261544};
|
|
|
|
|
static const Mat3f MAG_MAT = {0., -0.0335989, 0., -0.0330167, 0., |
|
|
|
|
0., 0., 0., 0.0335989}; |
|
|
|
|
static const Vec3f GYRO_OFFSET = {-4.33655, -2.76826, -0.908427}; |
|
|
|
|
static const Mat3f GYRO_MAT = {1., 0., 0., 0., 1., 0., 0., 0., 1.}; |
|
|
|
|
|
|
|
|
|
static const char *TAG = "ugv_io_mpu"; |
|
|
|
@ -42,6 +44,37 @@ MPU::MPU() : mpu_(nullptr) {}
@@ -42,6 +44,37 @@ MPU::MPU() : mpu_(nullptr) {}
|
|
|
|
|
MPU::~MPU() { delete mpu_; } |
|
|
|
|
|
|
|
|
|
void MPU::Init() { |
|
|
|
|
mutex_ = xSemaphoreCreateMutex(); |
|
|
|
|
|
|
|
|
|
BaseType_t xRet = xTaskCreate(MPU::TaskEntry, "ugv_io_mpu", 8 * 1024, this, 3, |
|
|
|
|
&this->task_); |
|
|
|
|
if (xRet != pdTRUE) { |
|
|
|
|
ESP_LOGE(TAG, "error creating MPU task"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MPU::Calibrate() { |
|
|
|
|
mpud::raw_axes_t accel_offset, gyro_offset; |
|
|
|
|
mpu_->computeOffsets(&accel_offset, &gyro_offset); |
|
|
|
|
mpu_->setAccelOffset(accel_offset); |
|
|
|
|
mpu_->setGyroOffset(gyro_offset); |
|
|
|
|
{ |
|
|
|
|
auto ao = mpud::math::accelGravity(accel_offset, mpud::ACCEL_FS_2G); |
|
|
|
|
auto go = mpud::math::gyroDegPerSec(gyro_offset, mpud::GYRO_FS_250DPS); |
|
|
|
|
ESP_LOGI(TAG, "MPU offsets: accel=(%f, %f, %f) gyro=(%f, %f, %f)", ao.x, |
|
|
|
|
ao.y, ao.z, go.x, go.y, go.z); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MPU::GetData(MpuData &data) { |
|
|
|
|
xSemaphoreTake(mutex_, pdMS_TO_TICKS(10)); |
|
|
|
|
data = last_data_; |
|
|
|
|
last_data_.gyro_rate = {0, 0, 0}; |
|
|
|
|
xSemaphoreGive(mutex_); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool MPU::Initialize() { |
|
|
|
|
xSemaphoreTake(i2c_mutex, portMAX_DELAY); |
|
|
|
|
mpu_bus_ = &i2c0; |
|
|
|
|
// This is shared with the oled, so just use those pins
|
|
|
|
@ -50,7 +83,7 @@ void MPU::Init() {
@@ -50,7 +83,7 @@ void MPU::Init() {
|
|
|
|
|
mpu_ = new mpud::MPU(*mpu_bus_); |
|
|
|
|
|
|
|
|
|
esp_err_t ret; |
|
|
|
|
int tries = 0; |
|
|
|
|
int tries = 0; |
|
|
|
|
for (; tries < 5; ++tries) { |
|
|
|
|
mpu_->getInterruptStatus(); |
|
|
|
|
ret = mpu_->testConnection(); |
|
|
|
@ -73,7 +106,7 @@ void MPU::Init() {
@@ -73,7 +106,7 @@ void MPU::Init() {
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (tries == 5) { |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
// Calibrate();
|
|
|
|
|
mpu_->setAccelFullScale(MPU_ACCEL_FS); |
|
|
|
@ -83,51 +116,62 @@ void MPU::Init() {
@@ -83,51 +116,62 @@ void MPU::Init() {
|
|
|
|
|
xSemaphoreGive(i2c_mutex); |
|
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "MPU initialized"); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MPU::Calibrate() { |
|
|
|
|
mpud::raw_axes_t accel_offset, gyro_offset; |
|
|
|
|
mpu_->computeOffsets(&accel_offset, &gyro_offset); |
|
|
|
|
mpu_->setAccelOffset(accel_offset); |
|
|
|
|
mpu_->setGyroOffset(gyro_offset); |
|
|
|
|
{ |
|
|
|
|
auto ao = mpud::math::accelGravity(accel_offset, mpud::ACCEL_FS_2G); |
|
|
|
|
auto go = mpud::math::gyroDegPerSec(gyro_offset, mpud::GYRO_FS_250DPS); |
|
|
|
|
ESP_LOGI(TAG, "MPU offsets: accel=(%f, %f, %f) gyro=(%f, %f, %f)", ao.x, |
|
|
|
|
ao.y, ao.z, go.x, go.y, go.z); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
void MPU::DoTask() { |
|
|
|
|
ESP_LOGI(TAG, "MPU task start"); |
|
|
|
|
mpud::raw_axes_t accel_, gyro_, mag_; |
|
|
|
|
esp_err_t ret; |
|
|
|
|
MpuData data; |
|
|
|
|
|
|
|
|
|
void MPU::GetData(MpuData &data) { |
|
|
|
|
esp_err_t ret; |
|
|
|
|
xSemaphoreTake(i2c_mutex, portMAX_DELAY); |
|
|
|
|
ret = mpu_->motion(&accel_, &gyro_); |
|
|
|
|
if (ret != ESP_OK) { |
|
|
|
|
ESP_LOGE(TAG, "error reading MPU: %#x", ret); |
|
|
|
|
if (!Initialize()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
uint8_t compass_data[7]; |
|
|
|
|
mpu_->setAuxI2CBypass(true); |
|
|
|
|
ret = mpu_bus_->readBytes(mpud::COMPASS_I2CADDRESS, 0x03, 7, compass_data); |
|
|
|
|
if (ret != ESP_OK) { |
|
|
|
|
ESP_LOGE(TAG, "error reading MPU compass: %#x", ret); |
|
|
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
xSemaphoreTake(i2c_mutex, portMAX_DELAY); |
|
|
|
|
ret = mpu_->motion(&accel_, &gyro_); |
|
|
|
|
if (ret != ESP_OK) { |
|
|
|
|
ESP_LOGE(TAG, "error reading MPU: %#x", ret); |
|
|
|
|
xSemaphoreGive(i2c_mutex); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
uint8_t compass_data[7]; |
|
|
|
|
mpu_->setAuxI2CBypass(true); |
|
|
|
|
ret = mpu_bus_->readBytes(mpud::COMPASS_I2CADDRESS, 0x03, 7, compass_data); |
|
|
|
|
if (ret != ESP_OK) { |
|
|
|
|
ESP_LOGE(TAG, "error reading MPU compass: %#x", ret); |
|
|
|
|
xSemaphoreGive(i2c_mutex); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
mpu_->setAuxI2CBypass(false); |
|
|
|
|
xSemaphoreGive(i2c_mutex); |
|
|
|
|
int16_t mx = (static_cast<int16_t>(compass_data[1]) << 8) | |
|
|
|
|
static_cast<int16_t>(compass_data[0]); |
|
|
|
|
int16_t my = (static_cast<int16_t>(compass_data[3]) << 8) | |
|
|
|
|
static_cast<int16_t>(compass_data[2]); |
|
|
|
|
int16_t mz = (static_cast<int16_t>(compass_data[5]) << 8) | |
|
|
|
|
static_cast<int16_t>(compass_data[4]); |
|
|
|
|
// ESP_LOGV(TAG, "compass: %d, %d, %d", mx, my, mz);
|
|
|
|
|
data.accel = mpud::accelGravity(accel_, MPU_ACCEL_FS); |
|
|
|
|
data.accel = ACCEL_MAT * (data.accel + ACCEL_OFFSET); |
|
|
|
|
data.gyro_rate = mpud::gyroDegPerSec(gyro_, MPU_GYRO_FS); |
|
|
|
|
data.gyro_rate = GYRO_MAT * (data.gyro_rate + GYRO_OFFSET); |
|
|
|
|
data.mag.x = ((float)mx) * MPU_MAG_TO_FLUX; |
|
|
|
|
data.mag.y = ((float)my) * MPU_MAG_TO_FLUX; |
|
|
|
|
data.mag.z = ((float)mz) * MPU_MAG_TO_FLUX; |
|
|
|
|
data.mag = MAG_MAT * (data.mag + MAG_OFFSET); |
|
|
|
|
xSemaphoreTake(mutex_, pdMS_TO_TICKS(100)); |
|
|
|
|
last_data_ = data; |
|
|
|
|
xSemaphoreGive(mutex_); |
|
|
|
|
} |
|
|
|
|
mpu_->setAuxI2CBypass(false); |
|
|
|
|
xSemaphoreGive(i2c_mutex); |
|
|
|
|
int16_t mx = (static_cast<int16_t>(compass_data[1]) << 8) | |
|
|
|
|
static_cast<int16_t>(compass_data[0]); |
|
|
|
|
int16_t my = (static_cast<int16_t>(compass_data[3]) << 8) | |
|
|
|
|
static_cast<int16_t>(compass_data[2]); |
|
|
|
|
int16_t mz = (static_cast<int16_t>(compass_data[5]) << 8) | |
|
|
|
|
static_cast<int16_t>(compass_data[4]); |
|
|
|
|
// ESP_LOGV(TAG, "compass: %d, %d, %d", mx, my, mz);
|
|
|
|
|
data.accel = mpud::accelGravity(accel_, MPU_ACCEL_FS); |
|
|
|
|
data.accel = ACCEL_MAT * (data.accel + ACCEL_OFFSET); |
|
|
|
|
data.gyro_rate = mpud::gyroDegPerSec(gyro_, MPU_GYRO_FS); |
|
|
|
|
data.gyro_rate = GYRO_MAT * (data.gyro_rate + GYRO_OFFSET); |
|
|
|
|
data.mag.x = ((float)mx) * MPU_MAG_TO_FLUX; |
|
|
|
|
data.mag.y = ((float)my) * MPU_MAG_TO_FLUX; |
|
|
|
|
data.mag.z = ((float)mz) * MPU_MAG_TO_FLUX; |
|
|
|
|
data.mag = MAG_MAT * (data.mag + MAG_OFFSET); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MPU::TaskEntry(void *arg) { |
|
|
|
|
MPU *mpu = (MPU *)arg; |
|
|
|
|
mpu->DoTask(); |
|
|
|
|
vTaskDelete(NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}; // namespace io
|
|
|
|
|