Робот, который должен был ехать строго на юг к зарядной станции, первые выезды делал с точностью до наоборот. Виноват был не мотор, а компас: модуль GY-271 с рынка, библиотека для HMC5883L — и вечно нули в ответе. Разбор занял два вечера и одной фразой в даташите: на одинаковых с виду модулях стоят разные чипы, и библиотеки у них не взаимозаменяемые.
В этом уроке разведём эти два чипа по именам, настроим QMC5883L на непрерывную работу, вытащим магнитные проекции X и Y, соберём из них курс в градусах и нарисуем на LCD стрелку со сторонами света. По пути разберём калибровку поворотом на 360 градусов, магнитное склонение и почему компас нельзя ставить вплотную к мотору. Всё по голому Wire — как и датчик движения из прошлых уроков, компас живёт на общих A4 и A5 и делит шину с чем угодно.
Зачем это в самоделках? Флюгер, который пишет в лог, откуда дует ветер, робот, возвращающийся к базе не по памяти о траектории, а по честному курсу, солнечная панель, поворачивающаяся на юг. Во всех трёх случаях на шину вешается один маленький магнитометр, и двадцать строк кода превращают его в стрелку. Единственная непривычная часть — то, что компас меряет не ваши намерения, а реальное магнитное поле, включая всё железо вокруг; с этим и будем разбираться.
Два компаса на одной плате: HMC против QMC
Первое, что я делаю с новым компасом, — спрашиваю его имя сканером I2C-адресов: ответ 0x0D — это QMC5883L, ответ 0x1E — оригинальный HMC5883L. Дальше конфигурация двумя записями: в регистр 0x09 кладём 0x1D — чувствительность на максимуме, диапазон 8 Гаусс, опрос 200 раз в секунду, режим непрерывный; в регистр 0x0B — единицу, так требует даташит для периодического сброса магнитных доменов. Без второй записи курс медленно плывёт — я проверял на своём флюгере, час работы стоил пять градусов вранья.
Данные лежат с 0x00 по 0x05 — по три оси, и порядок байтов обратный к MPU6050: младший байт первый. Читаем Wire.read() | (Wire.read() << 8) — и не наоборот. Я однажды перепутал и получал курс с зеркалом по диагонали: повороты на восток читались как повороты на юг. Для курса хватает четырёх байтов — X и Y; ось Z нужна только с наклонной поправкой.
Пара слов про режимы из старшего полубайта конфигурации: OSR 512 ужимает шум, но требует больше времени на замер, OSR 128 шумнее — зато бодрее. Частота опроса 200 Гц нужна только быстро вращающимся штукам; флюгеру хватает десяти, а батарейный проект на 200 Гц высадит аккумулятор в считанные дни. Для медленной самоделки я ставлю 0x01 вместо 0x1D — те же оси, опрос раз в сотую секунды, ток падает во много раз.
Если датчик молчит, а сканер не видит 0x0D — проверьте питание: модуль трёхвольтовый, на платах с 5 В должен стоять стабилизатор, и на дешёвых клонах его иногда забывают. А про саму шину — два провода, подтяжки, борьбу с длинными линиями — я подробно писал в уроке про два провода на все устройства.
Курс из X и Y: арктангенс, склонение, наклон
Курс вылезает из горизонтальных проекций магнитного поля: heading = atan2(my, mx) * 57.2958, а если число вышло отрицательным — прибавляем 360 и получаем честные 0-359. Ноль — север, 90 — восток, 180 — юг. atan2 здесь не украшение, а необходимость: на диагоналях оба плеча могут быть любыми, и деление в лоб рвётся на нулях — тот же аргумент, что и с углом наклона из акселерометра.
Сырой курс — магнитный, а на картах географический: между ними магнитное склонение, в средней полосе России порядка восьми-одиннадцати градусов к востоку, и оно медленно меняется год от года. Для флюгера разница неважна, для похода на азимут — уже важна. Точное значение для своего города берите из свежих геофизических таблиц, а не из старых гайдов десятилетней давности.
Третья поправка — наклон. Стоит поднять край платы на десяток градусов, и часть поля переливается из горизонтальных осей в вертикальную, курс уезжает на десятки градусов. Полное лечение — измерять наклон акселерометром и выправлять оси: такой угол мы только что собирали в уроке про наклон из MPU6050. Дешёвая профилактика — держать плату горизонтально: лежащий компас честен.
Как проверить собранный курс, не выходя из комнаты, — моё любимое: телефон. Любое приложение-компас показывает магнитный курс, и его отклонение от вашего на два-три градуса — норма, на десять — ищите железо рядом или калибруйте заново. Телефон, правда, сам компенсирует наклон, поэтому сверяться нужно с платой, лежащей на столе, а не висящей в воздухе.
#include <Wire.h> const byte QMC = 0x0D; // у HMC5883L адрес 0x1E — это другой чип! int xMin = 32767, xMax = -32768;int yMin = 32767, yMax = -32768; void setup() { Serial.begin(9600); Wire.begin(); Wire.beginTransmission(QMC); Wire.write(0x09); // регистр конфигурации Wire.write(0x1D); // OSR 512, 8 Гаусс, 200 Гц, непрерывно Wire.endTransmission(); Wire.beginTransmission(QMC); Wire.write(0x0B); // SET/RESET period — требует даташит Wire.write(0x01); Wire.endTransmission();} void loop() { Wire.beginTransmission(QMC); Wire.write(0x00); // данные начинаются с младшего байта X Wire.endTransmission(false); Wire.requestFrom(QMC, 4); int mx = 0, my = 0; if (Wire.available() == 4) { mx = Wire.read() | Wire.read() << 8; // младший байт идёт первым! my = Wire.read() | Wire.read() << 8; } // калибровка: медленно вращайте плату на 360 градусов по столу if (mx < xMin) xMin = mx; if (mx > xMax) xMax = mx; if (my < yMin) yMin = my; if (my > yMax) yMax = my; float cx = mx - (xMin + xMax) / 2; float cy = my - (yMin + yMax) / 2; float heading = atan2(cy, cx) * 57.2958; // курс из магнитных осей if (heading < 0) heading += 360; // 0-360 вместо -180..180 Serial.print("hdg="); Serial.println(heading, 1); delay(100);}| Что искажает курс | Как это выглядит | Как лечу |
|---|---|---|
| Железо и магниты рядом | Курс скачет или залипает в одном секторе | Убрать источник, держать 20-30 см |
| Наклон платы | Курс уезжает при подъёме края на десяток градусов | Держать горизонтально или править по акселю |
| Нет калибровки | Курс несимметричен, повороты влево и вправо разные | Оборот на 360 и offset = (min + max) / 2 |
| Магнитное склонение | Курс стабильно врёт на 8-11 градусов в средней полосе | Прибавить склонение своего города числом |
Компас со стрелкой на LCD
Для человека градусы — мусор, сторона света — еда. Восемь секторов по 45 градусов решают вопрос цепочкой if: от 22,5 до 67,5 — северо-восток, от 67,5 до 112,5 — восток и так по кругу; сектор севера живёт с двух концов диапазона, потому что круг замыкается через ноль. На LCD печатаю латиницей — N, NE, E: в знакогенераторе HD44780 кириллицы нет, а самодельные шрифты — отдельное развлечение, разобранное в уроке про кириллицу на LCD.
Стрелку рисую символами: уголок-«стрелочка» поворачивается вместе с сектором, либо печатается само название — как в симуляторе этого урока. Если хочется плавной стрелки, курс с экрана перекладывается в угол сервопривода один в один; а подключение самого экрана по I2C я показывал в уроке про первый текст на LCD1602 — компас и дисплей мирно делят одну шину, у каждого свой адрес. Только помните: 16 столбцов LCD — это пять символов на курс и шесть на сектор, печатайте без хвостов и затирите пробелами остаток прошлой строки, иначе получите то самое призрачное «NW», которое на самом деле «N» от прошлого поворота.
В панели I2C видно весь сеанс: две записи конфигурации в 0x09 и 0x0B, затем постоянные запросы по четыре байта с регистра 0x00. Сектора и курс на LCD обновляются раз в триста миллисекунд — быстрее не нужно, флюгер направление не меняет чаще. Три задачи на закрепление: впишите своё магнитное склонение строкой heading = heading + 10; снизьте опрос с 200 до 10 Гц, заменив 0x1D на 0x01, — для батарейного флюгера это правильный режим; замените печать сектора стрелкой-символом из if-цепочки — на HD44780 отлично живут символы и латиница. А когда решите убрать delay() из батарейного флюгера и опрашивать компас по таймеру — урок про millis вместо delay покажет, как это делается без ломки логики.
И практическое напутствие: компас — датчик с характером, он верит в магнитное поле земли, а не в ваши ожидания. Калибруйте там, где он будет работать, держите подальше от моторов и не ставьте его вертикально без наклонной поправки — и тогда двадцать строк кода дают курс, который не стыдно показать на экране.
- 1. По какому адресу шины живёт QMC5883L?
- 2. Чем QMC5883L отличается от HMC5883L?
- 3. Какой байт идёт первым в данных оси X у QMC5883L?
- 4. Что сделать сразу после включения компаса, прежде чем верить курсу?
- 5. Почему компас нельзя вешать вплотную к мотору робота?
- GY-271 бывает двух видов: QMC5883L на 0x0D и HMC5883L на 0x1E — библиотеки не взаимозаменяемы
- Конфигурация QMC: регистр 0x09 = 0x1D (8 Гаусс, 200 Гц, непрерывно), регистр 0x0B = 0x01
- Байты осей идут младшим вперёд — противоположно MPU6050
- Курс = atan2(my, mx) * 57.2958, минус закрывается добавлением 360; склонение прибавляется числом
- Калибровка — оборот на 360 градусов, offset = (min + max) / 2; рядом с моторами компас не ставят
Частые вопросы по теме урока
- По какому адресу шины живёт QMC5883L?
- 0x0D — QMC5883L. 0x1E — его собрат HMC5883L, 0x68 — MPU6050, 0x27 — переходник PCF8574 на LCD. Сканер шины различит их за секунды. 0x0D
- Чем QMC5883L отличается от HMC5883L?
- Это разные микросхемы от разных производителей. Библиотека одного не работает с другим — отсюда и мои два вечера с нулями в мониторе. Другой чип: другой адрес, регистры и порядок байтов
- Какой байт идёт первым в данных оси X у QMC5883L?
- QMC5883L отдаёт младший байт первым — противоположно MPU6050. Перепутаете — получите курс, отражённый по диагонали. Младший
- Что сделать сразу после включения компаса, прежде чем верить курсу?
- Правильный ответ — калибровка оборотом: без неё смещения железа вокруг дают курс с сюрпризами. Регистр 0x75 — это у MPU6050, компас его не знает. Прочитать регистр 0x75
- Почему компас нельзя вешать вплотную к мотору робота?
- Магниты и катушки мотора в десятки раз сильнее земного поля. Компас честно покажет на мотор — держите его в двадцати-тридцати сантиметрах. Магниты мотора добавляют своё поле, и курс уезжает