Skip to content

Latest commit

 

History

History
798 lines (588 loc) · 55.2 KB

readme_rus.md

File metadata and controls

798 lines (588 loc) · 55.2 KB

AFFBWheel (Arduino Force FeedBack Wheel)

United States Description in English

Это проект контроллера руля с обратной связью на Arduino. Для настройки параметров контроллера нужно использовать графический интерфейс AFFBWheelGUI

  • 8 осей: руль (X), газ (Y), тормоз (Z), сцепление (Rx), и еще 4 дополнительно (Ry, Rz, Slider, Dial) (например для стика, ручного тормоза, и т.п.).
  • 32 кнопки.
  • Эффекты обратной связи - весь набор: constant/ramp/square/sine/triangle/sawtooth/spring/damper/inertia/friction
  • Диапазон руля можно менять: 1080/900/360/270/180 градусов, и вообще любое значение.

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

В проекте использован код коммуникации USB HID из проекта VNWheel.

Оборудование:

  • Arduino на контроллере Atmega32U4 (Leonardo, ProMicro, Micro, и др.)
  • инкрементальный энкодер или TLE5010/AS5600 магнит
  • потенциометры для аналоговых осей (или датчики холла)
  • сдвиговые регистры 74HC165 для кнопок (или i2c-расширители MCP23017)
  • драйвер BTS7960
  • двигатель постоянного тока
  • источник питания для двигателя
  • опционально: АЦП MCP3204, ADS1015, или аналоговый мультиплексор 74HC4051/74HC4052/74HC4067 сдвиговый регистр 74HC164

Инструкция по прошивке

  1. Скачайте проект с github в виде zip:

    И распакуйте архив в любую удобную папку.
  2. Скачайте Arduino IDE. Рекомендуется версия 1.8.19 в более поздних версиях возможны ошибки.
  3. Загрузите дополнительные библиотеки:
  4. Установите скачанные библиотеки:
    • 4.1. Загрузите библиотеку в виде zip.
    • 4.2. Откройте Arduino IDE, далее нажмите Скетч > Подключить библиотеку > Добавить .ZIP библиотеку.... и выберите zip со скачанной библиотекой. Инструкция на английском:
  5. Откройте папку куда вы распаковали архив проекта, перейдите в папку AFFBWheel и откройте файл AFFBWheel.ino в Arduino IDE.
  6. Внесите нужные изменения в файл config.h для настройки.
  7. Подключите плату Arduino к вашему ПК.
  8. Выберите свой тип платы Arduino Инструменты > Плата (Leonardo, ProMicro, Micro, и др.):
  9. Выберите порт на котором определяется Arduino Инструменты > Порт:
  10. Нажмите кнопку загрузки:
  11. Дождитесь окончания процесса прошивки. Все готово!

Схема подключений:

Схема подключения показана на примере Arduino Pro Micro, для остальных плат распиновка точно такая же по тем же номерам. Есть небольшие отличия для Arduino Leonardo в расположении контактов на плате.

Так же существует несколько вариантов подключения драйвера мотора.

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

Возможны другие варианты подключения кнопок и педалей (см.ниже)

PPR энкодера

Укажите PPR энкодера в файле config.h, в строке #define ENCODER_PPR 400.

Блокировочные конденсаторы

Для защиты от помех по питанию желательно добавлять блокировочные конденсаторы (керамические емкостью 0.1-1мкф между VCC и GND) на каждую микросхему (TLE5010, 74HC165, 74HC4052, MCP2304...) поближе к выводам микросхемы. На модулях такие конденсаторы уже имеются.

Блокировка ненужных осей.

Если к контакту аналоговой оси не подключен потенциометр, ось будет выдавать шум. Чтобы этого избежать, либо притяните контакт оси к GND резистором 1-10кОм, либо отключите ось при помощи команды axisdisable(см.команды ниже). Тогда ось будет всегда выдавать одно и то же значение и не будет мешаться при определении осей в играх.
Также, дополнительные оси (AUX1-AUX4) можно выключить в config.h. Для этого надо закомментировать строчки #define PIN_AUXN .. для ненужных осей.
Выключенная ось будет исключена из опроса (экономя около 45мкс) и всегда будет выдавать значение 0%.

Если игра не поддерживает неизвестный руль

Можно воспользоваться эмулятором контроллеров GIMX (потребуется плата на Atmega32U4 - promicro/leonardo/teensy2, и usb-uart преобразователь на CP1202).

