From 989874b7bf0f480433d57418ee8cee5d383f67bc Mon Sep 17 00:00:00 2001 From: Abel Tim Date: Wed, 3 Jul 2024 15:37:21 +0200 Subject: direction code and better IR seeker code --- debug/IMU_comp/IMU_comp.ino | 104 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 18 deletions(-) (limited to 'debug/IMU_comp/IMU_comp.ino') diff --git a/debug/IMU_comp/IMU_comp.ino b/debug/IMU_comp/IMU_comp.ino index 0c3928d..fc35244 100644 --- a/debug/IMU_comp/IMU_comp.ino +++ b/debug/IMU_comp/IMU_comp.ino @@ -1,8 +1,33 @@ +/* +This sketch combines magnetometer readings from an LIS3MDL and accelerometer +readings from an LSM6 to calculate a tilt-compensated magnetic heading. It +requires Pololu's LSM6 Arduino library to be installed: + +https://github.com/pololu/lsm6-arduino + +This program can be used with a board that includes both sensors, like the +Pololu MinIMU-9 v5 and AltIMU-10 v5, or with separate carrier boards for the two +sensors, both connected to the same I2C bus. If you are using separate boards, +make sure the axes are oriented the same way on both (i.e. the X, Y, and Z axes +of both boards should point in the same direction, and the surfaces of the +boards should be as close to parallel as possible). +*/ + #include #include -#include +#include LIS3MDL mag; +LSM6 imu; +int front = 0; + +/* +Calibration values; the default values of +/-32767 for each axis +lead to an assumed magnetometer bias of 0. Use the Calibrate example +program to determine appropriate values for your particular unit. +*/ +LIS3MDL::vector m_min = {+942, +3436, -3323}; +LIS3MDL::vector m_max = {+1053, +3559, -3142}; void setup() { @@ -11,35 +36,78 @@ void setup() if (!mag.init()) { - Serial.println("Failed to detect and initialize magnetometer!"); + Serial.println("Failed to detect and initialize LIS3MDL magnetometer!"); while (1); } - mag.enableDefault(); + + if (!imu.init()) + { + Serial.println("Failed to detect and initialize LSM6 IMU!"); + while (1); + } + imu.enableDefault(); + + //get start heading + mag.read(); + imu.read(); + float heading = computeHeading(); + front = heading; + Serial.println(heading); + } void loop() { mag.read(); + imu.read(); - // Calculate heading - float heading = atan2(mag.m.y, mag.m.x); - if (heading < 0) - heading += 2 * PI; // Normalize heading to positive angles - // Convert from radians to degrees - float headingDegrees = heading * 180.0 / PI; + float heading = computeHeading(); + int offset = front - heading; + + Serial.print("heading: "); + Serial.print(heading); + Serial.print(", goal location: "); + Serial.print(front); + Serial.print(", offset: "); + + Serial.println(offset); - // Adjust for magnetic declination if needed - // headingDegrees += magneticDeclination; + delay(100); +} - // Normalize headingDegrees to [0, 360) range - if (headingDegrees >= 360.0) - headingDegrees -= 360.0; +template float computeHeading(LIS3MDL::vector from) +{ + LIS3MDL::vector temp_m = {mag.m.x, mag.m.y, mag.m.z}; - // Print heading - Serial.print("Heading: "); - Serial.println(headingDegrees); + // copy acceleration readings from LSM6::vector into an LIS3MDL::vector + LIS3MDL::vector a = {imu.a.x, imu.a.y, imu.a.z}; - delay(100); + // subtract offset (average of min and max) from magnetometer readings + temp_m.x -= ((int32_t)m_min.x + m_max.x) / 2; + temp_m.y -= ((int32_t)m_min.y + m_max.y) / 2; + temp_m.z -= ((int32_t)m_min.z + m_max.z) / 2; + + // compute E and N + LIS3MDL::vector E; + LIS3MDL::vector N; + LIS3MDL::vector_cross(&temp_m, &a, &E); + LIS3MDL::vector_normalize(&E); + LIS3MDL::vector_cross(&a, &E, &N); + LIS3MDL::vector_normalize(&N); + + // compute heading + float heading = atan2(LIS3MDL::vector_dot(&E, &from), LIS3MDL::vector_dot(&N, &from)) * 180 / PI; + if (heading < 0) heading += 360; + return heading; +} + +/* +Returns the angular difference in the horizontal plane between a +default vector (the +X axis) and north, in degrees. +*/ +float computeHeading() +{ + return computeHeading((LIS3MDL::vector){1, 0, 0}); } -- cgit v1.2.3