Оглавление:

Уоллес - Автономный робот DIY - Часть 5 - Добавление IMU: 9 шагов
Уоллес - Автономный робот DIY - Часть 5 - Добавление IMU: 9 шагов

Видео: Уоллес - Автономный робот DIY - Часть 5 - Добавление IMU: 9 шагов

Видео: Уоллес - Автономный робот DIY - Часть 5 - Добавление IMU: 9 шагов
Видео: Происхождение человека: документальный фильм об эволюционном путешествии | ОДИН КУСОЧЕК 2024, Декабрь
Anonim
Image
Image

Мы идем вместе с Уоллесом. Имя Wallace произошло от смеси "Wall-E" и предыдущего проекта (распознавание голоса), и при использовании утилиты "espeak" оно звучало немного по-британски. И как камердинер или дворецкий. И это конечная цель: превратить этот проект во что-то полезное. Таким образом "Уоллес".

Уоллес может передвигаться, он может избегать препятствий, используя ИК-датчики расстояния (в последнее время они как-то поджарились (?) (Нужно разобраться в этом, когда у меня появится возможность), также есть некоторые акустические датчики расстояния (три из них вышли из строя одновременно time, вместе с расширителем MCP23017), и, наконец, может обнаруживать изменения в токе двигателя, чтобы знать, когда он во что-то врезался.

В дополнение к датчикам Уоллес «помнит» 100 движений и проводит некоторый элементарный анализ, используя историю движений.

На данный момент цель Уоллеса состоит в том, чтобы просто попытаться продолжать двигаться вперед и знать, когда он застревает в каком-то повторяющемся шаблоне (например, в углу), а не двигаться вперед.

Я прошел несколько итераций для движения и навигации, и постоянная головная боль была во время вращения.

Поскольку Уоллес - это отслеживаемый робот, и я хотел упростить программное обеспечение (на будущее), чтобы повернуть, я просто заставил его поворачивать / вращать на месте. Таким образом, подайте на двигатели равную, но противоположную мощность / рабочий цикл.

Возникшая проблема связана с конструкцией платформы робота Agent 390. Гусеничные ремни имеют тенденцию тереться о стороны. И что еще хуже, одна сторона делает это больше, чем другая.

На настиле и прямом движении это не было проблемой. Он появляется на ковровом покрытии. Я решил не прикасаться Уоллесом к ковровому покрытию после того, как его следы стали грязными (они очень легко собирают грязь).

Настоящая проблема возникает при повороте на полу.

Если у меня программное обеспечение применяет рабочий цикл высокого уровня, то оно более или менее стабильно крутится. Однако во время низкого рабочего цикла он может на самом деле повернуться, а может и не включиться. Или он может немного повернуться, а затем замедлиться. Поворотное действие кажется неконтролируемым с помощью программного обеспечения или, в лучшем случае, очень сложным.

Проблема проявляется во время навигации, а также при движении вокруг препятствий или вдали от них. Он может либо слишком сильно качнуться в сторону, либо застрять, пытаясь сделать очень незначительные изменения, даже не двигаясь.

Таким образом, вышеприведенное объяснение послужило толчком для создания данного Руководства.

Изначально я хотел обойтись без или отложить внедрение модуля обнаружения движения (IMU), потому что они: A) сложные, B) шумные, C) со временем могут появиться ошибки и т. Д. И т. Д. Было так, что мы могли бы преуспеть, перескочив вперед к времяпролетным инфракрасным лазерным датчикам. И мы могли - используя лазеры, мы могли узнать, вращается робот или нет, отслеживая изменения расстояния.

Фактически, мы могли бы (вроде) сделать это сейчас с помощью акустических датчиков.

Однако все это очень непрямой и сложный способ ответить на один простой вопрос: «Мы поменялись местами или нет?»

Мне казалось, что переход к использованию лазерных датчиков ToF выведет меня на новый уровень программного обеспечения; а именно SLAM (одновременная локализация и отображение). Я еще не был готов туда поехать.

Хорошо делать проект робота в слоях, причем первые (нижние) слои проще, а вторые (верхние) слои более абстрактны и решают более сложные проблемы.