ПО для тестирования:

Конфигурация

Опции конфигурации находятся в файле config.h.
В основном они относятся к разным вариантам подключений (см.ниже)

Настройки и команды.

Изменяемые настройки руля можно менять с помощью GUI или команд по последовательному порту (Serial monitor в Arduino)
Большинство команд, если не указан параметр, выводит текущее значение.

  • center
    Устанавливает текущее положение руля как центр. (происходит при старте)

  • centerbtn
    centerbtn <button>
    Показать/изменить кнопку центровки.
    <button> - номер кнопки, 1-32. Установка в 0 означает отсутствие кнопки центровки.
    Этой командой можно назначить одну из кнопок для выполнения команды центровки (см. выше). Назначенная кнопка будет исключена из опроса.

  • range
    range <degrees>
    Показать/изменить градусы руля

  • axisinfo <axis>
    Включить вывод данных (положение оси и другие ее параметры) по одной из осей.
    Номера осей:
    0 - руль
    1 - газ
    2 - тормоз
    3 - сцепление
    4 - доп ось 1
    5 - доп ось 2
    6 - доп ось 3
    7 - доп ось 4
    значение отсутствует - выключить вывод
    Вывод данных тормозит работу, так что не забывайте отключать.

  • limit <axis>
    limit <axis> <min> <max>
    Показать/установить минимальные/максимальные значения для аналоговой оси (аналоговые оси - все кроме руля).
    номера осей см. выше.

  • axiscenter <axis>
    axiscenter <axis> <pos>
    Показать/установить центральное положение для аналоговой оси.
    Бывает нужно, если у оси есть центральное положение (например, ось стика. у педалей центра нет) и ось при установке в центр рапортует о положении не в центре.
    Пример: при стике в центре ось принимает raw значение не 512 как должно быть, а 530, и соответственно бывает чуть смещена от 0. Установите центр в 530 и ось в этом положении будет показывать 0.
    Чтобы отключить центр, выставите его в положение за пределами минимума/максимума, тогда центр будет определяться как средняя точка между минимумом и максимумом.

  • axisdz <axis>
    axisdz <axis> <dz>
    Показать/установить мертвую зону центра для аналоговой оси.
    Если для оси установлено центральное положение (см.выше), можно добавить мертвую зону в центр.
    Пример: центр оси установлен в 530, а мертвая зона в 10. Теперь ось будет сообщать значение 0 когда показания будут находиться между 520 и 540.
    Это касается только центра. Мертвая зона не работает, если центр оси отключен.
    Чтобы установить мертвые зоны по краям, устанавливайте минимум/максимум несколько меньше чем реальные границы.

  • axisdisable <axis>
    Включить/выключить вывод оси.
    Ось с выключенным выводом всегда выдает минимальное значение (0%).

  • axistrim <axis>
    axistrim <axis> <trimlevel>
    Показать/установить значение округления для аналоговой оси.
    Побитово уменьшает разрешение исходных (raw) показаний оси для борьбы с нежелательным шумом. Например, при установке значения 3 показания будут меняться с шагом 8 (2 в степени 3).
    Если на оси присутствует шум, можно попробовать увеличить это значение (однако, все же лучше найти причину шума а не скрывать его таким образом)

  • autolimit <axis>
    Вкл/выкл автоматическую установку минимума/максимума для аналоговой оси.
    Если это включено, то при любом превышении существующих границ текущее значение становится новой границей.
    (Иначе говоря: включите, прожмите педаль до упора и назад, выключите - готово, границы определены)
    Центральное положение и мертвая зона будут отключены.

  • debounce <count>
    Показать/установить значение антидребезга для кнопок.
    Если это значение больше 0, кнопки будут регистрировать изменения только после <count> циклов (1 цикл - около 1мс)
    Если у кнопок проблема с дребезгом - попробуйте увеличить это значение.

  • gain <effectNum>
    gain <effectNum> <value>
    Показать/установить коэффициент усиления для определенного эффекта.
    Номера эффектов:
    0 - общий (влияет на все эффекты кроме endstop),
    1 - constant,
    2 - ramp,
    3 - square,
    4 - sine,
    5 - triangle,
    6 - sawtoothdown
    7 - sawtoothup
    8 - spring
    9 - damper
    10 - inertia
    11 - friction
    12 - endstop (сила, возвращающая руль обратно при достижении границы диапазона)
    Значение по умолчанию - 1024, что соответствует 100%.
    2048 = 200%, 512 = 50% и так далее.

  • forcelimit <minforce> <maxforce> <cutforce>
    Показать/установить минимальное/максимальное значение ШИМ для обратной связи и уровень обрезки усилия. Диапазон значений 0...16383.
    Если усилие не нулевое, его значение будет пересчитано из диапазона [1..16383] в [minforce...maxforce].
    Чтобы избежать рывка при переходе от отрицательного усилия к положительному и наоборот, наличествует небольшая переходная зона.
    Далее, если результирующее значение больше чем значение <cutforce> - значение усилия будет обрезано на уровне <cutforce>.
    Значения по умолчанию - minforce=0, maxforce=16383, cutforce=16383 (т.е. без изменений)

  • maxvd
    maxvd <value>
    Показать/установить максимальное значение скорости для эффекта демпфера.
    (принцип вычисления эффекта требует задания значения скорости, которому будет соответствовать максимальное усилие)
    При увеличении этого параметра эффект демпфера ослабевает, и наоборот.

  • maxvf
    maxvf <value>
    Показать/установить максимальное значение скорости для эффекта трения.
    оказывает воздействие только на действие эффекта для малых значений скорости.

  • maxacc
    maxacc <value>
    Показать/установить максимальное значение ускорения для эффекта инерции.
    При увеличении этого параметра эффект инерции ослабевает, и наоборот.

  • endstop
    endstop <offset> <width>
    Показать/установить параметры эффекта Endstop.

    <offset> (0..16383) - уровень, с которого начнется усилие возврата руля при выходе за границы. При увеличении значения жесткость эффекта возрастает.
    <width> - ширина участка, на протяжении которого усилие возврата линейно нарастает до максимума. При увеличении значения эффект становится мягче.

  • ffbbd
    ffbbd <value>
    Показать/установить разрядность ШИМ обратной связи.
    Знак игнорируется: разрядность 8 означает что абсолютное усилие может принимать 256 значений от 0 до максимума, таким образом весь диапазон составляет [-255..0..255].
    Разрядность влияет на частоту ШИМ: freq = 16000000 / 2^(bitdepth 1)
    Рассчитанные значения:
    8: 31.25 кГц
    9: 15.625 кГц
    10: 7.8 кГц
    11: 3.9 кГц
    12: 1.95 кГц
    13: 0.97 кГц
    14: 0.48 кГц
    Значение по умолчанию - 9, частота 15.625кГц. Менять его не следует.
    Значения больше 9 приводят к уменьшению частоты и возникновению противного писка.
    Меньшие значения - только теряют в разрешении.
    Настройка оставлена просто на всякий случай.

  • save
    Сохранить настройки в EEPROM.
    Настройки, изменяемые при помощи команд, будут действовать только до сброса.
    Используйте эту команду чтобы их сохранить в постоянную память.

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

  • defaults
    Загрузить настройки по умолчанию.

  • timing
    вкл/выкл отладочный вывод времени (в мкс) исполнения разных процедур, а также количество циклов в секунду.
    S - время чтения позиции руля
    A - время чтения аналоговых осей
    B - время чтения кнопок
    U - время коммуникации по USB
    F - время расчета обратной связи
    loop/sec - кол-во циклов в секунду.

  • fvaout
    вкл/выкл отладочный вывод значений усилия обратной связи, скорости и ускорения руля в оси Rz, Slider, Dial.
    Это значительно быстрее чем вывод в последовательный порт, можно видеть график в приложениях вроде VKB Joystick Tester.

