Микронавигатор на STM32F100

Прототип выглядит так

Предыстория

  1. Весьма неочевидное управление. В некоторых приложениях я так и не понял, как заставить стрелку показывать в нужном мне направлении. Показывать на север — сколько угодно. Как задать другую точку назначения — почти всегда проблема.
  2. Часть приложений начинает показывать на юг, а не на север, если перевернуть телефон.
  3. Мой смартфон работает без подзарядки дня 3, не больше. Некоторые работают вообще 1 день. Маловато, честно говоря.

Постановка задачи

  1. Показывать направление из текущей точки и ориентации в пространстве в сторону заранее определенной координаты (например мой дом или местная достопримечательность).
  2. Иметь простой интерфейс и малые размеры.
  3. Питаться от батарейки и работать в автономном режиме без подзарядки не меньше месяца.
  4. Рассчитано на “эконом” сектор рынка.

Определение азимута

By derivative work: Pbroks13 (talk)RechtwKugeldreieck.svg: Traced by User:Stannered from a PNG by en:User:Rt66lt — RechtwKugeldreieck.svg, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4375381

Определение текущей ориентации

Куда должна показывать стрелка?

Так выглядит нормальный режим работы, когда устройство показывает туда, куда нужно, т.е. угол dX = О.
Взято отсюда: https://ru.onlinemschool.com/math/library/vector/multiply1/

Используемые компоненты

  1. Микроконтроллер stm32f100rbt6
  2. LCD дисплей Nokia 5110
  3. Акселерометр + гироскоп MPU6050
  4. GPS приемник Neo-6m
  5. Магнитометр LIS3MDL
  1. Коррекция времени, если разница со значением в RTC (встроенные часы реального времени) больше, чем 5 секунд.
  2. Коррекция своего положения и азимута.

Аппаратная часть

Сделано в https://easyeda.com/
  1. Контроллер общается с дисплеем по SPI.
  2. Магнитометр, гироскоп и акселерометр висят на шине I2C1.
  3. GPS модуль NEO-6M посылает данные по USART3.

Что не так с I2C в stm32f100x?

  • Генерация тактового сигнала
  • Генерация старт-сигнала и стоп-сигнала
  • Механизм подтверждения адреса
  • Использование двух Slave адресов
  • Обнаружение стоп-бита, выданного ведущим на линию
  • Генерация и определение 7/10 битных адресов
  • Поддержка разных скоростей передачи данных
  • Наличие множества флагов, сигнализирующих о событиях, а также об ошибках на линии
  • Slave приемник
  • Slave передатчик
  • Master приемник
  • Master передатчик
Взято из официальной документации
  1. Устанавливаем START (S)
  2. Ждем, когда установится бит SB (прерывание это или постоянный опрос регистра состояния — не имеет значения).
  3. Посылаем адрес устройства, с которым хотим общаться и признак того, что будем писать в устройство.
  4. Получаем ACK от него.
  5. Посылаем адрес регистра устройства, из которого хотим читать.
  6. Получаем ACK.
  7. Повторно посылаем START, чтоб другой мастер не перехватил управление линией.
  8. Посылаем адрес устройства, но на этот раз с признаком того, что будем читать из устройства.
  9. Читаем.
  10. После последнего принятого байта посылаем NACK и устанавливаем STOP состояние.
  1. Генерируем START.
  2. До состояния 2 включительно всё отрабатывает как надо. В состоянии 2 генерируется повторный START.
  3. После повторного старта возникает прерывание, но ни один из флагов прерывания I2C не выставлен. Ну т.е. вообще ни одного флага. Нет флагов ошибок, нет ни одного флага из таблицы прерываний, приведенной выше. Однако следующее чтение регистра SR поясняет, что всё таки выставлен флаг SB.

Что не так с магнитометрами?

#define MagXMin 1880#define MagXMax 5547#define MagYMin 6185#define MagYMax 10157#define MagZMin -6530#define MagZMax 5305#define MagXBias ((MagXMin + MagXMax) / 2)#define MagYBias ((MagYMin + MagYMax) / 2)#define MagZBias ((MagZMin + MagZMax) / 2)#define MagXAvgDelta ((MagXMax - MagXMin) / 2.0f)#define MagYAvgDelta ((MagYMax - MagYMin) / 2.0f)#define MagZAvgDelta ((MagZMax - MagZMin) / 2.0f)#define MagAvgDelta ((MagXAvgDelta + MagYAvgDelta + MagZAvgDelta) / 3.0f)#define MagXScale (MagAvgDelta / MagXAvgDelta)#define MagYScale (MagAvgDelta / MagYAvgDelta)#define MagZScale (MagAvgDelta / MagZAvgDelta)mx = (float)(m_magRaw.data.mx - MagXBias) * MagXScale;my = (float)(m_magRaw.data.my - MagYBias) * MagYScale;mz = (float)(m_magRaw.data.mz - MagZBias) * MagZScale;

Борьба с магнитным склонением

Результат

Попытка продемонстрировать, что стрелка действительно указывает в одном направлении при вращении устройства.
  1. Нормальное меню для настроек. Необходимо дать возможность менять свою временную зону.
  2. Добавить возможность удобно калибровать девайс.
  3. Добить PCB и заказать пару экземпляров.

Используйте и развивайте

Ссылки на используемые материалы

--

--

Mad Devs is a London-headquartered IT company developing enterprise-level software solutions for finance, transportation & logistics, security, edtech, and advertising industries. For more information about us, please browse our website: https://maddevs.io/

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store