Слои можно представить примерно так:

  1. физическая рама робота / механическая структурная основа
  2. элементарная система привода (Raspberry, Roboclaw, двигатели, кабели и т. д., базовое программное обеспечение, управляемое с клавиатуры)
  3. необходимые схемы для поддержки датчиков (двунаправленный переключатель напряжения, расширитель портов, аварийный останов, распределение питания и т. д.)
  4. датчики предотвращения препятствий (акустические, ИК)
  5. основное, базовое позиционирование и обнаружение движения (акселерометр, гироскоп, магнитометр, энкодеры двигателя, энкодеры колес)

Вы можете составить свой список. Смысл этого списка в том, что вам, вероятно, следует делать это более или менее в этом порядке, а также то, что если вы потратите некоторое время на каждый слой, чтобы привести каждый в хорошее рабочее состояние, это должно помочь вам позже, когда все станет более сложным.

Приведенный выше список может быть более или менее сопоставлен с этими концептуальными уровнями в программном обеспечении.

  • SLAM (одновременная локализация и отображение)
  • Контроль и осведомленность о движении, ротации
  • Избегание основных препятствий
  • Контроль и обнаружение данных датчиков
  • Существенное движение вперед, назад, влево и вправо, ускорение, замедление, остановка

Как видите, в этом списке первыми элементами будут верхние, более сложные уровни, которые решают более абстрактные проблемы и вопросы, такие как «где я» и «куда я иду», а последние элементы будут нижние программные уровни, которые обрабатывают «как говорить / слушать датчик A» или «как перемещать это колесо».

Я не говорю, что когда вы начинаете со слоя, вы завершаете его, а затем переходите на следующий слой, чтобы никогда не вернуться к предыдущему. Проект робота может во многом напоминать современные итеративные методы разработки программного обеспечения (гибкие, SCRUM и т. Д.).

Я просто говорю, чтобы уделить время каждому. Вам нужно будет сбалансировать, сколько нужно сделать на каждом уровне, и решить, стоит ли то, что вы пытаетесь сделать на определенном уровне, потратить время и усилия.

Существует определенный «конфликт» или «напряжение» между двумя конкурирующими идеями или направлениями.

Один из них - это то, что я бы назвал «plug-n-play» для решения проблемы A.

Другой - сделай сам (сделай сам). И это, возможно, даже не лучший лейбл для этой другой идеи.

Вот пример каждого из них, надеюсь, вы увидите напряжение или конфликт между двумя вариантами.

В этом примере давайте объединим SLAM, уклонение от препятствий и необходимое базовое движение как одну задачу, которую нужно решать одновременно.

  1. Если мы решим пойти по пути plug-n-play, мы немедленно перейдем (в зависимости от бюджета) к таким вещам, как установленные наверху вращающиеся лазеры, или камера глубины резкости, или лазеры ToF, и IMU (тема данной статьи). Поучительно).
  2. Если мы, с другой стороны, хотим пойти по второму пути, мы можем попытаться извлечь все возможные биты информации из некоторых акустических датчиков или ИК-датчиков или вообще без датчиков - мы просто используем мониторинг тока двигателя (удар)

Что можно сказать о №1 и №2? Одно может заключаться в том, что мы многому научимся, выполняя №2. Ограничения работы только с акустическими датчиками заставляют нас думать о гораздо большем количестве проблем.

С другой стороны, если мы слишком сосредоточены на выполнении действий с помощью пункта 2, мы можем зря тратить время, потому что просим от акустических датчиков большего, чем следовало бы.

Еще одна концепция или идея для размышления: какая комбинация аппаратного и программного обеспечения лучше всего отвечает на вопросы «как», а какая комбинация программного обеспечения (и оборудования?) Отвечает на вопрос «что», «когда», «где». Потому что «как сделать» обычно является вопросом более низкого уровня, от которого «что», «когда» и «где» зависят, чтобы получить ответ.

В любом случае, все вышесказанное было чем-то, над чем можно было подумать.

В моем случае, после огромных усилий и постоянной досадной проблемы трения гусеницы и невозможности обеспечить постоянный контроль и движение, пришло время заняться чем-то другим.

Таким образом, эта инструкция - ИДУ.

Цель состоит в том, чтобы, если IMU сообщает, что робот НЕ вращается, мы увеличиваем рабочий цикл. Если мы поворачиваемся слишком быстро, мы уменьшаем рабочий цикл.

Шаг 1. Датчик IMU

Датчик IMU
Датчик IMU
Датчик IMU
Датчик IMU