Альтернативные конфигурации оборудования.

Разное

  • Диоды 1n5817 на схемах можно заменить на другие: 1n4148, 1n5819 и т.п.
  • При использовании мощного двигателя возможна ситуация перегрузки БП. Во избежание повреждений можно использовать что-то для ограничения тока через двигатель, например - понижающий DC-DC преобразователь с возможностью ограничения по току (лимит по току следует выставить так, чтобы не превышать возможности БП ):

Arduino Leonardo вместо ProMicro:

На Leonardo не обозначены пины 14,15,16. Там они находятся на коннекторе ICSP, это MISO, SCK, и MOSI. В остальном подключения не отличаются от ProMicro, изменений в коде не требуется.

Управление двигателем.

Есть 3 варианта подключения:

  1. этот вариант отображен на основной схеме. Пины EN на BTS7960 подключены через диоды.

Здесь питание на двигатель подается лишь в рабочей части периода ШИМ, что дает более "мягкую" обратную связь.

  1. пины EN управляются с arduino по отдельному проводу.

Питание двигателя подключается только если должна присутствовать обратная связь. ОС ощущается сильнее чем при первом варианте, но руль становится "тяжелее".
В config.h нужно раскомментировать строчку #define MOTOR_ENABLE_PIN и указать в ней свободный пин для управления.

  1. пины EN постоянно подключены к VCC.

