Привет, Хабр! В предыдущей статье я рассказывал о наших продуктах – поворотных столах для круговой фотосъёмки. За прошедшее время нам удалось серьёзно продвинуться вперёд и разработать новые устройства на базе Ардуино с использованием коллекторных и бесколлекторных двигателей.
Поворотный стол не такое уж простое техническое изделие как может показаться на первый взгляд. Например, в автоматическом режиме стол поворачивается на нужный угол, выдерживает паузу для того чтобы предмет съёмки смог успокоиться и стать неподвижным, автоматически делает снимок с фотоаппарата, затем некоторое время ожидает окончания экспозиции и переходит к следующему шагу. Так стол совершает полный оборот, и получается серия снимков предмета со всех сторон. Есть и другие режимы работы.
Мы выпускаем столы разных размеров. Самые ходовые – с диаметром столешницы 400, 600 и 900 миллиметров. Столы способны вращать довольно приличный груз, например, стол 600 выдерживает 150 кг, а стол 900 – 250 кг. Как-то приходилось делать по спецзаказу стол диаметром 2700 миллиметров, выдерживающий груз до 700 кг.
Как говорилось в части 1, стол с промышленным контроллером выходил слишком дорогим, поэтому мы решили переходить на Ардуино. Кроме того, мы хотели заменить шаговый двигатель коллекторным.
Почему мы решили менять двигатель? Шаговый двигатель – отличный вариант для программирования. Не надо заботиться о том, как переместить стол на заданное расстояние, всё уже сделано за нас. Шаговый двигатель оснащён логическим контроллером, просто используй нужные команды и ни о чём не думай.
Но есть один существенный недостаток. Шаговый двигатель сильно шумит. Иногда двигатель попадает в резонанс, и тогда тарахтение стола становится невыносимым.
Новая схема работы стола была простой: есть двигатель с питанием на 24 вольта и встроенным редуктором. Двигатель вращает столешницу и управляется через преобразователь ШИМа, так называемый драйвер двигателя. К вращающейся столешнице подсоединён оптический энкодер, передающий текущее положение в скетч Ардуино, который должен управлять двигателем посредством ШИМ-сигнала. И первой моей задачей было научить скетч перемещать стол из точки A в точку B.
Признаться, начинал я эту работу с некоторой робостью. Придётся ли погружаться в изучение ТАУ-регуляторов? Если да, то, скорее всего, надо будет оперировать значением мгновенной скорости. Позволит ли медленная и ограниченная ардуина проводить необходимые вычисления в реальном времени? К счастью, всё оказалось намного проще.
Итак, скетч должен получать данные от энкодера и управлять двигателем посредством ШИМ-сигнала. Библиотека для энкодера сразу нашлась. Называется, как ни странно, Encoder, легко находится в менеджере библиотек Arduino IDE. Выводы энкодера подсоединяем к пинам 2 и 3, чтобы использовать прерывания – так значения текущего положения стола будут максимально близки к реальности.
Через какое-то время выяснится, что энкодер тем не менее слегка привирает. В чём дело? Плохой энкодер? Библиотека? Несколько отладочных скетчей, измерение импульсов, всё не то… Проблема в том, что мест, где может возникать ошибка энкодера, множество. Да и ошибка плавающая, то она есть, то нет. И вдруг совершенно случайно обнаруживается, что текущая конструкция стола несколько мм… шаткая что-ли. Раньше это было незаметно, ведь обратная связь в системе отсутствовала. А в новом изделии небольшой люфт приводил к большой погрешности в показаниях энкодера, так что потребовалось сделать конструкцию более жёсткой.
Ну что ж, теперь можно приступать к решению главной задачи по перемещению стола на заданное расстояние. Двигатель управляется ШИМ-сигналом. Это значение от единицы до 255, если не использовать большее разрешение. Сразу выяснилось, что двигатель с редуктором начинает вращать стол с некоторого минимального значения ШИМ. На первом макетном столе это значение равнялось 60.
Итак, попробуем реализовать самый простой алгоритм: первую половину пути линейно увеличиваем ШИМ, вторую половину – линейно уменьшаем:
Если значение ШИМ превышает 255, оно будет обрезано:
Угол наклонных прямых на графике можно сделать настраиваемым, тогда пользователь сможет регулировать движения и шаги стола: сделать их более резкими и быстрыми, либо плавными и медленными. И оказалось, что этот простейший подход даёт неплохие результаты!
Правда, иногда стол всё-таки слегка перескакивал через заданную точку. На этот случай мы предусмотрели коррекционное перемещение для возврата назад на минимальном ШИМе. Тем не менее, хотелось бы добиться того, чтобы стол совершал минимальное количество таких ошибок.
Если на минимальном ШИМе стол безошибочно переходит в нужную точку, то что надо сделать? Может быть, стоит использовать квадратичное замедление вместо линейного? Тогда стол будет подходить к концу движениях на скоростях, близких к минимальному значению. Можно и так. Но оказалось, что есть более простое решение. Достаточно начинать тормозить чуть раньше, как на картинке:
Большое значение имеет правильный выбор минимального значения ШИМ. Если значение слишком велико, стол будет часто ошибаться и перескакивать через заданную точку. Слишком маленькое значение приведёт к тому, что нагруженный стол не сможет тронуться.
Тут родилась идея о том, что столу с тяжёлым грузом надо помогать начать движение. То есть если стол в течение определённого промежутка времени не сдвигается с места, надо слегка увеличивать минимальный ШИМ. Но нужно также предусмотреть и верхний лимит увеличения, чтобы в случае короткого перемещения стол не перескочил через заданную точку.
В процессе тестирования выяснилась странная вещь: вроде бы стол вовремя останавливается, но затем оказывается, что текущая позиция немного смещена. Особенно это заметно, если на столе стоит тяжёлый и неустойчивый предмет, например, канистра с плещущейся водой. Стало понятно, что это происходит в результате вибрации в конце движения. Чтобы дождаться полного окончания движения стола и принять решение о необходимости коррекции, нужно подождать какое-то время. Я решил задачу так: делю время на короткие интервалы по 10 мс и дожидаюсь, пока в течении десяти последних интервалов стол не меняет своего положения. Это позволяет минимизировать время ожидания. Попробовал трясти стол с грузом в конце движения – и класс! Стол ждёт, пока тряска не закончится!
Итак, задача перемещения стола была решена. И решена, как выяснилось, неплохо: калибровочные скетчи и скетчи, измеряющие время и осуществляющие десятки и даже сотни циклов по перемещению стола на 360°, приводили стол в исходное положение с точностью до долей миллиметра.
Теперь можно было приступать к реализации режимов стола: автоматическому, ручному, безостановочному, режиму видео и вращению на 90°. Тут дело техники. Упомяну только о том, что в шаговых режимах, автоматическом и ручном, была реализована ещё одна стадия отслеживания ошибок перемещения. Если на предыдущем шаге обнаружилась ошибка, её надо учесть и скорректировать количество меток энкодера, на которое надо переместить стол на следующем шаге. Это важно, поскольку стол в процессе работы может быть случайно сдвинут фотографом.
Как мы и предполагали, новый двигатель работал гораздо тише шагового. Тем не менее, во время работы был слышен лёгкий звон. Дело в том, что стандартная частота ШИМ в Ардуино менее 1 кГц, именно она и ощущается при работе мотора. После того, как мы увеличили частоту ШИМ до 15 кГц при помощи библиотеки PWM, звон исчез. Звук работающего двигателя стал приятным и чем-то напоминал звук движений Робокопа из голливудского фильма. После изменения частоты пришлось немного подкорректировать минимальное значение ШИМ в скетче.
Теперь об управлении. Мы предполагали, что стол будет управляться при помощи проводного пульта. Предыдущий опыт общения с пользователями говорил о том, что длина кабеля должна быть достаточно большой, не менее 5 метров. Когда-то мы пытались использовать беспроводные пульты, но этот опыт был не слишком удачным.
Кроме того, надо было предусмотреть дисплей. Режимов и настроек не так уж и мало, надо информировать пользователя о текущем состоянии. Нашли на Алиэкспресс подходящие коробочки. Вот таким получился пульт, с управляющим энкодером, кнопками и дисплеем:
По ходу дела попался нам на глаза китайский бесщёточный двигатель. Вот такой:
Ему не нужен драйвер, контроллер у него внутри, и ШИМ можно подавать непосредственно на выходы. Кроме того, не нужно менять частоту ШИМ, он работает одинаково тихо на любой частоте. Позже стало ясно, что это тоже важно.
В один прекрасный момент посмотрели мы на наш пульт и подумали, что как-то он не слишком удобен. Надо крутить энкодер, чтобы попасть в нужный пункт меню, жать кнопку, проваливаться в подменю… Да тут ещё и проблема с дисплеем нарисовалась. Подсоединён он у нас был к двум пинам ардуинки и управлялся по протоколу I2C. Оказалось, что если быстро крутить управляющий энкодер и переключать пункты меню на экране, дисплей начинает глючить, пропускать или путать буквы, а через какое-то время и вовсе зависает.
А что, если вообще отказаться от пульта и использовать вместо него смартфон? Мобильное приложение может отображать движения стола в реальном времени и вообще сделает процесс управления очень удобным. Соединяться со столом можно через bluetooth, тут проблем нет. Кроме того, в мобильном приложении можно реализовать такие фишки пользовательского интерфейса, которые трудно сделать на пульте, например, поворот стола на произвольный угол. Так у нас начался второй этап разработки.
Со средой разработки вопросов не было, это должен быть Xamarin. Во-первых, у меня уже был опыт разработки на этой платформе. А во-вторых, нужно приложение и для Android, и для iOS. Многие фотографы – пижоны, и любят пользоваться айфонами.
Xamarin не предоставляет стандартных средств для работы с bluetooth, поэтому пришлось искать библиотеку. Я остановился на Bluetooth LE. Собственно, и выбора-то особого не было, да и где-то на форумах MSDN сотрудник Microsoft рекомендовал эту библиотеку для работы в Xamarin. На первый взгляд, плагин оставлял впечатление какой-то незавершённости, но потом оказалось, что он вполне рабочий.
О железе: вначале я использовал имеющийся у меня bluetooth модуль HC-6. Он не подходил для полноценной работы, поскольку нам был нужен bluetooth не ниже 4 версии, то есть bluetooth low energy – iOS в отличие от Android не работает со старыми версиями. Но я набросал нечто вроде тестового фреймворка для первых экспериментов. Потом мы перешли на модули JDY-34, вот такие:
Архитектура была ясна с самого начала: приложение должно устанавливать связь со столом и посылать команды. Стол, то есть скетч, будет отвечать на команды и во время движения информировать приложение о своём текущем положении. Протокол обмена лучше всего построить на основе коротких текстовых сообщений, так отладка будет проще.
Пришло время изучать Bluetooth GATT. И вот что я вам скажу: вроде и Интернет у нас есть, и информации море, а найти то, что тебе нужно, с каждым годом всё сложнее и сложнее. В общем виде оно вроде бы понятно: GATT как иерархическая структура, устройство, сервисы, характеристики, но вот детали…
Лирическое отступление
Вспоминаю прекрасные руководства пользователя по операционным системам, программам и библиотекам 30-летней давности. Любая библиотека имела исчерпывающее описание всех методов и возможностей, это было очевидно и даже не обсуждалось. Написаны они были простым английским языком, и там можно было найти всю необходимую информацию. Кроме руководств своевременно выходили объёмные учебники, детально объясняющие все тонкости и проблемы.
Сейчас всё не так. Фреймворки меняют друг друга с калейдоскопической быстротой. Гайды пишутся, скорее, для галочки, а то их и вовсе нет. Массу времени приходится тратить на сбор информации в Интернете по крупицам… Да, судари мои, куда катится этот мир?
Исходя из архитектуры приложения, мне были нужны две возможности – write, чтобы посылать команды, и notify, чтобы получать ответы и уведомления. Но какую GATT-характеристику следует выбрать? В модуле JDY-34 есть несколько подходящих. Где-то в одном из описаний я нашёл UUID сервиса как в моём модуле и решил, что эту характеристику и надо использовать для записи и нотификации.
В этом и заключалась моя ошибка. Сначала вроде бы всё работало, но потом я стал замечать, что иногда ответы от стола приходят в искажённом виде. Вскоре я понял, что проблема заключается в следующем: приложение отправляет команду столу, но в это самое время от стола приходит очередной токен, и данные в общем буфере портятся. Как оказалось, никакой синхронизации на уровне характеристики нет, то есть запись и чтение могут перекрывать друг друга, и другого выхода, кроме использования раздельных характеристик для write и update нет. К счастью, модуль JDY-34 позволяет сделать это.
Кстати, ещё во время работы с модулем HC-6 я заметил, что мои короткие текстовые сообщения буквально в несколько символов, приходящие от стола, могут иногда разбиваться. То есть сначала приложение получает нотификацию с первой частью сообщения, а потом – со второй. Я надеялся, что в Bluetooth LE этого не будет, но нет, поведение осталось таким же. Так что мне пришлось ввести в протокол обмена разделитель термов и реализовать стрим, куда поступает входной поток сообщений.
В итоге, мобильное приложение получилось таким:
И вот пришло время решать вопрос с комплектующими. Платы Nano были ненадёжны, среди модулей JDY-41 попадались бракованные. Предлагать недешёвое изделие с подобной начинкой – это неуважение к покупателю. Хотелось бы найти хорошие надёжные платы со встроенным bluetooth.
Первое, что мы попробовали, – это ESP32, но она нам не зашла. То ли плата была левая, то ли делали мы что-то неправильно, но нам никак не удавалось заставить работать энкодер.
Потом мы стали смотреть в сторону BLE Nano V3.0 Micro с интегрированным чипом Bluetooth TI CC2540 BLE. Тут вообще интересная история случилась: вроде как и характеристики были такие же, как в модуле JDY-34, вплоть до совпадения UUID, но характеристика для записи не работала. То есть нотификация и чтение работает, а запись – нет.
Хорошо, если найти подходящую плату со встроенным bluetooth модулем не получается, надо хотя бы заменить устаревшие китайские Nano на что-то приличное. Вот в Москве есть в продаже фирменная Nano Every, позиционируется как эволюция традиционной Nano. Но – парадокс! библиотека PWM на ней не работает, и, похоже, возможности устанавливать частоту ШИМ для отдельных пинов нет вовсе. Можно, правда, ускорить системное время, тогда и частота увеличится. Не слишком элегантно, но этот подход работает. Надо только увеличить все временные интервалы, использующиеся в скетче, ведь функции millis и micros будут выдавать ускоренное время.
Тем не менее, такой подход довольно стрёмный. Вот, например, функции чтения в классе Serial используют временную задержку. Выходит, надо её переустанавливать при помощи Serial.setTimeout. А сколько ещё подобных подводных камней?
Под конец нам всё-таки удалось найти плату с интегрированным bluetooth модулем. Это Nano 33 IoT. Эта плата позволяет программно сконструировать в скетче bluetooth-устройство со всеми его сервисами и характеристиками, используя библиотеку ArduinoBLE. Библиотека эта реализует полноценный GATT. Это здорово! Программисты меня поймут – я был впечатлён!
И напоследок о моторах. Бесколлекторный двигатель, конечно, предпочтительней. Он не требует драйвера, но самое главное – не нужно менять частоту ШИМ, двигатель не звенит на стандартной частоте. На самом деле, важнейшей характеристикой является передаточное число, чем оно больше – тем лучше. На достаточно большом передаточном числе стол работает очень устойчиво. Кроме того, можно добиться медленного перемещения стола на минимальном ШИМе, а это важно для безостановочного режима.
Наш финальный выбор – бесщёточный двигатель с передаточным числом 131 и плата Nano 33 IoT.
На всякий случай оставлю ссылки на исходники, вдруг кому-то будет интересно:
→ Ардуино: Github
→ Xamarin: Github
Комментарии (18)
iliasam
06.06.2022 11:49Но есть один существенный недостаток. Шаговый двигатель сильно шумит. Иногда двигатель попадает в резонанс, и тогда тарахтение стола становится невыносимым.
Если использовать приличный драйвер мотора с большим числом микрошагов, то шум становится значительно меньше.AndreyRodin Автор
06.06.2022 12:04Верно, играя с количеством микрошагов, можно слегка уменьшить шум шагового двигателя. Но коллекторные и бесколлекторные двигатели работают в любом случае тише.
connected201
06.06.2022 11:51Очень классно! Советую делать фото либо на камере которая вам не нужна, либо видео сплитить на картинки, иначе камера быстро изнашивается если вам надо будет сделать 100500 снимков.
111djagernaut111
07.06.2022 09:34+1У некоторых камер есть электронный затвор. Вроде как в таком режиме можно много снимать.
alextrof94
08.06.2022 03:02Медленная и ограниченная ардуина... Мда...
С таким проектом самая простая ардуина на 328 атмеге будет более 99% времени простаивать.
Я делал проект отображения изображений на вращающемся колесе велосипеда, упёрся в скорость обмена с лентой ws2812b, которой стало недостаточно даже для прогулочной скорости. Вторую версию делал на более плотной ленте, и сначала тоже думал, ардуина виновата, но когда посчитал количество передаваемой инфы по одному пину - оказалось, упёрся в 900кбит/сек.
А тут даже скорости велосипедного колёса нет и столько инфы обрабатывать не требуется.
Вообще, про html+js тут уже сказали. Для меня некоторое время назад выбор упал бы не на esp32, а на esp8266, из-за стоимости, но может всё поменялось. Интерфейс с использованием какого-нибудь bootstrap можно сделать красивым без особых знаний css. Ajax запросы для обновления полей без обновления страницы тоже простая гуглящаяся штука. Ну, а сама esp8266 прекрасно программируется с использованием arduino фреймворка.
Esp8266 может и раздавать вафлю и одновременно быть подключенной к какой-то сети. Собственно всякие iot-девайсы зачастую на её основе сделаны, где изначально подключился к розданной девайсом вафле, выставил настройки, и затем уже через домашнюю сеть коннектишься и работаешь с девайсом.
Любой мк и любой софт ненадёжен. Будь то китайская дуина, или супер-пупер микроконтроллер. Для избежания фатальных проблем придумали вачдог таймеры. Не надо думать, что какое-то "революционное" новое устройство лучше протестированного десяток лет.
FGV
08.06.2022 05:13Для меня некоторое время назад выбор упал бы не на esp32, а на esp8266, из-за стоимости, но может всё поменялось.
Сейчас на али 8266 - 100р, 32 - 140р, вобщем то не принципиально.
Но! у 32 периферия гораздо богаче (есть например тот же "аппаратный" энкодер который тут очень кстати) и есть блюпуп.
FGV
Вероятнее всего - второе. У есп32 есть Pulse Counter (PCNT), который можно сконфигурировать для работы с энкодером:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
AndreyRodin Автор
Да, я тоже думаю, что это мы что-то делали не так.
Но проблема была в том, что к тому времени, как мы стали подбирать комплектующие, у нас уже были работающие скетчи в Ардуино. Тратить лишнее время на переход на другую платформу не хотелось, а в Ардуино нам не удалось найти работающую библиотеку для энкодера.
FGV
Чую что в поворотных столах все таки главное механика. А в остальном:
С точки зрения электроники, и возможно организации софта, по моему мнению сделано "не так" многое, как раз по причине:
Т.к. то к чему в конечном итоге пришли - автономный девайс управляемый через беспроводной интерфейс с телефона вполне себе реализуется на одной esp32 (драйвер движка для бесколлекторника - не нужен) и без дополнительного ПМО на телефоне. А вышло в итоге: связка кортекс и та же esp32 + еще дополнительный софт надо на телефон ставить.
Собственно как бы я реализовал:
Аппаратная часть - один контроллер esp32 + енкодер с согласованием уровней подключенный через pcnt + бесколлекторник с встроенным регулятором.
Программная часть:
Управление положением стола - через ПИД по положению + внутренний пропорциональный (или ПД) контур по скорости.
На esp32 запускается HTML сервер + WiFi точка доступа, при коннекте телефона - редирект на html станицу управления. Все управление столом производится из встроенного в телефон браузера.
Да, с разработкой программной части придется немного повозится, но это хоть как то будет похоже на проф. электронику а не на поделку студента 3-го курса.
AndreyRodin Автор
Использование WI-FI вместо bluetooth - это другой подход, но я не думаю, что в данном случае он оправдан. Фотограф должен находиться рядом со столом и контролировать процесс, а обмен при этом должен быть двусторонним, если мы хотим отрисовывать прогресс так же красиво, как в мобильном приложении. Так что я думаю, что мобильное приложение в данном случае гораздо удобнее.
ПИД-регулятор служит для поддержания заданного параметра, способного к изменениям. Как его использовать для перемещения стола на нужное расстояние? В статье сказано, что нам удалось обойтись более простыми средствами, но мне интересно, как можно было бы использовать ПИД для этой задачи.
DungeonLords
Кстати в stm32wb
Есть и квадратурный вход таймера и Bluetooth. Квадратурный вход таймера работает так: вы подключение энкодер (через RC фильтр низких частот) на две ножки stm32: ноджку A и ножку B. Далее с помощью регистров конфигурируете свой таймер на работу с энкодером.
Далее уже автоматически факт изменения шага энкодера отражается в счётом регистре таймера, никаких библиотек не надо. А с инициализацией HAL поможет. Очень удобно.
AndreyRodin Автор
Боюсь, при таком подходе стол в силу инерции будет часто перескакивать через заданную точку, а это недопустимо. Придётся добавлять в конструкцию тормоз, что усложнит и удорожит её.
strvv
кто мешает как у вас здесь, в статье указано, установить пороги, их 4 в таймере у stm32,
1 с минимума на максимум (когда отключать увеличение шим),
2 с с максимума на минимум (когда необходимо притормаживать),
3 остановка минимального шим, точка достигнута.
а работа не с библиотекой, а с прерываниями от таймера по порогам.
кстати 1 порог позволит автоматически поднимать шим, пока не стронется стол, т.е. можно сдвинуть 1->2, 2->3, 3->4,
а 1 каналом или не сдвигая, 4-ым ;) сделать минимальный сдвиг позиции энкодера, с учётом шума, тремора и прочих внешних воздействий, т.е. минимум это 0, а когда отработает минимальный сдвиг по энкодеру = шим в текущем состоянии это работа шим на доводке.
м... и влазя в следующий чат - приложение использует вэб-сервис, и там просто кодируется информация, а штатный компонент системы-браузер отображает.
тогда и приложение проще писать и отлаживать - как обычное html в редакторах html (я ушел с сЫсАдминства до 2007 года и не знаю текущего состояния c web2.0, html5 и прочим...)
DungeonLords
Пороги таймера stm32? Четыре? Вы с каналами не путаете?
"Боюсь, при таком подходе стол в силу инерции будет часто перескакивать через заданную точку"
Диво дивное. Я предложил аппаратный способ, который вообще не вносит программных задержек, работает так быстро, как позволяет железо, только и успевай из счетного регистра таймера считывать актуальное значение.
А то, что из-за инерции стол перескочит - так точно перескочит, надо лишь начальные условия подобрать. И любое бесконечно малое время реакции на изменение энкодера принципиально проблему не решит. Поэтому или вводите допустимую ошибку или механически предохраняйтесь, например, поставьте червячный редуктор.
strvv
там не только инерция, там и внешние условия - рукой помогут или ещё как.
да, каналы, а не пороги. я видать термин с статьи или с другой причины сказал, извините :)
поэтому на изменение счётчика вне работы изменение угла надо думать как реагировать.
FGV
Что значит двухсторонний обмен? Отображение от девайса угла поворота стола и прием от пользователя команд на поворот? Так html с этим вполне справится. Насчет красивостей ввиде секторов круга - не знаю но думаю поковыряв js тоже можно что то приличное изобразить. Вобщем ничего не мешает это красивое приложение сделать на html + js.
Угол поворота стола - это величина? И не просто величина, а регулируемая. Ее собственно и контролируем, дальше от этого и пляшем:
PWMмотора = ПИД(ошибки по углу);
ошибка по углу = заданный угол поворота - угол поворота с энкодера.
PWMмотора - ограничить (допустимой макс. скоростью), углы - после окончания движения приводить к диапазону +/-360град.
AndreyRodin Автор
Да я и не спорю. Возможно, придётся сокеты использовать, чтобы динамически сектора рисовать, можно ещё что-то придумать. Как вы справедливо заметили вначале, мороки много. А потом, по моему субъективному мнению, мобильное приложение в любом случае будет удобней, чем браузер.
Ясно, то есть регулятор должен стремиться к нулевому значению ошибки. Но тогда в половине случаев стол будет перескакивать через заданную точку, и придётся возвращать его назад. А задача ставится так, чтобы минимизировать количество таких перескакиваний. Таким образом, мы минимизируем общее время цикла. Мне удалось решить эту задачу без применения ПИД. Столы с разными размерами и моторами с разными передаточными числами работают устойчиво (проверено).
FGV
В ТАУ это называется перегулирование, в данном случае оно успешно лечится подбором коэффициентов ПИД регулятора.
Зато браузер всегда есть на любом телефоне и под любой осью :) Вобще некоторые девайсы имеют оба интерфейса и блюпуп и веб.