Итак, наш следующий датчик, который мы добавим к Уоллесу, - это IMU. После некоторых исследований я остановился на MPU6050. Но в то время MPU9050 (а еще недавно MPU9250) казался даже лучшей идеей.

Моим постоянным источником была Amazon (в США). Поэтому я заказал два из них.

Фактически, я получил (похоже, здесь нет никакого контроля; это то, что мне не нравится в Amazon), были два MPU92 / 65. Я немного задаюсь вопросом об обозначении. Взгляните на изображения; это похоже на «семейное» обозначение. В любом случае это то, с чем я застрял.

Добавить очень просто - получить макетную плату с соединительными дорожками, припаять датчик к плате, добавить 10-контактную клеммную колодку (я получил свой от Pololu).

Чтобы свести к минимуму любые помехи, я попытался разместить эти датчики подальше от всего остального.

Это также означало использование нейлоновых болтов / гаек.

Собираюсь использовать протокол I2C. Надеюсь, общая длина провода будет неплохой.

В другом месте есть много информации об основных соединениях, уровнях напряжения и т. Д., Поэтому я не буду повторять это здесь.

Шаг 2. Вещи не всегда чистые и легкие

На момент написания этой статьи, похоже, не так много онлайн для этого конкретного MPU-92/65. То, что доступно, как и большинство датчиков, похоже, является примерами использования Arduino.

Я стараюсь сделать эти инструкции немного другими, представляя не очень чистый процесс, потому что не всегда все работает сразу.

Я полагаю, что эти Instructables больше похожи на блог, чем на прямые A-B-C, 1-2-3 «вот как вы это делаете».

Шаг 3: Начальный тест

Начальный тест
Начальный тест
Начальный тест
Начальный тест

Из изображений на предыдущем шаге видно, что красный и черный провода, идущие к датчикам, - это, конечно, VCC (5 В) и GND. Зеленый и желтый провода - это соединения I2C.

Если вы выполняли другие проекты I2C или следили за этими сериями, то вы уже знаете о «i2cdetect», и это первый шаг, чтобы узнать, видит ли Raspberry новый датчик.

Как видно из изображений на этом этапе, наша первая попытка оказалась неудачной. IMU не отображается (должен быть идентификатор устройства 0x68).

Однако хорошая новость в том, что шина I2C работает. Мы действительно видим одно устройство 0x20, и это расширитель портов MCP23017 (в настоящее время отвечает за акустические датчики HCSR04).

Это непросто увидеть на изображении, но я подключил зеленые и желтые провода того же цвета от IMU к MCP23017 (см. Рисунок внизу слева).

Нам нужно будет устранить неполадки.

Шаг 4. Устранение неполадок

Image
Image
Исправление проблем
Исправление проблем
Исправление проблем
Исправление проблем

Используя настройку непрерывности на вольтметре (с высоким тональным сигналом), я проверил соединения VCC (5 В), GND, SDA и SCL. Это было хорошо.

Следующей попыткой было отключить MCP23017 от шины I2C, оставив на шине только MPU-92/65. Это оказалось безрезультатным - «i2cdetect» тогда не показал никаких устройств.

Итак, затем я снял датчик с тотемного столба и повторно подключил его прямо к двунаправленной шине с 5 В на 3 В; то есть прямо к Raspberry. (более короткие провода?).

И вуаля. На этот раз успех. Мы видим, что 0x68 отображается с помощью «i2cdetect».

Но мы пока не знаем, почему это сработало на этот раз. Может быть, дело в длине проводов? Предыдущее место?

Примечание: не имело никакого значения, обоснована АДО или нет. Возможно, на плате есть подтягивающие и понижающие резисторы. То же самое можно сказать и о FSYNC.

Затем я повторно подключил MCP23017. Итак, теперь у нас есть два устройства на шине I2C. (см. изображение). Успешно, теперь мы видим как 0x20, так и 0x68 с i2cdetect.

В видеороликах немного больше о том, что произошло во время устранения неполадок.

Шаг 5: Считывание данных датчика

Image
Image
Чтение данных датчика
Чтение данных датчика
Чтение данных датчика
Чтение данных датчика

Различные подходы

Я решил использовать несколько подходов к получению полезной информации от датчика. Вот они, не в любом порядке:

  1. попробуйте базовое программирование
  2. просмотрите онлайн-документацию по регистрам
  3. взгляните на чужие примеры и / или код