ОС такая же как во втором варианте, но питание на двигатель подается постоянно, что приводит к постоянной "нагруженности" руля. Зато не требуется лишний пин.

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

Установка направления вращения датчика руля и мотора обратной связи.

Сначала проверьте датчик руля, не подавая питания на обратную связь.

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

  • если у вас энкодер, поменяйте местами подключение линий A/B.
  • с магнитными датчиками такая проблема может возникнуть, если датчик установлен не прямо на оси руля, а связан с ним через передачу, изменяющую направление вращения. В таком случае воспользуйтесь поправочными коэффициентами в config.h.

Обратную связь можно проверить при помощи программы Fedit. Создайте слабый эффект постоянного вращения и проверьте, в какую сторону будет вращаться руль.

Подробнее, как это сделать:

  • Для первого запуска желательно понизить напряжение БП обратной связи, чтобы в случае чего ничего не сломать.
  • Запустите FEdit.
  • File - Select device - выберите устройство (Arduino Leonardo). В логе внизу должна появиться строка "Got FF Device"
  • Создайте новый эффект: Effect - Insert - Constant Force.
  • В окне появится новый эффект ConstantForce1. Нажмите на него два раза, откроется окно свойств.
  • В закладке Timing поставьте галочку Infinite
  • В закладке Constant перетащите вертикальный ползунок в середину, красная область должна превратиться в линию. Так вы установите околонулевое значение усилия.
  • Нажмите Play, эффект начнет работать. Его параметры можно изменять на ходу. Не переключайтесь из окна Fedit! При потере фокуса Fedit отключает все эффекты, при переключении назад придется снова нажимать Play.
  • Медленно тяните ползунок вниз, пока руль не начнет вращаться, после чего тут же нажмите Stop. Вращение должно быть по часовой стрелке. Если вращение было против часовой - либо поменяйте полярность подключения мотора к BTS7960 (контакты M M-), или же поменяйте местами провода L_PWM/R_PWM. Потом проверьте заново.

Альтернативные варианты подключения руля

TLE5010

TLE5010 это цифровой датчик поворота магнита. Можно использовать вместо энкодера.

Схема: полная схема

Установка магнита по отношению к TLE5010:

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

Изменения в config.h:

  • раскомментируйте #define STEER_TYPE ST_TLE5010
  • закомментируйте остальные строки со STEER_TYPE

Подключите библиотеки:

AS5600

AS5600 - цифровой датчик поворота магнита с интерфейсом I2C. Используется аналогично TLE5010.

Схема:

Если питание модуля 5в, резистор R1 (0ом) нужно с него убрать.

Изменения в config.h:

  • раскомментируйте #define STEER_TYPE ST_AS5600
  • закомментируйте остальные строки со STEER_TYPE
  • установите пины для I2C (можно использовать любые свободные) в строках:
     #define I2C_PIN_SDA 0
     #define I2C_PIN_SCL 1

При использовании других I2C устройств (AD1015,MCP23017) - они подключаются параллельно к тем же пинам.

MLX90316

Еще один магнитный датчик поворота. Используется так же как и предыдущие. Применяется в руле Thrustmaster T500. (Поддержка экспериментальная - у меня нет такого датчика, проверялось на стороннем оборудовании)

Подключение аналогично TLE5010:

Изменения в config.h:

  • раскомментируйте #define STEER_TYPE ST_MLX90316
  • закомментируйте остальные строки со STEER_TYPE

Альтернативные варианты подключения педалей:

Вариант 1: подтяжки.

Количество проводов для подключения педалей снижается до 4 (можно использовать распространенные 4-жильные кабели и разъемы - USB, UTP2, телефонные).

Просто и дешево, но есть минусы.

  • показания становятся нелинейными. Добавлена возможность пересчитывать их в линейные, но на это тратится некоторое время.
  • при таком подключении нельзя заменить потенциометры на датчики холла (нет линии VCC)
  • подтяжки необходимо ставить на все аналоговые оси

Схема:
Wiring diagram

Сопротивление резистора подтяжки должно быть равно сопротивлению потенциометра, если потенциометр на 10кОм то и подтяжку ставьте 10кОм.

Изменения в config.h:

  • убедитесь что раскомментирована строка #define PEDALS_TYPE PT_INTERNAL и закомментированы остальные строки с PEDALS_TYPE.
  • раскомментируйте #define AA_INT_PULLUP
  • раскомментируйте #define AA_LINEARIZE, если требуется пересчет в линейную характеристику

Вариант 2: аналоговый мультиплексор 74HC4051/74HC4052/74HC4067 сдвиговый регистр 74HC164.

Также способ уменьшить количество проводов.

Схема:
74HC4051
Схема для 74HC4052
Схема для 74HC4067

Изменения в config.h:

  • раскомментируйте #define PEDALS_TYPE PT_MP_HC164 и закомментируйте остальные строки с PEDALS_TYPE

Вариант 3: внешний АЦП MCP3204

В педалях имеет смысл применение АЦП (аналогово-цифрового преобразователя), так как к ним требуется длинный провод, который может ловить помехи. Цифровой сигнал АЦП, в отличие от аналогового, к таким помехам нечувствителен. Кроме того, внешний АЦП может иметь большую точность, чем 10-битный АЦП в Arduino.

MCP3204 - достаточно быстрый 12-битный 4-канальный АЦП. Работает по 6 проводам, но можно добиться работы и по 5, и даже по 4 проводам.

Схемы:
6 проводов
5 проводов
4 провода v1
4 провода v2
4 провода v3

Если используется TLE5010, линии соединяются параллельно:

6 проводов TLE5010
5 проводов TLE5010
4 провода v1 TLE5010
4 провода v2 TLE5010

Изменения в config.h:

  • Для 6 или 5 проводов:
    • раскомментируйте #define PEDALS_TYPE PT_MCP3204_SPI и закомментируйте остальные строки с PEDALS_TYPE
  • Для 4 проводов:
    • раскомментируйте #define PEDALS_TYPE PT_MCP3204_4W и закомментируйте остальные строки с PEDALS_TYPE
    • укажите пины для SCK, MISO и MOSI соответственно выбранному варианту подключения (на схемах v1, v2, v3):
      • Для v1 (общие MOSI/MISO):
       #define MCP3204_4W_PIN_SCK	A0
       #define MCP3204_4W_PIN_MOSI	16
       #define MCP3204_4W_PIN_MISO	14
      • Для v2: (общий SCK)
       #define MCP3204_4W_PIN_SCK	15
       #define MCP3204_4W_PIN_MOSI	A0
       #define MCP3204_4W_PIN_MISO	A0
      • Для v3: (раздельное подключение)
       #define MCP3204_4W_PIN_SCK	A0
       #define MCP3204_4W_PIN_MOSI	A1
       #define MCP3204_4W_PIN_MISO	A1

Вариант 4: внешний I2C АЦП ADS1015

ADS1015 - 12 битный АЦП с интерфейсом I2C.

Схема:
ADS1015

Этот АЦП относительно медленный (~0.3мс на преобразование), поэтому значения осей будут читаться по одной за цикл, что приводит к втрое меньшей частоте чтения.
Также, в нем фиксированные уровни опорного напряжения (используется ±2.048в) так что при питании 5в на осях будут мертвые зоны в ~10% по краям диапазона. Если требуется использовать полный диапазон потенциометра, то это можно компенсировать, если добавить по паре дополнительных резисторов (схема) на каждый потенциометр (сопротивление подбирать, начать с 1/10 от сопротивления потенциометра).
Или же обеспечить питание потенциометров на уровне 4.1в (например, с помощью TL431 - схема).

Изменения в config.h:

  • раскомментируйте #define PEDALS_TYPE PT_ADS1015 и закомментируйте остальные строки с PEDALS_TYPE
  • установите пины для I2C (можно использовать любые свободные) в строках:
     #define I2C_PIN_SDA 2
     #define I2C_PIN_SCL 7

При использовании других I2C устройств (AS5600,MCP23017) - они подключаются параллельно к тем же пинам.

Вариант 5: внешний I2C АЦП ADS7828

Еще один АЦП с интерфейсом I2C. 12битный, достаточно быстрый, относительно недорогой. Корпус TSSOP-16 довольно мелкий, но при некотором старании его все-таки можно припаять паяльником на переходную плату.

