Как реализовать компас с компенсацией наклона?
Поэтому я пытался реализовать компас с компенсацией наклона, используя HMC5883L и MPU6050. Проблема, с которой я сталкиваюсь, заключается в том, что существует 2 уравнения компенсации наклона
Компенсация наклона X: X,Y,Z-это выход компаса (необработанный выход).
new_X = X*cos(pitch) + Y*sin(roll)*sin(pitch) – Z*cos(roll)*sin(pitch)
Компенсация наклона Y:
новый Y = Y*cos(рулон) + Z*sin(рулон)
Заключительный заголовок :
Азимут = atan2(Y, X) * RAD_TO_DEG
Углы, которые я получаю от mpu,-это углы с поправкой на дрейф гироскопа, которые проходят через фильтр Калмана. Эти углы подаются в вышеприведенные уравнения, и после atan2
я получаю направление с компенсацией наклона. Но проблема/наблюдение здесь заключается в том, что когда я поворачиваю тело(на котором находятся компас и mpu) вдоль оси Z (ось рыскания), заголовок не меняется(вроде как заблокирован), но меняется, когда я наклоняю тело в X/Y.
Я искал подробные ссылки, но не смог найти ни одной!
Вот мой фрагмент кода (использует библиотеку compass part form adafruit):
double HEADING(double r, double p){
sensors_event_t event;
mag.getEvent(&event);
r = r * (PI/180);
p = p * (PI/180);
double x = (event.magnetic.x)*cos(p) + (event.magnetic.y)*sin(r)*sin(p) - (event.magnetic.z)*cos(r)*sin(p);
double y = (event.magnetic.y)*cos(r) + (event.magnetic.z)*sin(r);
float heading = atan2(y,x);
float declinationAngle = 0.366667 * (PI/180);// (0°22')positve склонение
heading += declinationAngle;
if(heading < 0)
heading += 2*PI;
if(heading > 2*PI)
heading -= 2*PI;
heading = heading * 180/PI;
return heading;
}
Сбор данных HMC5883L я написал :
// мне просто нужна ссылка на направление, а не на фактический курс, просто чтобы сохранить свой беспилотник
// устойчиво на оси рыскания относительно этого направления, но оно должно быть компенсировано наклоном.
#include<Wire.h>
#define MAG 0x1E
#define R 0
#define P 1
#define Y 2
float mag_raw[3],h;
float CMP_DEC = 0.36667 * (PI/180);
void setup(){
Serial.begin(115200);
Wire.begin();
Wire.setClock(400000);
Wire.beginTransmission(MAG);
Wire.write(0x02);
Wire.write(0x00);
Wire.endTransmission(true);
}
void loop(){
Wire.beginTransmission(MAG);
Wire.write(0x03);
Wire.endTransmission(false);
Wire.requestFrom(MAG,6,true);
mag_raw[R] = Wire.read() << 8 | Wire.read();
mag_raw[P] = Wire.read() << 8 | Wire.read();
mag_raw[Y] = Wire.read() << 8 | Wire.read();
h = atan2(mag_raw[P],mag_raw[R]);
// h += CMP_DEC;
if(h < 0) h+= (2*PI);
if(h > (2*PI)) h -= (2*PI);
h *= (180/PI);
// Serial.print("X : ");
// Serial.print(mag_raw[R]);
// Serial.print(" Y : ");
// Serial.print(mag_raw[P]);
// Serial.print(" Z : ");
// Serial.print(mag_raw[Y]);
Serial.print(" H : ");
Serial.println(h);
}
Некоторые рекомендации будут очень полезны!
@Sajil, 👍3
Обсуждение1 ответ
Проверяя ваш код, вы не обнаруживаете, что компенсируете необработанные значения магнитометра для эффектов мягкого и твердого железа. Эти термины примерно относятся к регулировке диапазона и величины каждого из отдельных магнитометров (X, Y и Z). Некоторые производители магнитометров позволяют записывать эти значения компенсации в микросхему. Даже в этом случае разработчику и пользователю все равно придется выполнить некоторую калибровку, так как магнитометр не может предсказать, при каких условиях он будет использоваться. Вот еще одно объяснение с использованием матриц компенсации твердого и мягкого железа.
Однажды компас дает ожидаемые результаты на плоской поверхности, параллельной поверхности земли (в том месте на земле, где магнитные линии примерно совпадают с истинным севером). Подумайте о добавлении компенсации наклона. Акселерометры обычно не нуждаются в такой интенсивной компенсации, как магнитометры.
Это можно сделать с помощью тригонометрической математики и углов Эйлера. Однако, как и в случае с физическими азартнымииграми, это может привести к ситуации, аналогичной карданной блокировке. Где тригонометрическая математика уходит в бесконечность.
Чтобы избежать подобной ситуации с карданным замком, большинство компасов с компенсацией наклона используют кватернионы. Кватернионы используют мнимые числа и матричную математику для описания трехмерного вращения.
- Как очистить буфер FIFO на MPU6050?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Понимание того, почему следует избегать «String» и альтернативных решений
- Объяснение кода MPU6050
- Изменение адреса I2C MPU-6050
- Снять гравитацию с акселерометра MPU-6050
- Скорость передачи данных акселерометра mpu6050 в Arduino Uno и частота дискретизации mpu6050
- Как соединить L293D и MPU6050 для совместной работы?
Вы пишете весь код? (Не используете библиотеки?) Я спрашиваю, поскольку вы не упомянули, как вы компенсируете выход магнитометра для ошибок твердого и мягкого железа. Создать наклонный компас достаточно сложно. Но я считаю, что лучше, если писать большую часть или весь код с нуля, создать обычный (использовать его плашмя на столе) компас 1st., @st2000
@st2000 Я попытался написать свой собственный код (общий подход для i2C Wire lib). Иногда я получал сплошной вывод (никаких изменений в данных, даже если я двигаюсь по другой оси), иногда данные приходили, но диапазон оставался почти около 170 для осей X , 65000 для осей Y и 56 для осей Z. Я не понимал, что происходит, поэтому начал использовать библиотеки :( можете ли вы дать мне несколько соответствующих ссылок ?, @Sajil
Малы ли углы тангажа и крена, когда тело лежит плашмя на столе? Изменяются ли необработанные значения компонентов магнитного поля при его вращении?, @Edgar Bonet
@EdgarBonet я отвечу в соответствии с тем, что я понял; Таким образом, углы R&P, исходящие от MPU, составляют 0±0.1°, когда они находятся на плоской поверхности. Теперь, когда я поворачиваю компас вдоль оси Z, значения не меняются(на самом деле они есть, но они изменились примерно на 3 точки, когда я повернул их на 90°!). Для осей X,Y значения сильно меняются !почти ±120 единиц. я просто добавлю свой *с нуля* написанный код в вопрос. Посмотрите на него, может быть, что-то не так видно..., @Sajil
@Sajil, начни с простого! Просто старайтесь заставить магнитометр работать. Забудьте об акселерометре. Тем не менее, я еще не видел, чтобы магнитометр выводил полезную информацию без компенсации диапазона (сложение или вычитание числа так, чтобы максимум и минимум данной оси были одинаковыми) и величины (умножение на число так, чтобы максимум и минимум всех 3 осей были одинаковыми). Пока вы этого не сделаете, выполнение математики на выходе магнитометра даст вам мусор., @st2000
@st2000 да, позвольте мне еще немного поработать над магнитометром. Не могли бы вы прислать мне несколько рекомендаций по этому поводу ? Возможно, не используя библиотеки (мне легко без библиотек )., @Sajil