Почему эти подходы? Почему бы просто не поискать какую-нибудь существующую библиотеку или код?

Экспериментируя и пробуя некоторые идеи, мы можем лучше усвоить некоторые знания не только об этом конкретном датчике, но также получить некоторую технику, навыки и способы размышления о том, чтобы заняться чем-то новым и тем, что может не иметь большого количества документации; что-то, что может иметь много неизвестного.

Кроме того, после того, как мы поигрались и опробовали некоторые из наших собственных идей и получили некоторое понимание, мы можем лучше оценить чужой код или библиотеку.

Например, посмотрев некоторый код C ++ для MPU9250 в github, я понял, что он вынуждает меня использовать прерывания, чего я пока не хочу.

Кроме того, он поставляется с дополнительными функциями, такими как калибровка; опять же, кое-что мне пока неинтересно.

Может случиться так, что то, что мне нужно сделать, чтобы ответить на простой вопрос «вращается ли робот, да или нет», можно было ответить очень просто, просто прочитав несколько регистров.

Регистры

На момент написания этой статьи, похоже, не так много возможностей для этого датчика. На самом деле, если вы посмотрите на изображения, которые идут с этим Instructable, и внимательно посмотрите на надписи на реальных чипах, это заставит меня задуматься, не является ли это подделкой. Я не связываю то, что вижу, ни с чем из Invense. Тем не менее, я решил посмотреть регистрационную информацию для моделей, которые я нашел: MPU-6050 и MPU-9250.

В обоих случаях для обоих одинаково следующее. И для начала, мы предполагаем, что он будет таким же и для этого MPU-92/65.

59-64 - измерения акселерометра

65, 66 - измерения температуры с 67 по 72 - измерения с помощью гироскопа с 73 по 96 - данные внешнего датчика

Примечание: MPU-6050, похоже, НЕ имеет магнитометра, в то время как MPU-9250 (и мы предполагаем, что он тоже) есть.

Еще одна интересная, надеюсь, полезная информация почерпнута из регистрационного документа:

Информация о магнитометре:

идентификатор магнитометра: 0x48 регистров с 00 по 09: 00H WIA 0 1 0 0 1 0 0 0 01H INFO INFO7 INFO6 INFO5 INFO4 INFO3 INFO2 INFO1 INFO0 02H ST1 0 0 0 0 0 0 DOR DRDY 03H HXL HX7 HX6 HX5 HX4 HX3 HX2 HX1 HX1 HXH HX15 HX14 HX13 HX12 HX11 HX10 HX9 HX8 05H HYL HY7 HY6 HY5 HY4 HY3 HY2 HY1 HY0 06H HYH HY15 HY14 HY13 HY12 HY11 HY10 HY9 HY8 HY12 HY11 HY10 HY9 HY8 07H HZL HZ1 HZ7 HZ HZ 08 HZ HZ1 HZ7 HZ6 HZ0 HZ8 HZ1 HZ1 HZ7 HZ6 ST2 0 0 0 BITM HOFL 0 0 0 разбивка того, что означает каждый регистр: HXL [7: 0]: данные измерения по оси X ниже 8 бит HXH [15: 8]: данные измерения по оси X выше 8 бит HYL [7: 0]: Данные измерения по оси Y ниже 8 бит HYH [15: 8]: данные измерения по оси Y выше 8 бит HZL [7: 0]: данные измерения по оси Z ниже 8 бит HZH [15: 8]: данные измерения по оси Z выше 8 бит

Программирование

Еще одна часть информации из документации по регистрам - это то, что, по-видимому, было всего около 100 или около того регистров. Таким образом, можно было бы написать простую программу, которая обращается к устройству (0x68) и пытается последовательно читать серию регистров, не обращая внимания на их значение, просто чтобы посмотреть, какие данные можно увидеть.

А затем выполните последовательные проходы, используя один и тот же код, и сравните данные одного прохода с данными следующего.

Идея состоит в том, что мы могли бы, вероятно, исключить любые регистры, которые кажутся не имеющими данных (нулей или FF?) Или которые абсолютно никогда не меняются, и мы также могли бы сосредоточиться на тех, которые действительно меняются.