ADS7828

Схема:
ADS7828

Изменения в config.h:

  • раскомментируйте #define PEDALS_TYPE PT_ADS7828 и закомментируйте остальные строки с PEDALS_TYPE
  • установите пины для I2C (можно использовать любые свободные) в строках:
     #define I2C_PIN_SDA A0
     #define I2C_PIN_SCL A1

При использовании других I2C устройств (AS5600,MCP23017) - они подключаются параллельно к тем же пинам.

Альтернативные варианты подключения кнопок.

Вариант 1: 74HC165 по 4 проводам

Можно избавиться от провода PL (от 74HC165 до Arduino) и сократить количество проводов до 4.

Cхема:
Wiring diagram

Изменения в config.h:

  • убедитесь что раскомментирована строка #define BUTTONS_TYPE BT_74HC165 и закомментированы остальные строки с BUTTONS_TYPE
  • закомментируйте строку #define HC165_PIN_PL 3

Вариант 2: I2C-расширители MCP23017.

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

Схема:
Wiring diagram

Изменения в config.h:

  • раскомментируйте #define BUTTONS_TYPE BT_MCP23017 и закомментируйте остальные строки с BUTTONS_TYPE
  • установите пины для I2C (можно использовать любые свободные) в строках:
     #define I2C_PIN_SDA 2
     #define I2C_PIN_SCL 7

При использовании других I2C устройств (AS5600,AD1015) - они подключаются параллельно к тем же пинам.

Вариант 3: сдвиговые регистры CD4021B.

Возможно, также подойдут CD4014B (на практике не проверялось, т.к. у меня таких нет)

Подключение аналогично 74HC165, но у этих микросхем другое расположение выводов.

Wiring diagram

С этими регистрами также можно избавиться от линии PL для 4-проводного подключения:

Wiring diagram

Изменения в config.h:

  • раскомментируйте #define BUTTONS_TYPE BT_CD4021B, и закомментируйте остальные строки с BUTTONS_TYPE.
  • Если применяете показанный выше способ убрать линию PL, закомментируйте строку с CD4021_PIN_PL

Вариант 4: I2C-расширители PCF8574 или PCF8575

Схемы:

Возможно смешанное подключение - для одной половины кнопок использовать PCF8575, а для другой - пару PCF8574. (например: 16 кнопок на руле 8 кнопок на базе 8 кнопок КПП).

Важно: для каждого модуля нужно будет задать свой I2c адрес.

На платах PCF8574 адрес устанавливается переключателями, джамперами или пинами A0-A2.
На платах с переключателями они установлены в обратном порядке, т.е. переключатель 1 соответствует A2, а 3 - A0.
На платах PCF8575 для настройки адреса нужно запаивать перемычки A0-A2. Перемычки состоят из трех контактов, средний нужно соединить либо с GND(правый контакт на рисунке), либо с VCC(левый).

На "квадратных" платах PCF8575 (на рисунке выше - красного цвета) нет резисторов подтяжки для I2c.
Если это единственные подключенные I2c устройства - потребуется добавить резисторы 1-10кОм от SCL к VCС, и от SDA к VCC (показаны на схеме подключений). Можно установить их на площадки R1 и R2, но туда требуются SMD-резисторы 0603.

"Прямоугольные" платы PCF8575 (синие на рисунке) с чипом PCF8575TS в моем случае работали некорректно (не включалась подтяжка на выводах, требовалось добавлять внешние резисторы - возможно, брак), так что их брать не рекомендую.

Соответствие перемычек и адресов: (0 - GND, 1 - VCC)

Адрес A2 A1 A0
0x20 0 0 0
0x21 0 0 1
0x22 0 1 0
0x23 0 1 1
0x24 1 0 0
0x25 1 0 1
0x26 1 1 0
0x27 1 1 1

Изменения в config.h:

  • раскомментируйте #define BUTTONS_TYPE BT_PCF857x и закомментируйте остальные строки с BUTTONS_TYPE

  • установите пины для I2C (можно использовать любые свободные) в строках:

     #define I2C_PIN_SDA 2
     #define I2C_PIN_SCL 7
  • укажите i2c адреса:

    вариант с 2 х PCF8575:

     #define PCF857x_L1_TYPE   PCF8575   //тип микросхем для кнопок 1-16
     #define PCF857x_L1_ADDR1  0x20      //адрес микросхемы
     
     #define PCF857x_L2_TYPE   PCF8575   //тип микросхем для кнопок 17-32
     #define PCF857x_L2_ADDR1  0x21      //адрес микросхемы

    вариант с 4 х PCF8574:

     #define PCF857x_L1_TYPE   PCF8574
     #define PCF857x_L1_ADDR1  0x20
     #define PCF857x_L1_ADDR2  0x21
     
     #define PCF857x_L2_TYPE   PCF8574
     #define PCF857x_L2_ADDR1  0x22
     #define PCF857x_L2_ADDR2  0x23

    вариант с 1 х PCF8575 2х PCF8574:

     #define PCF857x_L1_TYPE   PCF8575
     #define PCF857x_L1_ADDR1  0x20
     
     #define PCF857x_L2_TYPE   PCF8574
     #define PCF857x_L2_ADDR1  0x21
     #define PCF857x_L2_ADDR2  0x22

При использовании других I2C устройств (AS5600,AD1015) - они подключаются параллельно к тем же пинам.

Дополнительные возможности

Датчик руля через передачу

Датчик положения руля может быть установлен не непосредственно на оси руля, а связан с ней через передачу (ременную, зубчатую...).
Тогда, если передаточное число не 1:1, требуется применение поправочного коэффициента.
Это возможно при помощи следующих параметров в config.h:

#define STEER_TM_RATIO_ENABLED  //Раскомментируйте для включения функции
#define STEER_TM_RATIO_MUL      //Множитель
#define STEER_TM_RATIO_DIV      //Делитель

Показания датчика умножаются на STEER_TM_RATIO_MUL и делятся на STEER_TM_RATIO_DIV.

Пример: ось руля и датчика связаны ременной передачей, диаметр шкива на руле - 200 единиц, на датчике - 20, на один оборот руля ось датчика совершает 10 оборотов, тогда для коррекции показаний необходимо применить коэффициент 20:200, т.е. 1:10 и конфигурация будет такой:

#define STEER_TM_RATIO_ENABLED
#define STEER_TM_RATIO_MUL 1
#define STEER_TM_RATIO_DIV 10

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

#define STEER_TM_RATIO_ENABLED
#define STEER_TM_RATIO_MUL 1
#define STEER_TM_RATIO_DIV -10

Можно использовать и дробные числа.

Кнопки на аналоговом пине.

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

Варианты схем подключения:

Wiring diagram

Суть подобных схем: при нажатии кнопки меняется напряжение на аналоговом пине.

Плюс: можно использовать всего 3 или 2 провода для подключения
Минус: одновременно должна быть нажата только одна такая кнопка, так что таким образом имеет смысл подключать только КПП.

Пример конфигурации:

#define APB                    //раскомментировать для включения функции
#define APB_PIN        A11     //аналоговый пин
#define APB_BTN_COUNT  2       //количество подключаемых кнопок
#define APB_VALUES     32,96   //Значения АЦП (0-255) для каждой кнопки
#define APB_TOLERANCE  10      //допуск (плюс-минус к значению АЦП)
#define APB_BTNS       25,26   //номера переназначаемых кнопок (1-32)

Означает следующее:

  • на пин A11 подключены 2 кнопки, они заместят кнопки с номерами 25 и 26.
  • кнопка 25 будет считаться нажатой, если на A11 значение АЦП будет в пределах 32±10, т.е. от 22 до 42.
  • кнопка 26 будет считаться нажатой, если на A11 значение АЦП будет в пределах 96±10, т.е. от 86 до 106.

Командой apbout в Serial monitor можно включить вывод значений АЦП с указанного пина.

Аналоговый шифтер (КПП).

Есть возможность использования h-шифтера в виде стика, на двух потенциометрах вместо кнопок.
Потенциометры подключаются на свободные аналоговые пины.
Шифтер может быть на 6 или 8 позиций.

Принцип настройки на картинке:

по оси Х значения АЦП с одного потенциометра, по оси Y c другого.
Кнопка N считается нажатой, если текущие значения X/Y попадают в соответствующую зону(на картинке серым цветом).
Значения X1,X2,X3,Y1,Y2 задают границы зон. Значения должны идти в порядке возрастания, т.е. X1<X2<X3, Y1<Y2.
В варианте на 6 позиций X3 не используется.

Командой ahsout можно включить вывод значений АЦП.

Настройка в config.h:

#define ASHIFTER                //раскоммментируйте для включения функции
#define ASHIFTER_PINX     A4    //пин для потенциометра X
#define ASHIFTER_PINY     A5    //пин для потенциометра Y
#define ASHIFTER_POS      8     //количество позиций - 6 или 8
#define ASHIFTER_Y1       50    //границы зон (0-255)
#define ASHIFTER_Y2       200
#define ASHIFTER_X1       64  
#define ASHIFTER_X2       128  
#define ASHIFTER_X3       192
#define ASHIFTER_1ST_BTN  25    //номер кнопки для позиции 1 (1-32)

Кнопки будут заменены последовательно, начиная с ASHIFTER_1ST_BTN. Например, если указано 8 позиций, и первая кнопка - 25, то под шифтер будут выделены кнопки 25,26,27,28,29,30,31,32.

Hat switch

Любые 4 кнопки можно назначить для использования как 8-позиционный Hat Switch.

Настройка в config.h:

#define HATSWITCH           //раскомментируйте для включения функции
#define HAT_BTN_UP     20   //номера кнопок для направлений hat switch - вверх, вниз, влево, вправо
#define HAT_BTN_DOWN   21
#define HAT_BTN_LEFT   22
#define HAT_BTN_RIGHT  23
#define HAT_CLR_BTNS   	    //если закомментировать, назначенные кнопки будут срабатывать вместе с hat switch

###Автонахождение центра и диапазона.

Если на вашей оси руля есть механические ограничители (в основном это касается готовых заводских рулей), можно включить возможность автоматического определения диапазона и центровки. Это происходит следующим образом: Руль начнет вращение против часовой стрелки, пока не упрется в ограничитель, затем повернется по часовой до другого ограничителя.
При остановках будут установлены соответствующие пределы перемещения, вычислены новые значения диапазона и положения центра, после чего руль вернется в центр.

Не включайте, если ограничителей нет, иначе руль в поиске предела будет вращаться бесконечно.

Для включения в config.h раскомментируйте строку #define AFC_ON.

Также необходимо задать настройки:

#define AFC_FORCE    0   //усилие вращения, от 0 до 16383. По умолчанию 0, чтобы ничего случайно не сломать.
#define AFC_PERIOD   50  //интервал проверки в миллисекундах.
#define AFC_TRESHOLD 10  //минимально необходимое смещение, в условных единицах (один оборот - 8192 отсчета)
#define AFC_NORANGE      //раскомментируйте, чтобы не устанавливать диапазон
#define AFC_RANGE_FIX 1  //поправка к найденному диапазону в градусах

Логика работы: если ось за время AFC_PERIOD смещается меньше, чем на AFC_TRESHOLD - считается, что ось уперлась в ограничитель и предел найден.
После нахождения пределов будет определен диапазон руля в градусах и уменьшен на AFC_RANGE_FIX - это нужно, чтобы программное ограничение диапазона срабатывало немного раньше чем реальные ограничители, и руль о них сильно не бился.
AFC_NORANGE - отключает задание диапазона, процедура будет только находить центр.
Если найденный диапазон будет слишком мал (менее 2 градусов - очевидно, руль не сдвинулся, то ли не работает обратная связь, то ли значение усилия слишком мало) - процедура будет прервана.

Т.к. рули, моторы и редукторы разные, параметры придется подобрать индивидуально.
Это можно сделать так:
при включении AFC_ON станет доступна команда для мониторa порта - autocenter <force> <period> <treshold>
Параметры команды соответствуют настройкам из config.h. Команда позволяет испытать автоцентрирование с разными настройками.
Если параметр не указан, будет использоваться значение из config.h.
Для начала, убедитесь что направления оси руля и обратной связи настроены правильно.
Далее в config.h включите только AFC_ON, значение AFC_FORCE оставьте равным 0.
Если указать слишком высокое значение AFC_FORCE, и если у вас мощный двигатель и редуктор - он может сломать ограничители или себя, поэтому начните подбирать с малых значений, например 3000: autocenter 3000.
Если руль не сдвинулся с места - попробуйте autocenter 4000, и так далее, пока не начнет вращаться.
Может случиться что руль упрется в первый ограничитель и остановится, посчитав что тут же обнаружил и второй.
В этом случае можно либо далее увеличить , либо поиграть с другими двумя параметрами.
В процессе в монитор порта будут выводиться текущие значения положения и пути, пройденного за период.
После нахождения подходящих значений, поместите их в config.h для использования по умолчанию.