bool imu6ManufacturingTest(void) { bool testStatus = false; Axis3f gyro; // Gyro axis data in deg/s Axis3f acc; // Accelerometer axis data in mG float pitch, roll; uint32_t startTick = xTaskGetTickCount(); testStatus = mpu6500SelfTest(); if (testStatus) { while (xTaskGetTickCount() - startTick < IMU_VARIANCE_MAN_TEST_TIMEOUT) { imu6Read(&gyro, &acc); if (gyroBias.isBiasValueFound) { DEBUG_PRINT("Gyro variance test [OK]\n"); break; } } if (gyroBias.isBiasValueFound) { // Calculate pitch and roll based on accelerometer. Board must be level pitch = tanf(-acc.x/(sqrtf(acc.y*acc.y + acc.z*acc.z))) * 180/(float) M_PI; roll = tanf(acc.y/acc.z) * 180/(float) M_PI; if ((fabsf(roll) < IMU_MAN_TEST_LEVEL_MAX) && (fabsf(pitch) < IMU_MAN_TEST_LEVEL_MAX)) { DEBUG_PRINT("Acc level test [OK]\n"); testStatus = true; } else { DEBUG_PRINT("Acc level test Roll:%0.2f, Pitch:%0.2f [FAIL]\n", roll, pitch); testStatus = false; } } else { DEBUG_PRINT("Gyro variance test [FAIL]\n"); testStatus = false; } } return testStatus; }
void imu9Read(Axis3f* gyroOut, Axis3f* accOut, Axis3f* magOut) { imu6Read(gyroOut, accOut); if (isHmc5883lPresent) { hmc5883lGetHeading(&mag.x, &mag.y, &mag.z); magOut->x = (float)mag.x / MAG_GAUSS_PER_LSB; magOut->y = (float)mag.y / MAG_GAUSS_PER_LSB; magOut->z = (float)mag.z / MAG_GAUSS_PER_LSB; } else { magOut->x = 0.0; magOut->y = 0.0; magOut->z = 0.0; } }
void imu9Read(Axis3f* gyroOut, Axis3f* accOut, Axis3f* magOut) { imu6Read(gyroOut, accOut); if (isHmc5883lPresent) { hmc5883lGetHeading(&mag.x, &mag.y, &mag.z); magOut->x = (fix_t)mag.x * (1.0k / MAG_GAUSS_PER_LSB); magOut->y = (fix_t)mag.y * (1.0k / MAG_GAUSS_PER_LSB); magOut->z = (fix_t)mag.z * (1.0k / MAG_GAUSS_PER_LSB); } else { magOut->x = 0.0k; magOut->y = 0.0k; magOut->z = 0.0k; } }
void imu9Read(Axis3f* gyroOut, Axis3f* accOut, Axis3f* magOut) { imu6Read(gyroOut, accOut); if (isMagPresent) { ak8963GetHeading(&mag.x, &mag.y, &mag.z); ak8963GetOverflowStatus(); magOut->x = (float)mag.x / MAG_GAUSS_PER_LSB; magOut->y = (float)mag.y / MAG_GAUSS_PER_LSB; magOut->z = (float)mag.z / MAG_GAUSS_PER_LSB; } else { magOut->x = 0.0; magOut->y = 0.0; magOut->z = 0.0; } }
static void stabilizerTask(void* param) { uint32_t attitudeCounter = 0; uint32_t altHoldCounter = 0; uint32_t lastWakeTime; vTaskSetApplicationTaskTag(0, (void*)TASK_STABILIZER_ID_NBR); //Wait for the system to be fully started to start stabilization loop systemWaitStart(); lastWakeTime = xTaskGetTickCount (); while(1) { vTaskDelayUntil(&lastWakeTime, F2T(IMU_UPDATE_FREQ)); // 500Hz imu6Read(&gyro, &acc); hmc5883lGetHeading(&heading.x, &heading.y, &heading.z); if (imu6IsCalibrated()) { commanderGetRPY(&eulerRollDesired, &eulerPitchDesired, &eulerYawDesired); commanderGetRPYType(&rollType, &pitchType, &yawType); // 250HZ if (++attitudeCounter >= ATTITUDE_UPDATE_RATE_DIVIDER) { sensfusion6UpdateQ(gyro.x, gyro.y, gyro.z, acc.x, acc.y, acc.z, FUSION_UPDATE_DT); sensfusion6GetEulerRPY(&eulerRollActual, &eulerPitchActual, &eulerYawActual); accWZ = sensfusion6GetAccZWithoutGravity(acc.x, acc.y, acc.z); // Estimate speed from acc (drifts) vSpeed += deadband(accWZ, vAccDeadband) * FUSION_UPDATE_DT; controllerCorrectAttitudePID(eulerRollActual, eulerPitchActual, eulerYawActual, eulerRollDesired, eulerPitchDesired, -eulerYawDesired, &rollRateDesired, &pitchRateDesired, &yawRateDesired); attitudeCounter = 0; } // 100HZ if (imuHasBarometer() && (++altHoldCounter >= HOVER_UPDATE_RATE_DIVIDER)) { stabilizerAltHoldUpdate(); altHoldCounter = 0; } if (rollType == RATE) { rollRateDesired = eulerRollDesired; } if (pitchType == RATE) { pitchRateDesired = eulerPitchDesired; } if (yawType == RATE) { yawRateDesired = -eulerYawDesired; } // TODO: Investigate possibility to subtract gyro drift. controllerCorrectRatePID(gyro.x, -gyro.y, gyro.z, rollRateDesired, pitchRateDesired, yawRateDesired); controllerGetActuatorOutput(&actuatorRoll, &actuatorPitch, &actuatorYaw); if (!altHold || !imuHasBarometer()) { // Use thrust from controller if not in altitude hold mode commanderGetThrust(&actuatorThrust); } else { // Added so thrust can be set to 0 while in altitude hold mode after disconnect commanderWatchdog(); } if (actuatorThrust > 0) { #if defined(TUNE_ROLL) distributePower(actuatorThrust, actuatorRoll, 0, 0); #elif defined(TUNE_PITCH) distributePower(actuatorThrust, 0, actuatorPitch, 0); #elif defined(TUNE_YAW) distributePower(actuatorThrust, 0, 0, -actuatorYaw); #else distributePower(actuatorThrust, actuatorRoll, actuatorPitch, -actuatorYaw); #endif } else { distributePower(0, 0, 0, 0); controllerResetAllPID(); } } } }
bool sensorsAreCalibrated() { Axis3f dummyData; imu6Read(&dummyData, &dummyData); return imu6IsCalibrated(); }
static void stabilizerTask(void* param) { uint32_t attitudeCounter = 0; uint32_t lastWakeTime; vTaskSetApplicationTaskTag(0, (void*)TASK_STABILIZER_ID_NBR); //Wait for the system to be fully started to start stabilization loop systemWaitStart(); lastWakeTime = xTaskGetTickCount (); while(1) { vTaskDelayUntil(&lastWakeTime, F2T(IMU_UPDATE_FREQ)); imu6Read(&gyro, &acc); hmc5883lGetHeading(&magHeadingX, &magHeadingY, &magHeadingZ); if(altMode == ALTIMETER_MODE_PRESSURE) { altimeterTmp = ms5611GetPressure(MS5611_OSR_4096); if(altimeterTmp > 0.0f) { pressure = altimeterTmp; altMode = ALTIMETER_MODE_TEMPERATURE; } } if(altMode == ALTIMETER_MODE_TEMPERATURE) { altimeterTmp = ms5611GetTemperature(MS5611_OSR_4096); if(altimeterTmp > 0.0f) { temperature = altimeterTmp; altMode = ALTIMETER_MODE_PRESSURE; } } if (imu6IsCalibrated()) { commanderGetRPY(&eulerRollDesired, &eulerPitchDesired, &eulerYawDesired); commanderGetRPYType(&rollType, &pitchType, &yawType); if (++attitudeCounter >= ATTITUDE_UPDATE_RATE_DIVIDER) { //sensfusion6UpdateQ(gyro.x, gyro.y, gyro.z, acc.x, acc.y, acc.z, FUSION_UPDATE_DT); //sensfusion6GetEulerRPY(&eulerRollActual, &eulerPitchActual, &eulerYawActual); //controllerCorrectAttitudePID(eulerRollActual, eulerPitchActual, eulerYawActual, // eulerRollDesired, eulerPitchDesired, -eulerYawDesired, // &rollRateDesired, &pitchRateDesired, &yawRateDesired); //controllerCorrectAttitudePID(0, 0, 0, 0, 0, 0, &rollRateDesired, &pitchRateDesired, &yawRateDesired); attitudeCounter = 0; } if (rollType == RATE) { rollRateDesired = eulerRollDesired; } if (pitchType == RATE) { pitchRateDesired = eulerPitchDesired; } if (yawType == RATE) { yawRateDesired = -eulerYawDesired; } /* // TODO: Investigate possibility to subtract gyro drift. controllerCorrectRatePID(gyro.x, -gyro.y, gyro.z, rollRateDesired, pitchRateDesired, yawRateDesired); controllerGetActuatorOutput(&actuatorRoll, &actuatorPitch, &actuatorYaw); */ commanderGetTrust(&actuatorThrust); distributePower(actuatorThrust, 0, 0, 0); if (actuatorThrust > 0) { #if defined(TUNE_ROLL) distributePower(actuatorThrust, actuatorRoll, 0, 0); #elif defined(TUNE_PITCH) distributePower(actuatorThrust, 0, actuatorPitch, 0); #elif defined(TUNE_YAW) distributePower(actuatorThrust, 0, 0, -actuatorYaw); #else distributePower(actuatorThrust, actuatorRoll, actuatorPitch, -actuatorYaw); #endif } else { distributePower(0, 0, 0, 0); controllerResetAllPID(); } #if 0 static int i = 0; if (++i > 19) { uartPrintf("%i, %i, %i\n", (int32_t)(eulerRollActual*100), (int32_t)(eulerPitchActual*100), (int32_t)(eulerYawActual*100)); i = 0; } #endif } } }