Затем, когда мы смотрим только на те, которые меняются, добавляем функцию усреднения, которая усредняет последние N чтений этого регистра, чтобы увидеть, действительно ли существует определенное устойчивое значение для этого регистра. Это предполагает, что мы держим датчик неподвижно и в одном и том же месте.

Наконец, мы могли бы затем осторожно попробовать что-то с датчиком, например, подтолкнуть его (акселерометр, гироскоп) или подуть на него (температура) или повернуть его (предыдущие два плюс магнитометр) и посмотреть, как это повлияет на значения.

Мне нравится использовать библиотеку wiringPi, насколько это возможно. Имеет поддержку I2C.

Первый забег:

/********************************************************************************

* для сборки: gcc first.test.mpu9265.c -o first.test.mpu9265 -lwiringPi * * для запуска: sudo./first.test.mpu9265 * * эта программа просто выводит диапазон (возможных) регистров из MCP23017, * а затем из MPU9265 (или любого другого MPU по этому адресу 0x68) * * Я использовал его, чтобы проверить, могу ли я вообще читать с датчика, поскольку я уже * был уверен в MCP23017. * ************************************************ *************************** / #include #include #include #include #include int main (int argc, char ** argv) {put ("Посмотрим, что скажет MCP23017 @ 0x20:"); errno = 0; int deviceId1 = 0x20; int fd1 = wiringPiI2CSetup (deviceId1); if (-1 == fd1) {fprintf (stderr, «Невозможно открыть устройство WiringPi I2C:% s / n», strerror (errno)); возврат 1; } для (int reg = 0; reg <300; reg ++) {fprintf (stderr, "% d", wiringPiI2CReadReg8 (fd1, reg)); fflush (stderr); задержка (10); } кладет (""); put ("Посмотрим, что скажет MPU9265 @ 0x20:"); errno = 0; int deviceId2 = 0x68; int fd2 = wiringPiI2CSetup (deviceId2); if (-1 == fd2) {fprintf (stderr, «Невозможно открыть устройство WiringPi I2C:% s / n», strerror (errno)); возврат 1; } для (int reg = 0; reg <300; reg ++) {fprintf (stderr, "% d", wiringPiI2CReadReg8 (fd2, reg)); fflush (stderr); задержка (10); } кладет (""); возврат 0; }

Второй запуск:

/********************************************************************************

* для сборки: gcc second.test.mpu9265.c -o second.test.mpu9265 -lwiringPi * * для запуска: sudo./second.test.mpu9265 * * Эта программа выводит номер регистра вместе с прочитанным значением. * * Это делает полезным направлять (перенаправлять) вывод в файл, а затем * можно выполнить несколько запусков для сравнения. Это может дать некоторое представление о том, какие регистры важны и как могут вести себя данные. * ************************************************ *************************** / #include #include #include #include #include #include int main (int argc, char ** argv) {int deviceId = -1; if (0) {} else if (! strncmp (argv [1], "0x20", strlen ("0x20"))) {deviceId = 0x20; } иначе, если (! strncmp (argv [1], «0x68», strlen («0x68»))) {deviceId = 0x68; } иначе, если (! strncmp (argv [1], «0x69», strlen («0x69»))) {deviceId = 0x69; } put ("Давайте посмотрим, что скажет MPU9265 @ 0x20:"); errno = 0; int fd = wiringPiI2CSetup (deviceId); if (-1 == fd) {fprintf (stderr, «Невозможно открыть устройство WiringPi I2C:% s / n», strerror (errno)); возврат 1; } для (int reg = 0; reg <300; reg ++) {fprintf (stderr, "% d:% d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); задержка (10); } return 0; }

Третий запуск:

/********************************************************************************

* для сборки: gcc third.test.mpu9265.c -o third.test.mpu9265 -lwiringPi * * для запуска: sudo./third.test.mpu9265 * * Эта программа является результатом второй. Он только читает из регистров *, которые указывают разницу между одним запуском и другим.* ************************************************ *************************** / #include #include #include #include #include #include int main (int argc, char ** argv) {int deviceId = -1; if (0) {} else if (! strncmp (argv [1], "0x68", strlen ("0x68"))) {deviceId = 0x68; } иначе, если (! strncmp (argv [1], «0x69», strlen («0x69»))) {deviceId = 0x69; } put ("Давайте посмотрим, что скажет MPU9265 @ 0x20:"); errno = 0; int fd = wiringPiI2CSetup (deviceId); if (-1 == fd) {fprintf (stderr, «Невозможно открыть устройство WiringPi I2C:% s / n», strerror (errno)); возврат 1; } для (int reg = 61; reg <= 73; reg ++) {fprintf (stderr, "% d:% d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); задержка (10); } для (int reg = 111; reg <= 112; reg ++) {fprintf (stderr, "% d:% d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); задержка (10); } для (int reg = 189; reg <= 201; reg ++) {fprintf (stderr, "% d:% d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); задержка (10); } для (int reg = 239; reg <= 240; reg ++) {fprintf (stderr, "% d:% d / n", reg, wiringPiI2CReadReg8 (fd, reg)); fflush (stderr); задержка (10); } return 0; }

Итак, что мы узнали на данный момент? Изображение таблицы с цветными выделенными областями указывает на то, что выходные данные соответствуют первым наборам регистров.

Полученные на данный момент результаты могут породить новые вопросы.

Вопрос: почему для "внешней" группы результат только один?

Вопрос: что это за неизвестные регистры "??????"

Вопрос: поскольку программа не управляется прерываниями, не слишком ли медленно она запрашивает данные? слишком быстро?

Вопрос: можем ли мы повлиять на результаты, попробовав что-то с самим датчиком во время его работы?

Шаг 6: давайте углубимся в показания / данные

Я думаю, что следующий шаг, прежде чем что-либо еще, - это усовершенствовать программу, чтобы:

  • быть гибким в том, сколько задержки цикла (мс)
  • быть гибким в том, сколько показаний давать среднее значение на регистр

(Мне пришлось прикрепить программу в виде файла. При вставке ее сюда возникла проблема. "4th.test.mpu9265.c")

Вот прогон с использованием последних 10 показаний для среднего с периодом 10 мс:

sudo./fourth.test.mpu9265 0x68 10 10

61:255 0 255 0 255 0 255 0 0 0: 102 62:204 112 140 164 148 156 188 248 88 228: 167 63:189 188 189 187 189 188 188 188 188 189: 188 64: 60 40 16 96 208 132 116 252 172 36: 112 65: 7 7 7 7 7 7 7 7 7 7: 7 66:224 224 224 240 160 208 224 208 144 96: 195 67: 0 0 0 0 0 0 0 0 0 0: 0 68:215 228 226 228 203 221 239 208 214 187: 216 69: 0 255 0 255 255 0 255 0 0 0: 102 70:242 43 253 239 239 45 206 28 247 207: 174 71: 0 255 255 0 255 255 255 255 255 255: 204 72: 51 199 19 214 11 223 21 236 193 8: 117 73: 0 0 0 0 0 0 0 0 0 0: 0 111: 46 149 91 199 215 46 142 2 233 199: 132 112: 0 0 0 0 0 0 0 0 0 0: 0 189:255 0 255 0 255 0 0 255 0 255: 127 190: 76 36 240 36 100 0 164 164 152 244: 121 191:188 188 188 188 187 188 187 189 187 189: 187 192: 8 48 48 196 96 220 144 0 76 40: 87 193: 7 7 7 7 7 8 7 7 7 7: 7 194:208 224 144 240 176 240 224 208 240 224: 212 195: 0 0 0 0 0 0 0 0 0 0: 0 196:243 184 233 200 225 192 189 242 188 203: 209 197:255 0 0 0 255 0 255 0 0 255: 102 198:223 39 247 43 245 22 255 221 0 6: 130 199: 0 255 255 255 0 255 255 255 255 0: 178 200:231 225 251 1 252 20 211 216 218 16: 164 201: 0 0 0 0 0 0 0 0 0 0: 0 239: 21 138 196 87 26 89 16 245 187 144: 114 240: 0 0 0 0 0 0 0 0 0 0: 0

Первый крайний левый столбец - это номер регистра. Затем следуют 10 последних показаний этого регистра. Наконец, последний столбец - это среднее значение для каждой строки.

Похоже, что регистры 61, 69, 71, 189, 197 и 199 либо только двоичные, либо готовы / не готовы, либо они являются старшим байтом 16-битного значения (отрицательное?).

Другие интересные наблюдения:

  • регистры 65, 193 - очень стабильные и одинаковые значения
  • регистр 63, 191 - очень стабильное и одинаковое значение
  • регистры 73, 112, 195, 201, 240 - все в ноль

Давайте свяжем эти наблюдения с разноцветным выделенным изображением таблицы ранее.

Регистр 65 - температура

Регистр 193 - ??????

Регистр 63 - акселерометр

Регистрация 191 - ??????

Регистр 73 - внешний

Зарегистрируйте 112 и дальше - ??????

Что ж, у нас еще есть неизвестные, однако мы узнали кое-что полезное.

Регистр 65 (температура) и регистр 63 (акселерометр) работали очень стабильно. Этого мы и ожидали. Сенсор не трогал; он не движется, за исключением случайных вибраций, так как робот стоит на том же столе, что и мой компьютер.

Есть один интересный тест, который мы можем провести для каждого из этих регистров температуры / акселерометра. Для этого теста нам понадобится еще одна версия программы.

Шаг 7: мы можем влиять на температуру и ускорение

На предыдущих шагах мы сузили по крайней мере один регистр для температуры и один для ускорения.

В следующей версии программы ("Friday.test.mpu9265.c") мы действительно можем увидеть изменение, происходящее для обоих регистров. Пожалуйста, посмотрите видео.

Больше копать

Если мы вернемся и взглянем на информацию о регистре, мы увидим, что есть:

  • три 16-битных выхода для гироскопа
  • три 16-битных выхода для акселерометра
  • три 16-битных выхода для магнитометра
  • один 16-битный выход для температуры

Однако все результаты, полученные с помощью наших простых тестовых программ, были одиночными 8-битными выходами. (единичные регистры).

Итак, давайте попробуем использовать тот же подход, но на этот раз чтение 16 бит вместо 8.

Вероятно, нам придется сделать что-то вроде того, что показано ниже. Давайте возьмем температуру в качестве примера, так как это всего лишь один 16-битный выход.

// получаем файловый дескриптор fd…

int tempRegHi = 65; int tempRegLo = 66; int hiByte = wiringPiI2CReadReg8 (fd, tempRegHi); int loByte = wiringPiI2CReadReg8 (fd, tempRegLo); int result = hiByte << 8; // помещаем 8 бит высокого порядка в верхнюю часть 16-битного значения result | = loByte; // теперь добавляем в нижнем порядке 8 бит, получая полное 16-битное число // распечатываем это число или используем функцию отображения горизонтального графика, описанную ранее

Из наших предыдущих шагов мы видели, что регистр 65 довольно устойчивый, а регистр 66 очень шумный. Поскольку 65 - это старший байт, а 66 - младший, это имеет смысл.

Для чтения мы можем взять данные регистра 65 как есть, но мы можем усреднить значения регистра 66.

Или мы можем просто усреднить весь результат.

Взгляните на последнее видео этой части; он демонстрирует чтение всего 16-битного значения температуры. Код: "sixth.test.mpu9265.c".

Шаг 8: акселерометр и гироскоп

Image
Image

В видеороликах для этого раздела показаны выходные данные акселерометра и гироскопа с использованием тестовой программы "sevenh.test.mpu9265.c". Этот код может считывать 1, 2 или 3 последовательные пары байтов (байты hi и lo) и преобразовывать значения в одно 16-битное значение. Таким образом, мы можем прочитать любую отдельную ось, или мы можем прочитать две из них вместе (и он суммирует изменения), или мы можем прочитать все три (и он суммирует изменения).

Повторюсь, на этом этапе, для этого руководства я просто хочу ответить на простой вопрос: «вращался ли робот?». Я не ищу точного значения, например, повернулся ли он на 90 градусов. Это произойдет позже, когда мы перейдем к SLAM, но это не требуется для простого уклонения от препятствий и случайного движения.

Шаг 9: (работа в процессе) магнитометр

при использовании инструмента i2cdetect MPU9265 отображается в таблице как 0x68:

0 1 2 3 4 5 6 7 8 9 а б в г д е

00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

Для считывания показаний магнитометра IMU требуются дополнительные действия.

Из PDF-документа Invesense регистрирует:

РЕГИСТРАЦИИ 37–39 - КОНТРОЛЬ I2C SLAVE 0

  • РЕГИСТР 37 - I2C_SLV0_ADDR
  • РЕГИСТР 38 - I2C_SLV0_REG
  • РЕГИСТР 39 - I2C_SLV0_CTRL

Рекомендуемые: